diff --git a/compiler/channel.go b/compiler/channel.go index b5bcd95b99..8098ea99a5 100644 --- a/compiler/channel.go +++ b/compiler/channel.go @@ -12,7 +12,7 @@ import ( // emitMakeChan returns a new channel value for the given channel type. func (c *Compiler) emitMakeChan(expr *ssa.MakeChan) (llvm.Value, error) { - chanType := c.mod.GetTypeByName("runtime.channel") + chanType := c.getLLVMType(c.getRuntimeType("channel")) size := c.targetData.TypeAllocSize(chanType) sizeValue := llvm.ConstInt(c.uintptrType, size, false) ptr := c.createRuntimeCall("alloc", []llvm.Value{sizeValue}, "chan.alloc") diff --git a/compiler/compiler.go b/compiler/compiler.go index 4364b03acf..73efc8d6b8 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -3,6 +3,7 @@ package compiler import ( "errors" "fmt" + "go/ast" "go/build" "go/constant" "go/token" @@ -66,6 +67,7 @@ type Compiler struct { interfaceInvokeWrappers []interfaceInvokeWrapper ir *ir.Program diagnostics []error + astComments map[string]*ast.CommentGroup } type Frame struct { @@ -275,39 +277,7 @@ func (c *Compiler) Compile(mainPath string) []error { var frames []*Frame - // Declare all named struct types. - for _, t := range c.ir.NamedTypes { - if named, ok := t.Type.Type().(*types.Named); ok { - if _, ok := named.Underlying().(*types.Struct); ok { - t.LLVMType = c.ctx.StructCreateNamed(named.Obj().Pkg().Path() + "." + named.Obj().Name()) - } - } - } - - // Define all named struct types. - for _, t := range c.ir.NamedTypes { - if named, ok := t.Type.Type().(*types.Named); ok { - if st, ok := named.Underlying().(*types.Struct); ok { - llvmType := c.getLLVMType(st) - t.LLVMType.StructSetBody(llvmType.StructElementTypes(), false) - } - } - } - - // Declare all globals. - for _, g := range c.ir.Globals { - typ := g.Type().(*types.Pointer).Elem() - llvmType := c.getLLVMType(typ) - global := c.mod.NamedGlobal(g.LinkName()) - if global.IsNil() { - global = llvm.AddGlobal(c.mod, llvmType, g.LinkName()) - } - g.LLVMGlobal = global - if !g.IsExtern() { - global.SetLinkage(llvm.InternalLinkage) - global.SetInitializer(c.getZeroValue(llvmType)) - } - } + c.loadASTComments(lprogram) // Declare all functions. for _, f := range c.ir.Functions { @@ -413,6 +383,22 @@ func (c *Compiler) Compile(mainPath string) []error { return c.diagnostics } +// getRuntimeType obtains a named type from the runtime package and returns it +// as a Go type. +func (c *Compiler) getRuntimeType(name string) types.Type { + return c.ir.Program.ImportedPackage("runtime").Type(name).Type() +} + +// getLLVMRuntimeType obtains a named type from the runtime package and returns +// it as a LLVM type, creating it if necessary. It is a shorthand for +// getLLVMType(getRuntimeType(name)). +func (c *Compiler) getLLVMRuntimeType(name string) llvm.Type { + return c.getLLVMType(c.getRuntimeType(name)) +} + +// getLLVMType creates and returns a LLVM type for a Go type. In the case of +// named struct types (or Go types implemented as named LLVM structs such as +// strings) it also creates it first if necessary. func (c *Compiler) getLLVMType(goType types.Type) llvm.Type { switch typ := goType.(type) { case *types.Array: @@ -441,7 +427,7 @@ func (c *Compiler) getLLVMType(goType types.Type) llvm.Type { case types.Complex128: return c.ctx.StructType([]llvm.Type{c.ctx.DoubleType(), c.ctx.DoubleType()}, false) case types.String, types.UntypedString: - return c.mod.GetTypeByName("runtime._string") + return c.getLLVMRuntimeType("_string") case types.Uintptr: return c.uintptrType case types.UnsafePointer: @@ -450,16 +436,23 @@ func (c *Compiler) getLLVMType(goType types.Type) llvm.Type { panic("unknown basic type: " + typ.String()) } case *types.Chan: - return llvm.PointerType(c.mod.GetTypeByName("runtime.channel"), 0) + return llvm.PointerType(c.getLLVMRuntimeType("channel"), 0) case *types.Interface: - return c.mod.GetTypeByName("runtime._interface") + return c.getLLVMRuntimeType("_interface") case *types.Map: - return llvm.PointerType(c.mod.GetTypeByName("runtime.hashmap"), 0) + return llvm.PointerType(c.getLLVMRuntimeType("hashmap"), 0) case *types.Named: - if _, ok := typ.Underlying().(*types.Struct); ok { - llvmType := c.mod.GetTypeByName(typ.Obj().Pkg().Path() + "." + typ.Obj().Name()) + if st, ok := typ.Underlying().(*types.Struct); ok { + // Structs are a special case. While other named types are ignored + // in LLVM IR, named structs are implemented as named structs in + // LLVM. This is because it is otherwise impossible to create + // self-referencing types such as linked lists. + llvmName := typ.Obj().Pkg().Path() + "." + typ.Obj().Name() + llvmType := c.mod.GetTypeByName(llvmName) if llvmType.IsNil() { - panic("underlying type not found: " + typ.Obj().Pkg().Path() + "." + typ.Obj().Name()) + llvmType = c.ctx.StructCreateNamed(llvmName) + underlying := c.getLLVMType(st) + llvmType.StructSetBody(underlying.StructElementTypes(), false) } return llvmType } @@ -1356,9 +1349,9 @@ func (c *Compiler) getValue(frame *Frame, expr ssa.Value) llvm.Value { } return c.createFuncValue(fn.LLVMFn, llvm.Undef(c.i8ptrType), fn.Signature) case *ssa.Global: - value := c.ir.GetGlobal(expr).LLVMGlobal + value := c.getGlobal(expr) if value.IsNil() { - c.addError(expr.Pos(), "global not found: "+c.ir.GetGlobal(expr).LinkName()) + c.addError(expr.Pos(), "global not found: "+expr.RelString(nil)) return llvm.Undef(c.getLLVMType(expr.Type())) } return value @@ -1696,9 +1689,9 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) { var iteratorType llvm.Type switch typ := expr.X.Type().Underlying().(type) { case *types.Basic: // string - iteratorType = c.mod.GetTypeByName("runtime.stringIterator") + iteratorType = c.getLLVMRuntimeType("stringIterator") case *types.Map: - iteratorType = c.mod.GetTypeByName("runtime.hashmapIterator") + iteratorType = c.getLLVMRuntimeType("hashmapIterator") default: panic("unknown type in range: " + typ.String()) } @@ -1858,7 +1851,7 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) { newPtr := c.builder.CreateInBoundsGEP(oldPtr, []llvm.Value{low}, "") newLen := c.builder.CreateSub(high, low, "") - str := llvm.Undef(c.mod.GetTypeByName("runtime._string")) + str := llvm.Undef(c.getLLVMRuntimeType("_string")) str = c.builder.CreateInsertValue(str, newPtr, 0, "") str = c.builder.CreateInsertValue(str, newLen, 1, "") return str, nil @@ -2237,7 +2230,7 @@ func (c *Compiler) parseConst(prefix string, expr *ssa.Const) llvm.Value { global.SetUnnamedAddr(true) zero := llvm.ConstInt(c.ctx.Int32Type(), 0, false) strPtr := c.builder.CreateInBoundsGEP(global, []llvm.Value{zero, zero}, "") - strObj := llvm.ConstNamedStruct(c.mod.GetTypeByName("runtime._string"), []llvm.Value{strPtr, strLen}) + strObj := llvm.ConstNamedStruct(c.getLLVMRuntimeType("_string"), []llvm.Value{strPtr, strLen}) return strObj } else if typ.Kind() == types.UnsafePointer { if !expr.IsNil() { @@ -2290,7 +2283,7 @@ func (c *Compiler) parseConst(prefix string, expr *ssa.Const) llvm.Value { llvm.ConstInt(c.uintptrType, 0, false), llvm.ConstPointerNull(c.i8ptrType), } - return llvm.ConstNamedStruct(c.mod.GetTypeByName("runtime._interface"), fields) + return llvm.ConstNamedStruct(c.getLLVMRuntimeType("_interface"), fields) case *types.Pointer: if expr.Value != nil { panic("expected nil pointer constant") @@ -2510,8 +2503,8 @@ func (c *Compiler) parseUnOp(frame *Frame, unop *ssa.UnOp) (llvm.Value, error) { // var C.add unsafe.Pointer // Instead of a load from the global, create a bitcast of the // function pointer itself. - global := c.ir.GetGlobal(unop.X.(*ssa.Global)) - name := global.LinkName()[:len(global.LinkName())-len("$funcaddr")] + globalName := c.getGlobalInfo(unop.X.(*ssa.Global)).linkName + name := globalName[:len(globalName)-len("$funcaddr")] fn := c.mod.NamedFunction(name) if fn.IsNil() { return llvm.Value{}, c.makeError(unop.Pos(), "cgo function not found: "+name) diff --git a/compiler/defer.go b/compiler/defer.go index 1246f03a0d..21fff3aad5 100644 --- a/compiler/defer.go +++ b/compiler/defer.go @@ -29,7 +29,7 @@ func (c *Compiler) deferInitFunc(frame *Frame) { frame.deferClosureFuncs = make(map[*ir.Function]int) // Create defer list pointer. - deferType := llvm.PointerType(c.mod.GetTypeByName("runtime._defer"), 0) + deferType := llvm.PointerType(c.getLLVMRuntimeType("_defer"), 0) frame.deferPtr = c.builder.CreateAlloca(deferType, "deferPtr") c.builder.CreateStore(llvm.ConstPointerNull(deferType), frame.deferPtr) } @@ -200,7 +200,7 @@ func (c *Compiler) emitRunDefers(frame *Frame) { } // Get the real defer struct type and cast to it. - valueTypes := []llvm.Type{c.uintptrType, llvm.PointerType(c.mod.GetTypeByName("runtime._defer"), 0), c.i8ptrType} + valueTypes := []llvm.Type{c.uintptrType, llvm.PointerType(c.getLLVMRuntimeType("_defer"), 0), c.i8ptrType} for _, arg := range callback.Args { valueTypes = append(valueTypes, c.getLLVMType(arg.Type())) } @@ -231,7 +231,7 @@ func (c *Compiler) emitRunDefers(frame *Frame) { // Direct call. // Get the real defer struct type and cast to it. - valueTypes := []llvm.Type{c.uintptrType, llvm.PointerType(c.mod.GetTypeByName("runtime._defer"), 0)} + valueTypes := []llvm.Type{c.uintptrType, llvm.PointerType(c.getLLVMRuntimeType("_defer"), 0)} for _, param := range callback.Params { valueTypes = append(valueTypes, c.getLLVMType(param.Type())) } @@ -260,7 +260,7 @@ func (c *Compiler) emitRunDefers(frame *Frame) { case *ssa.MakeClosure: // Get the real defer struct type and cast to it. fn := c.ir.GetFunction(callback.Fn.(*ssa.Function)) - valueTypes := []llvm.Type{c.uintptrType, llvm.PointerType(c.mod.GetTypeByName("runtime._defer"), 0)} + valueTypes := []llvm.Type{c.uintptrType, llvm.PointerType(c.getLLVMRuntimeType("_defer"), 0)} params := fn.Signature.Params() for i := 0; i < params.Len(); i++ { valueTypes = append(valueTypes, c.getLLVMType(params.At(i).Type())) diff --git a/compiler/func-lowering.go b/compiler/func-lowering.go index a774b23ac1..2d67e2a5f2 100644 --- a/compiler/func-lowering.go +++ b/compiler/func-lowering.go @@ -51,7 +51,7 @@ func (c *Compiler) LowerFuncValues() { } // Find all func values used in the program with their signatures. - funcValueWithSignaturePtr := llvm.PointerType(c.mod.GetTypeByName("runtime.funcValueWithSignature"), 0) + funcValueWithSignaturePtr := llvm.PointerType(c.getLLVMRuntimeType("funcValueWithSignature"), 0) signatures := map[string]*funcSignatureInfo{} for global := c.mod.FirstGlobal(); !global.IsNil(); global = llvm.NextGlobal(global) { if global.Type() != funcValueWithSignaturePtr { diff --git a/compiler/func.go b/compiler/func.go index 2a2af95429..5c66006188 100644 --- a/compiler/func.go +++ b/compiler/func.go @@ -52,7 +52,7 @@ func (c *Compiler) createFuncValue(funcPtr, context llvm.Value, sig *types.Signa funcValueWithSignatureGlobalName := funcPtr.Name() + "$withSignature" funcValueWithSignatureGlobal := c.mod.NamedGlobal(funcValueWithSignatureGlobalName) if funcValueWithSignatureGlobal.IsNil() { - funcValueWithSignatureType := c.mod.GetTypeByName("runtime.funcValueWithSignature") + funcValueWithSignatureType := c.getLLVMRuntimeType("funcValueWithSignature") funcValueWithSignature := llvm.ConstNamedStruct(funcValueWithSignatureType, []llvm.Value{ llvm.ConstPtrToInt(funcPtr, c.uintptrType), sigGlobal, @@ -126,7 +126,7 @@ func (c *Compiler) getFuncType(typ *types.Signature) llvm.Type { rawPtr := c.getRawFuncType(typ) return c.ctx.StructType([]llvm.Type{c.i8ptrType, rawPtr}, false) case funcValueSwitch: - return c.mod.GetTypeByName("runtime.funcValue") + return c.getLLVMRuntimeType("funcValue") default: panic("unimplemented func value variant") } diff --git a/compiler/goroutine-lowering.go b/compiler/goroutine-lowering.go index c493bf48ca..3aa72e938c 100644 --- a/compiler/goroutine-lowering.go +++ b/compiler/goroutine-lowering.go @@ -321,7 +321,7 @@ func (c *Compiler) markAsyncFunctions() (needsScheduler bool, err error) { // Coroutine setup. c.builder.SetInsertPointBefore(f.EntryBasicBlock().FirstInstruction()) - taskState := c.builder.CreateAlloca(c.mod.GetTypeByName("runtime.taskState"), "task.state") + taskState := c.builder.CreateAlloca(c.getLLVMRuntimeType("taskState"), "task.state") stateI8 := c.builder.CreateBitCast(taskState, c.i8ptrType, "task.state.i8") id := c.builder.CreateCall(coroIdFunc, []llvm.Value{ llvm.ConstInt(c.ctx.Int32Type(), 0, false), diff --git a/compiler/interface-lowering.go b/compiler/interface-lowering.go index 3df1c64430..6a756410c5 100644 --- a/compiler/interface-lowering.go +++ b/compiler/interface-lowering.go @@ -163,8 +163,8 @@ func (c *Compiler) LowerInterfaces() { // run runs the pass itself. func (p *lowerInterfacesPass) run() { // Collect all type codes. - typecodeIDPtr := llvm.PointerType(p.mod.GetTypeByName("runtime.typecodeID"), 0) - typeInInterfacePtr := llvm.PointerType(p.mod.GetTypeByName("runtime.typeInInterface"), 0) + typecodeIDPtr := llvm.PointerType(p.getLLVMRuntimeType("typecodeID"), 0) + typeInInterfacePtr := llvm.PointerType(p.getLLVMRuntimeType("typeInInterface"), 0) var typesInInterfaces []llvm.Value for global := p.mod.FirstGlobal(); !global.IsNil(); global = llvm.NextGlobal(global) { switch global.Type() { diff --git a/compiler/interface.go b/compiler/interface.go index 3d2014f317..d91b8063f6 100644 --- a/compiler/interface.go +++ b/compiler/interface.go @@ -28,14 +28,14 @@ func (c *Compiler) parseMakeInterface(val llvm.Value, typ types.Type, pos token. itfMethodSetGlobal := c.getTypeMethodSet(typ) itfConcreteTypeGlobal := c.mod.NamedGlobal("typeInInterface:" + itfTypeCodeGlobal.Name()) if itfConcreteTypeGlobal.IsNil() { - typeInInterface := c.mod.GetTypeByName("runtime.typeInInterface") + typeInInterface := c.getLLVMRuntimeType("typeInInterface") itfConcreteTypeGlobal = llvm.AddGlobal(c.mod, typeInInterface, "typeInInterface:"+itfTypeCodeGlobal.Name()) itfConcreteTypeGlobal.SetInitializer(llvm.ConstNamedStruct(typeInInterface, []llvm.Value{itfTypeCodeGlobal, itfMethodSetGlobal})) itfConcreteTypeGlobal.SetGlobalConstant(true) itfConcreteTypeGlobal.SetLinkage(llvm.PrivateLinkage) } itfTypeCode := c.builder.CreatePtrToInt(itfConcreteTypeGlobal, c.uintptrType, "") - itf := llvm.Undef(c.mod.GetTypeByName("runtime._interface")) + itf := llvm.Undef(c.getLLVMRuntimeType("_interface")) itf = c.builder.CreateInsertValue(itf, itfTypeCode, 0, "") itf = c.builder.CreateInsertValue(itf, itfValue, 1, "") return itf @@ -48,7 +48,7 @@ func (c *Compiler) getTypeCode(typ types.Type) llvm.Value { globalName := "type:" + getTypeCodeName(typ) global := c.mod.NamedGlobal(globalName) if global.IsNil() { - global = llvm.AddGlobal(c.mod, c.mod.GetTypeByName("runtime.typecodeID"), globalName) + global = llvm.AddGlobal(c.mod, c.getLLVMRuntimeType("typecodeID"), globalName) global.SetGlobalConstant(true) } return global @@ -163,11 +163,11 @@ func (c *Compiler) getTypeMethodSet(typ types.Type) llvm.Value { ms := c.ir.Program.MethodSets.MethodSet(typ) if ms.Len() == 0 { // no methods, so can leave that one out - return llvm.ConstPointerNull(llvm.PointerType(c.mod.GetTypeByName("runtime.interfaceMethodInfo"), 0)) + return llvm.ConstPointerNull(llvm.PointerType(c.getLLVMRuntimeType("interfaceMethodInfo"), 0)) } methods := make([]llvm.Value, ms.Len()) - interfaceMethodInfoType := c.mod.GetTypeByName("runtime.interfaceMethodInfo") + interfaceMethodInfoType := c.getLLVMRuntimeType("interfaceMethodInfo") for i := 0; i < ms.Len(); i++ { method := ms.At(i) signatureGlobal := c.getMethodSignature(method.Obj().(*types.Func)) diff --git a/compiler/symbol.go b/compiler/symbol.go new file mode 100644 index 0000000000..0df2ab6e42 --- /dev/null +++ b/compiler/symbol.go @@ -0,0 +1,107 @@ +package compiler + +// This file manages symbols, that is, functions and globals. It reads their +// pragmas, determines the link name, etc. + +import ( + "go/ast" + "go/token" + "go/types" + "strings" + + "github.com/tinygo-org/tinygo/loader" + "golang.org/x/tools/go/ssa" + "tinygo.org/x/go-llvm" +) + +// globalInfo contains some information about a specific global. By default, +// linkName is equal to .RelString(nil) on a global and extern is false, but for +// some symbols this is different (due to //go:extern for example). +type globalInfo struct { + linkName string // go:extern + extern bool // go:extern +} + +// loadASTComments loads comments on globals from the AST, for use later in the +// program. In particular, they are required for //go:extern pragmas on globals. +func (c *Compiler) loadASTComments(lprogram *loader.Program) { + c.astComments = map[string]*ast.CommentGroup{} + for _, pkgInfo := range lprogram.Sorted() { + for _, file := range pkgInfo.Files { + for _, decl := range file.Decls { + switch decl := decl.(type) { + case *ast.GenDecl: + switch decl.Tok { + case token.VAR: + if len(decl.Specs) != 1 { + continue + } + for _, spec := range decl.Specs { + switch spec := spec.(type) { + case *ast.ValueSpec: // decl.Tok == token.VAR + for _, name := range spec.Names { + id := pkgInfo.Pkg.Path() + "." + name.Name + c.astComments[id] = decl.Doc + } + } + } + } + } + } + } + } +} + +// getGlobal returns a LLVM IR global value for a Go SSA global. It is added to +// the LLVM IR if it has not been added already. +func (c *Compiler) getGlobal(g *ssa.Global) llvm.Value { + info := c.getGlobalInfo(g) + llvmGlobal := c.mod.NamedGlobal(info.linkName) + if llvmGlobal.IsNil() { + llvmType := c.getLLVMType(g.Type().(*types.Pointer).Elem()) + llvmGlobal = llvm.AddGlobal(c.mod, llvmType, info.linkName) + if !info.extern { + llvmGlobal.SetInitializer(c.getZeroValue(llvmType)) + llvmGlobal.SetLinkage(llvm.InternalLinkage) + } + } + return llvmGlobal +} + +// getGlobalInfo returns some information about a specific global. +func (c *Compiler) getGlobalInfo(g *ssa.Global) globalInfo { + info := globalInfo{} + if strings.HasPrefix(g.Name(), "C.") { + // Created by CGo: such a name cannot be created by regular C code. + info.linkName = g.Name()[2:] + info.extern = true + } else { + // Pick the default linkName. + info.linkName = g.RelString(nil) + // Check for //go: pragmas, which may change the link name (among + // others). + doc := c.astComments[info.linkName] + if doc != nil { + info.parsePragmas(doc) + } + } + return info +} + +// Parse //go: pragma comments from the source. In particular, it parses the +// //go:extern pragma on globals. +func (info *globalInfo) parsePragmas(doc *ast.CommentGroup) { + for _, comment := range doc.List { + if !strings.HasPrefix(comment.Text, "//go:") { + continue + } + parts := strings.Fields(comment.Text) + switch parts[0] { + case "//go:extern": + info.extern = true + if len(parts) == 2 { + info.linkName = parts[1] + } + } + } +} diff --git a/ir/ir.go b/ir/ir.go index 1556330ef3..d9d5764ee3 100644 --- a/ir/ir.go +++ b/ir/ir.go @@ -2,7 +2,6 @@ package ir import ( "go/ast" - "go/token" "go/types" "sort" "strings" @@ -23,10 +22,6 @@ type Program struct { mainPkg *ssa.Package Functions []*Function functionMap map[*ssa.Function]*Function - Globals []*Global - globalMap map[*ssa.Global]*Global - comments map[string]*ast.CommentGroup - NamedTypes []*NamedType } // Function or method. @@ -41,28 +36,6 @@ type Function struct { inline InlineType // go:inline } -// Global variable, possibly constant. -type Global struct { - *ssa.Global - program *Program - LLVMGlobal llvm.Value - linkName string // go:extern - extern bool // go:extern -} - -// Type with a name and possibly methods. -type NamedType struct { - *ssa.Type - LLVMType llvm.Type -} - -// Type that is at some point put in an interface. -type TypeWithMethods struct { - t types.Type - Num int - Methods map[string]*types.Selection -} - // Interface type that is at some point used in a type assert (to check whether // it implements another interface). type Interface struct { @@ -87,32 +60,6 @@ const ( // Create and initialize a new *Program from a *ssa.Program. func NewProgram(lprogram *loader.Program, mainPath string) *Program { - comments := map[string]*ast.CommentGroup{} - for _, pkgInfo := range lprogram.Sorted() { - for _, file := range pkgInfo.Files { - for _, decl := range file.Decls { - switch decl := decl.(type) { - case *ast.GenDecl: - switch decl.Tok { - case token.TYPE, token.VAR: - if len(decl.Specs) != 1 { - continue - } - for _, spec := range decl.Specs { - switch spec := spec.(type) { - case *ast.ValueSpec: // decl.Tok == token.VAR - for _, name := range spec.Names { - id := pkgInfo.Pkg.Path() + "." + name.Name - comments[id] = decl.Doc - } - } - } - } - } - } - } - } - program := lprogram.LoadSSA() program.Build() @@ -184,8 +131,6 @@ func NewProgram(lprogram *loader.Program, mainPath string) *Program { LoaderProgram: lprogram, mainPkg: mainPkg, functionMap: make(map[*ssa.Function]*Function), - globalMap: make(map[*ssa.Global]*Global), - comments: comments, } for _, pkg := range packageList { @@ -210,8 +155,6 @@ func (p *Program) AddPackage(pkg *ssa.Package) { case *ssa.Function: p.addFunction(member) case *ssa.Type: - t := &NamedType{Type: member} - p.NamedTypes = append(p.NamedTypes, t) methods := getAllMethods(pkg.Prog, member.Type()) if !types.IsInterface(member.Type()) { // named type @@ -220,13 +163,7 @@ func (p *Program) AddPackage(pkg *ssa.Package) { } } case *ssa.Global: - g := &Global{program: p, Global: member} - doc := p.comments[g.RelString(nil)] - if doc != nil { - g.parsePragmas(doc) - } - p.Globals = append(p.Globals, g) - p.globalMap[member] = g + // Ignore. Globals are not handled here. case *ssa.NamedConst: // Ignore: these are already resolved. default: @@ -260,10 +197,6 @@ func (p *Program) GetFunction(ssaFn *ssa.Function) *Function { return p.functionMap[ssaFn] } -func (p *Program) GetGlobal(ssaGlobal *ssa.Global) *Global { - return p.globalMap[ssaGlobal] -} - func (p *Program) MainPkg() *ssa.Package { return p.mainPkg } @@ -386,49 +319,6 @@ func (f *Function) CName() string { return "" } -// Parse //go: pragma comments from the source. -func (g *Global) parsePragmas(doc *ast.CommentGroup) { - for _, comment := range doc.List { - if !strings.HasPrefix(comment.Text, "//go:") { - continue - } - parts := strings.Fields(comment.Text) - switch parts[0] { - case "//go:extern": - g.extern = true - if len(parts) == 2 { - g.linkName = parts[1] - } - } - } -} - -// Return the link name for this global. -func (g *Global) LinkName() string { - if g.linkName != "" { - return g.linkName - } - if name := g.CName(); name != "" { - return name - } - return g.RelString(nil) -} - -func (g *Global) IsExtern() bool { - return g.extern || g.CName() != "" -} - -// Return the name of the C global if this is a CGo wrapper. Otherwise, return a -// zero-length string. -func (g *Global) CName() string { - name := g.Name() - if strings.HasPrefix(name, "C.") { - // created by ../loader/cgo.go - return name[2:] - } - return "" -} - // Get all methods of a type. func getAllMethods(prog *ssa.Program, typ types.Type) []*types.Selection { ms := prog.MethodSets.MethodSet(typ)