Skip to content

llvm: expose target machine section options#38

Merged
xushiwei merged 1 commit intoxgo-dev:goplusfrom
zhouguangyuan0718:targetoptions-shim
Apr 19, 2026
Merged

llvm: expose target machine section options#38
xushiwei merged 1 commit intoxgo-dev:goplusfrom
zhouguangyuan0718:targetoptions-shim

Conversation

@zhouguangyuan0718
Copy link
Copy Markdown

Summary

  • expose section-related target machine options through TargetMachineOptions
  • add a target binding to pass function/data section flags and unique section names into TargetOptions
  • keep CreateTargetMachine behavior unchanged and add CreateTargetMachineWithOptions for explicit section configuration

Testing

  • go test ./...

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 introduces LLVMGoCreateTargetMachineWithOptions to the Go LLVM bindings, enabling configuration of TargetOptions like function and data sections. The review identifies critical compilation issues where parameter names shadow LLVM namespaces and suggests using idiomatic wrap and unwrap helpers instead of reinterpret_cast for safer and more consistent C-binding management.

Comment thread TargetBindings.cpp Outdated
Comment on lines +20 to +21
static std::optional<Reloc::Model> mapRelocMode(LLVMRelocMode Reloc) {
switch (Reloc) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

critical

The parameter name Reloc shadows the llvm::Reloc namespace, which will cause a compilation error when trying to access Reloc::Model or Reloc::Static. Rename the parameter to RelocMode to avoid this conflict.

Suggested change
static std::optional<Reloc::Model> mapRelocMode(LLVMRelocMode Reloc) {
switch (Reloc) {
static std::optional<Reloc::Model> mapRelocMode(LLVMRelocMode RelocMode) {
switch (RelocMode) {

Comment thread TargetBindings.cpp Outdated
Comment thread TargetBindings.cpp Outdated
Comment thread TargetBindings.cpp Outdated
Comment on lines +77 to +79
const Target *TheTarget = reinterpret_cast<const Target *>(T);
if (TheTarget == nullptr)
return nullptr;
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

Use the idiomatic unwrap function provided by llvm/Support/CBindingWrapping.h instead of reinterpret_cast. It is also safer to check the input pointer T for null before unwrapping.

Suggested change
const Target *TheTarget = reinterpret_cast<const Target *>(T);
if (TheTarget == nullptr)
return nullptr;
if (!T)
return nullptr;
const Target *TheTarget = unwrap(T);

Comment thread TargetBindings.cpp Outdated
Comment thread TargetBindings.cpp Outdated
Copy link
Copy Markdown

@fennoai fennoai Bot left a comment

Choose a reason for hiding this comment

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

Overall this is a clean, focused addition. The Go wrapper follows the existing patterns correctly (paired C.CString/defer C.free, boolToLLVMBool, named-return style). A few issues worth addressing before merge:

Comment thread TargetBindings.cpp Outdated
TargetOptions Options;
Options.FunctionSections = FunctionSections;
Options.DataSections = DataSections;
Options.UniqueSectionNames = UniqueSectionNames;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Null-check ordering / wasted work on error path

TargetOptions is fully constructed and its three fields written (lines 72–75) before the null-check on T (lines 77–79). TargetOptions default-constructs a non-trivial object (initialises ~30 fields in LLVM 18+). Move the null-check — and the reinterpret_cast — above the TargetOptions construction so the object is never allocated on the error path:

const Target *TheTarget = reinterpret_cast<const Target *>(T);
if (TheTarget == nullptr)
  return nullptr;

TargetOptions Options;
Options.FunctionSections = FunctionSections;
Options.DataSections = DataSections;
Options.UniqueSectionNames = UniqueSectionNames;

Comment thread TargetBindings.cpp Outdated
LLVMBool FunctionSections, LLVMBool DataSections,
LLVMBool UniqueSectionNames) {
TargetOptions Options;
Options.FunctionSections = FunctionSections;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

LLVMBool → bit-field assignment: consider normalising to 0/1 in C

LLVMBool is typedef int. TargetOptions::FunctionSections (and the other two) are bool / 1-bit unsigned fields depending on LLVM version. The Go caller always goes through boolToLLVMBool, which guarantees 0 or 1, so this is safe today. However, the C function itself accepts any int; a direct C/C++ caller passing 2 would silently produce 0 for a 1-bit field.

Consider normalising at the C layer to make the function defensively correct on its own:

Options.FunctionSections  = !!FunctionSections;
Options.DataSections      = !!DataSections;
Options.UniqueSectionNames = !!UniqueSectionNames;

Comment thread TargetBindings.cpp Outdated
return CodeModel::Large;
case LLVMCodeModelDefault:
case LLVMCodeModelJITDefault:
default:
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

LLVMCodeModelJITDefault silently treated as "no code model"

Both LLVMCodeModelDefault and LLVMCodeModelJITDefault return std::nullopt, giving LLVM its default code model. That is the same behaviour as the existing CreateTargetMachine, so it is not a regression — but the silent equivalence of a JIT-specific enum value is non-obvious. A brief inline comment here (and ideally a note in the Go doc comment) would prevent confusion:

case LLVMCodeModelJITDefault:
  // JIT-specific model; let LLVM pick the target default, same as LLVMCodeModelDefault
  return std::nullopt;

Comment thread target.go
Comment thread target.go
return
}

// CreateTargetMachineWithOptions creates a new TargetMachine with explicit
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Doc comment slightly misleading

"Use CreateTargetMachine if you want LLVM's built-in default TargetOptions" implies the two functions differ in who supplies the defaults. The real distinction is that the options exposed here (FunctionSections, DataSections, UniqueSectionNames) are absent from the stable LLVM C API. A clearer phrasing:

Use CreateTargetMachine if you do not need to override TargetOptions fields that are absent from the LLVM C API.

@xushiwei xushiwei merged commit b74f094 into xgo-dev:goplus Apr 19, 2026
32 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.

2 participants