Skip to content

[WIP] llgo build#466

Open
visualfc wants to merge 1 commit into
goplus:mainfrom
visualfc:llgo
Open

[WIP] llgo build#466
visualfc wants to merge 1 commit into
goplus:mainfrom
visualfc:llgo

Conversation

@visualfc

@visualfc visualfc commented Jul 1, 2026

Copy link
Copy Markdown
Member

No description provided.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces build-tag separation for the llgo compiler by moving the CallerFrames method to runtime.go (built with !llgo) and adding a new runtime_llgo.go file. It also updates several dependencies in go.mod. However, two critical issues were identified: first, using "main" as a version in go.mod is invalid and will break the Go toolchain; second, excluding runtime.go under the llgo tag leaves debugStack unregistered and breaks API compatibility due to the missing CallerFrames method on Frame. Suggestions have been provided to resolve both issues.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread go.mod Outdated
Comment thread runtime_llgo.go
Comment on lines +5 to +14

import "runtime"

func runtimeGC(fr *frame) {
runtime.GC()
}

func debugStack(fr *frame) []byte {
return nil
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Under the llgo build tag, runtime.go is excluded, which means its init() function is not executed. As a result, debugStack is defined here but never registered with RegisterExternal. Additionally, CallerFrames is an exported method on Frame (defined in context.go), and excluding it entirely under llgo breaks API compatibility for downstream consumers.

To fix these issues, we should:

  1. Add an init() function to register debugStack.
  2. Implement a stub for CallerFrames on Frame to maintain API compatibility.
Suggested change
import "runtime"
func runtimeGC(fr *frame) {
runtime.GC()
}
func debugStack(fr *frame) []byte {
return nil
}
import "runtime"
func init() {
RegisterExternal("runtime/debug.Stack", debugStack)
}
func runtimeGC(fr *frame) {
runtime.GC()
}
func debugStack(fr *frame) []byte {
return nil
}
func (fr *Frame) CallerFrames() (frames []runtime.Frame) {
return nil
}

@fennoai fennoai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FennoAI Review — PR #466 [WIP] llgo build

Non-blocking review (COMMENT). The PR partitions the package into !llgo / llgo build paths and bumps dependencies. The default (!llgo) build compiles cleanly and the CallerFrames() move is correct for that path. Since this is marked [WIP], most items below are expected gaps for the llgo target — the two highest-impact ones are the build-breaking go.mod/go.sum state and the missing init() registrations under llgo.

Blocking-for-merge (not for WIP)

  • go.modgithub.com/goplus/reflectx main is not a valid module version. The committed go.mod pins reflectx to the literal branch ref main, and go.sum contains no h1: content hash for the intended revision (only stale v1.7.0 entries). A default go build ./... (readonly mode) fails with "updates to go.mod needed; to update it: go mod tidy". Run go mod tidy and commit a proper tagged version or pseudo-version plus the matching go.sum hashes. (Confirmed by reproducing the readonly build failure.)

  • runtime_llgo.go — the init() external registrations from runtime.go are lost under llgo. runtime.go now carries //go:build !llgo, so under the llgo tag its entire init() is excluded and runtime_llgo.go provides no replacement. That init() registers interpreter-critical externals — most notably os.Exit (routes through interp.chexit so the interpreter returns an exit code) and runtime.Goexit (panic-based main-goroutine handling), plus runtime.Caller/Callers/FuncForPC/Stack, runtime/debug.Stack, runtime/debug.PrintStack, and the funcval-based (reflect.Value).Pointer override. Under llgo an interpreted os.Exit(N) would call the real os.Exit and hard-exit the host process without propagating the code. Either add an init() to runtime_llgo.go (at minimum os.Exit / runtime.Goexit) or document explicitly why these overrides are dropped for llgo.

Consistency / documentation

  • runtime_llgo.go has no license header. Every other file in the package root carries the GoPlus Authors Apache-2.0 block; the new file has none.
  • debugStack returns nil under llgo with no comment. It feeds PanicError.stack / FatalError.stack, so panic stacks are silently empty under llgo. Add a short comment explaining the intentional stub.
  • runtime.go:1 uses only //go:build !llgo while the rest of the repo (and the new runtime_llgo.go) pairs it with the legacy // +build line. Minor consistency nit; go 1.24 makes the legacy form optional.

API-surface note (body-only)

  • (*Frame).CallerFrames() (runtime.go:401) is now defined only under !llgo. As an exported method on the exported Frame alias, external callers building with -tags llgo will hit a compile error. If dropping it under llgo is intentional, note it; otherwise add a stub to runtime_llgo.go.
  • go.sum still retains the orphan reflectx v1.7.0 hash entries, indicating go mod tidy was not fully run — worth cleaning up alongside the go.mod fix above.

Performance: no regressions — the change is additive/build-tag partitioning; the llgo runtimeGC path is strictly cheaper (it skips the frame-walk), which is an acceptable trade-off.

Comment thread go.mod
github.com/goplus/gogen v1.23.3
github.com/goplus/mod v0.20.2
github.com/goplus/reflectx v1.7.0
github.com/goplus/reflectx v1.7.1-0.20260701065815-36c179f3d48f

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Invalid module version: the committed go.mod pins github.com/goplus/reflectx to the literal branch ref main, which is not a valid version. Combined with a go.sum that lacks the h1: content hash for the intended revision, a default go build ./... fails in readonly mode with "updates to go.mod needed; to update it: go mod tidy". Run go mod tidy and commit a tagged version (or a full pseudo-version) with matching go.sum hashes.

Comment thread runtime.go
@@ -1,3 +1,5 @@
//go:build !llgo

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding //go:build !llgo here excludes the entire file — including its init() — under the llgo tag. That init() registers interpreter-critical externals (os.Exit via interp.chexit, runtime.Goexit, runtime.Caller/Callers/FuncForPC/Stack, runtime/debug.Stack/PrintStack, and the funcval (reflect.Value).Pointer override) that are NOT re-provided by runtime_llgo.go. Under llgo, an interpreted os.Exit(N) would call the real os.Exit and hard-exit the host without returning an exit code. Add a replacement init() in runtime_llgo.go (at least os.Exit/runtime.Goexit) or document why these are intentionally dropped.

Minor: the rest of the repo pairs this with the legacy // +build !llgo line for consistency.

Comment thread runtime_llgo.go
//go:build llgo
// +build llgo

package ixgo

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing license header: every other file in the package root carries the GoPlus Authors Apache-2.0 copyright block; this new file has none. Add it for consistency.

Comment thread runtime_llgo.go
runtime.GC()
}

func debugStack(fr *frame) []byte {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

debugStack silently returns nil under llgo. Its result is stored in PanicError.stack/FatalError.stack (see builtin.go, opblock.go, interp.go), so panic/fatal stack traces will be empty under llgo. Acceptable as a known limitation, but add a brief comment stating that stack introspection is unsupported under llgo and the empty result is intentional.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant