]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: accept and parse symabis
authorAustin Clements <austin@google.com>
Mon, 22 Oct 2018 14:10:23 +0000 (10:10 -0400)
committerAustin Clements <austin@google.com>
Mon, 12 Nov 2018 20:46:37 +0000 (20:46 +0000)
This doesn't yet do anything with this information.

For #27539.

Change-Id: Ia12c905812aa1ed425eedd6ab2f55ec75d81c0ce
Reviewed-on: https://go-review.googlesource.com/c/147099
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
src/cmd/compile/internal/gc/main.go
src/cmd/internal/obj/abi_string.go [new file with mode: 0644]
src/cmd/internal/obj/link.go

index 78142d3bf82bcac9b066663113a775610ff2eef1..55d6d55e6dfc886c82e77685ecc3dfeb792ad813 100644 (file)
@@ -247,6 +247,9 @@ func Main(archInit func(*Arch)) {
        flag.Int64Var(&memprofilerate, "memprofilerate", 0, "set runtime.MemProfileRate to `rate`")
        var goversion string
        flag.StringVar(&goversion, "goversion", "", "required version of the runtime")
+       var symabisPath string
+       flag.StringVar(&symabisPath, "symabis", "", "read symbol ABIs from `file`")
+       flag.BoolVar(&allABIs, "allabis", false, "generate ABI wrappers for all symbols (for bootstrap)")
        flag.StringVar(&traceprofile, "traceprofile", "", "write an execution trace to `file`")
        flag.StringVar(&blockprofile, "blockprofile", "", "write block profile to `file`")
        flag.StringVar(&mutexprofile, "mutexprofile", "", "write mutex profile to `file`")
@@ -285,6 +288,10 @@ func Main(archInit func(*Arch)) {
 
        checkLang()
 
+       if symabisPath != "" {
+               readSymABIs(symabisPath, myimportpath)
+       }
+
        thearch.LinkArch.Init(Ctxt)
 
        if outfile == "" {
@@ -810,6 +817,81 @@ func readImportCfg(file string) {
        }
 }
 
+// symabiDefs and symabiRefs record the defined and referenced ABIs of
+// symbols required by non-Go code. These are keyed by link symbol
+// name, where the local package prefix is always `"".`
+var symabiDefs, symabiRefs map[string]obj.ABI
+
+// allABIs indicates that all symbol definitions should have ABI
+// wrappers. This is used during toolchain bootstrapping to avoid
+// having to find cross-package references.
+var allABIs bool
+
+// readSymABIs reads a symabis file that specifies definitions and
+// references of text symbols by ABI.
+//
+// The symabis format is a set of lines, where each line is a sequence
+// of whitespace-separated fields. The first field is a verb and is
+// either "def" for defining a symbol ABI or "ref" for referencing a
+// symbol using an ABI. For both "def" and "ref", the second field is
+// the symbol name and the third field is the ABI name, as one of the
+// named cmd/internal/obj.ABI constants.
+func readSymABIs(file, myimportpath string) {
+       data, err := ioutil.ReadFile(file)
+       if err != nil {
+               log.Fatalf("-symabis: %v", err)
+       }
+
+       symabiDefs = make(map[string]obj.ABI)
+       symabiRefs = make(map[string]obj.ABI)
+
+       localPrefix := ""
+       if myimportpath != "" {
+               // Symbols in this package may be written either as
+               // "".X or with the package's import path already in
+               // the symbol.
+               localPrefix = objabi.PathToPrefix(myimportpath) + "."
+       }
+
+       for lineNum, line := range strings.Split(string(data), "\n") {
+               lineNum++ // 1-based
+               line = strings.TrimSpace(line)
+               if line == "" || strings.HasPrefix(line, "#") {
+                       continue
+               }
+
+               parts := strings.Fields(line)
+               switch parts[0] {
+               case "def", "ref":
+                       // Parse line.
+                       if len(parts) != 3 {
+                               log.Fatalf(`%s:%d: invalid symabi: syntax is "%s sym abi"`, file, lineNum, parts[0])
+                       }
+                       sym, abi := parts[1], parts[2]
+                       if abi != "ABI0" { // Only supported external ABI right now
+                               log.Fatalf(`%s:%d: invalid symabi: unknown abi "%s"`, file, lineNum, abi)
+                       }
+
+                       // If the symbol is already prefixed with
+                       // myimportpath, rewrite it to start with ""
+                       // so it matches the compiler's internal
+                       // symbol names.
+                       if localPrefix != "" && strings.HasPrefix(sym, localPrefix) {
+                               sym = `"".` + sym[len(localPrefix):]
+                       }
+
+                       // Record for later.
+                       if parts[0] == "def" {
+                               symabiDefs[sym] = obj.ABI0
+                       } else {
+                               symabiRefs[sym] = obj.ABI0
+                       }
+               default:
+                       log.Fatalf(`%s:%d: invalid symabi type "%s"`, file, lineNum, parts[0])
+               }
+       }
+}
+
 func saveerrors() {
        nsavederrors += nerrors
        nerrors = 0
diff --git a/src/cmd/internal/obj/abi_string.go b/src/cmd/internal/obj/abi_string.go
new file mode 100644 (file)
index 0000000..a439da3
--- /dev/null
@@ -0,0 +1,16 @@
+// Code generated by "stringer -type ABI"; DO NOT EDIT.
+
+package obj
+
+import "strconv"
+
+const _ABI_name = "ABI0ABIInternalABICount"
+
+var _ABI_index = [...]uint8{0, 4, 15, 23}
+
+func (i ABI) String() string {
+       if i >= ABI(len(_ABI_index)-1) {
+               return "ABI(" + strconv.FormatInt(int64(i), 10) + ")"
+       }
+       return _ABI_name[_ABI_index[i]:_ABI_index[i+1]]
+}
index d924cbc21424b98fd3eeda8488d93ce58d100356..d3721dd0234662ffd0a9bb5d922ebbc82900240d 100644 (file)
@@ -409,6 +409,28 @@ type FuncInfo struct {
        StackObjects *LSym
 }
 
+//go:generate stringer -type ABI
+
+// ABI is the calling convention of a text symbol.
+type ABI uint8
+
+const (
+       // ABI0 is the stable stack-based ABI. It's important that the
+       // value of this is "0": we can't distinguish between
+       // references to data and ABI0 text symbols in assembly code,
+       // and hence this doesn't distinguish between symbols without
+       // an ABI and text symbols with ABI0.
+       ABI0 ABI = iota
+
+       // ABIInternal is the internal ABI that may change between Go
+       // versions. All Go functions use the internal ABI and the
+       // compiler generates wrappers for calls to and from other
+       // ABIs.
+       ABIInternal
+
+       ABICount
+)
+
 // Attribute is a set of symbol attributes.
 type Attribute int16