diff --git a/compiler/compiler.go b/compiler/compiler.go index f5057836..77fd3f36 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -62,10 +62,6 @@ type Compiler struct { initFuncs []llvm.Value } -type Frame struct { - builder -} - // builder contains all information relevant to build a single function. type builder struct { *compilerContext @@ -263,8 +259,6 @@ func (c *Compiler) Compile(mainPath string) []error { }) } - var frames []*Frame - c.loadASTComments(lprogram) // Declare runtime types. @@ -283,21 +277,32 @@ func (c *Compiler) Compile(mainPath string) []error { // Declare all functions. for _, f := range c.ir.Functions { - frames = append(frames, c.parseFuncDecl(f)) + c.createFunctionDeclaration(f) } // Add definitions to declarations. - for _, frame := range frames { - if frame.fn.Synthetic == "package initializer" { - c.initFuncs = append(c.initFuncs, frame.fn.LLVMFn) + for _, f := range c.ir.Functions { + if f.Synthetic == "package initializer" { + c.initFuncs = append(c.initFuncs, f.LLVMFn) } - if frame.fn.CName() != "" { + if f.CName() != "" { continue } - if frame.fn.Blocks == nil { + if f.Blocks == nil { continue // external function } - frame.createFunctionDefinition() + + // Create the function definition. + b := builder{ + compilerContext: &c.compilerContext, + Builder: c.builder, + fn: f, + locals: make(map[ssa.Value]llvm.Value), + dilocals: make(map[*types.Var]llvm.Metadata), + blockEntries: make(map[*ssa.BasicBlock]llvm.BasicBlock), + blockExits: make(map[*ssa.BasicBlock]llvm.BasicBlock), + } + b.createFunctionDefinition() } // After all packages are imported, add a synthetic initializer function @@ -726,19 +731,9 @@ func (b *builder) getLocalVariable(variable *types.Var) llvm.Metadata { return dilocal } -func (c *Compiler) parseFuncDecl(f *ir.Function) *Frame { - frame := &Frame{ - builder: builder{ - compilerContext: &c.compilerContext, - Builder: c.builder, // TODO: use a separate builder per function - fn: f, - locals: make(map[ssa.Value]llvm.Value), - dilocals: make(map[*types.Var]llvm.Metadata), - blockEntries: make(map[*ssa.BasicBlock]llvm.BasicBlock), - blockExits: make(map[*ssa.BasicBlock]llvm.BasicBlock), - }, - } - +// createFunctionDeclaration creates a LLVM function declaration without body. +// It can later be filled with frame.createFunctionDefinition(). +func (c *compilerContext) createFunctionDeclaration(f *ir.Function) { var retType llvm.Type if f.Signature.Results() == nil { retType = c.ctx.VoidType() @@ -769,9 +764,9 @@ func (c *Compiler) parseFuncDecl(f *ir.Function) *Frame { fnType := llvm.FunctionType(retType, paramTypes, false) name := f.LinkName() - frame.fn.LLVMFn = c.mod.NamedFunction(name) - if frame.fn.LLVMFn.IsNil() { - frame.fn.LLVMFn = llvm.AddFunction(c.mod, name, fnType) + f.LLVMFn = c.mod.NamedFunction(name) + if f.LLVMFn.IsNil() { + f.LLVMFn = llvm.AddFunction(c.mod, name, fnType) } // External/exported functions may not retain pointer values. @@ -780,18 +775,16 @@ func (c *Compiler) parseFuncDecl(f *ir.Function) *Frame { // Set the wasm-import-module attribute if the function's module is set. if f.Module() != "" { wasmImportModuleAttr := c.ctx.CreateStringAttribute("wasm-import-module", f.Module()) - frame.fn.LLVMFn.AddFunctionAttr(wasmImportModuleAttr) + f.LLVMFn.AddFunctionAttr(wasmImportModuleAttr) } nocaptureKind := llvm.AttributeKindID("nocapture") nocapture := c.ctx.CreateEnumAttribute(nocaptureKind, 0) for i, typ := range paramTypes { if typ.TypeKind() == llvm.PointerTypeKind { - frame.fn.LLVMFn.AddAttributeAtIndex(i+1, nocapture) + f.LLVMFn.AddAttributeAtIndex(i+1, nocapture) } } } - - return frame } // attachDebugInfo adds debug info to a function declaration. It returns the