Merge pull request #1164 from visualfc/codegen
build: gen pkg.ll to object
This commit is contained in:
@@ -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
|
||||
@@ -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 {
|
||||
@@ -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 {
|
||||
@@ -341,6 +350,8 @@ type context struct {
|
||||
nLibdir int
|
||||
output bool
|
||||
|
||||
isCheckEnable bool
|
||||
|
||||
needRt map[*packages.Package]bool
|
||||
needPyInit map[*packages.Package]bool
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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\"()"
|
||||
@@ -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 := ""
|
||||
@@ -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'
|
||||
@@ -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 {
|
||||
@@ -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)
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
@@ -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",
|
||||
@@ -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,
|
||||
@@ -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",
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user