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; } }
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; } }
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 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); }