public override Value Visit(FunctionDefinition definition)
        {
            var function = GetOrDeclareFunction(definition.Signature);

            if (!function.IsDeclaration)
            {
                throw new CodeGeneratorException($"Function {function.Name} cannot be redefined in the same module");
            }

            try
            {
                var entryBlock = function.AppendBasicBlock("entry");
                InstructionBuilder.PositionAtEnd(entryBlock);
                using (NamedValues.EnterScope( ))
                {
                    foreach (var param in definition.Signature.Parameters)
                    {
                        NamedValues[param.Name] = function.Parameters[param.Index];
                    }

                    var funcReturn = definition.Body.Accept(this);
                    InstructionBuilder.Return(funcReturn);
                    function.Verify( );

                    FunctionPassManager.Run(function);
                    return(function);
                }
            }
            catch (CodeGeneratorException)
            {
                function.EraseFromParent( );
                throw;
            }
        }
Beispiel #2
0
 public void Dispose( )
 {
     JIT.Dispose( );
     Module?.Dispose( );
     FunctionPassManager?.Dispose( );
     Context.Dispose( );
 }
Beispiel #3
0
        public CodeGenerator(DynamicRuntimeState globalState, TargetMachine machine, bool disableOptimization = false)
            : base(null)
        {
            globalState.ValidateNotNull(nameof(globalState));
            machine.ValidateNotNull(nameof(machine));

            if (globalState.LanguageLevel > LanguageLevel.MutableVariables)
            {
                throw new ArgumentException("Language features not supported by this generator", nameof(globalState));
            }

            RuntimeState         = globalState;
            Context              = new Context( );
            TargetMachine        = machine;
            DisableOptimizations = disableOptimization;
            InstructionBuilder   = new InstructionBuilder(Context);
            Module = Context.CreateBitcodeModule( );
            Module.TargetTriple = machine.Triple;
            Module.Layout       = TargetMachine.TargetData;
            FunctionPassManager = new FunctionPassManager(Module);
            FunctionPassManager.AddPromoteMemoryToRegisterPass( );

            if (!DisableOptimizations)
            {
                FunctionPassManager.AddInstructionCombiningPass( )
                .AddReassociatePass( )
                .AddGVNPass( )
                .AddCFGSimplificationPass( );
            }

            FunctionPassManager.Initialize( );
        }
Beispiel #4
0
        public override Value?Visit(FunctionDefinition definition)
        {
            definition.ValidateNotNull(nameof(definition));
            var function = GetOrDeclareFunction(definition.Signature);

            if (!function.IsDeclaration)
            {
                throw new CodeGeneratorException($"Function {function.Name} cannot be redefined in the same module");
            }

            try
            {
                var entryBlock = function.AppendBasicBlock("entry");
                InstructionBuilder.PositionAtEnd(entryBlock);
                using (NamedValues.EnterScope( ))
                {
                    foreach (var param in definition.Signature.Parameters)
                    {
                        var argSlot = InstructionBuilder.Alloca(function.Context.DoubleType)
                                      .RegisterName(param.Name);
                        InstructionBuilder.Store(function.Parameters[param.Index], argSlot);
                        NamedValues[param.Name] = argSlot;
                    }

                    foreach (LocalVariableDeclaration local in definition.LocalVariables)
                    {
                        var localSlot = InstructionBuilder.Alloca(function.Context.DoubleType)
                                        .RegisterName(local.Name);
                        NamedValues[local.Name] = localSlot;
                    }

                    EmitBranchToNewBlock("body");

                    var funcReturn = definition.Body.Accept(this) ?? throw new CodeGeneratorException(ExpectValidFunc);
                    InstructionBuilder.Return(funcReturn);
                    function.Verify( );

                    FunctionPassManager.Run(function);

                    if (definition.IsAnonymous)
                    {
                        function.AddAttribute(FunctionAttributeIndex.Function, AttributeKind.AlwaysInline)
                        .Linkage(Linkage.Private);

                        AnonymousFunctions.Add(function);
                    }

                    return(function);
                }
            }
            catch (CodeGeneratorException)
            {
                function.EraseFromParent( );
                throw;
            }
        }
Beispiel #5
0
 private void InitializeModuleAndPassManager( )
 {
     Module = new BitcodeModule(Context, "Kaleidoscope");
     FunctionPassManager = new FunctionPassManager(Module);
     FunctionPassManager.AddInstructionCombiningPass( )
     .AddReassociatePass( )
     .AddGVNPass( )
     .AddCFGSimplificationPass( )
     .Initialize( );
 }
        private void InitializeModuleAndPassManager( )
        {
            Module              = Context.CreateBitcodeModule( );
            Module.Layout       = JIT.TargetMachine.TargetData;
            FunctionPassManager = new FunctionPassManager(Module);

            if (!DisableOptimizations)
            {
                FunctionPassManager.AddInstructionCombiningPass( )
                .AddReassociatePass( )
                .AddGVNPass( )
                .AddCFGSimplificationPass( );
            }

            FunctionPassManager.Initialize( );
        }
        internal void InitializeModuleAndPassManager( )
        {
            this.Module = this._ctx.CreateBitcodeModule( );
            this.Module.TargetTriple  = this._machine.Triple;
            this.Module.Layout        = this._machine.TargetData;
            this._functionPassManager = new FunctionPassManager(this.Module)
                                        .AddPromoteMemoryToRegisterPass( );

            if (!this._disableOptimizations)
            {
                this._functionPassManager.AddInstructionCombiningPass( )
                .AddReassociatePass( )
                .AddGVNPass( )
                .AddCFGSimplificationPass( );
            }

            this._functionPassManager.Initialize( );
        }
        private void InitializeModuleAndPassManager(string sourcePath)
        {
            Module = Context.CreateBitcodeModule(Path.GetFileName(sourcePath), SourceLanguage.C, sourcePath, "Kaleidoscope Compiler");
            Module.TargetTriple = TargetMachine.Triple;
            Module.Layout       = TargetMachine.TargetData;
            DoubleType          = new DebugBasicType(Context.DoubleType, Module, "double", DiTypeKind.Float);

            FunctionPassManager = new FunctionPassManager(Module);
            FunctionPassManager.AddPromoteMemoryToRegisterPass( );

            if (!DisableOptimizations)
            {
                FunctionPassManager.AddInstructionCombiningPass( )
                .AddReassociatePass( )
                .AddGVNPass( )
                .AddCFGSimplificationPass( );
            }

            FunctionPassManager.Initialize( );
        }
Beispiel #9
0
        public CodeGenerator(DynamicRuntimeState globalState, TargetMachine machine, string sourcePath, bool disableOptimization = false)
            : base(null)
        {
            globalState.ValidateNotNull(nameof(globalState));
            machine.ValidateNotNull(nameof(machine));
            if (globalState.LanguageLevel > LanguageLevel.MutableVariables)
            {
                throw new ArgumentException("Language features not supported by this generator", nameof(globalState));
            }

            RuntimeState         = globalState;
            Context              = new Context( );
            TargetMachine        = machine;
            DisableOptimizations = disableOptimization;
            InstructionBuilder   = new InstructionBuilder(Context);

            #region InitializeModuleAndPassManager
            Module = Context.CreateBitcodeModule(Path.GetFileName(sourcePath), SourceLanguage.C, sourcePath, "Kaleidoscope Compiler");
            Debug.Assert(Module.DICompileUnit != null, "Expected non null compile unit");
            Debug.Assert(Module.DICompileUnit.File != null, "Expected non-null file for compile unit");

            Module.TargetTriple = machine.Triple;
            Module.Layout       = TargetMachine.TargetData;
            DoubleType          = new DebugBasicType(Context.DoubleType, Module, "double", DiTypeKind.Float);

            FunctionPassManager = new FunctionPassManager(Module);
            FunctionPassManager.AddPromoteMemoryToRegisterPass( );

            if (!DisableOptimizations)
            {
                FunctionPassManager.AddInstructionCombiningPass( )
                .AddReassociatePass( )
                .AddGVNPass( )
                .AddCFGSimplificationPass( );
            }

            FunctionPassManager.Initialize( );
            #endregion
        }
Beispiel #10
0
        public override Value?Visit(FunctionDefinition definition)
        {
            definition.ValidateNotNull(nameof(definition));
            var function = GetOrDeclareFunction(definition.Signature);

            if (!function.IsDeclaration)
            {
                throw new CodeGeneratorException($"Function {function.Name} cannot be redefined in the same module");
            }

            Debug.Assert(function.DISubProgram != null, "Expected function with non-null DISubProgram");
            LexicalBlocks.Push(function.DISubProgram);
            try
            {
                var entryBlock = function.AppendBasicBlock("entry");
                InstructionBuilder.PositionAtEnd(entryBlock);

                // Unset the location for the prologue emission (leading instructions with no
                // location in a function are considered part of the prologue and the debugger
                // will run past them when breaking on a function)
                EmitLocation(null);

                using (NamedValues.EnterScope( ))
                {
                    foreach (var param in definition.Signature.Parameters)
                    {
                        var argSlot = InstructionBuilder.Alloca(function.Context.DoubleType)
                                      .RegisterName(param.Name);
                        AddDebugInfoForAlloca(argSlot, function, param);
                        InstructionBuilder.Store(function.Parameters[param.Index], argSlot);
                        NamedValues[param.Name] = argSlot;
                    }

                    foreach (LocalVariableDeclaration local in definition.LocalVariables)
                    {
                        var localSlot = InstructionBuilder.Alloca(function.Context.DoubleType)
                                        .RegisterName(local.Name);
                        AddDebugInfoForAlloca(localSlot, function, local);
                        NamedValues[local.Name] = localSlot;
                    }

                    EmitBranchToNewBlock("body");

                    var funcReturn = definition.Body.Accept(this) ?? throw new CodeGeneratorException(ExpectValidFunc);
                    InstructionBuilder.Return(funcReturn);
                    Module.DIBuilder.Finish(function.DISubProgram);
                    function.Verify( );

                    FunctionPassManager.Run(function);

                    if (definition.IsAnonymous)
                    {
                        function.AddAttribute(FunctionAttributeIndex.Function, AttributeKind.AlwaysInline)
                        .Linkage(Linkage.Private);

                        AnonymousFunctions.Add(function);
                    }

                    return(function);
                }
            }
            catch (CodeGeneratorException)
            {
                function.EraseFromParent( );
                throw;
            }
        }
 public void Dispose( )
 {
     FunctionPassManager?.Dispose( );
     Context.Dispose( );
 }
Beispiel #12
0
        public static Module Generate(Context context, string path, SemanticModule module,
                                      SemanticContext semanticContext, string targetTriple, PassManagerBuilder?optBuilder, bool debugInfo,
                                      bool columnInfo)
        {
            // Path information for debug info nodes
            string fileName = Path.GetFileName(path);
            string dirName  = Path.GetDirectoryName(path);

            if (dirName == null)
            {
                dirName = "/";
            }
            else if (dirName.Length == 0)
            {
                dirName = ".";
            }

            // Create module and file-level debug info nodes
            using CodeGeneratorContext genContext = new CodeGeneratorContext(context, module, semanticContext, fileName,
                                                                             dirName, targetTriple, optBuilder != null, debugInfo, columnInfo);

            // Enum pass
            foreach (EnumNode enumNode in genContext.ParseModule.Enums)
            {
                Metadata[] enumerators = new Metadata[enumNode.Declarations.Count];
                for (int i = 0, ilen = enumNode.Declarations.Count; i < ilen; ++i)
                {
                    var enumeration = enumNode.Declarations[i];
                    enumerators[i] = genContext.DiBuilder.CreateEnumerator(enumeration.Name, i, false);
                }

                genContext.TryGetNodeSymbol(enumNode, out Symbol range);
                genContext.DiBuilder.CreateEnumerationType(genContext.DiFile,
                                                           (enumNode.IsExported ? "export." : "") + $"enum.{fileName}.{range.LLVMLine}", genContext.DiFile,
                                                           range.LLVMLine, genContext.DiBuilder.Int32Type.GetTypeSizeInBits(),
                                                           genContext.DiBuilder.Int32Type.GetTypeAlignInBits(), enumerators, genContext.DiBuilder.Int32Type);
            }

            // Struct pass
            foreach (StructNode structNode in genContext.ParseModule.Structs)
            {
                genContext.EnsureStruct(structNode);
            }

            // Declaration pass
            foreach (FunctionDefinitionNode function in genContext.ParseModule.Functions)
            {
                genContext.RegisterDefinedFunction(function);
            }

            // Definition pass
            foreach (FunctionDefinitionNode function in genContext.ParseModule.Functions)
            {
                CodeGeneratorContext.Function ctxFunction = genContext.GetFunctionDefinition(function);

                using Builder builder = genContext.Context.CreateBuilder();
                FunctionCodeGenVisitor functionCodeGenVisitor = new FunctionCodeGenVisitor(genContext, ctxFunction,
                                                                                           builder, ctxFunction.StartDefinition(genContext, builder));
                builder.PositionAtEnd(functionCodeGenVisitor._basicBlock);
                function.Body.VisitStatements(functionCodeGenVisitor);

                if (genContext.DebugInfo)
                {
                    // TODO: Use the body end rather than the function end
                    genContext.TryGetNodeSymbol(function, out Symbol range);
                    Metadata location = genContext.Context.CreateDebugLocation(range.End.Line + 1,
                                                                               genContext.ColumnInfo ? range.End.Column + 1 : 0, ctxFunction.DiFunctionDef,
                                                                               Metadata.Null);
                    builder.SetCurrentDebugLocation(location);
                }

                // If we still have a valid insert block, this function did not end with a return; Insert one now
                if (builder.InsertBlock.IsValid)
                {
                    if (ctxFunction.ReturnBlock != null)
                    {
                        builder.BuildBr(ctxFunction.ReturnBlock.Value);
                    }
                    else
                    {
                        builder.BuildRetVoid();
                    }
                }

                if (ctxFunction.ReturnBlock != null && ctxFunction.RetvalStorage != null)
                {
                    ctxFunction.FunctionValue.AppendExistingBasicBlock(ctxFunction.ReturnBlock.Value);
                    builder.PositionAtEnd(ctxFunction.ReturnBlock.Value);
                    Value retVal = builder.BuildLoad(ctxFunction.RetvalStorage.Value);
                    builder.BuildRet(retVal);
                }
            }

            // Remove unused metadata nodes for undefined functions
            genContext.FinalizeFunctions();

            // Finalize debug info
            genContext.DiBuilder.BuilderFinalize();

            // Run optimization passes on functions and module if a builder is supplied
            if (optBuilder != null)
            {
                using ModulePassManager modulePassManager     = new ModulePassManager(optBuilder);
                using FunctionPassManager functionPassManager = new FunctionPassManager(genContext.Module, optBuilder);

                functionPassManager.Initialize();
                foreach (var function in genContext.DefinedFunctions)
                {
                    functionPassManager.Run(function.Value.FunctionValue);
                }

                functionPassManager.FinalizeFunctionPassManager();

                modulePassManager.Run(genContext.Module);
            }

            // Done with everything in CodeGeneratorContext besides the Module
            return(genContext.Module);
        }
Beispiel #13
0
 public void Dispose( )
 {
     Module.Dispose( );
     FunctionPassManager.Dispose( );
     Context.Dispose( );
 }