Skip to content

test: cover arm64 stdlib sysreg cross-target paths#12

Merged
cpunion merged 2 commits intoxgo-dev:mainfrom
cpunion:fix/arm64-sysreg-mrs-msr
Mar 23, 2026
Merged

test: cover arm64 stdlib sysreg cross-target paths#12
cpunion merged 2 commits intoxgo-dev:mainfrom
cpunion:fix/arm64-sysreg-mrs-msr

Conversation

@cpunion
Copy link
Copy Markdown
Collaborator

@cpunion cpunion commented Mar 23, 2026

Summary

  • run the arm64 stdlib runtime/sys and cpu compile tests as true cross-target aarch64 checks instead of skipping on non-arm64 hosts
  • add a TranslateGoModule regression for internal/runtime/sys/dit_arm64.s, which is the public entry llgo actually calls
  • keep the checks toolchain-aware by skipping when llc lacks the requested target

Why previous tests missed this

  • TestStdlibInternalRuntimeSys_ARM64_Compile and TestStdlibInternalCPU_ARM64_Compile only ran when runtime.GOARCH == "arm64"
  • the runtime/sys coverage only exercised low-level Translate, while llgo hits TranslateGoModule
  • that left the amd64-host -> arm64-target path effectively untested, even though that is where llgo exposed the dit_arm64.s regression

Validation

  • go test -run 'TestStdlibInternal(RuntimeSys|CPU)_ARM64_Compile|TestTranslateGoModule_StdlibInternalRuntimeSys_ARM64_Compile' ./...
  • go test ./...

@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the testing infrastructure for arm64 cross-compilation within the stdlib by allowing relevant tests to execute on any host architecture. It specifically addresses a gap in coverage for the TranslateGoModule path, which was previously untested for amd64-host to arm64-target scenarios, ensuring better detection of regressions in internal/runtime/sys/dit_arm64.s. The changes also make these tests more resilient by gracefully skipping when the llc compiler lacks support for the aarch64 target.

Highlights

  • Cross-Target Testing: Enabled cross-target testing for arm64 stdlib components (runtime/sys and cpu) on non-arm64 hosts, removing previous host architecture restrictions.
  • TranslateGoModule Coverage: Introduced a new regression test for TranslateGoModule specifically targeting internal/runtime/sys/dit_arm64.s, addressing a previous gap in testing for this critical path.
  • Toolchain Awareness: Improved test robustness by adding checks to skip tests gracefully when the llc toolchain does not support the specified aarch64 target triple.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 23, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 69.48%. Comparing base (7f506d4) to head (a7e4d58).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main      #12   +/-   ##
=======================================
  Coverage   69.48%   69.48%           
=======================================
  Files          57       57           
  Lines       16380    16380           
=======================================
  Hits        11382    11382           
  Misses       3683     3683           
  Partials     1315     1315           
Flag Coverage Δ
unittests 69.48% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown

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

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 updates the arm64 stdlib tests for runtime/sys and cpu to support cross-target compilation, which is a great improvement for testing. It also adds a new regression test for TranslateGoModule. The changes are well-aligned with the goal of improving test coverage for cross-compilation paths. My main feedback is to refactor duplicated code in the test functions to improve maintainability.

Comment thread stdlib_runtime_sys_arm64_test.go Outdated
Comment on lines +120 to +134
tmp := t.TempDir()
llPath := filepath.Join(tmp, "dit-gomod.ll")
objPath := filepath.Join(tmp, "dit-gomod.o")
if err := os.WriteFile(llPath, []byte(tr.Module.String()), 0644); err != nil {
t.Fatal(err)
}
cmd := exec.Command(llc, "-mtriple="+triple, "-filetype=obj", llPath, "-o", objPath)
out, err := cmd.CombinedOutput()
if err != nil {
s := string(out)
if llcUnsupportedTarget(s) {
t.Skipf("llc does not support triple %q: %s", triple, strings.TrimSpace(s))
}
t.Fatalf("llc failed: %v\n%s", err, s)
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

There's significant code duplication for compiling the generated LLVM IR. The logic for creating a temporary directory, writing the .ll file, executing llc, and handling errors is repeated in TestStdlibInternalRuntimeSys_ARM64_Compile, TestTranslateGoModule_StdlibInternalRuntimeSys_ARM64_Compile, and also in TestStdlibInternalCPU_ARM64_Compile in stdlib_cpu_arm64_test.go.

To improve maintainability and reduce redundancy, you could extract this logic into a shared helper function. For example:

func compileAndCheck(t *testing.T, llc, triple, llContent, name string) {
	t.Helper()
	tmp := t.TempDir()
	llPath := filepath.Join(tmp, name+".ll")
	objPath := filepath.Join(tmp, name+".o")
	if err := os.WriteFile(llPath, []byte(llContent), 0644); err != nil {
		t.Fatal(err)
	}
	cmd := exec.Command(llc, "-mtriple="+triple, "-filetype=obj", llPath, "-o", objPath)
	out, err := cmd.CombinedOutput()
	if err != nil {
		s := string(out)
		if llcUnsupportedTarget(s) {
			t.Skipf("llc does not support triple %q: %s", triple, strings.TrimSpace(s))
		}
		t.Fatalf("llc failed: %v\n%s", err, s)
	}
}

You could add this helper to stdlib_runtime_sys_arm64_test.go and then call it from the test functions like this:

In TestStdlibInternalRuntimeSys_ARM64_Compile:
compileAndCheck(t, llc, triple, ll, "dit")

In TestTranslateGoModule_StdlibInternalRuntimeSys_ARM64_Compile:
compileAndCheck(t, llc, triple, tr.Module.String(), "dit-gomod")

This would make the tests cleaner and easier to maintain.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Addressed in a7e4d58. I factored the repeated llc/object-build path into compileLLVMToObject in stdlib_arm64_test_helpers_test.go, and both runtime/sys tests plus TestStdlibInternalCPU_ARM64_Compile now call the shared helper. Re-ran the targeted arm64 tests and go test ./... after the refactor.

Comment thread stdlib_cpu_arm64_test.go
goroot := testGOROOT(t)
src, err := os.ReadFile(filepath.Join(goroot, "src", "internal", "cpu", "cpu_arm64.s"))
if err != nil {
t.Fatal(err)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Both TestStdlibInternalRuntimeSys_ARM64_Compile and TestTranslateGoModule_StdlibInternalRuntimeSys_ARM64_Compile (added in this same PR) guard os.ReadFile errors with an os.IsNotExist check and skip gracefully when the file is absent from the GOROOT. This test does not — a stripped or non-standard GOROOT that lacks cpu_arm64.s will hard-fail here rather than skip.

Suggested change
t.Fatal(err)
src, err := os.ReadFile(filepath.Join(goroot, "src", "internal", "cpu", "cpu_arm64.s"))
if err != nil {
if os.IsNotExist(err) {
t.Skip("internal/cpu/cpu_arm64.s not present in this GOROOT")
}
t.Fatal(err)
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Addressed in a7e4d58. TestStdlibInternalCPU_ARM64_Compile now mirrors the runtime/sys tests and skips cleanly on os.IsNotExist(err) for internal/cpu/cpu_arm64.s.

Comment thread stdlib_runtime_sys_arm64_test.go Outdated
}
}

func testGOROOT(t *testing.T) string {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

testGOROOT and testGoEnv are defined here but are also called from stdlib_cpu_arm64_test.go. Every other cross-file test helper in this repo (mustGoPackage, testResolveSym, findLlcAndClang, etc.) lives in a dedicated helper file. Placing these in stdlib_runtime_sys_arm64_test.go creates an implicit dependency: if this file is ever renamed or its build tag changes, the CPU test silently breaks. Consider moving them to a shared file like stdlib_helpers_test.go.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Addressed in a7e4d58. I moved testGOROOT / testGoEnv out of stdlib_runtime_sys_arm64_test.go into the new shared helper file stdlib_arm64_test_helpers_test.go, alongside the shared llc compile helper.

Comment thread stdlib_runtime_sys_arm64_test.go Outdated
return goroot
}

func testGoEnv(t *testing.T, key string) string {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

If the go binary is not on PATH (e.g. a minimal cross-compile container), exec.Command will error and t.Fatalf fires — the test hard-fails rather than skips. Meanwhile, the t.Skip("GOROOT not available") guard in testGOROOT (line 143) becomes unreachable, because testGoEnv either returns a non-empty string or stops the test via Fatalf before returning "".

Consider propagating the error to testGOROOT and converting it to a t.Skip there, so the intent of "skip when toolchain discovery fails" is actually reachable:

func testGoEnv(t *testing.T, key string) (string, error) {
    t.Helper()
    out, err := exec.Command("go", "env", key).CombinedOutput()
    if err != nil {
        return "", fmt.Errorf("go env %s: %w\n%s", key, err, out)
    }
    return strings.TrimSpace(string(out)), nil
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Addressed in a7e4d58. testGoEnv now returns (string, error) instead of calling t.Fatalf, and testGOROOT turns toolchain-discovery failure into a skip. That makes the GOROOT not available path reachable on minimal environments where go is missing from PATH.

@fennoai
Copy link
Copy Markdown

fennoai Bot commented Mar 23, 2026

Good change overall — removing the host-arch guard and hardcoding the cross-compile triple is the right approach, and the graceful llcUnsupportedTarget skip pattern is consistent with the rest of the codebase. Three minor issues worth addressing: (1) stdlib_cpu_arm64_test.go lacks the os.IsNotExist skip that the two new runtime/sys tests have; (2) testGOROOT/testGoEnv are cross-file helpers living in a single-concern file; (3) testGoEnv's error path calls t.Fatalf, making the t.Skip("GOROOT not available") guard in testGOROOT unreachable.

@cpunion
Copy link
Copy Markdown
Collaborator Author

cpunion commented Mar 23, 2026

Addressed the review feedback in a7e4d58:

  • added the missing os.IsNotExist skip for internal/cpu/cpu_arm64.s
  • moved testGOROOT / testGoEnv into a shared arm64 stdlib test helper file
  • changed testGoEnv to return an error instead of calling t.Fatalf, so testGOROOT can cleanly skip when GOROOT is unavailable
  • also factored the repeated llc compile step into compileLLVMToObject to reduce duplication

Re-verified with:

  • go test -run 'TestStdlibInternal(RuntimeSys|CPU)_ARM64_Compile|TestTranslateGoModule_StdlibInternalRuntimeSys_ARM64_Compile' ./...\n- go test ./...

@cpunion cpunion merged commit 33e8ba1 into xgo-dev:main Mar 23, 2026
28 checks passed
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