Example #1
0
        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);
            }
        }
Example #2
0
        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);
            }