Skip to content

Commit 5870829

Browse files
committed
[clang] Pass target-features to clang-linker-wrapper
1 parent 4eea157 commit 5870829

File tree

4 files changed

+117
-4
lines changed

4 files changed

+117
-4
lines changed

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9171,6 +9171,32 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA,
91719171
CmdArgs.push_back(
91729172
Args.MakeArgString("--host-triple=" + getToolChain().getTripleString()));
91739173

9174+
const Driver &D = getToolChain().getDriver();
9175+
const llvm::Triple TheTriple = getToolChain().getTriple();
9176+
std::string HostCPU = tools::getCPUName(D, Args, TheTriple);
9177+
if (!HostCPU.empty())
9178+
CmdArgs.push_back(Args.MakeArgString("--host-cpu=" + HostCPU));
9179+
9180+
ArgStringList HostFeatureArgs;
9181+
getTargetFeatures(D, TheTriple, Args, HostFeatureArgs, /*ForAS=*/false,
9182+
/*IsAux=*/false);
9183+
9184+
// getTargetFeatures() returns arguments in the form ["-target-feature", "+f",
9185+
// "-target-feature", "+d"] but clang-linker-wrapper expects
9186+
// --host-features=+f,+d format, so we need to extract only the feature
9187+
// strings ("+f", "+d") and skip the "-target-feature" flags.
9188+
std::vector<StringRef> HostFeatures;
9189+
// Features always come in pairs: ["-target-feature", "value"], so take every
9190+
// odd element
9191+
for (size_t i = 1; i < HostFeatureArgs.size(); i += 2) {
9192+
HostFeatures.push_back(HostFeatureArgs[i]);
9193+
}
9194+
9195+
if (!HostFeatures.empty()) {
9196+
std::string HostFeaturesStr = llvm::join(HostFeatures, ",");
9197+
CmdArgs.push_back(Args.MakeArgString("--host-features=" + HostFeaturesStr));
9198+
}
9199+
91749200
// CMake hack, suppress passing verbose arguments for the special-case HIP
91759201
// non-RDC mode compilation. This confuses default CMake implicit linker
91769202
// argument parsing when the language is set to HIP and the system linker is
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Test that RISC-V host target features are correctly passed to the linker wrapper compilation
2+
// and applied to wrapper object generation.
3+
// UNSUPPORTED: system-windows
4+
// REQUIRES: riscv-registered-target
5+
// REQUIRES: nvptx-registered-target
6+
7+
// Simple program that requires OpenMP offloading
8+
int main() {
9+
#pragma omp target
10+
{
11+
// Device code
12+
}
13+
return 0;
14+
}
15+
16+
// Verify that the driver invokes clang-linker-wrapper with correct host features.
17+
18+
// Test lp64d (double-float) ABI
19+
// RUN: %clang -target riscv64-linux-gnu -mabi=lp64d \
20+
// RUN: -fopenmp -fopenmp-targets=nvptx64-nvidia-cuda --offload-arch=sm_80 \
21+
// RUN: --libomptarget-nvptx-bc-path=%S/Inputs/libomptarget/libomptarget-nvptx-test.bc \
22+
// RUN: %s -o %t.lp64d -### 2>&1 | FileCheck %s --check-prefix=LP64D-DRIVER
23+
24+
// Check that the driver calls clang-linker-wrapper with correct host features for lp64d
25+
// LP64D-DRIVER: clang-linker-wrapper{{.*}}--host-triple=riscv64{{.*}}--host-features={{.*}}+f{{.*}}+d{{.*}}
26+
27+
// Test lp64f (single-float) ABI
28+
// RUN: %clang -target riscv64-linux-gnu -mabi=lp64f \
29+
// RUN: -fopenmp -fopenmp-targets=nvptx64-nvidia-cuda --offload-arch=sm_80 \
30+
// RUN: --libomptarget-nvptx-bc-path=%S/Inputs/libomptarget/libomptarget-nvptx-test.bc \
31+
// RUN: %s -o %t.lp64f -### 2>&1 | FileCheck %s --check-prefix=LP64F-DRIVER
32+
33+
// LP64F-DRIVER: clang-linker-wrapper{{.*}}--host-triple=riscv64{{.*}}--host-features={{.*}}+f{{.*}}-d{{.*}}
34+
35+
// Test lp64 (soft-float) ABI
36+
// RUN: %clang -target riscv64-linux-gnu -mabi=lp64 \
37+
// RUN: -fopenmp -fopenmp-targets=nvptx64-nvidia-cuda --offload-arch=sm_80 \
38+
// RUN: --libomptarget-nvptx-bc-path=%S/Inputs/libomptarget/libomptarget-nvptx-test.bc \
39+
// RUN: %s -o %t.lp64 -### 2>&1 | FileCheck %s --check-prefix=LP64-DRIVER
40+
41+
// LP64-DRIVER: clang-linker-wrapper{{.*}}--host-triple=riscv64{{.*}}--host-features={{.*}}-f{{.*}}-d{{.*}}
42+
43+
// Verify that clang-linker-wrapper applies RISC-V host features correctly when creating wrapper objects.
44+
// We do this by checking the ELF ABI flags in the generated wrapper object files.
45+
46+
// Create test objects for linker-wrapper testing
47+
// RUN: %clang -cc1 %s -triple nvptx64-nvidia-cuda -emit-llvm-bc -o %t.device.bc
48+
// RUN: llvm-offload-binary -o %t.openmp.out \
49+
// RUN: --image=file=%t.device.bc,kind=openmp,triple=nvptx64-nvidia-cuda,arch=sm_70
50+
// RUN: %clang -cc1 %s -triple riscv64-unknown-linux-gnu -emit-obj -o %t.riscv.host.o -fembed-offload-object=%t.openmp.out
51+
52+
// Test lp64 (soft-float) ABI - should generate ELF flags 0x0
53+
// RUN: rm -rf %t.tmpdir1 && mkdir %t.tmpdir1
54+
// RUN: cd %t.tmpdir1 && clang-linker-wrapper --host-triple=riscv64-unknown-linux-gnu \
55+
// RUN: --host-features=-f,-d --linker-path=/usr/bin/ld %t.riscv.host.o -o %t.lp64.out --dry-run --save-temps 2>&1
56+
// RUN: cd %t.tmpdir1 && find . -name "*.wrapper*.o" -exec llvm-readobj --file-headers "{}" ";" \
57+
// RUN: | FileCheck %s --check-prefix=SOFT-FLOAT-OBJ
58+
59+
// SOFT-FLOAT-OBJ: Flags [ (0x0)
60+
61+
// Test lp64f (single-float) ABI - should generate ELF flags 0x2
62+
// RUN: rm -rf %t.tmpdir2 && mkdir %t.tmpdir2
63+
// RUN: cd %t.tmpdir2 && clang-linker-wrapper --host-triple=riscv64-unknown-linux-gnu \
64+
// RUN: --host-features=+f,-d --linker-path=/usr/bin/ld %t.riscv.host.o -o %t.lp64f.out --dry-run --save-temps 2>&1
65+
// RUN: cd %t.tmpdir2 && find . -name "*.wrapper*.o" -exec llvm-readobj --file-headers "{}" ";" \
66+
// RUN: | FileCheck %s --check-prefix=SINGLE-FLOAT-OBJ
67+
68+
// SINGLE-FLOAT-OBJ: Flags [ (0x2)
69+
70+
// Test lp64d (double-float) ABI - should generate ELF flags 0x4
71+
// RUN: rm -rf %t.tmpdir3 && mkdir %t.tmpdir3
72+
// RUN: cd %t.tmpdir3 && clang-linker-wrapper --host-triple=riscv64-unknown-linux-gnu \
73+
// RUN: --host-features=+f,+d --linker-path=/usr/bin/ld %t.riscv.host.o -o %t.lp64d.out --dry-run --save-temps 2>&1
74+
// RUN: cd %t.tmpdir3 && find . -name "*.wrapper*.o" -exec llvm-readobj --file-headers "{}" ";" \
75+
// RUN: | FileCheck %s --check-prefix=DOUBLE-FLOAT-OBJ
76+
77+
// DOUBLE-FLOAT-OBJ: Flags [ (0x4)

clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -641,7 +641,8 @@ Expected<StringRef> writeOffloadFile(const OffloadFile &File) {
641641

642642
// Compile the module to an object file using the appropriate target machine for
643643
// the host triple.
644-
Expected<StringRef> compileModule(Module &M, OffloadKind Kind) {
644+
Expected<StringRef> compileModule(Module &M, const ArgList &Args,
645+
OffloadKind Kind) {
645646
llvm::TimeTraceScope TimeScope("Compile module");
646647
std::string Msg;
647648
const Target *T = TargetRegistry::lookupTarget(M.getTargetTriple(), Msg);
@@ -650,8 +651,8 @@ Expected<StringRef> compileModule(Module &M, OffloadKind Kind) {
650651

651652
auto Options =
652653
codegen::InitTargetOptionsFromCodeGenFlags(M.getTargetTriple());
653-
StringRef CPU = "";
654-
StringRef Features = "";
654+
StringRef CPU = Args.getLastArgValue(OPT_host_cpu_EQ, "");
655+
StringRef Features = Args.getLastArgValue(OPT_host_features_EQ, "");
655656
std::unique_ptr<TargetMachine> TM(
656657
T->createTargetMachine(M.getTargetTriple(), CPU, Features, Options,
657658
Reloc::PIC_, M.getCodeModel()));
@@ -746,7 +747,7 @@ wrapDeviceImages(ArrayRef<std::unique_ptr<MemoryBuffer>> Buffers,
746747
WriteBitcodeToFile(M, OS);
747748
}
748749

749-
auto FileOrErr = compileModule(M, Kind);
750+
auto FileOrErr = compileModule(M, Args, Kind);
750751
if (!FileOrErr)
751752
return FileOrErr.takeError();
752753
return *FileOrErr;

clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,15 @@ def host_triple_EQ : Joined<["--"], "host-triple=">,
2020
Flags<[WrapperOnlyOption]>,
2121
MetaVarName<"<triple>">,
2222
HelpText<"Triple to use for the host compilation">;
23+
def host_cpu_EQ : Joined<["--"], "host-cpu=">,
24+
Flags<[WrapperOnlyOption]>,
25+
MetaVarName<"<cpu>">,
26+
HelpText<"CPU name to use for the host compilation">;
27+
def host_features_EQ
28+
: Joined<["--"], "host-features=">,
29+
Flags<[WrapperOnlyOption]>,
30+
MetaVarName<"<features>">,
31+
HelpText<"Target features to use for the host compilation">;
2332
def device_linker_args_EQ : Joined<["--"], "device-linker=">,
2433
Flags<[WrapperOnlyOption]>, MetaVarName<"<value> or <triple>=<value>">,
2534
HelpText<"Arguments to pass to the device linker invocation">;

0 commit comments

Comments
 (0)