base.Fatalf("%v", err)
}
fmt.Fprintf(b, "// generated by compile -asmhdr from package %s\n\n", types.LocalPkg.Name)
- for _, n := range typecheck.Target.Asms {
+ for _, n := range typecheck.Target.AsmHdrDecls {
if n.Sym().IsBlank() {
continue
}
ir.CurFunc = nil
// Build init task, if needed.
- if initTask := pkginit.Task(); initTask != nil {
- typecheck.Export(initTask)
- }
+ pkginit.MakeTask()
// Generate ABI wrappers. Must happen before escape analysis
// and doesn't benefit from dead-coding or inlining.
numExterns := len(typecheck.Target.Externs)
numDecls := len(typecheck.Target.Funcs)
dumpglobls(typecheck.Target.Externs)
- reflectdata.CollectPTabs()
- numExports := len(typecheck.Target.Exports)
addsignats(typecheck.Target.Externs)
reflectdata.WriteRuntimeTypes()
- reflectdata.WriteTabs()
- numPTabs := reflectdata.CountPTabs()
+ reflectdata.WritePluginTable()
reflectdata.WriteImportStrings()
reflectdata.WriteBasicTypes()
dumpembeds()
staticdata.WriteFuncSyms()
addGCLocals()
-
- if numExports != len(typecheck.Target.Exports) {
- base.Fatalf("Target.Exports changed after compile functions loop")
- }
- newNumPTabs := reflectdata.CountPTabs()
- if newNumPTabs != numPTabs {
- base.Fatalf("ptabs changed after compile functions loop")
- }
}
func dumpLinkerObj(bout *bio.Writer) {
// declared at package scope.
Externs []*Name
- // Assembly function declarations.
- Asms []*Name
+ // AsmHdrDecls holds declared constants and struct types that should
+ // be included in -asmhdr output. It's only populated when -asmhdr
+ // is set.
+ AsmHdrDecls []*Name
// Cgo directives.
CgoPragmas [][]string
// Variables with //go:embed lines.
Embeds []*Name
- // Exported (or re-exported) symbols.
- Exports []*Name
+ // PluginExports holds exported functions and variables that are
+ // accessible through the package plugin API. It's only populated
+ // for -buildmode=plugin (i.e., compiling package main and -dynlink
+ // is set).
+ PluginExports []*Name
}
}
}
- if types.IsExported(sym.Name) {
+ if base.Ctxt.Flag_dynlink && types.LocalPkg.Name == "main" && types.IsExported(sym.Name) && name.Op() == ir.ONAME {
assert(!sym.OnExportList())
- target.Exports = append(target.Exports, name)
+ target.PluginExports = append(target.PluginExports, name)
sym.SetOnExportList(true)
}
- if base.Flag.AsmHdr != "" {
+ if base.Flag.AsmHdr != "" && (name.Op() == ir.OLITERAL || name.Op() == ir.OTYPE) {
assert(!sym.Asm())
- target.Asms = append(target.Asms, name)
+ target.AsmHdrDecls = append(target.AsmHdrDecls, name)
sym.SetAsm(true)
}
}
typecheck.InitTodoFunc = nil
}
-// Task makes and returns an initialization record for the package.
+// MakeTask makes an initialization record for the package, if necessary.
// See runtime/proc.go:initTask for its layout.
// The 3 tasks for initialization are:
// 1. Initialize all of the packages the current package depends on.
// 2. Initialize all the variables that have initializers.
// 3. Run any init functions.
-func Task() *ir.Name {
+func MakeTask() {
var deps []*obj.LSym // initTask records for packages the current package depends on
var fns []*obj.LSym // functions to call for package initialization
}
if len(deps) == 0 && len(fns) == 0 && types.LocalPkg.Path != "main" && types.LocalPkg.Path != "runtime" {
- return nil // nothing to initialize
+ return // nothing to initialize
}
// Make an .inittask structure.
// An initTask has pointers, but none into the Go heap.
// It's not quite read only, the state field must be modifiable.
objw.Global(lsym, int32(ot), obj.NOPTR)
- return task
}
// initRequiredForCoverage returns TRUE if we need to force creation
t *types.Type
}
-func CountPTabs() int {
- return len(ptabs)
-}
-
// runtime interface and reflection data structures
var (
// protects signatset and signatslice
gcsymmu sync.Mutex // protects gcsymset and gcsymslice
gcsymset = make(map[*types.Type]struct{})
-
- ptabs []*ir.Name
)
type typeSig struct {
lsym.Set(obj.AttrContentAddressable, true)
}
-func WriteTabs() {
- // process ptabs
- if types.LocalPkg.Name == "main" && len(ptabs) > 0 {
- ot := 0
- s := base.Ctxt.Lookup("go:plugin.tabs")
- for _, p := range ptabs {
- // Dump ptab symbol into go.pluginsym package.
- //
- // type ptab struct {
- // name nameOff
- // typ typeOff // pointer to symbol
- // }
- nsym := dname(p.Sym().Name, "", nil, true, false)
- t := p.Type()
- if p.Class != ir.PFUNC {
- t = types.NewPtr(t)
- }
- tsym := writeType(t)
- ot = objw.SymPtrOff(s, ot, nsym)
- ot = objw.SymPtrOff(s, ot, tsym)
- // Plugin exports symbols as interfaces. Mark their types
- // as UsedInIface.
- tsym.Set(obj.AttrUsedInIface, true)
- }
- objw.Global(s, int32(ot), int16(obj.RODATA))
+func WritePluginTable() {
+ ptabs := typecheck.Target.PluginExports
+ if len(ptabs) == 0 {
+ return
+ }
- ot = 0
- s = base.Ctxt.Lookup("go:plugin.exports")
- for _, p := range ptabs {
- ot = objw.SymPtr(s, ot, p.Linksym(), 0)
+ lsym := base.Ctxt.Lookup("go:plugin.tabs")
+ ot := 0
+ for _, p := range ptabs {
+ // Dump ptab symbol into go.pluginsym package.
+ //
+ // type ptab struct {
+ // name nameOff
+ // typ typeOff // pointer to symbol
+ // }
+ nsym := dname(p.Sym().Name, "", nil, true, false)
+ t := p.Type()
+ if p.Class != ir.PFUNC {
+ t = types.NewPtr(t)
}
- objw.Global(s, int32(ot), int16(obj.RODATA))
+ tsym := writeType(t)
+ ot = objw.SymPtrOff(lsym, ot, nsym)
+ ot = objw.SymPtrOff(lsym, ot, tsym)
+ // Plugin exports symbols as interfaces. Mark their types
+ // as UsedInIface.
+ tsym.Set(obj.AttrUsedInIface, true)
+ }
+ objw.Global(lsym, int32(ot), int16(obj.RODATA))
+
+ lsym = base.Ctxt.Lookup("go:plugin.exports")
+ ot = 0
+ for _, p := range ptabs {
+ ot = objw.SymPtr(lsym, ot, p.Linksym(), 0)
}
+ objw.Global(lsym, int32(ot), int16(obj.RODATA))
}
func WriteImportStrings() {
return typecheck.Expr(typecheck.NodAddr(x))
}
-func CollectPTabs() {
- if !base.Ctxt.Flag_dynlink || types.LocalPkg.Name != "main" {
- return
- }
- for _, exportn := range typecheck.Target.Exports {
- s := exportn.Sym()
- nn := ir.AsNode(s.Def)
- if nn == nil {
- continue
- }
- if nn.Op() != ir.ONAME {
- continue
- }
- n := nn.(*ir.Name)
- if !types.IsExported(s.Name) {
- continue
- }
- if s.Pkg.Name != "main" {
- continue
- }
- ptabs = append(ptabs, n)
- }
-}
-
// NeedEmit reports whether typ is a type that we need to emit code
// for (e.g., runtime type descriptors, method wrappers).
func NeedEmit(typ *types.Type) bool {
// Use readonlystaticname for read-only node.
func StaticName(t *types.Type) *ir.Name {
// Don't use LookupNum; it interns the resulting string, but these are all unique.
- n := typecheck.NewName(typecheck.Lookup(fmt.Sprintf("%s%d", obj.StaticNamePref, statuniqgen)))
+ sym := typecheck.Lookup(fmt.Sprintf("%s%d", obj.StaticNamePref, statuniqgen))
statuniqgen++
- typecheck.Declare(n, ir.PEXTERN)
+
+ n := typecheck.NewName(sym)
+ sym.Def = n
+
+ n.Class = ir.PEXTERN
+ typecheck.Target.Externs = append(typecheck.Target.Externs, n)
+
n.SetType(t)
n.Linksym().Set(obj.AttrStatic, true)
return n
var recv1 *types.Field
if recv != nil {
- recv1 = declareParam(ir.PPARAM, -1, recv)
+ recv1 = declareParam(fn, ir.PPARAM, -1, recv)
}
- typ := types.NewSignature(recv1, declareParams(ir.PPARAM, params), declareParams(ir.PPARAMOUT, results))
+ typ := types.NewSignature(recv1, declareParams(fn, ir.PPARAM, params), declareParams(fn, ir.PPARAMOUT, results))
checkdupfields("argument", typ.Recvs().FieldSlice(), typ.Params().FieldSlice(), typ.Results().FieldSlice())
fn.Nname.SetType(typ)
fn.Nname.SetTypecheck(1)
return fn
}
-// Declare records that Node n declares symbol n.Sym in the specified
-// declaration context.
-func Declare(n *ir.Name, ctxt ir.Class) {
- if ir.IsBlank(n) {
- return
- }
-
- s := n.Sym()
-
- // kludgy: TypecheckAllowed means we're past parsing. Eg reflectdata.methodWrapper may declare out of package names later.
- if !inimport && !TypecheckAllowed && s.Pkg != types.LocalPkg {
- base.ErrorfAt(n.Pos(), 0, "cannot declare name %v", s)
- }
-
- if ctxt == ir.PEXTERN {
- if s.Name == "init" {
- base.ErrorfAt(n.Pos(), errors.InvalidInitDecl, "cannot declare init - must be func")
- }
- if s.Name == "main" && s.Pkg.Name == "main" {
- base.ErrorfAt(n.Pos(), errors.InvalidMainDecl, "cannot declare main - must be func")
- }
- Target.Externs = append(Target.Externs, n)
- s.Def = n
- } else {
- if ir.CurFunc == nil && ctxt == ir.PAUTO {
- base.Pos = n.Pos()
- base.Fatalf("automatic outside function")
- }
- if ir.CurFunc != nil && ctxt != ir.PFUNC && n.Op() == ir.ONAME {
- ir.CurFunc.Dcl = append(ir.CurFunc.Dcl, n)
- }
- n.Curfn = ir.CurFunc
- }
-
- if ctxt == ir.PAUTO {
- n.SetFrameOffset(0)
- }
-
- n.Class = ctxt
- if ctxt == ir.PFUNC {
- n.Sym().SetFunc(true)
- }
-
- autoexport(n, ctxt)
-}
-
-// Export marks n for export (or reexport).
-func Export(n *ir.Name) {
- if n.Sym().OnExportList() {
- return
- }
- n.Sym().SetOnExportList(true)
-
- if base.Flag.E != 0 {
- fmt.Printf("export symbol %v\n", n.Sym())
- }
-
- Target.Exports = append(Target.Exports, n)
-}
-
// declare the function proper
// and declare the arguments.
// called in extern-declaration context
}
}
-func autoexport(n *ir.Name, ctxt ir.Class) {
- if n.Sym().Pkg != types.LocalPkg {
- return
- }
- if (ctxt != ir.PEXTERN && ctxt != ir.PFUNC) || DeclContext != ir.PEXTERN {
- return
- }
- if n.Type() != nil && n.Type().IsKind(types.TFUNC) && ir.IsMethod(n) {
- return
- }
-
- if types.IsExported(n.Sym().Name) || n.Sym().Name == "init" {
- Export(n)
- }
- if base.Flag.AsmHdr != "" && !n.Sym().Asm() {
- n.Sym().SetAsm(true)
- Target.Asms = append(Target.Asms, n)
- }
-}
-
// checkdupfields emits errors for duplicately named fields or methods in
// a list of struct or interface types.
func checkdupfields(what string, fss ...[]*types.Field) {
dclcontext ir.Class
}
-func declareParams(ctxt ir.Class, l []*ir.Field) []*types.Field {
+func declareParams(fn *ir.Func, ctxt ir.Class, l []*ir.Field) []*types.Field {
fields := make([]*types.Field, len(l))
for i, n := range l {
- fields[i] = declareParam(ctxt, i, n)
+ fields[i] = declareParam(fn, ctxt, i, n)
}
return fields
}
-func declareParam(ctxt ir.Class, i int, param *ir.Field) *types.Field {
+func declareParam(fn *ir.Func, ctxt ir.Class, i int, param *ir.Field) *types.Field {
f := types.NewField(param.Pos, param.Sym, param.Type)
f.SetIsDDD(param.IsDDD)
name := ir.NewNameAt(param.Pos, sym)
name.SetType(f.Type)
name.SetTypecheck(1)
- Declare(name, ctxt)
+
+ name.Class = ctxt
+ fn.Dcl = append(fn.Dcl, name)
+ name.Curfn = fn
f.Nname = name
}