Пример #1
0
        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;
            }
        }
Пример #2
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;
            }
        }
Пример #3
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;
            }
        }
Пример #4
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);
        }