Skip to content

Latest commit

 

History

History
190 lines (171 loc) · 6.47 KB

README.md

File metadata and controls

190 lines (171 loc) · 6.47 KB

Play with go compiler

This directory demonstrates how to play with the go compiler. It modifies the compiler so that it inserts two extra print:

  • by modifying AST: hello Syntax
  • by modifying IR: hello IR
  • by modifying IR and inserting __x_trap to runtime: hello Trap
$ ./debug.sh build-compiler
$ ./debug.sh build
$ ./main.bin 
hello IR
hello Trap
hello Syntax
hello world

Current go version is go1.22.

Debug the compiler

Compiler entrance: ../compile/main.go

./debug.sh build-compiler
./debug.sh debug # this will hang the terminal, and you can copy the output configuration to .vscode

The compiler should be compile-devel or compile? That depends on go version. Because compile-devel -V=full outputs compile-devel version go1.21.7,

  • With go1.22, that is accepted.

  • With go1.20, the compile-devel part does not match compile,so failed. The message is:

go: parsing buildID from go tool compile -V=full: unexpected output:
        compile-devel version go1.20.14

Emitted from src/cmd/go/internal/work/buildid.go.

Implement a mock framework

With this technique it is trivial to implement a mock framework.

Just use the trap.AddInterceptor({Pre:..., Post:...}) to define Pre to detect function point in interested, and return a trap.ErrAbort to skip the function.

See ./test/test_trap/mock/mock.go:

trap.AddInterceptor(trap.Interceptor{
    Pre: func(ctx context.Context, f *functab.FuncInfo, args *trap.FuncArgs) (interface{}, error) {
        if strings.Contains(f.FullName, "testArgs") {
            fmt.Printf("Mock: %s\n", f.FullName)
            p := args.Results[0].(*int)
            *p = 20
            return nil, trap.ErrAbort
        }
        return nil, nil
    }
})

Implement a stack trace collector

It is possible to collect a runtime stack trace collector, see core/trace/trace.go. Usage:

./with-go-devel ./debug.sh build -v -gcflags \"all=-N -l\" -o ./test_trap.bin ./test/test_trap

Or just use the VS Code launch config Launch test_trap.

Example:

{
    "Children": [
        {
            "FuncInfo": {
                "FullName": "main.main"
            },
            "Children": [
                {
                    "FuncInfo": {
                        "FullName": "main.testArgs"
                    },
                    "Recv": null,
                    "Args": [
                        "a"
                    ],
                    "Results": [
                        1
                    ],
                    "Children": [
                        {
                            "FuncInfo": {
                                "FullName": "main.num.add"
                            },
                            "Recv": 1,
                            "Args": [
                                2
                            ],
                            "Results": null,
                            "Children": [
                                {
                                    "FuncInfo": {
                                        "FullName": "github.com/xhd2015/xgo/runtime/pkg.Hello"
                                    },
                                    "Recv": null,
                                    "Args": [
                                        "pkg"
                                    ],
                                    "Results": null,
                                    "Children": [
                                        {
                                            "FuncInfo": {
                                                "FullName": "github.com/xhd2015/xgo/runtime/pkg.Mass.Print"
                                            },
                                            "Recv": 1,
                                            "Args": [
                                                "g"
                                            ],
                                            "Results": null,
                                            "Children": [
                                                {
                                                    "FuncInfo": {
                                                        "FullName": "github.com/xhd2015/xgo/runtime/pkg.(*Person).Greet"
                                                    },
                                                    "Recv": {
                                                        "Name": "test"
                                                    },
                                                    "Args": [
                                                        "runtime"
                                                    ],
                                                    "Results": null,
                                                    "Children": [
                                                        {
                                                            "FuncInfo": {
                                                                "FullName": "github.com/xhd2015/xgo/runtime/pkg.Hello.func1"
                                                            }
                                                        }
                                                    ]
                                                }
                                            ]
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                }
            ]
        }
    ]
}

Development

How to add customized function to runtime?

1.Edit ../compile/internal/typecheck/_builtin/runtime.go to add function declaration, 2.Execute go generate

./debug.sh gen-runtime-type
# or
./with-go-devel.sh go generate ../compile/internal/typecheck

Supported flags:

  • -stdout output to stdout instead of file
  • -nofmt skip formatting

See ../compile/internal/typecheck/mkbuiltin.go

Also:

(cd ../compile/internal/typecheck; ../../../test/with-go-devel.sh go run ./mkbuiltin.go -stdout -nofmt)

Check runtime symbols

./with-go-devel.sh go tool nm runtime.a

Configure git exclude

root=$(git rev-parse --show-toplevel)
mkdir -p "$root/.git/info"
cat >>"$root/.git/info/exclude" <<'EOF'
/src/cmd/test/*.log
/src/cmd/test/compile-devel
/src/cmd/test/*.bin
/src/cmd/test/*.a
EOF