Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions TargetBindings.cpp
Original file line number Diff line number Diff line change
@@ -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;
}
33 changes: 33 additions & 0 deletions TargetBindings.h
Original file line number Diff line number Diff line change
@@ -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
49 changes: 49 additions & 0 deletions target.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 <stdlib.h>
*/
import "C"
Expand All @@ -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
}
Comment thread
xushiwei marked this conversation as resolved.

const (
BigEndian ByteOrdering = C.LLVMBigEndian
LittleEndian ByteOrdering = C.LLVMLittleEndian
Expand Down Expand Up @@ -256,6 +268,43 @@ func (t Target) CreateTargetMachine(Triple string, CPU string, Features string,
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.

// 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.
Expand Down
55 changes: 55 additions & 0 deletions target_test.go
Original file line number Diff line number Diff line change
@@ -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)
}
})
}
}
Loading