diff options
author | Johannes Stoelp <johannes.stoelp@gmail.com> | 2021-09-25 00:48:45 +0200 |
---|---|---|
committer | Johannes Stoelp <johannes.stoelp@gmail.com> | 2021-09-25 00:48:45 +0200 |
commit | 6eb6ad9f574c783d471f6a863299af25b6f5a8c7 (patch) | |
tree | 38c087654f2c703d7d4c6afbf342aa9dd65557c9 /src/codegen.rs | |
parent | 425ba77074347f71283f75839224f78bd94f2e10 (diff) | |
download | llvm-kaleidoscope-rs-6eb6ad9f574c783d471f6a863299af25b6f5a8c7.tar.gz llvm-kaleidoscope-rs-6eb6ad9f574c783d471f6a863299af25b6f5a8c7.zip |
ch4: added jit
Diffstat (limited to 'src/codegen.rs')
-rw-r--r-- | src/codegen.rs | 35 |
1 files changed, 28 insertions, 7 deletions
diff --git a/src/codegen.rs b/src/codegen.rs index 08c3039..61634ad 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -11,18 +11,21 @@ pub struct Codegen<'llvm, 'a> { module: &'llvm Module, builder: &'a IRBuilder<'llvm>, fpm: &'a FunctionPassManager<'llvm>, + fn_protos: &'a mut HashMap<String, PrototypeAST>, } impl<'llvm, 'a> Codegen<'llvm, 'a> { /// Compile either a [`PrototypeAST`] or a [`FunctionAST`] into the LLVM `module`. pub fn compile( module: &'llvm Module, + fn_protos: &mut HashMap<String, PrototypeAST>, compilee: Either<&PrototypeAST, &FunctionAST>, ) -> CodegenResult<FnValue<'llvm>> { - let cg = Codegen { + let mut cg = Codegen { module, builder: &IRBuilder::with_ctx(module), fpm: &FunctionPassManager::with_ctx(module), + fn_protos, }; let mut variables = HashMap::new(); @@ -59,7 +62,7 @@ impl<'llvm, 'a> Codegen<'llvm, 'a> { _ => Err("invalid binary operator".into()), } } - ExprAST::Call(callee, args) => match self.module.get_fn(callee) { + ExprAST::Call(callee, args) => match self.get_function(callee) { Some(callee) => { if callee.args() != args.len() { return Err("Incorrect # arguments passed".into()); @@ -99,14 +102,16 @@ impl<'llvm, 'a> Codegen<'llvm, 'a> { } fn codegen_function( - &self, + &mut self, FunctionAST(proto, body): &FunctionAST, named_values: &mut HashMap<&'llvm str, Value<'llvm>>, ) -> CodegenResult<FnValue<'llvm>> { - let the_function = match self.module.get_fn(&proto.0) { - Some(f) => f, - None => self.codegen_prototype(proto), - }; + // Insert the function prototype into the `fn_protos` map to keep track for re-generating + // declarations in other modules. + self.fn_protos.insert(proto.0.clone(), proto.clone()); + + let the_function = self.get_function(&proto.0) + .expect("If proto not already generated, get_function will do for us since we updated fn_protos before-hand!"); if the_function.basic_blocks() > 0 { return Err("Function cannot be redefined.".into()); @@ -138,4 +143,20 @@ impl<'llvm, 'a> Codegen<'llvm, 'a> { todo!("Failed to codegen function body, erase from module!"); } } + + /// Lookup function with `name` in the LLVM module and return the corresponding value reference. + /// If the function is not available in the module, check if the prototype is known and codegen + /// it. + /// Return [`None`] if the prototype is not known. + fn get_function(&self, name: &str) -> Option<FnValue<'llvm>> { + let callee = match self.module.get_fn(name) { + Some(callee) => callee, + None => { + let proto = self.fn_protos.get(name)?; + self.codegen_prototype(proto) + } + }; + + Some(callee) + } } |