From a111b865ad924de6ba2938ef127d2be0733d9bb6 Mon Sep 17 00:00:00 2001 From: ZhouGuangyuan Date: Tue, 31 Mar 2026 21:02:32 +0800 Subject: [PATCH] llvm: expose target machine section options --- TargetBindings.cpp | 50 +++++++++++++++++++++++++++++++++++++++++ TargetBindings.h | 33 ++++++++++++++++++++++++++++ target.go | 49 +++++++++++++++++++++++++++++++++++++++++ target_test.go | 55 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 187 insertions(+) create mode 100644 TargetBindings.cpp create mode 100644 TargetBindings.h create mode 100644 target_test.go diff --git a/TargetBindings.cpp b/TargetBindings.cpp new file mode 100644 index 0000000..81c42c2 --- /dev/null +++ b/TargetBindings.cpp @@ -0,0 +1,50 @@ +//===- TargetBindings.cpp - Additional bindings for target ---------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "TargetBindings.h" + +#include "llvm/Support/CBindingWrapping.h" +#include "llvm/Target/TargetMachine.h" + +using namespace llvm; + +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef) + +LLVMTargetMachineRef LLVMGoCreateTargetMachineWithOptions( + LLVMTargetRef T, const char *Triple, const char *CPU, + const char *Features, LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc, + LLVMCodeModel CodeModel, + LLVMBool FunctionSections, LLVMBool DataSections, + LLVMBool UniqueSectionNames) { + LLVMTargetMachineRef TM = + LLVMCreateTargetMachine(T, Triple, CPU, Features, Level, Reloc, + CodeModel); + if (!TM) + return nullptr; + + TargetMachine *Machine = unwrap(TM); + Machine->Options.FunctionSections = !!FunctionSections; + Machine->Options.DataSections = !!DataSections; + Machine->Options.UniqueSectionNames = !!UniqueSectionNames; + return TM; +} + +LLVMBool LLVMGoTargetMachineFunctionSections(LLVMTargetMachineRef TM) { + TargetMachine *Machine = unwrap(TM); + return Machine && Machine->Options.FunctionSections; +} + +LLVMBool LLVMGoTargetMachineDataSections(LLVMTargetMachineRef TM) { + TargetMachine *Machine = unwrap(TM); + return Machine && Machine->Options.DataSections; +} + +LLVMBool LLVMGoTargetMachineUniqueSectionNames(LLVMTargetMachineRef TM) { + TargetMachine *Machine = unwrap(TM); + return Machine && Machine->Options.UniqueSectionNames; +} diff --git a/TargetBindings.h b/TargetBindings.h new file mode 100644 index 0000000..d6d1fb5 --- /dev/null +++ b/TargetBindings.h @@ -0,0 +1,33 @@ +//===- TargetBindings.h - Additional bindings for target --------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BINDINGS_GO_LLVM_TARGETBINDINGS_H +#define LLVM_BINDINGS_GO_LLVM_TARGETBINDINGS_H + +#include "llvm-c/Target.h" +#include "llvm-c/TargetMachine.h" + +#ifdef __cplusplus +extern "C" { +#endif + +LLVMTargetMachineRef LLVMGoCreateTargetMachineWithOptions( + LLVMTargetRef T, const char *Triple, const char *CPU, + const char *Features, LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc, + LLVMCodeModel CodeModel, + LLVMBool FunctionSections, LLVMBool DataSections, + LLVMBool UniqueSectionNames); +LLVMBool LLVMGoTargetMachineFunctionSections(LLVMTargetMachineRef TM); +LLVMBool LLVMGoTargetMachineDataSections(LLVMTargetMachineRef TM); +LLVMBool LLVMGoTargetMachineUniqueSectionNames(LLVMTargetMachineRef TM); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/target.go b/target.go index 5075d14..6ef8753 100644 --- a/target.go +++ b/target.go @@ -16,6 +16,7 @@ package llvm #include "llvm-c/Core.h" #include "llvm-c/Target.h" #include "llvm-c/TargetMachine.h" +#include "TargetBindings.h" #include */ import "C" @@ -41,6 +42,17 @@ type ( CodeModel C.LLVMCodeModel ) +// TargetMachineOptions contains explicit llvm::TargetOptions flags exposed by +// CreateTargetMachineWithOptions. +type TargetMachineOptions struct { + // FunctionSections places each function in its own section. + FunctionSections bool + // DataSections places each data object in its own section. + DataSections bool + // UniqueSectionNames qualifies section names with symbol names. + UniqueSectionNames bool +} + const ( BigEndian ByteOrdering = C.LLVMBigEndian LittleEndian ByteOrdering = C.LLVMLittleEndian @@ -256,6 +268,43 @@ func (t Target) CreateTargetMachine(Triple string, CPU string, Features string, return } +// CreateTargetMachineWithOptions creates a new TargetMachine with explicit +// llvm::TargetOptions flags that are not exposed by the LLVM C API. +// Use CreateTargetMachine if you do not need to override TargetOptions fields +// that are absent from the LLVM C API. +func (t Target) CreateTargetMachineWithOptions(Triple string, CPU string, Features string, + Level CodeGenOptLevel, Reloc RelocMode, + CodeModel CodeModel, opts TargetMachineOptions) (tm TargetMachine) { + cTriple := C.CString(Triple) + defer C.free(unsafe.Pointer(cTriple)) + cCPU := C.CString(CPU) + defer C.free(unsafe.Pointer(cCPU)) + cFeatures := C.CString(Features) + defer C.free(unsafe.Pointer(cFeatures)) + + tm.C = C.LLVMGoCreateTargetMachineWithOptions( + t.C, + cTriple, + cCPU, + cFeatures, + C.LLVMCodeGenOptLevel(Level), + C.LLVMRelocMode(Reloc), + C.LLVMCodeModel(CodeModel), + boolToLLVMBool(opts.FunctionSections), + boolToLLVMBool(opts.DataSections), + boolToLLVMBool(opts.UniqueSectionNames), + ) + return +} + +func (tm TargetMachine) sectionOptions() TargetMachineOptions { + return TargetMachineOptions{ + FunctionSections: C.LLVMGoTargetMachineFunctionSections(tm.C) != 0, + DataSections: C.LLVMGoTargetMachineDataSections(tm.C) != 0, + UniqueSectionNames: C.LLVMGoTargetMachineUniqueSectionNames(tm.C) != 0, + } +} + // CreateTargetData returns a new TargetData describing the TargetMachine's // data layout. The returned TargetData is owned by the caller, who is // responsible for disposing of it by calling the TargetData.Dispose method. diff --git a/target_test.go b/target_test.go new file mode 100644 index 0000000..f03a73a --- /dev/null +++ b/target_test.go @@ -0,0 +1,55 @@ +//===- target_test.go - Tests for target bindings -------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +package llvm + +import "testing" + +func TestCreateTargetMachineWithOptionsSectionOptions(t *testing.T) { + InitializeNativeTarget() + + triple := DefaultTargetTriple() + target, err := GetTargetFromTriple(triple) + if err != nil { + t.Fatal(err) + } + + tests := []struct { + name string + opts TargetMachineOptions + }{ + { + name: "zero value", + opts: TargetMachineOptions{}, + }, + { + name: "mixed flags", + opts: TargetMachineOptions{ + FunctionSections: true, + DataSections: false, + UniqueSectionNames: true, + }, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + tm := target.CreateTargetMachineWithOptions( + triple, "", "", CodeGenLevelDefault, RelocDefault, CodeModelDefault, tc.opts, + ) + if tm.C == nil { + t.Fatal("CreateTargetMachineWithOptions returned a nil target machine") + } + defer tm.Dispose() + + if got := tm.sectionOptions(); got != tc.opts { + t.Fatalf("section options mismatch: got %+v, want %+v", got, tc.opts) + } + }) + } +}