aboutsummaryrefslogtreecommitdiff
path: root/go/tools/builders/asm.go
diff options
context:
space:
mode:
Diffstat (limited to 'go/tools/builders/asm.go')
-rw-r--r--go/tools/builders/asm.go138
1 files changed, 138 insertions, 0 deletions
diff --git a/go/tools/builders/asm.go b/go/tools/builders/asm.go
new file mode 100644
index 00000000..3d64c9ba
--- /dev/null
+++ b/go/tools/builders/asm.go
@@ -0,0 +1,138 @@
+// Copyright 2017 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+ "go/build"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "regexp"
+ "runtime"
+ "strconv"
+ "strings"
+)
+
+var ASM_DEFINES = []string{
+ "-D", "GOOS_" + build.Default.GOOS,
+ "-D", "GOARCH_" + build.Default.GOARCH,
+ "-D", "GOOS_GOARCH_" + build.Default.GOOS + "_" + build.Default.GOARCH,
+}
+
+// buildSymabisFile generates a file from assembly files that is consumed
+// by the compiler. This is only needed in go1.12+ when there is at least one
+// .s file. If the symabis file is not needed, no file will be generated,
+// and "", nil will be returned.
+func buildSymabisFile(goenv *env, sFiles, hFiles []fileInfo, asmhdr string) (string, error) {
+ if len(sFiles) == 0 {
+ return "", nil
+ }
+
+ // Check version. The symabis file is only required and can only be built
+ // starting at go1.12.
+ version := runtime.Version()
+ if strings.HasPrefix(version, "go1.") {
+ minor := version[len("go1."):]
+ if i := strings.IndexByte(minor, '.'); i >= 0 {
+ minor = minor[:i]
+ }
+ n, err := strconv.Atoi(minor)
+ if err == nil && n <= 11 {
+ return "", nil
+ }
+ // Fall through if the version can't be parsed. It's probably a newer
+ // development version.
+ }
+
+ // Create an empty go_asm.h file. The compiler will write this later, but
+ // we need one to exist now.
+ asmhdrFile, err := os.Create(asmhdr)
+ if err != nil {
+ return "", err
+ }
+ if err := asmhdrFile.Close(); err != nil {
+ return "", err
+ }
+ asmhdrDir := filepath.Dir(asmhdr)
+
+ // Create a temporary output file. The caller is responsible for deleting it.
+ var symabisName string
+ symabisFile, err := ioutil.TempFile("", "symabis")
+ if err != nil {
+ return "", err
+ }
+ symabisName = symabisFile.Name()
+ symabisFile.Close()
+
+ // Run the assembler.
+ wd, err := os.Getwd()
+ if err != nil {
+ return symabisName, err
+ }
+ asmargs := goenv.goTool("asm")
+ asmargs = append(asmargs, "-trimpath", wd)
+ asmargs = append(asmargs, "-I", wd)
+ asmargs = append(asmargs, "-I", filepath.Join(os.Getenv("GOROOT"), "pkg", "include"))
+ asmargs = append(asmargs, "-I", asmhdrDir)
+ seenHdrDirs := map[string]bool{wd: true, asmhdrDir: true}
+ for _, hFile := range hFiles {
+ hdrDir := filepath.Dir(abs(hFile.filename))
+ if !seenHdrDirs[hdrDir] {
+ asmargs = append(asmargs, "-I", hdrDir)
+ seenHdrDirs[hdrDir] = true
+ }
+ }
+ asmargs = append(asmargs, ASM_DEFINES...)
+ asmargs = append(asmargs, "-gensymabis", "-o", symabisName, "--")
+ for _, sFile := range sFiles {
+ asmargs = append(asmargs, sFile.filename)
+ }
+
+ err = goenv.runCommand(asmargs)
+ return symabisName, err
+}
+
+func asmFile(goenv *env, srcPath, packagePath string, asmFlags []string, outPath string) error {
+ args := goenv.goTool("asm")
+ args = append(args, asmFlags...)
+ // The package path has to be specified as of Go 1.19 or the resulting
+ // object will be unlinkable, but the -p flag is also only available
+ // since Go 1.19.
+ if packagePath != "" && isGo119OrHigher() {
+ args = append(args, "-p", packagePath)
+ }
+ args = append(args, ASM_DEFINES...)
+ args = append(args, "-trimpath", ".")
+ args = append(args, "-o", outPath)
+ args = append(args, "--", srcPath)
+ absArgs(args, []string{"-I", "-o", "-trimpath"})
+ return goenv.runCommand(args)
+}
+
+var goMinorVersionRegexp = regexp.MustCompile(`^go1\.(\d+)`)
+
+func isGo119OrHigher() bool {
+ match := goMinorVersionRegexp.FindStringSubmatch(runtime.Version())
+ if match == nil {
+ // Developer version or something with an unparseable version string,
+ // assume Go 1.19 or higher.
+ return true
+ }
+ minorVersion, err := strconv.Atoi(match[1])
+ if err != nil {
+ return true
+ }
+ return minorVersion >= 19
+}