Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 75 additions & 37 deletions internal/build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ type Config struct {
Mode Mode
GenExpect bool // only valid for ModeCmpTest
Verbose bool
GenLL bool // generate pkg .ll files
Tags string
GlobalNames map[string][]string // pkg => names
GlobalDatas map[string]string // pkg.name => data
Expand Down Expand Up @@ -252,7 +253,15 @@ func Do(args []string, conf *Config) ([]Package, error) {
output := conf.OutFile != ""
export, err := crosscompile.Use(conf.Goos, conf.Goarch, IsWasiThreadsEnabled(), IsRpathChangeEnabled())
check(err)
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, export, false}
ctx := &context{env: env, conf: cfg, progSSA: progSSA, prog: prog, dedup: dedup,
patches: patches, built: make(map[string]none), initial: initial, mode: mode,
output: output,
needRt: make(map[*packages.Package]bool),
needPyInit: make(map[*packages.Package]bool),
buildConf: conf,
crossCompile: export,
isCheckEnable: IsCheckEnable(),
}
pkgs, err := buildAllPkgs(ctx, initial, verbose)
check(err)
if mode == ModeGen {
Expand All @@ -273,7 +282,7 @@ func Do(args []string, conf *Config) ([]Package, error) {
addGlobalString(conf, "runtime.defaultGOROOT="+runtime.GOROOT(), nil)
addGlobalString(conf, "runtime.buildVersion="+runtime.Version(), nil)

global, err := createGlobals(conf, ctx.prog, pkgs)
global, err := createGlobals(ctx, ctx.prog, pkgs)
check(err)

for _, pkg := range initial {
Expand Down Expand Up @@ -341,6 +350,8 @@ type context struct {
nLibdir int
output bool

isCheckEnable bool

needRt map[*packages.Package]bool
needPyInit map[*packages.Package]bool

Expand Down Expand Up @@ -476,25 +487,28 @@ func addGlobalString(conf *Config, arg string, mainPkgs []string) {
}
}

func createGlobals(conf *Config, prog llssa.Program, pkgs []*aPackage) (llssa.Package, error) {
if len(conf.GlobalDatas) == 0 {
func createGlobals(ctx *context, prog llssa.Program, pkgs []*aPackage) (llssa.Package, error) {
if len(ctx.buildConf.GlobalDatas) == 0 {
return nil, nil
}
for _, pkg := range pkgs {
if pkg.ExportFile == "" {
continue
}
if names, ok := conf.GlobalNames[pkg.PkgPath]; ok {
if names, ok := ctx.buildConf.GlobalNames[pkg.PkgPath]; ok {
err := pkg.LPkg.Undefined(names...)
if err != nil {
return nil, err
}
pkg.ExportFile = pkg.ExportFile + "-global.ll"
os.WriteFile(pkg.ExportFile, []byte(pkg.LPkg.String()), 0644)
pkg.ExportFile += "-global"
pkg.ExportFile, err = exportObject(ctx, pkg.PkgPath+".global", pkg.ExportFile, []byte(pkg.LPkg.String()))
if err != nil {
return nil, err
}
}
}
global := prog.NewPackage("", "global")
for name, value := range conf.GlobalDatas {
for name, value := range ctx.buildConf.GlobalDatas {
global.AddGlobalString(name, value)
}
return global, nil
Expand Down Expand Up @@ -543,14 +557,14 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, global l
}
}
})
entryLLFile, err := genMainModuleFile(conf, llssa.PkgRuntime, pkg.PkgPath, needRuntime, needPyInit)
entryLLFile, err := genMainModuleFile(ctx, llssa.PkgRuntime, pkg, needRuntime, needPyInit)
check(err)
// defer os.Remove(entryLLFile)
llFiles = append(llFiles, entryLLFile)

if global != nil {
export := pkg.ExportFile + "-global.ll"
os.WriteFile(export, []byte(global.String()), 0666)
export, err := exportObject(ctx, pkg.PkgPath+".global", pkg.ExportFile+"-global", []byte(global.String()))
check(err)
llFiles = append(llFiles, export)
}

Expand Down Expand Up @@ -663,13 +677,14 @@ 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) {
func genMainModuleFile(ctx *context, rtPkgPath string, pkg *packages.Package, needRuntime, needPyInit bool) (path string, err error) {
var (
pyInitDecl string
pyInit string
rtInitDecl string
rtInit string
)
mainPkgPath := pkg.PkgPath
if needRuntime {
rtInit = "call void @\"" + rtPkgPath + ".init\"()"
rtInitDecl = "declare void @\"" + rtPkgPath + ".init\"()"
Expand All @@ -679,7 +694,7 @@ func genMainModuleFile(conf *Config, rtPkgPath, mainPkgPath string, needRuntime,
pyInitDecl = "declare void @Py_Initialize()"
}
declSizeT := "%size_t = type i64"
if is32Bits(conf.Goarch) {
if is32Bits(ctx.buildConf.Goarch) {
declSizeT = "%size_t = type i32"
}
stdioDecl := ""
Expand All @@ -703,7 +718,7 @@ call i32 @setvbuf(ptr %stderr_ptr, ptr null, i32 2, %size_t 0)
`
}
mainDefine := "define i32 @main(i32 noundef %0, ptr nocapture noundef readnone %1) local_unnamed_addr"
if isWasmTarget(conf.Goos) {
if isWasmTarget(ctx.buildConf.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'
Expand Down Expand Up @@ -742,19 +757,7 @@ _llgo_0:
mainDefine, stdioNobuf,
pyInit, rtInit, mainPkgPath, mainPkgPath)

f, err := os.CreateTemp("", "main*.ll")
if err != nil {
return "", err
}
_, err = f.Write([]byte(mainCode))
if err != nil {
return "", err
}
err = f.Close()
if err != nil {
return "", err
}
return f.Name(), nil
return exportObject(ctx, pkg.PkgPath+".main", pkg.ExportFile+"-main", []byte(mainCode))
}

func is32Bits(goarch string) bool {
Expand Down Expand Up @@ -805,20 +808,50 @@ func buildPkg(ctx *context, aPkg *aPackage, verbose bool) error {
aPkg.LinkArgs = append(aPkg.LinkArgs, altLdflags...)
}
if pkg.ExportFile != "" {
pkg.ExportFile += ".ll"
os.WriteFile(pkg.ExportFile, []byte(ret.String()), 0644)
pkg.ExportFile, err = exportObject(ctx, pkg.PkgPath, pkg.ExportFile, []byte(ret.String()))
if err != nil {
return fmt.Errorf("export object of %v failed: %v", pkgPath, err)
}
if debugBuild || verbose {
fmt.Fprintf(os.Stderr, "==> Export %s: %s\n", aPkg.PkgPath, pkg.ExportFile)
}
if IsCheckEnable() {
if msg, err := llcCheck(ctx.env, pkg.ExportFile); err != nil {
fmt.Fprintf(os.Stderr, "==> lcc %v: %v\n%v\n", pkg.PkgPath, pkg.ExportFile, msg)
}
}
}
return nil
}

func exportObject(ctx *context, pkgPath string, exportFile string, data []byte) (string, error) {
f, err := os.CreateTemp("", "llgo-*.ll")
if err != nil {
return "", err
}
f.Write(data)
err = f.Close()
if err != nil {
return exportFile, err
}
if ctx.isCheckEnable {
if msg, err := llcCheck(ctx.env, f.Name()); err != nil {
fmt.Fprintf(os.Stderr, "==> lcc %v: %v\n%v\n", pkgPath, f.Name(), msg)
}
}
if ctx.buildConf.GenLL {
exportFile += ".ll"
err = os.Chmod(f.Name(), 0644)
if err != nil {
return exportFile, err
}
return exportFile, os.Rename(f.Name(), exportFile)
}
exportFile += ".o"
args := []string{"-o", exportFile, "-c", f.Name(), "-Wno-override-module"}
args = append(args, ctx.crossCompile.CCFLAGS...)
if ctx.buildConf.Verbose {
fmt.Fprintln(os.Stderr, "clang", args)
}
cmd := ctx.compiler()
return exportFile, cmd.Compile(args...)
}

func llcCheck(env *llvm.Env, exportFile string) (msg string, err error) {
bin := filepath.Join(env.BinDir(), "llc")
cmd := exec.Command(bin, "-filetype=null", exportFile)
Expand Down Expand Up @@ -1034,15 +1067,20 @@ 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) {
llFile := expFile + filepath.Base(cFile) + ".ll"
llFile := expFile + filepath.Base(cFile)
ext := filepath.Ext(cFile)

// default clang++ will use c++ to compile c file,will cause symbol be mangled
if ext == ".c" {
args = append(args, "-x", "c")
}

args = append(args, "-emit-llvm", "-S", "-o", llFile, "-c", cFile)
if ctx.buildConf.GenLL {
llFile += ".ll"
args = append(args, "-emit-llvm", "-S", "-o", llFile, "-c", cFile)
} else {
llFile += ".o"
args = append(args, "-o", llFile, "-c", cFile)
}
args = append(args, ctx.crossCompile.CCFLAGS...)
args = append(args, ctx.crossCompile.CFLAGS...)
if verbose {
Expand Down
12 changes: 11 additions & 1 deletion internal/crosscompile/cosscompile.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ func Use(goos, goarch string, wasiThreads, changeRpath bool) (export Export, err
"-Wno-override-module",
"-Wl,--error-limit=0",
"-fuse-ld=lld",
"-Wno-override-module",
}

// Add OS-specific flags
Expand All @@ -56,6 +55,11 @@ func Use(goos, goarch string, wasiThreads, changeRpath bool) (export Export, err
case "windows": // lld-link (Windows)
// TODO(lijie): Add options for Windows.
default: // ld.lld (Unix)
export.CCFLAGS = append(
export.CCFLAGS,
"-fdata-sections",
"-ffunction-sections",
)
export.LDFLAGS = append(
export.LDFLAGS,
"-fdata-sections",
Expand Down Expand Up @@ -105,6 +109,8 @@ func Use(goos, goarch string, wasiThreads, changeRpath bool) (export Export, err
"-target", targetTriple,
"--sysroot=" + sysrootDir,
"-resource-dir=" + libclangDir,
"-matomics",
"-mbulk-memory",
}
export.CFLAGS = []string{
"-I" + includeDir,
Expand Down Expand Up @@ -138,6 +144,10 @@ func Use(goos, goarch string, wasiThreads, changeRpath bool) (export Export, err
}
// Add thread support if enabled
if wasiThreads {
export.CCFLAGS = append(
export.CCFLAGS,
"-pthread",
)
export.LDFLAGS = append(
export.LDFLAGS,
"-lwasi-emulated-pthread",
Expand Down
2 changes: 1 addition & 1 deletion internal/crosscompile/crosscompile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ func TestUseCrossCompileSDK(t *testing.T) {
}
}
} else {
if len(export.CCFLAGS) != 0 || len(export.CFLAGS) != 0 {
if /*len(export.CCFLAGS) != 0 ||*/ len(export.CFLAGS) != 0 {
t.Errorf("Expected empty export, got CCFLAGS=%v, CFLAGS=%v, LDFLAGS=%v",
export.CCFLAGS, export.CFLAGS, export.LDFLAGS)
}
Expand Down
Loading