Skip to content

Commit 869ffcf

Browse files
authored
[CodeGen][i386] Move -mregparm storage earlier and fix Runtime calls (llvm#89707)
When building the Linux kernel for i386, the -mregparm=3 option is enabled. Crashes were observed in the sanitizer handler functions, and the problem was found to be mismatched calling convention. As was fixed in commit c167c0a ("[BuildLibCalls] infer inreg param attrs from NumRegisterParameters"), call arguments need to be marked as "in register" when -mregparm is set. Use the same helper developed there to update the function arguments. Since CreateRuntimeFunction() is actually part of CodeGenModule, storage of the -mregparm value is also moved to the constructor, as doing this in Release() is too late. Fixes: llvm#89670
1 parent 3a0d894 commit 869ffcf

File tree

4 files changed

+36
-6
lines changed

4 files changed

+36
-6
lines changed

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
#include "llvm/TargetParser/RISCVISAInfo.h"
7474
#include "llvm/TargetParser/Triple.h"
7575
#include "llvm/TargetParser/X86TargetParser.h"
76+
#include "llvm/Transforms/Utils/BuildLibCalls.h"
7677
#include <optional>
7778

7879
using namespace clang;
@@ -442,6 +443,11 @@ CodeGenModule::CodeGenModule(ASTContext &C,
442443
}
443444
ModuleNameHash = llvm::getUniqueInternalLinkagePostfix(Path);
444445
}
446+
447+
// Record mregparm value now so it is visible through all of codegen.
448+
if (Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86)
449+
getModule().addModuleFlag(llvm::Module::Error, "NumRegisterParameters",
450+
CodeGenOpts.NumRegisterParameters);
445451
}
446452

447453
CodeGenModule::~CodeGenModule() {}
@@ -980,11 +986,6 @@ void CodeGenModule::Release() {
980986
NMD->addOperand(MD);
981987
}
982988

983-
// Record mregparm value now so it is visible through rest of codegen.
984-
if (Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86)
985-
getModule().addModuleFlag(llvm::Module::Error, "NumRegisterParameters",
986-
CodeGenOpts.NumRegisterParameters);
987-
988989
if (CodeGenOpts.DwarfVersion) {
989990
getModule().addModuleFlag(llvm::Module::Max, "Dwarf Version",
990991
CodeGenOpts.DwarfVersion);
@@ -4781,6 +4782,10 @@ CodeGenModule::CreateRuntimeFunction(llvm::FunctionType *FTy, StringRef Name,
47814782
}
47824783
}
47834784
setDSOLocal(F);
4785+
// FIXME: We should use CodeGenModule::SetLLVMFunctionAttributes() instead
4786+
// of trying to approximate the attributes using the LLVM function
4787+
// signature. This requires revising the API of CreateRuntimeFunction().
4788+
markRegisterParameterAttributes(F);
47844789
}
47854790
}
47864791

clang/test/CodeGen/regparm-flag.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
// RUN: %clang_cc1 -triple i386-unknown-unknown -mregparm 4 %s -emit-llvm -o - | FileCheck %s
2+
// RUN: %clang_cc1 -triple i386-unknown-unknown -fsanitize=array-bounds %s -emit-llvm -o - | FileCheck %s --check-prefix=RUNTIME0
3+
// RUN: %clang_cc1 -triple i386-unknown-unknown -mregparm 1 -fsanitize=array-bounds %s -emit-llvm -o - | FileCheck %s --check-prefix=RUNTIME1
4+
// RUN: %clang_cc1 -triple i386-unknown-unknown -mregparm 2 -fsanitize=array-bounds %s -emit-llvm -o - | FileCheck %s --check-prefix=RUNTIME2
5+
// RUN: %clang_cc1 -triple i386-unknown-unknown -mregparm 3 -fsanitize=array-bounds %s -emit-llvm -o - | FileCheck %s --check-prefix=RUNTIME2
26

37
void f1(int a, int b, int c, int d,
48
int e, int f, int g, int h);
@@ -13,7 +17,21 @@ void f0(void) {
1317
f2(1, 2);
1418
}
1519

20+
struct has_array {
21+
int a;
22+
int b[4];
23+
int c;
24+
};
25+
26+
int access(struct has_array *p, int index)
27+
{
28+
return p->b[index];
29+
}
30+
1631
// CHECK: declare void @f1(i32 inreg noundef, i32 inreg noundef, i32 inreg noundef, i32 inreg noundef,
1732
// CHECK: i32 noundef, i32 noundef, i32 noundef, i32 noundef)
1833
// CHECK: declare void @f2(i32 noundef, i32 noundef)
1934

35+
// RUNTIME0: declare void @__ubsan_handle_out_of_bounds_abort(ptr, i32)
36+
// RUNTIME1: declare void @__ubsan_handle_out_of_bounds_abort(ptr inreg, i32)
37+
// RUNTIME2: declare void @__ubsan_handle_out_of_bounds_abort(ptr inreg, i32 inreg)

llvm/include/llvm/Transforms/Utils/BuildLibCalls.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,13 @@ namespace llvm {
6262
LibFunc TheLibFunc, AttributeList AttributeList,
6363
FunctionType *Invalid, ArgsTy... Args) = delete;
6464

65+
// Handle -mregparm for the given function.
66+
// Note that this function is a rough approximation that only works for simple
67+
// function signatures; it does not apply other relevant attributes for
68+
// function signatures, including sign/zero-extension for arguments and return
69+
// values.
70+
void markRegisterParameterAttributes(Function *F);
71+
6572
/// Check whether the library function is available on target and also that
6673
/// it in the current Module is a Function with the right type.
6774
bool isLibFuncEmittable(const Module *M, const TargetLibraryInfo *TLI,

llvm/lib/Transforms/Utils/BuildLibCalls.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1255,7 +1255,7 @@ static void setRetExtAttr(Function &F,
12551255
}
12561256

12571257
// Modeled after X86TargetLowering::markLibCallAttributes.
1258-
static void markRegisterParameterAttributes(Function *F) {
1258+
void llvm::markRegisterParameterAttributes(Function *F) {
12591259
if (!F->arg_size() || F->isVarArg())
12601260
return;
12611261

0 commit comments

Comments
 (0)