Skip to content

Commit 5e9b1fb

Browse files
committed
leverage compiler irgen for linking
1 parent a29b957 commit 5e9b1fb

File tree

174 files changed

+1030
-368
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

174 files changed

+1030
-368
lines changed

asset.go

Lines changed: 0 additions & 10 deletions
This file was deleted.

cmd/xgo/asset/asset.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package asset
2+
3+
import "embed"
4+
5+
// since go:embed does not work with ../ paths
6+
// so we add a global asset here.
7+
// https://github.com/golang/go/issues/46056
8+
9+
const (
10+
CompilerPatchGen = "compiler_patch_gen"
11+
RuntimeGen = "runtime_gen"
12+
)
13+
14+
//go:embed compiler_patch_gen
15+
var CompilerPatchGenFS embed.FS
16+
17+
//go:embed runtime_gen
18+
var RuntimeGenFS embed.FS
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//go:build go1.17 && !go1.22
2+
// +build go1.17,!go1.22
3+
4+
package funcs
5+
6+
import (
7+
"cmd/compile/internal/ir"
8+
"cmd/compile/internal/typecheck"
9+
)
10+
11+
// for go1.20, target does not have Target.Funcs, instead, use Target.Decls
12+
func ForEach(callback func(fn *ir.Func) bool) {
13+
// for go1.21 and above, this can just be:
14+
// for _, fn := range typecheck.Target.Funcs
15+
for _, decl := range typecheck.Target.Decls {
16+
fn, ok := decl.(*ir.Func)
17+
if !ok {
18+
continue
19+
}
20+
if !callback(fn) {
21+
return
22+
}
23+
}
24+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//go:build go1.22
2+
// +build go1.22
3+
4+
package funcs
5+
6+
import (
7+
"cmd/compile/internal/ir"
8+
"cmd/compile/internal/typecheck"
9+
)
10+
11+
func ForEach(callback func(fn *ir.Func) bool) {
12+
for _, fn := range typecheck.Target.Funcs {
13+
if !callback(fn) {
14+
return
15+
}
16+
}
17+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module github.com/xhd2015/xgo/patch
2+
3+
go 1.14
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package link
2+
3+
import (
4+
"cmd/compile/internal/ir"
5+
"cmd/compile/internal/typecheck"
6+
"strings"
7+
)
8+
9+
const xgoPrefix = "__xgo_"
10+
11+
// LinkXgoInit links function defined in
12+
// runtime
13+
// the function template:
14+
//
15+
// var __xgo_trap_0 = func() {}
16+
//
17+
// func init() {
18+
// __xgo_init_0()
19+
// }
20+
//
21+
// //go:noinline
22+
// func __xgo_init_0() {
23+
// __xgo_trap_0 = __xgo_trap_0
24+
// }
25+
func LinkXgoInit(fn *ir.Func) {
26+
if fn.Body == nil {
27+
// in go, function can have name without body
28+
return
29+
}
30+
31+
fnName := fn.Sym().Name
32+
if !strings.HasPrefix(fnName, "__xgo_init_") {
33+
return
34+
}
35+
for _, node := range fn.Body {
36+
assign, ok := node.(*ir.AssignStmt)
37+
if !ok {
38+
continue
39+
}
40+
if assign.Def {
41+
continue
42+
}
43+
xName, ok := assign.X.(*ir.Name)
44+
if !ok {
45+
continue
46+
}
47+
symName := xName.Sym().Name
48+
if !strings.HasPrefix(symName, xgoPrefix) {
49+
continue
50+
}
51+
52+
switch {
53+
case strings.HasPrefix(symName, "__xgo_trap_var_"):
54+
sym := typecheck.LookupRuntime("XgoTrapVar")
55+
if sym == nil {
56+
continue
57+
}
58+
assign.Y = sym
59+
case strings.HasPrefix(symName, "__xgo_trap_varptr_"):
60+
sym := typecheck.LookupRuntime("XgoTrapVarPtr")
61+
if sym == nil {
62+
continue
63+
}
64+
assign.Y = sym
65+
case strings.HasPrefix(symName, "__xgo_trap_"):
66+
sym := typecheck.LookupRuntime("XgoTrap")
67+
if sym == nil {
68+
continue
69+
}
70+
assign.Y = sym
71+
case strings.HasPrefix(symName, "__xgo_register_"):
72+
sym := typecheck.LookupRuntime("XgoRegister")
73+
if sym == nil {
74+
continue
75+
}
76+
assign.Y = sym
77+
}
78+
}
79+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package patch
2+
3+
import (
4+
"cmd/compile/internal/ir"
5+
6+
"cmd/compile/internal/xgo_rewrite_internal/patch/funcs"
7+
"cmd/compile/internal/xgo_rewrite_internal/patch/link"
8+
)
9+
10+
func Patch() {
11+
linkFuncs()
12+
}
13+
14+
func linkFuncs() {
15+
funcs.ForEach(func(fn *ir.Func) bool {
16+
link.LinkXgoInit(fn)
17+
return true
18+
})
19+
}
File renamed without changes.

cmd/xgo/runtime_gen/internal/runtime/runtime_link.go renamed to cmd/xgo/asset/runtime_gen/internal/runtime/runtime_link.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111

1212
// this ensures runtime to be always imported
1313
var _ = runtime.NumCPU
14+
var _ = unsafe.Pointer(nil)
1415

1516
type XgoFuncInfo struct{}
1617

cmd/xgo/runtime_gen/internal/runtime/runtime_link_template.go renamed to cmd/xgo/asset/runtime_gen/internal/runtime/runtime_link_template.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313

1414
// this ensures runtime to be always imported
1515
var _ = runtime.NumCPU
16+
var _ = unsafe.Pointer(nil)
1617

1718
type XgoFuncInfo = runtime.XgoFuncInfo
1819

cmd/xgo/runtime_gen/internal/runtime/xgo_trap_template.go renamed to cmd/xgo/asset/runtime_gen/internal/runtime/xgo_trap_template.go

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,30 +18,36 @@ var _ = unsafe.Pointer(nil)
1818

1919
// this signature is to avoid relying on defined type
2020
// just raw string,interface{},[]string, []interface{} are needed
21+
22+
type __xgo_intf_header struct {
23+
typ unsafe.Pointer
24+
data unsafe.Pointer
25+
}
26+
2127
var __xgo_trap func(info unsafe.Pointer, recvPtr interface{}, args []interface{}, results []interface{}) (func(), bool)
2228

2329
var __xgo_var_trap func(info unsafe.Pointer, varAddr interface{}, res interface{})
2430
var __xgo_var_ptr_trap func(info unsafe.Pointer, varAddr interface{}, res interface{})
2531

26-
func XgoTrap(info unsafe.Pointer, recvPtr interface{}, args []interface{}, results []interface{}) (func(), bool) {
32+
func XgoTrap(info interface{}, recvPtr interface{}, args []interface{}, results []interface{}) (func(), bool) {
2733
if __xgo_trap == nil {
2834
return nil, false
2935
}
30-
return __xgo_trap(info, recvPtr, args, results)
36+
return __xgo_trap((*__xgo_intf_header)(unsafe.Pointer(&info)).data, recvPtr, args, results)
3137
}
3238

33-
func XgoTrapVar(info unsafe.Pointer, varAddr interface{}, res interface{}) {
39+
func XgoTrapVar(info interface{}, varAddr interface{}, res interface{}) {
3440
if __xgo_var_trap == nil {
3541
return
3642
}
37-
__xgo_var_trap(info, varAddr, res)
43+
__xgo_var_trap((*__xgo_intf_header)(unsafe.Pointer(&info)).data, varAddr, res)
3844
}
3945

40-
func XgoTrapVarPtr(info unsafe.Pointer, varAddr interface{}, res interface{}) {
46+
func XgoTrapVarPtr(info interface{}, varAddr interface{}, res interface{}) {
4147
if __xgo_var_ptr_trap == nil {
4248
return
4349
}
44-
__xgo_var_ptr_trap(info, varAddr, res)
50+
__xgo_var_ptr_trap((*__xgo_intf_header)(unsafe.Pointer(&info)).data, varAddr, res)
4551
}
4652

4753
func XgoSetTrap(trap func(info unsafe.Pointer, recvPtr interface{}, args []interface{}, results []interface{}) (func(), bool)) {
@@ -188,7 +194,7 @@ type XgoFuncInfo struct {
188194

189195
// ==end xgo func==
190196

191-
var __xgo_staging_funcs []*XgoFuncInfo
197+
var __xgo_staging_funcs []interface{}
192198
var __xgo_register_handler func(fn unsafe.Pointer)
193199

194200
func XgoSetupRegisterHandler(register func(fn unsafe.Pointer)) {
@@ -199,13 +205,13 @@ func XgoSetupRegisterHandler(register func(fn unsafe.Pointer)) {
199205
saved := __xgo_staging_funcs
200206
__xgo_staging_funcs = nil
201207
for _, fn := range saved {
202-
register(unsafe.Pointer(fn))
208+
register((*__xgo_intf_header)(unsafe.Pointer(&fn)).data)
203209
}
204210
}
205211

206-
func XgoRegister(fn *XgoFuncInfo) {
212+
func XgoRegister(fn interface{}) {
207213
if __xgo_register_handler != nil {
208-
__xgo_register_handler(unsafe.Pointer(fn))
214+
__xgo_register_handler((*__xgo_intf_header)(unsafe.Pointer(&fn)).data)
209215
return
210216
}
211217
__xgo_staging_funcs = append(__xgo_staging_funcs, fn)
File renamed without changes.

cmd/xgo/go_build.go

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"os"
55
"os/exec"
66
"path/filepath"
7+
8+
"github.com/xhd2015/xgo/instrument/build"
79
)
810

911
// Deprecated: since xgo v1.1.0, xgo does not instrument the compiler anymore
@@ -16,27 +18,20 @@ func buildCompiler(goroot string, output string) error {
1618
cmd := exec.Command(filepath.Join(goroot, "bin", "go"), args...)
1719
cmd.Stdout = os.Stdout
1820
cmd.Stderr = os.Stderr
19-
env, err := patchEnvWithGoroot(os.Environ(), goroot)
20-
if err != nil {
21-
return err
22-
}
23-
cmd.Env = env
21+
cmd.Env = build.MakeGorootEnv(os.Environ(), goroot)
2422
// when building the compiler, we want native
2523
// build, see https://github.com/xhd2015/xgo/issues/231
26-
cmd.Env = appendNativeBuildEnv(cmd.Env)
24+
cmd.Env = build.AppendNativeBuildEnv(cmd.Env)
2725
cmd.Dir = filepath.Join(goroot, "src", "cmd", "compile")
2826
return cmd.Run()
2927
}
28+
3029
func buildExecTool(dir string, execToolBin string) error {
3130
// build exec tool
3231
cmd := exec.Command(getNakedGo(), "build", "-o", execToolBin, "./exec_tool")
3332
cmd.Dir = dir
3433
cmd.Stdout = os.Stdout
3534
cmd.Stderr = os.Stderr
36-
cmd.Env = appendNativeBuildEnv(os.Environ())
35+
cmd.Env = build.AppendNativeBuildEnv(os.Environ())
3736
return cmd.Run()
3837
}
39-
40-
func appendNativeBuildEnv(env []string) []string {
41-
return append(env, "GOOS=", "GOARCH=")
42-
}

cmd/xgo/main.go

Lines changed: 4 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/xhd2015/xgo/cmd/xgo/exec_tool"
1616
"github.com/xhd2015/xgo/cmd/xgo/pathsum"
1717
test_explorer "github.com/xhd2015/xgo/cmd/xgo/test-explorer"
18+
"github.com/xhd2015/xgo/instrument/build"
1819
"github.com/xhd2015/xgo/instrument/config"
1920
"github.com/xhd2015/xgo/instrument/constants"
2021
"github.com/xhd2015/xgo/instrument/instrument_xgo_runtime"
@@ -96,8 +97,7 @@ func main() {
9697
return
9798
}
9899
if cmd == "shadow" {
99-
err := handleShawdow()
100-
consumeErrAndExit(err)
100+
consumeErrAndExit(fmt.Errorf("shadow is deprecated, use `xgo setup` instead"))
101101
return
102102
}
103103
if cmd != "build" && cmd != "run" && cmd != "test" && cmd != "exec" && cmd != "setup" {
@@ -613,10 +613,8 @@ func handleBuild(cmd string, args []string) error {
613613
debugMode := runDebug || testDebug || buildDebug
614614
var finalBuildOutput string
615615

616-
execCmdEnv, err := patchEnvWithGoroot(os.Environ(), instrumentGoroot)
617-
if err != nil {
618-
return err
619-
}
616+
execCmdEnv := build.MakeGorootEnv(os.Environ(), instrumentGoroot)
617+
620618
var execCmd *exec.Cmd
621619
var logCmdExec func()
622620
if !cmdExec {
@@ -1246,42 +1244,6 @@ func ensureDirs(binDir string, logDir string, instrumentDir string, packageDataD
12461244
return nil
12471245
}
12481246

1249-
func patchEnvWithGoroot(env []string, goroot string) ([]string, error) {
1250-
goroot, err := filepath.Abs(goroot)
1251-
if err != nil {
1252-
return nil, err
1253-
}
1254-
1255-
newEnv := makeGorootEnv(env, goroot)
1256-
return newEnv, nil
1257-
}
1258-
1259-
// makeGorootEnv makes a new env with GOROOT and PATH set
1260-
func makeGorootEnv(env []string, goroot string) []string {
1261-
newEnv := make([]string, 0, len(env))
1262-
var lastPath string
1263-
for _, e := range env {
1264-
if strings.HasPrefix(e, "GOROOT=") {
1265-
continue
1266-
}
1267-
if strings.HasPrefix(e, "PATH=") {
1268-
lastPath = e
1269-
continue
1270-
}
1271-
newEnv = append(newEnv, e)
1272-
}
1273-
gorootBin := filepath.Join(goroot, "bin")
1274-
pathEnv := gorootBin
1275-
if lastPath != "" {
1276-
pathEnv = pathEnv + string(filepath.ListSeparator) + strings.TrimPrefix(lastPath, "PATH=")
1277-
}
1278-
newEnv = append(newEnv,
1279-
"GOROOT="+goroot,
1280-
"PATH="+pathEnv,
1281-
)
1282-
return newEnv
1283-
}
1284-
12851247
func assertDir(dir string) error {
12861248
fileInfo, err := os.Stat(dir)
12871249
if err != nil {

0 commit comments

Comments
 (0)