public Value Generate(IAstNode ast, Action <CodeGeneratorException> codeGenerationErroHandler) { try { // Prototypes, including extern are ignored as AST generation // adds them to the RuntimeState so that already has the declarations if (!(ast is FunctionDefinition definition)) { return(null); } InitializeModuleAndPassManager( ); var function = ( IrFunction )definition.Accept(this); if (definition.IsAnonymous) { // eagerly compile modules for anonymous functions as calling the function is the guaranteed next step ulong jitHandle = JIT.AddEagerlyCompiledModule(Module); var nativeFunc = JIT.GetFunctionDelegate <KaleidoscopeJIT.CallbackHandler0>(definition.Name); var retVal = Context.CreateConstant(nativeFunc( )); JIT.RemoveModule(jitHandle); return(retVal); } else { // Destroy any previously generated module for this function. // This allows re-definition as the new module will provide the // implementation. This is needed, otherwise both the MCJIT // and OrcJit engines will resolve to the original module, despite // claims to the contrary in the official tutorial text. (Though, // to be fair it may have been true in the original JIT and might // still be true for the interpreter) if (FunctionModuleMap.Remove(definition.Name, out ulong handle)) { JIT.RemoveModule(handle); } // Unknown if any future input will call the function so add it for lazy compilation. // Native code is generated for the module automatically only when required. ulong jitHandle = JIT.AddLazyCompiledModule(Module); FunctionModuleMap.Add(definition.Name, jitHandle); return(function); } } catch (CodeGeneratorException ex) when(codeGenerationErroHandler != null) { codeGenerationErroHandler(ex); return(null); } }
public override Value VisitTopLevelExpression([NotNull] TopLevelExpressionContext context) { var proto = new Prototype($"anon_expr_{AnonNameIndex++}"); var function = GetOrDeclareFunction(proto , isAnonymous: true ); var(_, jitHandle) = DefineFunction(function, context.expression()); var nativeFunc = JIT.GetDelegateForFunction <AnonExpressionFunc>(proto.Identifier.Name); var retVal = Context.CreateConstant(nativeFunc( )); JIT.RemoveModule(jitHandle); return(retVal); }
public Value Generate(IAstNode ast, Action <CodeGeneratorException> codeGenerationErroHandler) { try { // Prototypes, including extern are ignored as AST generation // adds them to the RuntimeState so that already has the declarations if (!(ast is FunctionDefinition definition)) { return(null); } // Anonymous functions are called immediately then removed from the JIT // so no point in setting them up as a lazy compilation item. if (definition.IsAnonymous) { InitializeModuleAndPassManager( ); var function = ( IrFunction )definition.Accept(this); // eagerly compile modules for anonymous functions as calling the function is the guaranteed next step ulong jitHandle = JIT.AddEagerlyCompiledModule(Module); var nativeFunc = JIT.GetFunctionDelegate <KaleidoscopeJIT.CallbackHandler0>(definition.Name); var retVal = Context.CreateConstant(nativeFunc( )); JIT.RemoveModule(jitHandle); return(retVal); } // Unknown if any future input will call the function so don't even generate IR // until it is needed. JIT triggers the callback to generate the IR module so the JIT // can then generate native code only when required. FunctionDefinition implDefinition = CloneAndRenameFunction(definition); // register the generator as a stub with the original source name JIT.AddLazyFunctionGenerator(definition.Name, () => { InitializeModuleAndPassManager( ); var function = ( IrFunction )implDefinition.Accept(this); return(implDefinition.Name, function.ParentModule); }); return(null); }