diff options
Diffstat (limited to 'src/cmd/compile/internal/gc')
-rw-r--r-- | src/cmd/compile/internal/gc/gen.go | 11 | ||||
-rw-r--r-- | src/cmd/compile/internal/gc/gsubr.go | 63 | ||||
-rw-r--r-- | src/cmd/compile/internal/gc/noder.go | 13 | ||||
-rw-r--r-- | src/cmd/compile/internal/gc/pgen.go | 4 | ||||
-rw-r--r-- | src/cmd/compile/internal/gc/reflect.go | 4 | ||||
-rw-r--r-- | src/cmd/compile/internal/gc/ssa.go | 40 |
6 files changed, 111 insertions, 24 deletions
diff --git a/src/cmd/compile/internal/gc/gen.go b/src/cmd/compile/internal/gc/gen.go index f9b4584cf6..43d12925eb 100644 --- a/src/cmd/compile/internal/gc/gen.go +++ b/src/cmd/compile/internal/gc/gen.go @@ -11,7 +11,18 @@ import ( "strconv" ) +// sysfunc looks up Go function name in package runtime. This function +// must follow the internal calling convention. func sysfunc(name string) *obj.LSym { + s := Runtimepkg.Lookup(name) + s.SetFunc(true) + return s.Linksym() +} + +// sysvar looks up a variable (or assembly function) name in package +// runtime. If this is a function, it may have a special calling +// convention. +func sysvar(name string) *obj.LSym { return Runtimepkg.Lookup(name).Linksym() } diff --git a/src/cmd/compile/internal/gc/gsubr.go b/src/cmd/compile/internal/gc/gsubr.go index 16602b9988..01ac4cb929 100644 --- a/src/cmd/compile/internal/gc/gsubr.go +++ b/src/cmd/compile/internal/gc/gsubr.go @@ -187,7 +187,13 @@ func (pp *Progs) settext(fn *Node) { ptxt.From.Sym = fn.Func.lsym } -func (f *Func) initLSym() { +// initLSym defines f's obj.LSym and initializes it based on the +// properties of f. This includes setting the symbol flags and ABI and +// creating and initializing related DWARF symbols. +// +// initLSym must be called exactly once per function and must be +// called for both functions with bodies and functions without bodies. +func (f *Func) initLSym(hasBody bool) { if f.lsym != nil { Fatalf("Func.initLSym called twice") } @@ -197,6 +203,61 @@ func (f *Func) initLSym() { if f.Pragma&Systemstack != 0 { f.lsym.Set(obj.AttrCFunc, true) } + + var aliasABI obj.ABI + needABIAlias := false + if abi, ok := symabiDefs[f.lsym.Name]; ok && abi == obj.ABI0 { + // Symbol is defined as ABI0. Create an + // Internal -> ABI0 wrapper. + f.lsym.SetABI(obj.ABI0) + needABIAlias, aliasABI = true, obj.ABIInternal + } else { + // No ABI override. Check that the symbol is + // using the expected ABI. + want := obj.ABIInternal + if f.lsym.ABI() != want { + Fatalf("function symbol %s has the wrong ABI %v, expected %v", f.lsym, f.lsym.ABI(), want) + } + } + + if abi, ok := symabiRefs[f.lsym.Name]; ok && abi == obj.ABI0 { + // Symbol is referenced as ABI0. Create an + // ABI0 -> Internal wrapper if necessary. + if f.lsym.ABI() != obj.ABI0 { + needABIAlias, aliasABI = true, obj.ABI0 + } + } + + if !needABIAlias && allABIs { + // The compiler was asked to produce ABI + // wrappers for everything. + switch f.lsym.ABI() { + case obj.ABI0: + needABIAlias, aliasABI = true, obj.ABIInternal + case obj.ABIInternal: + needABIAlias, aliasABI = true, obj.ABI0 + } + } + + if needABIAlias { + // These LSyms have the same name as the + // native function, so we create them directly + // rather than looking them up. The uniqueness + // of f.lsym ensures uniqueness of asym. + asym := &obj.LSym{ + Name: f.lsym.Name, + Type: objabi.SABIALIAS, + R: []obj.Reloc{{Sym: f.lsym}}, // 0 size, so "informational" + } + asym.SetABI(aliasABI) + asym.Set(obj.AttrDuplicateOK, true) + Ctxt.ABIAliases = append(Ctxt.ABIAliases, asym) + } + } + + if !hasBody { + // For body-less functions, we only create the LSym. + return } var flag int diff --git a/src/cmd/compile/internal/gc/noder.go b/src/cmd/compile/internal/gc/noder.go index f13d2cdbb5..a2ed103c80 100644 --- a/src/cmd/compile/internal/gc/noder.go +++ b/src/cmd/compile/internal/gc/noder.go @@ -15,6 +15,7 @@ import ( "cmd/compile/internal/syntax" "cmd/compile/internal/types" + "cmd/internal/obj" "cmd/internal/objabi" "cmd/internal/src" ) @@ -250,6 +251,18 @@ func (p *noder) node() { } } + // The linker expects an ABI0 wrapper for all cgo-exported + // functions. + for _, prag := range p.pragcgobuf { + switch prag[0] { + case "cgo_export_static", "cgo_export_dynamic": + if symabiRefs == nil { + symabiRefs = make(map[string]obj.ABI) + } + symabiRefs[prag[1]] = obj.ABI0 + } + } + pragcgobuf = append(pragcgobuf, p.pragcgobuf...) lineno = src.NoXPos clearImports() diff --git a/src/cmd/compile/internal/gc/pgen.go b/src/cmd/compile/internal/gc/pgen.go index 01dacb783b..d567cfe149 100644 --- a/src/cmd/compile/internal/gc/pgen.go +++ b/src/cmd/compile/internal/gc/pgen.go @@ -198,6 +198,8 @@ func funccompile(fn *Node) { dowidth(fn.Type) if fn.Nbody.Len() == 0 { + // Initialize ABI wrappers if necessary. + fn.Func.initLSym(false) emitptrargsmap(fn) return } @@ -231,7 +233,7 @@ func compile(fn *Node) { Curfn = nil // Set up the function's LSym early to avoid data races with the assemblers. - fn.Func.initLSym() + fn.Func.initLSym(true) // Make sure type syms are declared for all types that might // be types of stack objects. We need to do this here diff --git a/src/cmd/compile/internal/gc/reflect.go b/src/cmd/compile/internal/gc/reflect.go index 50b741358f..130c83036c 100644 --- a/src/cmd/compile/internal/gc/reflect.go +++ b/src/cmd/compile/internal/gc/reflect.go @@ -801,7 +801,7 @@ var ( func dcommontype(lsym *obj.LSym, t *types.Type) int { sizeofAlg := 2 * Widthptr if algarray == nil { - algarray = sysfunc("algarray") + algarray = sysvar("algarray") } dowidth(t) alg := algtype(t) @@ -1618,7 +1618,7 @@ func dalgsym(t *types.Type) *obj.LSym { if memhashvarlen == nil { memhashvarlen = sysfunc("memhash_varlen") - memequalvarlen = sysfunc("memequal_varlen") + memequalvarlen = sysvar("memequal_varlen") // asm func } // make hash closure diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index d43dc8e617..883cf7936d 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -68,9 +68,9 @@ func initssaconfig() { assertI2I2 = sysfunc("assertI2I2") deferproc = sysfunc("deferproc") Deferreturn = sysfunc("deferreturn") - Duffcopy = sysfunc("duffcopy") - Duffzero = sysfunc("duffzero") - gcWriteBarrier = sysfunc("gcWriteBarrier") + Duffcopy = sysvar("duffcopy") // asm func with special ABI + Duffzero = sysvar("duffzero") // asm func with special ABI + gcWriteBarrier = sysvar("gcWriteBarrier") // asm func with special ABI goschedguarded = sysfunc("goschedguarded") growslice = sysfunc("growslice") msanread = sysfunc("msanread") @@ -86,25 +86,25 @@ func initssaconfig() { racereadrange = sysfunc("racereadrange") racewrite = sysfunc("racewrite") racewriterange = sysfunc("racewriterange") - supportPopcnt = sysfunc("support_popcnt") - supportSSE41 = sysfunc("support_sse41") - arm64SupportAtomics = sysfunc("arm64_support_atomics") + supportPopcnt = sysvar("support_popcnt") // bool + supportSSE41 = sysvar("support_sse41") // bool + arm64SupportAtomics = sysvar("arm64_support_atomics") // bool typedmemclr = sysfunc("typedmemclr") typedmemmove = sysfunc("typedmemmove") - Udiv = sysfunc("udiv") - writeBarrier = sysfunc("writeBarrier") - - // GO386=387 runtime functions - ControlWord64trunc = sysfunc("controlWord64trunc") - ControlWord32 = sysfunc("controlWord32") - - // Wasm - WasmMove = sysfunc("wasmMove") - WasmZero = sysfunc("wasmZero") - WasmDiv = sysfunc("wasmDiv") - WasmTruncS = sysfunc("wasmTruncS") - WasmTruncU = sysfunc("wasmTruncU") - SigPanic = sysfunc("sigpanic") + Udiv = sysvar("udiv") // asm func with special ABI + writeBarrier = sysvar("writeBarrier") // struct { bool; ... } + + // GO386=387 runtime definitions + ControlWord64trunc = sysvar("controlWord64trunc") // uint16 + ControlWord32 = sysvar("controlWord32") // uint16 + + // Wasm (all asm funcs with special ABIs) + WasmMove = sysvar("wasmMove") + WasmZero = sysvar("wasmZero") + WasmDiv = sysvar("wasmDiv") + WasmTruncS = sysvar("wasmTruncS") + WasmTruncU = sysvar("wasmTruncU") + SigPanic = sysvar("sigpanic") } // buildssa builds an SSA function for fn. |