https://github.com/fzakaria created https://github.com/llvm/llvm-project/pull/210087
Clang never instantiated RegisterMCTargetOptionsFlags, so LLVM's machine-code target options (`-mllvm`) were not reachable from clang. This made certain flags such as `-large-eh-encoding` (MCTargetOptions::LargeEHEncoding) impossible to set in clang. Register the flags in the cc1 codegen path and in the integrated assembler, then seed MCTargetOptions before applying clang's own settings with proper precendence for matching flags. Value precedence: clang's driver flags stay authoritative. The seed runs first and clang's flag-derived assignments overwrite whatever they cover, so -mllvm only contributes Absent any -mllvm flags the seed equals a default-constructed MCTargetOptions, so existing behavior is unchanged. This change would supersede https://github.com/llvm/llvm-project/pull/187583 >From cfbc73adcd1d2cb5957267d60439fb353237213d Mon Sep 17 00:00:00 2001 From: Farid Zakaria <[email protected]> Date: Thu, 16 Jul 2026 08:51:07 -0700 Subject: [PATCH] [clang] Expose MC target options through -mllvm Clang never instantiated RegisterMCTargetOptionsFlags, so LLVM's machine-code target options (`-mllvm`) were not reachable from clang. This made certain flags such as `-large-eh-encoding` (MCTargetOptions::LargeEHEncoding) impossible to set in clang. Register the flags in the cc1 codegen path and in the integrated assembler, then seed MCTargetOptions before applying clang's own settings with proper precendence for matching flags. Value precedence: clang's driver flags stay authoritative. The seed runs first and clang's flag-derived assignments overwrite whatever they cover, so -mllvm only contributes Absent any -mllvm flags the seed equals a default-constructed MCTargetOptions, so existing behavior is unchanged. --- clang/lib/CodeGen/BackendUtil.cpp | 15 +++++++++++ clang/test/CodeGen/mllvm-mc-target-options.c | 28 ++++++++++++++++++++ clang/tools/driver/cc1as_main.cpp | 14 +++++++++- 3 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 clang/test/CodeGen/mllvm-mc-target-options.c diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 2b755fa916e55..4a3c3c579a367 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -39,6 +39,7 @@ #include "llvm/IR/Verifier.h" #include "llvm/IRPrinter/IRPrintingPasses.h" #include "llvm/LTO/LTOBackend.h" +#include "llvm/MC/MCTargetOptionsCommandFlags.h" #include "llvm/MC/TargetRegistry.h" #include "llvm/Object/OffloadBinary.h" #include "llvm/Passes/PassBuilder.h" @@ -99,6 +100,13 @@ using namespace clang; using namespace llvm; +// Register LLVM's machine-code target-option command-line flags (e.g. +// -large-eh-encoding) so they can be supplied through clang's -mllvm, mirroring +// what the standalone LLVM tools (llc, llvm-mc) do. This also makes it safe for +// initTargetOptions() to call mc::InitMCTargetOptionsFromFlags(), whose +// accessors require the flags to have been registered. +static llvm::mc::RegisterMCTargetOptionsFlags MCTargetOptionsFlags; + #define HANDLE_EXTENSION(Ext) \ llvm::PassPluginLibraryInfo get##Ext##PluginInfo(); #include "llvm/Support/Extension.def" @@ -503,6 +511,13 @@ static bool initTargetOptions(const CompilerInstance &CI, break; } + // Seed the MC layer with any machine-code options supplied via -mllvm. + // Clang's own driver-derived settings below overwrite whatever they cover, + // so -mllvm only contributes MC options that have no dedicated clang flag. + // Absent any -mllvm flags this is equivalent to a default-constructed + // MCTargetOptions. + Options.MCOptions = llvm::mc::InitMCTargetOptionsFromFlags(); + Options.MCOptions.SplitDwarfFile = CodeGenOpts.SplitDwarfFile; Options.MCOptions.EmitDwarfUnwind = CodeGenOpts.getEmitDwarfUnwind(); Options.MCOptions.EmitCompactUnwindNonCanonical = diff --git a/clang/test/CodeGen/mllvm-mc-target-options.c b/clang/test/CodeGen/mllvm-mc-target-options.c new file mode 100644 index 0000000000000..297a324754f69 --- /dev/null +++ b/clang/test/CodeGen/mllvm-mc-target-options.c @@ -0,0 +1,28 @@ +// REQUIRES: x86-registered-target +// +// Clang registers LLVM's machine-code target options (via +// RegisterMCTargetOptionsFlags) so they can be set through -mllvm. An MC option +// that has no dedicated clang flag takes effect directly; an MC option that also +// has a clang flag is governed by the clang flag, which takes precedence over +// -mllvm. + +// -asm-show-inst has no clang flag, so -mllvm controls it and the emitted +// assembly gains <MCInst ...> comments. +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -S %s -o - \ +// RUN: | FileCheck %s --check-prefix=NO-SHOW-INST +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -S -mllvm -asm-show-inst %s -o - \ +// RUN: | FileCheck %s --check-prefix=SHOW-INST +// NO-SHOW-INST-NOT: <MCInst +// SHOW-INST: <MCInst + +// -x86-relax-relocations also has a clang flag (-mrelax-relocations), which wins +// over -mllvm: with -mrelax-relocations=no the GOT load keeps its non-relaxable +// relocation even though -mllvm -x86-relax-relocations requests relaxation. +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -mrelocation-model pic \ +// RUN: -mrelax-relocations=no -mllvm -x86-relax-relocations -emit-obj %s -o %t +// RUN: llvm-readobj -r %t | FileCheck %s --check-prefix=PRECEDENCE +// PRECEDENCE: R_X86_64_GOTPCREL foo +// PRECEDENCE-NOT: R_X86_64_REX_GOTPCRELX foo + +extern int foo; +int *f(void) { return &foo; } diff --git a/clang/tools/driver/cc1as_main.cpp b/clang/tools/driver/cc1as_main.cpp index 077cd69ce4e2c..0792a37b22609 100644 --- a/clang/tools/driver/cc1as_main.cpp +++ b/clang/tools/driver/cc1as_main.cpp @@ -37,6 +37,7 @@ #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCTargetOptions.h" +#include "llvm/MC/MCTargetOptionsCommandFlags.h" #include "llvm/MC/TargetRegistry.h" #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" @@ -64,6 +65,12 @@ using namespace clang::options; using namespace llvm; using namespace llvm::opt; +// Register LLVM's machine-code target-option command-line flags (e.g. +// -large-eh-encoding) so they can be supplied through -cc1as -mllvm, mirroring +// what the standalone LLVM tools (llvm-mc) do. The parsed values are read back +// via mc::InitMCTargetOptionsFromFlags() in ExecuteAssemblerImpl(). +static llvm::mc::RegisterMCTargetOptionsFlags MCTargetOptionsFlags; + namespace { /// Helper class for representing a single invocation of the assembler. @@ -463,7 +470,12 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(Opts.Triple)); assert(MRI && "Unable to create target register info!"); - MCTargetOptions MCOptions; + // Seed the MC layer with any machine-code options supplied via -mllvm (for + // example -large-eh-encoding). The cc1as flag-derived settings below overwrite + // whatever they cover, so -mllvm only contributes MC options that have no + // dedicated cc1as flag. Absent any -mllvm flags this is equivalent to a + // default-constructed MCTargetOptions. + MCTargetOptions MCOptions = mc::InitMCTargetOptionsFromFlags(); MCOptions.MCRelaxAll = Opts.RelaxAll; MCOptions.EmitDwarfUnwind = Opts.EmitDwarfUnwind; MCOptions.EmitCompactUnwindNonCanonical = Opts.EmitCompactUnwindNonCanonical; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
