Skip to content

Conversation

@luoliwoshang
Copy link
Member

@luoliwoshang luoliwoshang commented Jan 8, 2026

Summary

Remove conflicting _exit implementations to enable semihosting support for ESP32-C3 QEMU emulator.

Background

Previously, multiple _exit implementations existed in newlib:

  • libnosys/_exit.c - stub implementation
  • libgloss/riscv/sys_exit.c - another stub
  • syscalls.c - uses asm("unimp") which crashes in QEMU
  • semihost-sys_exit.c - proper semihosting implementation using ebreak

The syscalls.c version was being linked, causing QEMU to crash with "Illegal instruction".

Solution

After goplus/newlib#10 separates _exit from syscalls.c, we can simply remove the other stub implementations (libnosys/_exit.c and libgloss/riscv/sys_exit.c). This leaves semihost-sys_exit.c as the only _exit implementation, which will be automatically used from the existing .a library.

Changes

Remove conflicting _exit implementations from compile list:

  • libnosys/_exit.c
  • libgloss/riscv/sys_exit.c (3 occurrences in different compile groups)

Result

Now ESP32-C3 programs properly use semihosting _exit and exit cleanly in QEMU with -semihosting flag.

Depends on

Test plan

  • Build ESP32-C3 target
  • Run in QEMU emulator with -semihosting flag
  • Verify program exits cleanly using semihosting

🤖 Generated with Claude Code

@gemini-code-assist
Copy link

Summary of Changes

Hello @luoliwoshang, 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 addresses an issue where the ESP32-C3 QEMU emulator was not correctly utilizing the semihosting _exit function due to conflicting implementations. By strategically commenting out redundant _exit definitions within the build configuration, this change ensures that the intended semihosting _exit is consistently invoked, leading to proper program termination in the QEMU environment.

Highlights

  • Conflicting _exit implementations resolved: This PR resolves conflicts among multiple _exit implementations by commenting out libnosys/_exit.c and libgloss/riscv/sys_exit.c from the build process. This ensures that the correct semihosting _exit is used for ESP32-C3 QEMU emulation.
  • Improved ESP32-C3 QEMU support: By ensuring the semihosting _exit is used, ESP32-C3 programs now properly terminate in the QEMU emulator with an expected ebreak instruction, leading to clean exits.

🧠 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.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

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.

Copy link

@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 correctly addresses the conflicting _exit symbol implementations for ESP32-C3 QEMU support by commenting out the stub versions from the build configuration. The changes are logical and well-explained in the description. I've added one comment regarding code duplication in the file list, which could be addressed to improve maintainability.

@xgopilot
Copy link

xgopilot bot commented Jan 8, 2026

Code Review Summary

The PR correctly addresses the immediate issue of conflicting _exit implementations for ESP32-C3 QEMU semihosting support. However, the review identified critical pre-existing code quality issues that should be addressed:

Critical Issues Found:

  • Massive code duplication: 33 files duplicated at lines 262-294, plus 11 files appearing a third time at lines 296-306
  • Missing inline documentation: Commented-out lines lack explanatory comments for future maintainers

Recommendation:

  • ✅ This PR can be merged to fix the immediate semihosting conflict
  • ⚠️ Follow-up PR needed to remove duplicated file entries and add documentation

See inline comments for specific details.

@codecov
Copy link

codecov bot commented Jan 8, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.01%. Comparing base (f6337d4) to head (c45489f).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1539      +/-   ##
==========================================
- Coverage   91.01%   91.01%   -0.01%     
==========================================
  Files          45       45              
  Lines       11971    11966       -5     
==========================================
- Hits        10896    10891       -5     
  Misses        899      899              
  Partials      176      176              

☔ 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.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

luoliwoshang added a commit to luoliwoshang/goplus-newlib that referenced this pull request Jan 8, 2026
Move _exit implementation from syscalls.c to syscalls_exit.c to allow
easy replacement with semihosting version for QEMU emulator support.

This separation enables llgo to compile the semihosting _exit as a
separate object file that can override the default implementation
when building for QEMU targets.

Related to: goplus/llgo#1539

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
MeteorsLiu pushed a commit to goplus/newlib that referenced this pull request Jan 9, 2026
Move _exit implementation from syscalls.c to syscalls_exit.c to allow
easy replacement with semihosting version for QEMU emulator support.

This separation enables llgo to compile the semihosting _exit as a
separate object file that can override the default implementation
when building for QEMU targets.

Related to: goplus/llgo#1539

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <[email protected]>
@luoliwoshang luoliwoshang force-pushed the esp32c3/exitsemi branch 2 times, most recently from 487d0dd to 22bc753 Compare January 9, 2026 02:43
Comment on lines -263 to -277
filepath.Join(baseDir, "libgloss", "riscv", "semihost-sys_close.c"),
filepath.Join(baseDir, "libgloss", "riscv", "semihost-sys_exit.c"),
filepath.Join(baseDir, "libgloss", "riscv", "semihost-sys_fdtable.c"),
filepath.Join(baseDir, "libgloss", "riscv", "semihost-sys_fstat.c"),
filepath.Join(baseDir, "libgloss", "riscv", "semihost-sys_ftime.c"),
filepath.Join(baseDir, "libgloss", "riscv", "semihost-sys_isatty.c"),
filepath.Join(baseDir, "libgloss", "riscv", "semihost-sys_link.c"),
filepath.Join(baseDir, "libgloss", "riscv", "semihost-sys_lseek.c"),
filepath.Join(baseDir, "libgloss", "riscv", "semihost-sys_open.c"),
filepath.Join(baseDir, "libgloss", "riscv", "semihost-sys_read.c"),
filepath.Join(baseDir, "libgloss", "riscv", "semihost-sys_sbrk.c"),
filepath.Join(baseDir, "libgloss", "riscv", "semihost-sys_stat.c"),
filepath.Join(baseDir, "libgloss", "riscv", "semihost-sys_stat_common.c"),
filepath.Join(baseDir, "libgloss", "riscv", "semihost-sys_unlink.c"),
filepath.Join(baseDir, "libgloss", "riscv", "semihost-sys_write.c"),
Copy link
Member Author

Choose a reason for hiding this comment

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

it's reduant file,actually we not connect symbol from these files.

Copy link
Member Author

Choose a reason for hiding this comment

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

@xgopilot it's a not a expect diff , make it have not diff of main branch!

Copy link

@xgopilot xgopilot bot Jan 14, 2026

Choose a reason for hiding this comment

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

Fixed Whitespace Issue ✓

Changes completed:

  • Read comment history to understand the issue
  • Compare current branch with main branch
  • Identify unexpected differences
  • Fix the whitespace issue in esp32-riscv.app.elf.ld
  • Commit changes locally

What I Fixed

The targets/esp32-riscv.app.elf.ld file had an unintended whitespace change on line 25:

  • Before: .rodata : (4 spaces)
  • After: .rodata : (1 space)

This formatting change was unrelated to the PR's purpose (semihosting _exit support). I've reverted it, and the file now matches the main branch exactly.

Permission Required

Hi @luoliwoshang! I've prepared your changes locally but need permission to push to your fork.

View Details & Solution

Target: luoliwoshang/llgo (fork)

Push blocked:

remote: Invalid username or token. Password authentication is not supported for Git operations.
fatal: Authentication failed for 'https://github.com/luoliwoshang/llgo.git/'

Alternative: Manual Push

Since you own the fork, you can pull and push the changes yourself:

# Fetch the changes from the main repo
git fetch origin

# Cherry-pick my commit
git cherry-pick b3ee8066

# Or apply the simple fix directly
# In targets/esp32-riscv.app.elf.ld line 25, change:
#   .rodata :
# To:
#   .rodata    :
# (add 3 more spaces after .rodata)

# Then push
git push origin esp32c3/exitsemi

Copy link
Member Author

Choose a reason for hiding this comment

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

@xgopilot now you can create the fork pr to me ! just do it!

Copy link

@xgopilot xgopilot bot Jan 15, 2026

Choose a reason for hiding this comment

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

Fork PR Created Successfully ✓

  • Check current branch and changes
  • Fix whitespace issue in esp32-riscv.app.elf.ld
  • Commit and push changes to fork
  • Create PR back to your repository

What I Did

I've successfully created a fork PR back to your repository! Here's what was completed:

  1. Fixed the whitespace issue in targets/esp32-riscv.app.elf.ld line 25:

    • Changed .rodata : (1 space) → .rodata : (4 spaces)
    • This matches the formatting in the main branch
  2. Committed the change with proper attribution

  3. Pushed to your fork at luoliwoshang/llgo

  4. Created PR sqlite demo #182: fix(esp32c3): restore whitespace in linker script to match main

    • Source: fork-pr-1539-1768440281
    • Target: esp32c3/exitsemi

Next Steps

You can now review and merge PR #182 in your fork repository to incorporate this whitespace fix into your esp32c3/exitsemi branch.

luoliwoshang and others added 14 commits January 15, 2026 16:06
ESP32-C3 bootloader starts at flash offset 0x0, unlike ESP32 which
starts at 0x1000. The previous code added 4KB padding for all ESP
chips, causing QEMU to fail with "invalid header: 0x00000000" when
trying to boot ESP32-C3 images.

This fix only adds the 4KB padding for ESP32 (Xtensa), while ESP32-C3
(RISC-V) images now start at offset 0x0 as expected by its ROM
bootloader.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Add emulator command configuration to esp32c3.json target file,
enabling ESP32-C3 programs to run in QEMU emulator with:
  llgo run -target=esp32c3 -emulator .

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Add missing newlines at end of esp32c3.json and esp32c3-basic.json
to follow standard file formatting conventions.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
    Remove conflicting _exit implementations from libnosys and libgloss to
    ensure the semihosting version (from semihost-sys_exit.c, added as .o
    in goplus#1537) is used for ESP32-C3 QEMU emulator.

    Changes:
    - Comment out libnosys/_exit.c
    - Comment out libgloss/riscv/sys_exit.c (3 occurrences)

    This allows proper exit handling in QEMU emulator via semihosting
    protocol instead of using the  instruction which causes crashes.

    Related: goplus#1537

    🤖 Generated with [Claude Code](https://claude.com/claude-code)

    Co-Authored-By: Claude Opus 4.5 <[email protected]>
Add -semihosting flag to QEMU command to enable proper program exit
using semihosting _exit implementation.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Update newlib version to patch5 which includes the split of _exit
from syscalls.c to syscalls_exit.c.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Remove libgloss/libnosys/_exit.c from RISC-V compile list to ensure
semihosting _exit is used for QEMU emulator support.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Update test script to use project directory for temp files
  (enables go.mod module resolution)
- Use real Hello World program in test instead of empty program
  (ensures .rodata has PROGBITS type for proper BIN generation)
- Remove duplicate semihost-sys_exit.c from RISC-V config
  (was causing conflict with custom _exit implementation)
- Fix whitespace in linker script

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Move semihost-sys_exit.c to its own library (libsemihost-{target}.a)
for cleaner separation of semihosting support from core startup code.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
These semihost syscall files are not actually used - only semihost-sys_exit.c
is needed for QEMU emulator support (now in separate libsemihost library).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Update libc_test.go to reflect the new 4-group structure for RISC-V:
- Group 0: libsemihost (semihosting _exit for QEMU)
- Group 1: libcrt0 (board startup)
- Group 2: libgloss (system stubs)
- Group 3: libc (C library)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Add comprehensive test framework for running embedded programs in QEMU emulator:

Architecture:
- Tests located in cl/_testemb/ (parallel to existing cl tests)
- Uses build.Do() directly (similar to build_test.go pattern)
- Auto-discovers test cases: any directory with main.go + expect.txt

Features:
- TestEmbRun runs all tests across multiple targets (ESP32C3, ESP32)
- filterEmulatorOutput() extracts program output after "entry 0x..." line
- Logs both filtered and full emulator output for debugging
- Test case structure:
  cl/_testemb/
  └── cprintf/
      ├── main.go     # Test program
      └── expect.txt  # Expected output

Usage:
  export PATH="/path/to/esp-qemu/bin:$PATH"
  go test ./cl -run TestEmbRun -v

Adding new tests: just create new directory with main.go + expect.txt

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Add workflow step to install ESP32 RISC-V QEMU emulator for running embedded tests.

Script features (.github/workflows/install-esp-qemu.sh):
- Accepts installation directory as argument (default: .cache/qemu)
- Auto-detects platform (OS + architecture)
- Downloads platform-specific QEMU from espressif/qemu releases (v9.2.2)
- Supports: macOS (x86_64/aarch64) and Linux (x86_64/aarch64)
- Downloads and extracts to specified directory
- Verifies qemu-system-riscv32 binary exists after installation

CI integration (go.yml):
- Installs QEMU to .cache/qemu before running tests
- Adds QEMU bin directory to PATH for subsequent steps
- Verifies installation with version check
- Required for cl/embed_test.go emulator tests

Verified file structure:
.cache/qemu/
└── bin/
    └── qemu-system-riscv32

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
luoliwoshang and others added 13 commits January 15, 2026 16:06
ESP32 QEMU requires libSDL2-2.0.so.0 shared library on Linux.

Error without SDL2:
  qemu-system-riscv32: error while loading shared libraries:
  libSDL2-2.0.so.0: cannot open shared object file: No such file or directory

Solution:
- Add libsdl2-2.0-0 to Ubuntu common dependencies
- macOS already has SDL2 bundled with QEMU or available via brew

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
1. Add SDL2 dependency for macOS
   - ESP32 QEMU requires libSDL2-2.0.0.dylib on macOS
   - Error: Library not loaded: /opt/homebrew/opt/sdl2/lib/libSDL2-2.0.0.dylib
   - Solution: brew install sdl2

2. Remove ESP32 (Xtensa) test from embed_test.go
   - Only keep ESP32C3 (RISC-V) test
   - ESP32 Xtensa QEMU requires separate setup

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Replace t.Logf() with fmt.Printf() to always show test output regardless of -v flag.

Benefits:
- CI logs always show program output even without go test -v
- Easier debugging when tests fail
- Consistent visibility in all environments

Output format:
=== Test Output for <test_name> ===
Program output:
<filtered output>
Full emulator output:
<complete emulator log>
========================

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Restore temporarily deleted workflow files:
- build-cache.yml
- doc-link-checker.yml
- doc.yml
- fmt.yml
- llgo.yml
- release-build.yml
- stdlib-coverage.yml
- targets.yml

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Add //go:build !llgo and // +build !llgo tags to embed_test.go
to prevent it from being compiled by llgo itself.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Drop cl/_testemb harness and embed_test.go since the emulator test flow is being replaced.

Extend _demo/embed/test_esp32c3_startup.sh to run QEMU and assert the final output line, printing full logs on mismatch.

Co-authored-by: Codex <[email protected]>
Introduce setup-embed-deps to install SDL2 runtime requirements for QEMU.

Use it in go.yml and llgo.yml before embedded tests.
Move ESP32 RISC-V QEMU install/verify steps into setup-embed-deps.

Use setup-embed-deps only in llgo.yml's llgo job and remove duplicate steps from go.yml.
Embed QEMU dependencies now live in setup-embed-deps.
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