mirror of
https://github.com/goplus/llgo.git
synced 2025-09-26 19:51:21 +08:00
cross compilation
This commit is contained in:
@@ -37,10 +37,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runCmd(cmd *base.Command, args []string) {
|
func runCmd(cmd *base.Command, args []string) {
|
||||||
conf := &build.Config{
|
conf := build.NewDefaultConf(build.ModeBuild)
|
||||||
Mode: build.ModeBuild,
|
|
||||||
AppExt: build.DefaultAppExt(),
|
|
||||||
}
|
|
||||||
if len(args) >= 2 && args[0] == "-o" {
|
if len(args) >= 2 && args[0] == "-o" {
|
||||||
conf.OutFile = args[1]
|
conf.OutFile = args[1]
|
||||||
args = args[2:]
|
args = args[2:]
|
||||||
|
@@ -21,7 +21,6 @@ import (
|
|||||||
"debug/macho"
|
"debug/macho"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"go/build"
|
|
||||||
"go/constant"
|
"go/constant"
|
||||||
"go/token"
|
"go/token"
|
||||||
"go/types"
|
"go/types"
|
||||||
@@ -31,6 +30,7 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
@@ -41,13 +41,13 @@ import (
|
|||||||
"github.com/goplus/llgo/internal/mockable"
|
"github.com/goplus/llgo/internal/mockable"
|
||||||
"github.com/goplus/llgo/internal/packages"
|
"github.com/goplus/llgo/internal/packages"
|
||||||
"github.com/goplus/llgo/internal/typepatch"
|
"github.com/goplus/llgo/internal/typepatch"
|
||||||
|
llvmTarget "github.com/goplus/llgo/internal/xtool/llvm"
|
||||||
"github.com/goplus/llgo/ssa/abi"
|
"github.com/goplus/llgo/ssa/abi"
|
||||||
xenv "github.com/goplus/llgo/xtool/env"
|
xenv "github.com/goplus/llgo/xtool/env"
|
||||||
"github.com/goplus/llgo/xtool/env/llvm"
|
"github.com/goplus/llgo/xtool/env/llvm"
|
||||||
|
|
||||||
llruntime "github.com/goplus/llgo/runtime"
|
llruntime "github.com/goplus/llgo/runtime"
|
||||||
llssa "github.com/goplus/llgo/ssa"
|
llssa "github.com/goplus/llgo/ssa"
|
||||||
clangCheck "github.com/goplus/llgo/xtool/clang/check"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Mode int
|
type Mode int
|
||||||
@@ -66,6 +66,8 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
Goos string
|
||||||
|
Goarch string
|
||||||
BinPath string
|
BinPath string
|
||||||
AppExt string // ".exe" on Windows, empty on Unix
|
AppExt string // ".exe" on Windows, empty on Unix
|
||||||
OutFile string // only valid for ModeBuild when len(pkgs) == 1
|
OutFile string // only valid for ModeBuild when len(pkgs) == 1
|
||||||
@@ -86,10 +88,19 @@ func NewDefaultConf(mode Mode) *Config {
|
|||||||
if err := os.MkdirAll(bin, 0755); err != nil {
|
if err := os.MkdirAll(bin, 0755); err != nil {
|
||||||
panic(fmt.Errorf("cannot create bin directory: %v", err))
|
panic(fmt.Errorf("cannot create bin directory: %v", err))
|
||||||
}
|
}
|
||||||
|
goos, goarch := os.Getenv("GOOS"), os.Getenv("GOARCH")
|
||||||
|
if goos == "" {
|
||||||
|
goos = runtime.GOOS
|
||||||
|
}
|
||||||
|
if goarch == "" {
|
||||||
|
goarch = runtime.GOARCH
|
||||||
|
}
|
||||||
conf := &Config{
|
conf := &Config{
|
||||||
|
Goos: goos,
|
||||||
|
Goarch: goarch,
|
||||||
BinPath: bin,
|
BinPath: bin,
|
||||||
Mode: mode,
|
Mode: mode,
|
||||||
AppExt: DefaultAppExt(),
|
AppExt: DefaultAppExt(goos),
|
||||||
}
|
}
|
||||||
return conf
|
return conf
|
||||||
}
|
}
|
||||||
@@ -105,9 +116,12 @@ func envGOPATH() (string, error) {
|
|||||||
return filepath.Join(home, "go"), nil
|
return filepath.Join(home, "go"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func DefaultAppExt() string {
|
func DefaultAppExt(goos string) string {
|
||||||
if runtime.GOOS == "windows" {
|
switch goos {
|
||||||
|
case "windows":
|
||||||
return ".exe"
|
return ".exe"
|
||||||
|
case "wasi", "wasip1", "js":
|
||||||
|
return ".wasm"
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@@ -121,9 +135,65 @@ const (
|
|||||||
loadSyntax = loadTypes | packages.NeedSyntax | packages.NeedTypesInfo
|
loadSyntax = loadTypes | packages.NeedSyntax | packages.NeedTypesInfo
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func mergeFlags(flags, extraFlags []string) (newFlags []string, tags []string) {
|
||||||
|
// Combine all flags
|
||||||
|
allFlags := append([]string{}, flags...)
|
||||||
|
allFlags = append(allFlags, extraFlags...)
|
||||||
|
|
||||||
|
// Find all -tags flags and extract their values
|
||||||
|
tagValues := []string{}
|
||||||
|
|
||||||
|
for i := 0; i < len(allFlags); i++ {
|
||||||
|
flag := allFlags[i]
|
||||||
|
// Handle -tags=value format
|
||||||
|
if strings.HasPrefix(flag, "-tags=") {
|
||||||
|
value := strings.TrimPrefix(flag, "-tags=")
|
||||||
|
if value != "" {
|
||||||
|
tagValues = append(tagValues, strings.Split(value, ",")...)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Handle -tags value format
|
||||||
|
if flag == "-tags" && i+1 < len(allFlags) {
|
||||||
|
i++
|
||||||
|
value := allFlags[i]
|
||||||
|
if value != "" {
|
||||||
|
tagValues = append(tagValues, strings.Split(value, ",")...)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Keep other flags
|
||||||
|
newFlags = append(newFlags, flag)
|
||||||
|
}
|
||||||
|
// Add combined -tags flag if we found any tag values
|
||||||
|
if len(tagValues) > 0 {
|
||||||
|
// Remove duplicates
|
||||||
|
uniqueTags := make([]string, 0, len(tagValues))
|
||||||
|
seen := make(map[string]bool)
|
||||||
|
for _, tag := range tagValues {
|
||||||
|
tag = strings.TrimSpace(tag)
|
||||||
|
if tag != "" && !seen[tag] {
|
||||||
|
seen[tag] = true
|
||||||
|
uniqueTags = append(uniqueTags, tag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(uniqueTags) > 0 {
|
||||||
|
newFlags = append(newFlags, "-tags", strings.Join(uniqueTags, ","))
|
||||||
|
tags = []string{"-tags", strings.Join(uniqueTags, ",")}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newFlags, tags
|
||||||
|
}
|
||||||
|
|
||||||
func Do(args []string, conf *Config) ([]Package, error) {
|
func Do(args []string, conf *Config) ([]Package, error) {
|
||||||
|
if conf.Goos == "" {
|
||||||
|
conf.Goos = runtime.GOOS
|
||||||
|
}
|
||||||
|
if conf.Goarch == "" {
|
||||||
|
conf.Goarch = runtime.GOARCH
|
||||||
|
}
|
||||||
flags, patterns, verbose := ParseArgs(args, buildFlags)
|
flags, patterns, verbose := ParseArgs(args, buildFlags)
|
||||||
flags = append(flags, "-tags", "llgo")
|
flags, _ = mergeFlags(flags, []string{"-tags", "llgo"})
|
||||||
cfg := &packages.Config{
|
cfg := &packages.Config{
|
||||||
Mode: loadSyntax | packages.NeedDeps | packages.NeedModule | packages.NeedExportFile,
|
Mode: loadSyntax | packages.NeedDeps | packages.NeedModule | packages.NeedExportFile,
|
||||||
BuildFlags: flags,
|
BuildFlags: flags,
|
||||||
@@ -148,8 +218,8 @@ func Do(args []string, conf *Config) ([]Package, error) {
|
|||||||
llssa.Initialize(llssa.InitAll)
|
llssa.Initialize(llssa.InitAll)
|
||||||
|
|
||||||
target := &llssa.Target{
|
target := &llssa.Target{
|
||||||
GOOS: build.Default.GOOS,
|
GOOS: conf.Goos,
|
||||||
GOARCH: build.Default.GOARCH,
|
GOARCH: conf.Goarch,
|
||||||
}
|
}
|
||||||
|
|
||||||
prog := llssa.NewProgram(target)
|
prog := llssa.NewProgram(target)
|
||||||
@@ -221,7 +291,7 @@ func Do(args []string, conf *Config) ([]Package, error) {
|
|||||||
os.Setenv("PATH", env.BinDir()+":"+os.Getenv("PATH")) // TODO(xsw): check windows
|
os.Setenv("PATH", env.BinDir()+":"+os.Getenv("PATH")) // TODO(xsw): check windows
|
||||||
|
|
||||||
output := conf.OutFile != ""
|
output := conf.OutFile != ""
|
||||||
ctx := &context{env, cfg, progSSA, prog, dedup, patches, make(map[string]none), initial, mode, 0, output, make(map[*packages.Package]bool), make(map[*packages.Package]bool)}
|
ctx := &context{env, cfg, progSSA, prog, dedup, patches, make(map[string]none), initial, mode, 0, output, make(map[*packages.Package]bool), make(map[*packages.Package]bool), conf}
|
||||||
pkgs, err := buildAllPkgs(ctx, initial, verbose)
|
pkgs, err := buildAllPkgs(ctx, initial, verbose)
|
||||||
check(err)
|
check(err)
|
||||||
if mode == ModeGen {
|
if mode == ModeGen {
|
||||||
@@ -286,6 +356,8 @@ type context struct {
|
|||||||
|
|
||||||
needRt map[*packages.Package]bool
|
needRt map[*packages.Package]bool
|
||||||
needPyInit map[*packages.Package]bool
|
needPyInit map[*packages.Package]bool
|
||||||
|
|
||||||
|
buildConf *Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildAllPkgs(ctx *context, initial []*packages.Package, verbose bool) (pkgs []*aPackage, err error) {
|
func buildAllPkgs(ctx *context, initial []*packages.Package, verbose bool) (pkgs []*aPackage, err error) {
|
||||||
@@ -364,7 +436,7 @@ func buildAllPkgs(ctx *context, initial []*packages.Package, verbose bool) (pkgs
|
|||||||
ctx.nLibdir++
|
ctx.nLibdir++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := clangCheck.CheckLinkArgs(pkgLinkArgs); err != nil {
|
if err := ctx.env.Clang().CheckLinkArgs(pkgLinkArgs); err != nil {
|
||||||
panic(fmt.Sprintf("test link args '%s' failed\n\texpanded to: %v\n\tresolved to: %v\n\terror: %v", param, expdArgs, pkgLinkArgs, err))
|
panic(fmt.Sprintf("test link args '%s' failed\n\texpanded to: %v\n\tresolved to: %v\n\terror: %v", param, expdArgs, pkgLinkArgs, err))
|
||||||
}
|
}
|
||||||
aPkg.LinkArgs = append(aPkg.LinkArgs, pkgLinkArgs...)
|
aPkg.LinkArgs = append(aPkg.LinkArgs, pkgLinkArgs...)
|
||||||
@@ -401,39 +473,18 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, linkArgs
|
|||||||
} else {
|
} else {
|
||||||
app = filepath.Join(conf.BinPath, name+conf.AppExt)
|
app = filepath.Join(conf.BinPath, name+conf.AppExt)
|
||||||
}
|
}
|
||||||
|
} else if !strings.HasSuffix(app, conf.AppExt) {
|
||||||
|
app += conf.AppExt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Start with output file argument
|
||||||
args := make([]string, 0, len(pkg.Imports)+len(linkArgs)+16)
|
args := make([]string, 0, len(pkg.Imports)+len(linkArgs)+16)
|
||||||
args = append(
|
args = append(args, "-o", app)
|
||||||
args,
|
|
||||||
"-o", app,
|
// Add common linker arguments based on target OS and architecture
|
||||||
"-Wl,--error-limit=0",
|
targetTriple := llvmTarget.GetTargetTriple(conf.Goos, conf.Goarch)
|
||||||
"-fuse-ld=lld",
|
args = append(args, buildLdflags(conf.Goos, conf.Goarch, targetTriple)...)
|
||||||
"-Wno-override-module",
|
|
||||||
// "-O2", // FIXME: This will cause TestFinalizer in _test/bdwgc.go to fail on macOS.
|
|
||||||
)
|
|
||||||
switch runtime.GOOS {
|
|
||||||
case "darwin": // ld64.lld (macOS)
|
|
||||||
args = append(
|
|
||||||
args,
|
|
||||||
"-rpath", "@loader_path",
|
|
||||||
"-rpath", "@loader_path/../lib",
|
|
||||||
"-Xlinker", "-dead_strip",
|
|
||||||
)
|
|
||||||
case "windows": // lld-link (Windows)
|
|
||||||
// TODO: Add options for Windows.
|
|
||||||
default: // ld.lld (Unix), wasm-ld (WebAssembly)
|
|
||||||
args = append(
|
|
||||||
args,
|
|
||||||
"-rpath", "$ORIGIN",
|
|
||||||
"-rpath", "$ORIGIN/../lib",
|
|
||||||
"-fdata-sections",
|
|
||||||
"-ffunction-sections",
|
|
||||||
"-Xlinker", "--gc-sections",
|
|
||||||
"-lm",
|
|
||||||
"-latomic",
|
|
||||||
"-lpthread", // libpthread is built-in since glibc 2.34 (2021-08-01); we need to support earlier versions.
|
|
||||||
)
|
|
||||||
}
|
|
||||||
needRuntime := false
|
needRuntime := false
|
||||||
needPyInit := false
|
needPyInit := false
|
||||||
pkgsMap := make(map[*packages.Package]*aPackage, len(pkgs))
|
pkgsMap := make(map[*packages.Package]*aPackage, len(pkgs))
|
||||||
@@ -453,7 +504,7 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, linkArgs
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
entryLLFile, err := genMainModuleFile(llssa.PkgRuntime, pkg.PkgPath, needRuntime, needPyInit)
|
entryLLFile, err := genMainModuleFile(conf, llssa.PkgRuntime, pkg.PkgPath, needRuntime, needPyInit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@@ -478,11 +529,13 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, linkArgs
|
|||||||
// add rpath and find libs
|
// add rpath and find libs
|
||||||
exargs := make([]string, 0, ctx.nLibdir<<1)
|
exargs := make([]string, 0, ctx.nLibdir<<1)
|
||||||
libs := make([]string, 0, ctx.nLibdir*3)
|
libs := make([]string, 0, ctx.nLibdir*3)
|
||||||
for _, arg := range args {
|
if IsRpathChangeEnabled() {
|
||||||
if strings.HasPrefix(arg, "-L") {
|
for _, arg := range args {
|
||||||
exargs = append(exargs, "-rpath", arg[2:])
|
if strings.HasPrefix(arg, "-L") {
|
||||||
} else if strings.HasPrefix(arg, "-l") {
|
exargs = append(exargs, "-rpath", arg[2:])
|
||||||
libs = append(libs, arg[2:])
|
} else if strings.HasPrefix(arg, "-l") {
|
||||||
|
libs = append(libs, arg[2:])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
args = append(args, exargs...)
|
args = append(args, exargs...)
|
||||||
@@ -490,14 +543,12 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, linkArgs
|
|||||||
args = append(args, "-gdwarf-4")
|
args = append(args, "-gdwarf-4")
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(xsw): show work
|
cmd := ctx.env.Clang()
|
||||||
if verbose {
|
cmd.Verbose = verbose
|
||||||
fmt.Fprintln(os.Stderr, "clang", args)
|
err = cmd.Link(args...)
|
||||||
}
|
|
||||||
err = ctx.env.Clang().Link(args...)
|
|
||||||
check(err)
|
check(err)
|
||||||
|
|
||||||
if IsRpathChangeEnabled() && runtime.GOOS == "darwin" {
|
if IsRpathChangeEnabled() && conf.Goos == "darwin" {
|
||||||
dylibDeps := make([]string, 0, len(libs))
|
dylibDeps := make([]string, 0, len(libs))
|
||||||
for _, lib := range libs {
|
for _, lib := range libs {
|
||||||
dylibDep := findDylibDep(app, lib)
|
dylibDep := findDylibDep(app, lib)
|
||||||
@@ -519,7 +570,16 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, linkArgs
|
|||||||
fmt.Fprintf(os.Stderr, "%s: exit code %d\n", app, s.ExitCode())
|
fmt.Fprintf(os.Stderr, "%s: exit code %d\n", app, s.ExitCode())
|
||||||
}
|
}
|
||||||
case ModeRun:
|
case ModeRun:
|
||||||
cmd := exec.Command(app, conf.RunArgs...)
|
args := make([]string, 0, len(conf.RunArgs)+1)
|
||||||
|
copy(args, conf.RunArgs)
|
||||||
|
if isWasmTarget(conf.Goos) {
|
||||||
|
args = append(args, app, "--wasm", "multi-memory=true")
|
||||||
|
args = append(args, conf.RunArgs...)
|
||||||
|
app = "wasmtime"
|
||||||
|
} else {
|
||||||
|
args = conf.RunArgs
|
||||||
|
}
|
||||||
|
cmd := exec.Command(app, args...)
|
||||||
cmd.Stdin = os.Stdin
|
cmd.Stdin = os.Stdin
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
@@ -532,7 +592,84 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, linkArgs
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func genMainModuleFile(rtPkgPath, mainPkgPath string, needRuntime, needPyInit bool) (path string, err error) {
|
func buildCflags(goos, goarch, targetTriple string) []string {
|
||||||
|
args := []string{}
|
||||||
|
if goarch == "wasm" {
|
||||||
|
args = append(args, "-target", targetTriple)
|
||||||
|
}
|
||||||
|
return args
|
||||||
|
}
|
||||||
|
|
||||||
|
// buildLdflags builds the common linker arguments based on target OS and architecture
|
||||||
|
func buildLdflags(goos, goarch, targetTriple string) []string {
|
||||||
|
args := []string{
|
||||||
|
"-target", targetTriple,
|
||||||
|
"-Wno-override-module",
|
||||||
|
}
|
||||||
|
if goos == runtime.GOOS {
|
||||||
|
// Non-cross-compile
|
||||||
|
args = append(args,
|
||||||
|
"-Wl,--error-limit=0",
|
||||||
|
"-fuse-ld=lld",
|
||||||
|
"-Wno-override-module",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch goos {
|
||||||
|
case "darwin": // ld64.lld (macOS)
|
||||||
|
if IsRpathChangeEnabled() {
|
||||||
|
args = append(
|
||||||
|
args,
|
||||||
|
"-rpath", "@loader_path",
|
||||||
|
"-rpath", "@loader_path/../lib",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
args = append(
|
||||||
|
args,
|
||||||
|
"-Xlinker", "-dead_strip",
|
||||||
|
)
|
||||||
|
case "windows": // lld-link (Windows)
|
||||||
|
// TODO(xsw): Add options for Windows.
|
||||||
|
case "wasi", "wasip1", "js": // wasm-ld (WebAssembly)
|
||||||
|
args = append(
|
||||||
|
args,
|
||||||
|
"-fdata-sections",
|
||||||
|
"-ffunction-sections",
|
||||||
|
// "-nostdlib",
|
||||||
|
// "-Wl,--no-entry",
|
||||||
|
"-Wl,--export-all",
|
||||||
|
"-Wl,--allow-undefined",
|
||||||
|
// "-Wl,--import-memory,",
|
||||||
|
"-Wl,--export-memory",
|
||||||
|
"-Wl,--initial-memory=16777216", // 16MB
|
||||||
|
// "-pthread",
|
||||||
|
// "-matomics",
|
||||||
|
// "-mbulk-memory",
|
||||||
|
// "-mmultimemory",
|
||||||
|
)
|
||||||
|
default: // ld.lld (Unix)
|
||||||
|
args = append(
|
||||||
|
args,
|
||||||
|
// "-rpath", "$ORIGIN",
|
||||||
|
// "-rpath", "$ORIGIN/../lib",
|
||||||
|
"-fdata-sections",
|
||||||
|
"-ffunction-sections",
|
||||||
|
"-Xlinker",
|
||||||
|
"--gc-sections",
|
||||||
|
"-lm",
|
||||||
|
"-latomic",
|
||||||
|
"-lpthread", // libpthread is built-in since glibc 2.34 (2021-08-01); we need to support earlier versions.
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return args
|
||||||
|
}
|
||||||
|
|
||||||
|
func isWasmTarget(goos string) bool {
|
||||||
|
return slices.Contains([]string{"wasi", "js", "wasip1"}, goos)
|
||||||
|
}
|
||||||
|
|
||||||
|
func genMainModuleFile(conf *Config, rtPkgPath, mainPkgPath string, needRuntime, needPyInit bool) (path string, err error) {
|
||||||
var (
|
var (
|
||||||
pyInitDecl string
|
pyInitDecl string
|
||||||
pyInit string
|
pyInit string
|
||||||
@@ -547,6 +684,10 @@ func genMainModuleFile(rtPkgPath, mainPkgPath string, needRuntime, needPyInit bo
|
|||||||
pyInit = "call void @Py_Initialize()"
|
pyInit = "call void @Py_Initialize()"
|
||||||
pyInitDecl = "declare void @Py_Initialize()"
|
pyInitDecl = "declare void @Py_Initialize()"
|
||||||
}
|
}
|
||||||
|
mainDefine := "define i32 @main(i32 noundef %0, ptr nocapture noundef readnone %1) local_unnamed_addr"
|
||||||
|
if isWasmTarget(conf.Goos) {
|
||||||
|
mainDefine = "define hidden noundef i32 @__main_argc_argv(i32 noundef %0, ptr nocapture noundef readnone %1) local_unnamed_addr"
|
||||||
|
}
|
||||||
mainCode := fmt.Sprintf(`; ModuleID = 'main'
|
mainCode := fmt.Sprintf(`; ModuleID = 'main'
|
||||||
source_filename = "main"
|
source_filename = "main"
|
||||||
|
|
||||||
@@ -566,7 +707,7 @@ define weak void @"syscall.init"() {
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define i32 @main(i32 %%0, ptr %%1) {
|
%s {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%s
|
%s
|
||||||
store i32 %%0, ptr @__llgo_argc, align 4
|
store i32 %%0, ptr @__llgo_argc, align 4
|
||||||
@@ -577,7 +718,7 @@ _llgo_0:
|
|||||||
call void @"%s.main"()
|
call void @"%s.main"()
|
||||||
ret i32 0
|
ret i32 0
|
||||||
}
|
}
|
||||||
`, pyInitDecl, rtInitDecl, mainPkgPath, mainPkgPath,
|
`, pyInitDecl, rtInitDecl, mainPkgPath, mainPkgPath, mainDefine,
|
||||||
pyInit, rtInit, mainPkgPath, mainPkgPath)
|
pyInit, rtInit, mainPkgPath, mainPkgPath)
|
||||||
|
|
||||||
f, err := os.CreateTemp("", "main*.ll")
|
f, err := os.CreateTemp("", "main*.ll")
|
||||||
@@ -877,11 +1018,15 @@ func clFiles(ctx *context, files string, pkg *packages.Package, procFile func(li
|
|||||||
|
|
||||||
func clFile(ctx *context, args []string, cFile, expFile string, procFile func(linkFile string), verbose bool) {
|
func clFile(ctx *context, args []string, cFile, expFile string, procFile func(linkFile string), verbose bool) {
|
||||||
llFile := expFile + filepath.Base(cFile) + ".ll"
|
llFile := expFile + filepath.Base(cFile) + ".ll"
|
||||||
|
targetTriple := llvmTarget.GetTargetTriple(ctx.buildConf.Goos, ctx.buildConf.Goarch)
|
||||||
|
cflags := buildCflags(ctx.buildConf.Goos, ctx.buildConf.Goarch, targetTriple)
|
||||||
|
args = append(cflags, args...)
|
||||||
args = append(args, "-emit-llvm", "-S", "-o", llFile, "-c", cFile)
|
args = append(args, "-emit-llvm", "-S", "-o", llFile, "-c", cFile)
|
||||||
if verbose {
|
if verbose {
|
||||||
fmt.Fprintln(os.Stderr, "clang", args)
|
fmt.Fprintln(os.Stderr, "clang", args)
|
||||||
}
|
}
|
||||||
err := ctx.env.Clang().Compile(args...)
|
cmd := ctx.env.Clang()
|
||||||
|
err := cmd.Compile(args...)
|
||||||
check(err)
|
check(err)
|
||||||
procFile(llFile)
|
procFile(llFile)
|
||||||
}
|
}
|
||||||
|
@@ -20,6 +20,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/goplus/llgo/internal/build"
|
"github.com/goplus/llgo/internal/build"
|
||||||
@@ -46,7 +47,7 @@ func genFrom(pkgPath string) (build.Package, error) {
|
|||||||
|
|
||||||
conf := &build.Config{
|
conf := &build.Config{
|
||||||
Mode: build.ModeGen,
|
Mode: build.ModeGen,
|
||||||
AppExt: build.DefaultAppExt(),
|
AppExt: build.DefaultAppExt(runtime.GOOS),
|
||||||
}
|
}
|
||||||
pkgs, err := build.Do([]string{pkgPath}, conf)
|
pkgs, err := build.Do([]string{pkgPath}, conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
55
internal/xtool/llvm/llvm.go
Normal file
55
internal/xtool/llvm/llvm.go
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
package llvm
|
||||||
|
|
||||||
|
import "runtime"
|
||||||
|
|
||||||
|
func GetTargetTriple(goos, goarch string) string {
|
||||||
|
var llvmarch string
|
||||||
|
if goarch == "" {
|
||||||
|
goarch = runtime.GOARCH
|
||||||
|
}
|
||||||
|
if goos == "" {
|
||||||
|
goos = runtime.GOOS
|
||||||
|
}
|
||||||
|
switch goarch {
|
||||||
|
case "386":
|
||||||
|
llvmarch = "i386"
|
||||||
|
case "amd64":
|
||||||
|
llvmarch = "x86_64"
|
||||||
|
case "arm64":
|
||||||
|
llvmarch = "aarch64"
|
||||||
|
case "arm":
|
||||||
|
switch goarch {
|
||||||
|
case "5":
|
||||||
|
llvmarch = "armv5"
|
||||||
|
case "6":
|
||||||
|
llvmarch = "armv6"
|
||||||
|
default:
|
||||||
|
llvmarch = "armv7"
|
||||||
|
}
|
||||||
|
case "wasm":
|
||||||
|
llvmarch = "wasm32"
|
||||||
|
default:
|
||||||
|
llvmarch = goarch
|
||||||
|
}
|
||||||
|
llvmvendor := "unknown"
|
||||||
|
llvmos := goos
|
||||||
|
switch goos {
|
||||||
|
case "darwin":
|
||||||
|
// Use macosx* instead of darwin, otherwise darwin/arm64 will refer
|
||||||
|
// to iOS!
|
||||||
|
llvmos = "macosx"
|
||||||
|
if llvmarch == "aarch64" {
|
||||||
|
// Looks like Apple prefers to call this architecture ARM64
|
||||||
|
// instead of AArch64.
|
||||||
|
llvmarch = "arm64"
|
||||||
|
llvmos = "macosx"
|
||||||
|
}
|
||||||
|
llvmvendor = "apple"
|
||||||
|
case "wasip1":
|
||||||
|
llvmos = "wasip1"
|
||||||
|
}
|
||||||
|
// Target triples (which actually have four components, but are called
|
||||||
|
// triples for historical reasons) have the form:
|
||||||
|
// arch-vendor-os-environment
|
||||||
|
return llvmarch + "-" + llvmvendor + "-" + llvmos
|
||||||
|
}
|
150
internal/xtool/llvm/llvm_test.go
Normal file
150
internal/xtool/llvm/llvm_test.go
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
//go:build !llgo
|
||||||
|
// +build !llgo
|
||||||
|
|
||||||
|
package llvm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetTargetTriple(t *testing.T) {
|
||||||
|
// Get the list of supported architectures from clang
|
||||||
|
cmd := exec.Command("clang", "--print-targets")
|
||||||
|
output, err := cmd.Output()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to run clang --print-targets: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the output to get the list of supported architectures
|
||||||
|
supportedArchs := make(map[string]bool)
|
||||||
|
lines := strings.Split(string(output), "\n")
|
||||||
|
for _, line := range lines {
|
||||||
|
line = strings.TrimSpace(line)
|
||||||
|
if line != "" && !strings.HasPrefix(line, "Registered Targets:") {
|
||||||
|
// Extract the architecture from the line
|
||||||
|
parts := strings.SplitN(line, " - ", 2)
|
||||||
|
if len(parts) > 0 {
|
||||||
|
arch := strings.TrimSpace(parts[0])
|
||||||
|
supportedArchs[arch] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(supportedArchs) == 0 {
|
||||||
|
t.Fatal("No supported architectures found from clang --print-targets")
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Logf("Found %d supported architectures from clang", len(supportedArchs))
|
||||||
|
|
||||||
|
// Map our architecture names to clang's architecture names
|
||||||
|
clangArchMap := map[string][]string{
|
||||||
|
"x86_64": {"x86-64", "x86_64"},
|
||||||
|
"i386": {"x86", "i386"},
|
||||||
|
"aarch64": {"aarch64", "arm64"},
|
||||||
|
"arm64": {"arm64", "aarch64"},
|
||||||
|
"armv7": {"arm", "thumb"},
|
||||||
|
"wasm32": {"wasm32"},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define a function to check if the architecture is supported by clang
|
||||||
|
isArchSupported := func(archPart string) (bool, string) {
|
||||||
|
if mappedArchs, ok := clangArchMap[archPart]; ok {
|
||||||
|
for _, mappedArch := range mappedArchs {
|
||||||
|
if supportedArchs[mappedArch] {
|
||||||
|
return true, mappedArch
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if supportedArchs[archPart] {
|
||||||
|
// Direct match
|
||||||
|
return true, archPart
|
||||||
|
}
|
||||||
|
return false, ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define a function to verify OS name
|
||||||
|
isOSValid := func(os, goos string) bool {
|
||||||
|
validOSMap := map[string][]string{
|
||||||
|
"linux": {"linux", "linux-gnu"},
|
||||||
|
"darwin": {"macosx", "darwin"},
|
||||||
|
"windows": {"windows", "win32"},
|
||||||
|
"wasip1": {"wasip1", "wasi"},
|
||||||
|
"js": {"js", "javascript"},
|
||||||
|
}
|
||||||
|
|
||||||
|
if validVariants, ok := validOSMap[goos]; ok {
|
||||||
|
for _, validVariant := range validVariants {
|
||||||
|
if strings.HasPrefix(os, validVariant) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define a function to check if vendor is valid
|
||||||
|
isVendorValid := func(vendor string) bool {
|
||||||
|
validVendors := map[string]bool{
|
||||||
|
"unknown": true,
|
||||||
|
"apple": true,
|
||||||
|
"pc": true,
|
||||||
|
"ibm": true,
|
||||||
|
}
|
||||||
|
return validVendors[vendor]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define the test function
|
||||||
|
checkTriple := func(t *testing.T, testName, goos, goarch, expected string) {
|
||||||
|
t.Helper()
|
||||||
|
got := GetTargetTriple(goos, goarch)
|
||||||
|
|
||||||
|
// Check if the generated triple matches the expected value
|
||||||
|
if got != expected {
|
||||||
|
t.Errorf("getTargetTriple(%q, %q) = %q, want %q",
|
||||||
|
goos, goarch, got, expected)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract the architecture part from the triple (first component)
|
||||||
|
parts := strings.Split(got, "-")
|
||||||
|
if len(parts) < 3 {
|
||||||
|
t.Errorf("Invalid target triple format: %s, should have at least 3 components", got)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
archPart := parts[0]
|
||||||
|
vendor := parts[1]
|
||||||
|
os := parts[2]
|
||||||
|
|
||||||
|
// Check if the architecture is supported by clang
|
||||||
|
supported, mappedArch := isArchSupported(archPart)
|
||||||
|
if supported {
|
||||||
|
t.Logf("Architecture %s (mapped to %s) is supported by clang", archPart, mappedArch)
|
||||||
|
} else {
|
||||||
|
t.Logf("WARNING: Architecture %s from triple %q for %s/%s not found in clang's supported architectures",
|
||||||
|
archPart, got, goos, goarch)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify vendor
|
||||||
|
if !isVendorValid(vendor) {
|
||||||
|
t.Errorf("Invalid vendor in triple: %s", vendor)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify OS
|
||||||
|
if !isOSValid(os, goos) {
|
||||||
|
t.Errorf("OS in triple %q doesn't match expected OS %q", os, goos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run tests for different OS/arch combinations
|
||||||
|
checkTriple(t, "wasip1/wasm", "wasip1", "wasm", "wasm32-unknown-wasip1")
|
||||||
|
checkTriple(t, "linux/amd64", "linux", "amd64", "x86_64-unknown-linux")
|
||||||
|
checkTriple(t, "linux/386", "linux", "386", "i386-unknown-linux")
|
||||||
|
checkTriple(t, "linux/arm64", "linux", "arm64", "aarch64-unknown-linux")
|
||||||
|
checkTriple(t, "linux/arm", "linux", "arm", "armv7-unknown-linux")
|
||||||
|
checkTriple(t, "darwin/amd64", "darwin", "amd64", "x86_64-apple-macosx")
|
||||||
|
checkTriple(t, "darwin/arm64", "darwin", "arm64", "arm64-apple-macosx")
|
||||||
|
checkTriple(t, "windows/amd64", "windows", "amd64", "x86_64-unknown-windows")
|
||||||
|
checkTriple(t, "windows/386", "windows", "386", "i386-unknown-windows")
|
||||||
|
checkTriple(t, "js/wasm", "js", "wasm", "wasm32-unknown-js")
|
||||||
|
}
|
11
llgo_wasm
Executable file
11
llgo_wasm
Executable file
@@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
WORKDIR=''
|
||||||
|
WORKDIR=$(pwd)
|
||||||
|
LLGO_ROOT=''
|
||||||
|
LLGO_ROOT=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )
|
||||||
|
export LLGO_ROOT
|
||||||
|
cd $LLGO_ROOT
|
||||||
|
go install ./cmd/llgo
|
||||||
|
cd $WORKDIR
|
||||||
|
GOOS=wasip1 GOARCH=wasm llgo "$@"
|
@@ -24,6 +24,8 @@ import (
|
|||||||
"go/types"
|
"go/types"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/goplus/llgo/cl/cltest"
|
"github.com/goplus/llgo/cl/cltest"
|
||||||
@@ -65,7 +67,13 @@ func TestFromTestdata(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestMakeInterface(t *testing.T) {
|
func TestMakeInterface(t *testing.T) {
|
||||||
prog := ssatest.NewProgram(t, &ssa.Target{GOARCH: "x86"})
|
wd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
os.Chdir("../runtime")
|
||||||
|
defer os.Chdir(wd)
|
||||||
|
prog := ssatest.NewProgram(t, &ssa.Target{GOARCH: runtime.GOARCH})
|
||||||
pkg := prog.NewPackage("foo", "foo")
|
pkg := prog.NewPackage("foo", "foo")
|
||||||
fn := pkg.NewFunc("main", types.NewSignatureType(nil, nil, nil, nil, nil, false), ssa.InC)
|
fn := pkg.NewFunc("main", types.NewSignatureType(nil, nil, nil, nil, nil, false), ssa.InC)
|
||||||
b := fn.MakeBody(1)
|
b := fn.MakeBody(1)
|
||||||
|
@@ -245,7 +245,7 @@ func (b Builder) checkIndex(idx Expr, max Expr) Expr {
|
|||||||
} else {
|
} else {
|
||||||
typ = prog.Uint()
|
typ = prog.Uint()
|
||||||
}
|
}
|
||||||
if prog.SizeOf(idx.Type) < prog.SizeOf(typ) {
|
if prog.SizeOf(idx.Type) != prog.SizeOf(typ) {
|
||||||
idx.Type = typ
|
idx.Type = typ
|
||||||
idx.impl = castUintptr(b, idx.impl, typ)
|
idx.impl = castUintptr(b, idx.impl, typ)
|
||||||
}
|
}
|
||||||
|
@@ -210,6 +210,22 @@ type aProgram struct {
|
|||||||
// A Program presents a program.
|
// A Program presents a program.
|
||||||
type Program = *aProgram
|
type Program = *aProgram
|
||||||
|
|
||||||
|
var arch32 = map[string]bool{
|
||||||
|
"386": true,
|
||||||
|
"arm": true,
|
||||||
|
"mips": true,
|
||||||
|
"mipsle": true,
|
||||||
|
"s390x": true,
|
||||||
|
"wasm": true,
|
||||||
|
}
|
||||||
|
|
||||||
|
func is32Bits(arch string) bool {
|
||||||
|
if v, ok := arch32[arch]; ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// NewProgram creates a new program.
|
// NewProgram creates a new program.
|
||||||
func NewProgram(target *Target) Program {
|
func NewProgram(target *Target) Program {
|
||||||
if target == nil {
|
if target == nil {
|
||||||
@@ -231,7 +247,7 @@ func NewProgram(target *Target) Program {
|
|||||||
// TODO(xsw): Finalize may cause panic, so comment it.
|
// TODO(xsw): Finalize may cause panic, so comment it.
|
||||||
ctx.Finalize()
|
ctx.Finalize()
|
||||||
*/
|
*/
|
||||||
is32Bits := (td.PointerSize() == 4 || target.GOARCH == "x86") // TODO(xsw): remove temp code
|
is32Bits := (td.PointerSize() == 4 || is32Bits(target.GOARCH))
|
||||||
return &aProgram{
|
return &aProgram{
|
||||||
ctx: ctx, gocvt: newGoTypes(), fnsCompiled: fnsCompiled,
|
ctx: ctx, gocvt: newGoTypes(), fnsCompiled: fnsCompiled,
|
||||||
target: target, td: td, is32Bits: is32Bits,
|
target: target, td: td, is32Bits: is32Bits,
|
||||||
@@ -379,6 +395,12 @@ func (p Program) tyComplex128() llvm.Type {
|
|||||||
// NewPackage creates a new package.
|
// NewPackage creates a new package.
|
||||||
func (p Program) NewPackage(name, pkgPath string) Package {
|
func (p Program) NewPackage(name, pkgPath string) Package {
|
||||||
mod := p.ctx.NewModule(pkgPath)
|
mod := p.ctx.NewModule(pkgPath)
|
||||||
|
// TODO(lijie): enable target output will check module override, but can't
|
||||||
|
// pass the snapshot test, so disable it for now
|
||||||
|
// if p.target.GOARCH != runtime.GOARCH && p.target.GOOS != runtime.GOOS {
|
||||||
|
// mod.SetTarget(p.target.Spec().Triple)
|
||||||
|
// }
|
||||||
|
|
||||||
// TODO(xsw): Finalize may cause panic, so comment it.
|
// TODO(xsw): Finalize may cause panic, so comment it.
|
||||||
// mod.Finalize()
|
// mod.Finalize()
|
||||||
gbls := make(map[string]Global)
|
gbls := make(map[string]Global)
|
||||||
|
@@ -23,6 +23,7 @@ import (
|
|||||||
"go/constant"
|
"go/constant"
|
||||||
"go/token"
|
"go/token"
|
||||||
"go/types"
|
"go/types"
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
@@ -40,6 +41,12 @@ func TestEndDefer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestUnsafeString(t *testing.T) {
|
func TestUnsafeString(t *testing.T) {
|
||||||
|
wd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
os.Chdir("../../runtime")
|
||||||
|
defer os.Chdir(wd)
|
||||||
prog := NewProgram(nil)
|
prog := NewProgram(nil)
|
||||||
prog.SetRuntime(func() *types.Package {
|
prog.SetRuntime(func() *types.Package {
|
||||||
fset := token.NewFileSet()
|
fset := token.NewFileSet()
|
||||||
|
@@ -17,6 +17,8 @@
|
|||||||
package ssa
|
package ssa
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"runtime"
|
||||||
|
|
||||||
"github.com/goplus/llvm"
|
"github.com/goplus/llvm"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -29,15 +31,15 @@ type Target struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *Target) targetData() llvm.TargetData {
|
func (p *Target) targetData() llvm.TargetData {
|
||||||
spec := p.toSpec()
|
spec := p.Spec()
|
||||||
if spec.triple == "" {
|
if spec.Triple == "" {
|
||||||
spec.triple = llvm.DefaultTargetTriple()
|
spec.Triple = llvm.DefaultTargetTriple()
|
||||||
}
|
}
|
||||||
t, err := llvm.GetTargetFromTriple(spec.triple)
|
t, err := llvm.GetTargetFromTriple(spec.Triple)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
machine := t.CreateTargetMachine(spec.triple, spec.cpu, spec.features, llvm.CodeGenLevelDefault, llvm.RelocDefault, llvm.CodeModelDefault)
|
machine := t.CreateTargetMachine(spec.Triple, spec.CPU, spec.Features, llvm.CodeGenLevelDefault, llvm.RelocDefault, llvm.CodeModelDefault)
|
||||||
return machine.CreateTargetData()
|
return machine.CreateTargetData()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,19 +64,13 @@ func (p *Program) targetMachine() llvm.TargetMachine {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
type targetSpec struct {
|
type TargetSpec struct {
|
||||||
triple string
|
Triple string
|
||||||
cpu string
|
CPU string
|
||||||
features string
|
Features string
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO config
|
func (p *Target) Spec() (spec TargetSpec) {
|
||||||
func (p *Target) toSpec() (spec targetSpec) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
func (p *Target) toSpec() (spec targetSpec) {
|
|
||||||
// Configure based on GOOS/GOARCH environment variables (falling back to
|
// Configure based on GOOS/GOARCH environment variables (falling back to
|
||||||
// runtime.GOOS/runtime.GOARCH), and generate a LLVM target based on it.
|
// runtime.GOOS/runtime.GOARCH), and generate a LLVM target based on it.
|
||||||
var llvmarch string
|
var llvmarch string
|
||||||
@@ -113,56 +109,55 @@ func (p *Target) toSpec() (spec targetSpec) {
|
|||||||
case "darwin":
|
case "darwin":
|
||||||
// Use macosx* instead of darwin, otherwise darwin/arm64 will refer
|
// Use macosx* instead of darwin, otherwise darwin/arm64 will refer
|
||||||
// to iOS!
|
// to iOS!
|
||||||
llvmos = "macosx10.12.0"
|
llvmos = "macosx"
|
||||||
if llvmarch == "aarch64" {
|
if llvmarch == "aarch64" {
|
||||||
// Looks like Apple prefers to call this architecture ARM64
|
// Looks like Apple prefers to call this architecture ARM64
|
||||||
// instead of AArch64.
|
// instead of AArch64.
|
||||||
llvmarch = "arm64"
|
llvmarch = "arm64"
|
||||||
llvmos = "macosx11.0.0"
|
llvmos = "macosx"
|
||||||
}
|
}
|
||||||
llvmvendor = "apple"
|
llvmvendor = "apple"
|
||||||
case "wasip1":
|
case "wasip1":
|
||||||
llvmos = "wasi"
|
llvmos = "wasip1"
|
||||||
}
|
}
|
||||||
// Target triples (which actually have four components, but are called
|
// Target triples (which actually have four components, but are called
|
||||||
// triples for historical reasons) have the form:
|
// triples for historical reasons) have the form:
|
||||||
// arch-vendor-os-environment
|
// arch-vendor-os-environment
|
||||||
spec.triple = llvmarch + "-" + llvmvendor + "-" + llvmos
|
spec.Triple = llvmarch + "-" + llvmvendor + "-" + llvmos
|
||||||
if llvmos == "windows" {
|
if llvmos == "windows" {
|
||||||
spec.triple += "-gnu"
|
spec.Triple += "-gnu"
|
||||||
} else if goarch == "arm" {
|
} else if goarch == "arm" {
|
||||||
spec.triple += "-gnueabihf"
|
spec.Triple += "-gnueabihf"
|
||||||
}
|
}
|
||||||
switch goarch {
|
switch goarch {
|
||||||
case "386":
|
case "386":
|
||||||
spec.cpu = "pentium4"
|
spec.CPU = "pentium4"
|
||||||
spec.features = "+cx8,+fxsr,+mmx,+sse,+sse2,+x87"
|
spec.Features = "+cx8,+fxsr,+mmx,+sse,+sse2,+x87"
|
||||||
case "amd64":
|
case "amd64":
|
||||||
spec.cpu = "x86-64"
|
spec.CPU = "x86-64"
|
||||||
spec.features = "+cx8,+fxsr,+mmx,+sse,+sse2,+x87"
|
spec.Features = "+cx8,+fxsr,+mmx,+sse,+sse2,+x87"
|
||||||
case "arm":
|
case "arm":
|
||||||
spec.cpu = "generic"
|
spec.CPU = "generic"
|
||||||
switch llvmarch {
|
switch llvmarch {
|
||||||
case "armv5":
|
case "armv5":
|
||||||
spec.features = "+armv5t,+strict-align,-aes,-bf16,-d32,-dotprod,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-mve.fp,-neon,-sha2,-thumb-mode,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
|
spec.Features = "+armv5t,+strict-align,-aes,-bf16,-d32,-dotprod,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-mve.fp,-neon,-sha2,-thumb-mode,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
|
||||||
case "armv6":
|
case "armv6":
|
||||||
spec.features = "+armv6,+dsp,+fp64,+strict-align,+vfp2,+vfp2sp,-aes,-d32,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fullfp16,-neon,-sha2,-thumb-mode,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
|
spec.Features = "+armv6,+dsp,+fp64,+strict-align,+vfp2,+vfp2sp,-aes,-d32,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fullfp16,-neon,-sha2,-thumb-mode,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
|
||||||
case "armv7":
|
case "armv7":
|
||||||
spec.features = "+armv7-a,+d32,+dsp,+fp64,+neon,+vfp2,+vfp2sp,+vfp3,+vfp3d16,+vfp3d16sp,+vfp3sp,-aes,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fullfp16,-sha2,-thumb-mode,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
|
spec.Features = "+armv7-a,+d32,+dsp,+fp64,+neon,+vfp2,+vfp2sp,+vfp3,+vfp3d16,+vfp3d16sp,+vfp3sp,-aes,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fullfp16,-sha2,-thumb-mode,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
|
||||||
}
|
}
|
||||||
case "arm64":
|
case "arm64":
|
||||||
spec.cpu = "generic"
|
spec.CPU = "generic"
|
||||||
if goos == "darwin" {
|
if goos == "darwin" {
|
||||||
spec.features = "+neon"
|
spec.Features = "+neon"
|
||||||
} else { // windows, linux
|
} else { // windows, linux
|
||||||
spec.features = "+neon,-fmv"
|
spec.Features = "+neon,-fmv"
|
||||||
}
|
}
|
||||||
case "wasm":
|
case "wasm":
|
||||||
spec.cpu = "generic"
|
spec.CPU = "generic"
|
||||||
spec.features = "+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext"
|
spec.Features = "+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext"
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
@@ -1,3 +1,6 @@
|
|||||||
|
//go:build !llgo
|
||||||
|
// +build !llgo
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
|
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
|
||||||
*
|
*
|
||||||
|
Reference in New Issue
Block a user