Skip to content

Commit d1d7bec

Browse files
committed
[BoundsSafety] Improve the soft trap call interface to reduce codesize impact
This patch makes several changes motivated to reduce the code size impact at call sites to runtime functions. * `__bounds_safety_soft_trap_c` function no longer takes an integer argument and has been renamed to remove the `_c` suffix. The corresponding `call-with-code` option to `-fbounds-safety-soft-traps=` has been renamed to `call-minimal`. We can reduce codeisze by avoiding writing constants into the `x0` on arm64 which saves us 1 instruction (4 bytes) per call. The original motivation for passing an integer code was to aid debugging in the scenario where debug info is missing. This scenario isn't the primary use case and codesize is far more important so removing the argument seems like the better design choice. * The runtime functions now use the `preserve_all` calling convention on x86_64 and arm64. This calling convention means that some registers that are normally caller-saved become callee-saved. This means that these registers do not need to be spilled at callsites which should reduce some code size overhead. This isn't the perfect calling convention because the argument passing registers could also be made callee saved currently aren't but such a calling convention isn't currently implemented in LLVM so this is the best we can do for now. A hidden flag (`-bounds-safety-soft-trap-preserve-all-cc=false`) to turn off this behavior is included. It is primarly there to make it easy to measure the codesize impact without having to rebuild the compiler. Note: While this is an ABI breaking change `__CLANG_BOUNDS_SAFETY_SOFT_TRAP_API_VERSION` has not been bumped because there are currently aren't any adopters of the soft trap mode yet. rdar://164341162 (cherry picked from commit 4455ec3) Conflicts: clang/test/BoundsSafety/CodeGen/soft-traps/call_minimal.c clang/test/BoundsSafety/CodeGen/soft-traps/call_minimal_custom_func.c clang/test/BoundsSafety/CodeGen/soft-traps/call_minimal_with_ubsan.c clang/test/BoundsSafety/CodeGen/soft-traps/call_with_str.c clang/test/BoundsSafety/CodeGen/soft-traps/call_with_str_custom_func.c clang/test/BoundsSafety/CodeGen/soft-traps/call_with_str_with_ubsan.c
1 parent 5ff34b0 commit d1d7bec

20 files changed

+301
-123
lines changed

clang/include/clang/Basic/CodeGenOptions.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -194,14 +194,15 @@ class CodeGenOptions : public CodeGenOptionsBase {
194194
SoftCallWithTrapString, ///< Emit a non-fatal call. The call
195195
///< is passed a string description of the failed
196196
///< bounds check.
197-
SoftCallWithTrapCode, ///< Emit a non-fatal call. The call
198-
///< is passed an integer describing the failed
199-
///< bounds check.
197+
SoftCallMinimal, ///< Emit a non-fatal call. The call
198+
///< has no arguments. The reason for trapping is
199+
///< intended to be inferred from the trap reason
200+
///< being embedded in the debug info.
200201
};
201202

202203
/// The name of the function to call for BoundsSafety soft traps. This is used
203204
/// with `BoundsSafetyTrapModeKind::SoftCallWithTrapString` and
204-
// `BoundsSafetyTrapModeKind::SoftCallWithTrapCode`.
205+
// `BoundsSafetyTrapModeKind::SoftCallMinimal`.
205206
std::string BoundsSafetySoftTrapFuncName;
206207

207208
/* TO_UPSTREAM(BoundsSafety) OFF*/

clang/include/clang/Driver/Options.td

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2065,17 +2065,18 @@ def fbounds_safety_soft_traps_EQ
20652065
HelpText<"Enables soft traps which causes the compiler to emit a non-fatal "
20662066
"instruction sequence when a bounds check fails. After this instruction "
20672067
"sequence execution resumes as if the bounds check had succeeded."
2068-
"For `call-with-*` modes see 'bounds_safety_soft_traps.h' for the runtime"
2068+
"For `call-*` modes see 'bounds_safety_soft_traps.h' for the runtime"
20692069
" function interface. This option supports the following modes: "
20702070
"`none` - No soft traps, i.e. use hard traps (default)."
20712071
"`call-with-str` - Emit a call to a runtime function that receives the "
20722072
"trap reason as a string."
2073-
"`call-with-code` - Emit a call to a runtime function that receives an "
2074-
"integer describing the trap reason. This is better for codesize than "
2075-
"`call-with-str` but is harder to debug if debug info is missing.">,
2076-
Values<"none,call-with-str,call-with-code">,
2073+
"`call-minimal` - Emit a call to a runtime function that takes no "
2074+
"arguments and uses a custom calling convention if possible. This is "
2075+
"better for codesize than `call-with-str` but is harder to debug if debug"
2076+
" info is missing.">,
2077+
Values<"none,call-with-str,call-minimal">,
20772078
NormalizedValuesScope<"CodeGenOptions::BoundsSafetyTrapModeKind">,
2078-
NormalizedValues<["Hard", "SoftCallWithTrapString", "SoftCallWithTrapCode"]>,
2079+
NormalizedValues<["Hard", "SoftCallWithTrapString", "SoftCallMinimal"]>,
20792080
MarshallingInfoEnum<CodeGenOpts<"BoundsSafetyTrapMode">, "Hard">;
20802081

20812082
def fbounds_safety_soft_trap_function_EQ : Joined<["-"],

clang/lib/CodeGen/CGExpr.cpp

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,14 @@ llvm::cl::opt<bool> ClSanitizeGuardChecks(
6666
"ubsan-guard-checks", llvm::cl::Optional,
6767
llvm::cl::desc("Guard UBSAN checks with `llvm.allow.ubsan.check()`."));
6868

69+
// TO_UPSTREAM(BoundsSafety) ON
70+
llvm::cl::opt<bool> ClBoundsSafetySoftTrapPreserveAllCC(
71+
"bounds-safety-soft-trap-preserve-all-cc", llvm::cl::init(true),
72+
llvm::cl::Optional,
73+
llvm::cl::desc("Use preserve_all calling convention for -fbounds-safety "
74+
"soft trap function calls on x86_64 and arm64"));
75+
// TO_UPSTREAM(BoundsSafety) OFF
76+
6977
} // namespace clang
7078

7179
//===--------------------------------------------------------------------===//
@@ -4714,35 +4722,59 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked,
47144722
// `__CLANG_BOUNDS_SAFETY_SOFT_TRAP_API_VERSION` and adjust the interface
47154723
// in `bounds_safety_soft_traps.h` if the API is changed.
47164724
llvm::FunctionType *FnType = nullptr;
4717-
llvm::Constant *SoftTrapCallArg = nullptr;
4725+
llvm::SmallVector<llvm::Value *, 1> RuntimeCallArgs;
47184726
// Emit calls to one of the interfaces defined in
47194727
// `bounds_safety_soft_traps.h`
47204728
switch (CGM.getCodeGenOpts().getBoundsSafetyTrapMode()) {
4721-
case CodeGenOptions::BoundsSafetyTrapModeKind::SoftCallWithTrapCode: {
4722-
// void __bounds_safety_soft_trap_c(uint16_t);
4723-
// TODO: Set correct value from the `TrapReason` object
4724-
// (rdar://162824128).
4725-
SoftTrapCallArg = llvm::ConstantInt::get(CGM.Int16Ty, 0);
4729+
case CodeGenOptions::BoundsSafetyTrapModeKind::SoftCallMinimal: {
4730+
// void __bounds_safety_soft_trap();
4731+
FnType = llvm::FunctionType::get(CGM.VoidTy, {}, false);
4732+
assert(RuntimeCallArgs.empty());
47264733
break;
47274734
}
47284735
case CodeGenOptions::BoundsSafetyTrapModeKind::SoftCallWithTrapString: {
47294736
// void __bounds_safety_soft_trap_s(const char*);
4730-
if (!TrapMessage.empty()) {
4731-
SoftTrapCallArg =
4732-
CGM.GetOrCreateGlobalStr(TrapMessage, Builder, "trap.reason");
4733-
} else {
4734-
SoftTrapCallArg = llvm::Constant::getNullValue(CGM.Int8PtrTy);
4735-
}
4737+
FnType = llvm::FunctionType::get(CGM.VoidTy, {CGM.Int8PtrTy}, false);
4738+
if (!TrapMessage.empty())
4739+
RuntimeCallArgs.push_back(
4740+
CGM.GetOrCreateGlobalStr(TrapMessage, Builder, "trap.reason"));
4741+
else
4742+
RuntimeCallArgs.push_back(
4743+
llvm::Constant::getNullValue(CGM.Int8PtrTy));
47364744
break;
47374745
}
47384746
default:
47394747
llvm_unreachable("Unhandled BoundsSafetyTrapMode");
47404748
}
4741-
FnType = llvm::FunctionType::get(CGM.VoidTy, {SoftTrapCallArg->getType()},
4742-
false);
47434749
auto TrapFunc = CGM.CreateRuntimeFunction(
47444750
FnType, CGM.getCodeGenOpts().BoundsSafetySoftTrapFuncName);
4745-
TrapCall = EmitNounwindRuntimeCall(TrapFunc, {SoftTrapCallArg});
4751+
4752+
// Change calling convention if necessary. This needs to be kept in sync
4753+
// with `bounds_safety_soft_traps.h`.
4754+
std::optional<llvm::CallingConv::ID> SoftTrapCC;
4755+
if (ClBoundsSafetySoftTrapPreserveAllCC &&
4756+
(CGM.getTarget().getTriple().isAArch64() ||
4757+
CGM.getTarget().getTriple().getArch() == llvm::Triple::x86_64)) {
4758+
auto *Fn = cast<llvm::Function>(TrapFunc.getCallee());
4759+
// This calling convention is used to reduce the codesize at the
4760+
// callsite. It makes more registers be callee saved which means if
4761+
// those registers are being used in the caller they no longer need to
4762+
// be spilled. Unfortunately despite the name this calling convention
4763+
// doesn't preserve all registers. We should add a new calling
4764+
// convention that actually preserves almost all the general purposes
4765+
// registers (rdar://164341162).
4766+
SoftTrapCC = llvm::CallingConv::PreserveAll;
4767+
Fn->setCallingConv(SoftTrapCC.value());
4768+
}
4769+
4770+
TrapCall = EmitNounwindRuntimeCall(TrapFunc, RuntimeCallArgs);
4771+
if (SoftTrapCC.has_value()) {
4772+
// Marking the called function as having a particular calling convention
4773+
// (above) does not trigger different codegen at callsites. The call
4774+
// itself needs to be marked as using the same calling convention too to
4775+
// get different codegen at callsites.
4776+
TrapCall->setCallingConv(SoftTrapCC.value());
4777+
}
47464778
Builder.CreateBr(Cont);
47474779
} else if (CGM.getCodeGenOpts().TrapFuncReturns) {
47484780
auto *TrapID = llvm::ConstantInt::get(CGM.Int8Ty, CheckHandlerID);

clang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2566,8 +2566,8 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
25662566
case CodeGenOptions::BoundsSafetyTrapModeKind::SoftCallWithTrapString:
25672567
Opts.BoundsSafetySoftTrapFuncName = "__bounds_safety_soft_trap_s";
25682568
break;
2569-
case CodeGenOptions::BoundsSafetyTrapModeKind::SoftCallWithTrapCode:
2570-
Opts.BoundsSafetySoftTrapFuncName = "__bounds_safety_soft_trap_c";
2569+
case CodeGenOptions::BoundsSafetyTrapModeKind::SoftCallMinimal:
2570+
Opts.BoundsSafetySoftTrapFuncName = "__bounds_safety_soft_trap";
25712571
break;
25722572
case CodeGenOptions::BoundsSafetyTrapModeKind::Hard:
25732573
break;

clang/lib/Headers/bounds_safety_soft_traps.h

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,24 +22,31 @@ extern "C" {
2222
/// compile time to know which interface version the compiler uses.
2323
#define __CLANG_BOUNDS_SAFETY_SOFT_TRAP_API_VERSION 0
2424

25+
// `__CLANG_BOUNDS_SAFETY_SOFT_TRAP_FN_ATTRS` is guarded because `preserve_all`
26+
// is only implemented for x86_64 and arm64. For other targets we get a
27+
// `'preserve_all' calling convention is not supported for this target` warning.
28+
#if defined(__aarch64__) || defined(__x86_64__)
29+
// This attribute is used to try to reduce the codesize impact of making calls
30+
// to the soft trap runtime function(s).
31+
#define __CLANG_BOUNDS_SAFETY_SOFT_TRAP_FN_ATTRS __attribute__((preserve_all))
32+
#else
33+
#define __CLANG_BOUNDS_SAFETY_SOFT_TRAP_FN_ATTRS
34+
#endif
35+
2536
/// Called when a `-fbounds-safety` bounds check fails when building with
2637
/// `-fbounds-safety-soft-traps=call-with-str`. This function is allowed to
2738
/// to return.
2839
///
2940
/// \param reason A string constant describing the reason for trapping or
3041
/// NULL.
42+
__CLANG_BOUNDS_SAFETY_SOFT_TRAP_FN_ATTRS
3143
void __bounds_safety_soft_trap_s(const char *reason);
3244

33-
// TODO(dliew): Document the `reason_code` values (rdar://162824128)
34-
3545
/// Called when a `-fbounds-safety` bounds check fails when building with
3646
/// `-fbounds-safety-soft-traps=call-with-code`. This function is allowed to
37-
/// to return.
38-
///
39-
/// \param reason_code. An integer the represents the reason for trapping.
40-
/// The values are currently not documented but will be in the future.
41-
///
42-
void __bounds_safety_soft_trap_c(uint16_t reason_code);
47+
/// to return. This function takes no arguments.
48+
__CLANG_BOUNDS_SAFETY_SOFT_TRAP_FN_ATTRS
49+
void __bounds_safety_soft_trap(void);
4350

4451
#ifdef __cplusplus
4552
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Check that when a runtime implementation uses the `bounds_safety_soft_traps.h`
2+
// header that the right calling convention is used.
3+
4+
// x86_64 and arm64 use preserve_all
5+
6+
// RUN: %clang_cc1 -O0 -triple arm64-apple-macos \
7+
// RUN: -emit-llvm %s -o - | \
8+
// RUN: FileCheck --check-prefixes=PRESERVE_ALL_CC %s
9+
10+
// RUN: %clang_cc1 -O0 -triple x86_64-apple-macos \
11+
// RUN: -emit-llvm %s -o - | \
12+
// RUN: FileCheck --check-prefixes=PRESERVE_ALL_CC %s
13+
14+
// Other targets use the normal calling convention
15+
16+
// RUN: %clang_cc1 -O0 -triple i686-apple-macos \
17+
// RUN: -emit-llvm %s -o - | \
18+
// RUN: FileCheck --check-prefixes=NORMAL_CC %s
19+
#include <bounds_safety_soft_traps.h>
20+
21+
#if __CLANG_BOUNDS_SAFETY_SOFT_TRAP_API_VERSION > 0
22+
#error ABI changed
23+
#endif
24+
25+
// Note the explicit calling convention macro isn't used here. Clang should
26+
// use the attribute from the declaration in the header.
27+
28+
// PRESERVE_ALL_CC: define preserve_allcc void @__bounds_safety_soft_trap_s(ptr {{.+}})
29+
// NORMAL_CC: define void @__bounds_safety_soft_trap_s(ptr {{.+}})
30+
void __bounds_safety_soft_trap_s(const char *reason) {
31+
32+
}
33+
34+
// PRESERVE_ALL_CC: define preserve_allcc void @__bounds_safety_soft_trap()
35+
// NORMAL_CC: define void @__bounds_safety_soft_trap()
36+
void __bounds_safety_soft_trap(void) {
37+
38+
}
39+

clang/test/BoundsSafety/CodeGen/soft-traps/call_with_code.c renamed to clang/test/BoundsSafety/CodeGen/soft-traps/call_minimal.c

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6
1+
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-globals all --version 6
22
// RUN: %clang_cc1 -O0 -fbounds-safety -triple arm64-apple-iphoneos \
3-
// RUN: -emit-llvm %s -o - -fbounds-safety-soft-traps=call-with-code | \
3+
// RUN: -emit-llvm %s -o - -fbounds-safety-soft-traps=call-minimal | \
44
// RUN: FileCheck --check-prefixes=UNOPT %s
55

66
// Check `-ftrap-function` is ignored for `-fbounds-safety` when using
77
// `-fbounds-safety-soft-traps=`
88
// RUN: %clang_cc1 -O0 -fbounds-safety -triple arm64-apple-iphoneos \
9-
// RUN: -emit-llvm %s -o - -fbounds-safety-soft-traps=call-with-code \
9+
// RUN: -emit-llvm %s -o - -fbounds-safety-soft-traps=call-minimal \
1010
// RUN: -ftrap-function=not_used | \
1111
// RUN: FileCheck --check-prefixes=UNOPT %s
1212

1313
// RUN: %clang_cc1 -O2 -fbounds-safety -triple arm64-apple-iphoneos \
14-
// RUN: -emit-llvm %s -o - -fbounds-safety-soft-traps=call-with-code | \
14+
// RUN: -emit-llvm %s -o - -fbounds-safety-soft-traps=call-minimal | \
1515
// RUN: FileCheck --check-prefixes=OPT %s
1616
#include <ptrcheck.h>
1717

@@ -37,19 +37,19 @@
3737
// UNOPT-NEXT: [[TMP2:%.*]] = icmp ule ptr [[TMP1]], [[WIDE_PTR_UB]], !annotation [[META2]]
3838
// UNOPT-NEXT: br i1 [[TMP2]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF3:![0-9]+]], !annotation [[META2]]
3939
// UNOPT: [[TRAP]]:
40-
// UNOPT-NEXT: call void @__bounds_safety_soft_trap_c(i16 0) #[[ATTR2:[0-9]+]], !annotation [[META2]]
40+
// UNOPT-NEXT: call preserve_allcc void @__bounds_safety_soft_trap() #[[ATTR2:[0-9]+]], !annotation [[META2]]
4141
// UNOPT-NEXT: br label %[[CONT]], !annotation [[META2]]
4242
// UNOPT: [[CONT]]:
4343
// UNOPT-NEXT: [[TMP3:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP1]], !annotation [[META2]]
4444
// UNOPT-NEXT: br i1 [[TMP3]], label %[[CONT2:.*]], label %[[TRAP1:.*]], !prof [[PROF3]], !annotation [[META2]]
4545
// UNOPT: [[TRAP1]]:
46-
// UNOPT-NEXT: call void @__bounds_safety_soft_trap_c(i16 0) #[[ATTR2]], !annotation [[META2]]
46+
// UNOPT-NEXT: call preserve_allcc void @__bounds_safety_soft_trap() #[[ATTR2]], !annotation [[META2]]
4747
// UNOPT-NEXT: br label %[[CONT2]], !annotation [[META2]]
4848
// UNOPT: [[CONT2]]:
4949
// UNOPT-NEXT: [[TMP4:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB]], !annotation [[META4:![0-9]+]]
5050
// UNOPT-NEXT: br i1 [[TMP4]], label %[[CONT4:.*]], label %[[TRAP3:.*]], !prof [[PROF3]], !annotation [[META4]]
5151
// UNOPT: [[TRAP3]]:
52-
// UNOPT-NEXT: call void @__bounds_safety_soft_trap_c(i16 0) #[[ATTR2]], !annotation [[META4]]
52+
// UNOPT-NEXT: call preserve_allcc void @__bounds_safety_soft_trap() #[[ATTR2]], !annotation [[META4]]
5353
// UNOPT-NEXT: br label %[[CONT4]], !annotation [[META4]]
5454
// UNOPT: [[CONT4]]:
5555
// UNOPT-NEXT: [[TMP5:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
@@ -69,19 +69,19 @@
6969
// OPT-NEXT: [[DOTNOT:%.*]] = icmp ugt ptr [[TMP0]], [[AGG_TEMP_SROA_2_0_COPYLOAD]], !annotation [[META7]]
7070
// OPT-NEXT: br i1 [[DOTNOT]], label %[[TRAP:.*]], label %[[CONT:.*]], !prof [[PROF8:![0-9]+]], !annotation [[META7]]
7171
// OPT: [[TRAP]]:
72-
// OPT-NEXT: tail call void @__bounds_safety_soft_trap_c(i16 0) #[[ATTR1:[0-9]+]], !annotation [[META7]]
72+
// OPT-NEXT: tail call preserve_allcc void @__bounds_safety_soft_trap() #[[ATTR1:[0-9]+]], !annotation [[META7]]
7373
// OPT-NEXT: br label %[[CONT]], !annotation [[META7]]
7474
// OPT: [[CONT]]:
7575
// OPT-NEXT: [[DOTNOT5:%.*]] = icmp ugt ptr [[ARRAYIDX]], [[TMP0]], !annotation [[META7]]
7676
// OPT-NEXT: br i1 [[DOTNOT5]], label %[[TRAP1:.*]], label %[[CONT2:.*]], !prof [[PROF8]], !annotation [[META7]]
7777
// OPT: [[TRAP1]]:
78-
// OPT-NEXT: tail call void @__bounds_safety_soft_trap_c(i16 0) #[[ATTR1]], !annotation [[META7]]
78+
// OPT-NEXT: tail call preserve_allcc void @__bounds_safety_soft_trap() #[[ATTR1]], !annotation [[META7]]
7979
// OPT-NEXT: br label %[[CONT2]], !annotation [[META7]]
8080
// OPT: [[CONT2]]:
8181
// OPT-NEXT: [[DOTNOT6:%.*]] = icmp ult ptr [[ARRAYIDX]], [[AGG_TEMP_SROA_3_0_COPYLOAD]], !annotation [[META9:![0-9]+]]
8282
// OPT-NEXT: br i1 [[DOTNOT6]], label %[[TRAP3:.*]], label %[[CONT4:.*]], !prof [[PROF8]], !annotation [[META9]]
8383
// OPT: [[TRAP3]]:
84-
// OPT-NEXT: tail call void @__bounds_safety_soft_trap_c(i16 0) #[[ATTR1]], !annotation [[META9]]
84+
// OPT-NEXT: tail call preserve_allcc void @__bounds_safety_soft_trap() #[[ATTR1]], !annotation [[META9]]
8585
// OPT-NEXT: br label %[[CONT4]], !annotation [[META9]]
8686
// OPT: [[CONT4]]:
8787
// OPT-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA10:![0-9]+]]
@@ -91,11 +91,25 @@ int read(int* __bidi_indexable ptr, int idx) {
9191
return ptr[idx];
9292
}
9393

94+
//
95+
//
96+
//
97+
//.
98+
// UNOPT: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
99+
// UNOPT: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
100+
// UNOPT: attributes #[[ATTR2]] = { nounwind }
101+
//.
102+
// OPT: attributes #[[ATTR0]] = { nounwind "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
103+
// OPT: attributes #[[ATTR1]] = { nounwind }
94104
//.
105+
// UNOPT: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}
106+
// UNOPT: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"}
95107
// UNOPT: [[META2]] = !{!"bounds-safety-check-ptr-le-upper-bound"}
96108
// UNOPT: [[PROF3]] = !{!"branch_weights", i32 1048575, i32 1}
97109
// UNOPT: [[META4]] = !{!"bounds-safety-check-ptr-ge-lower-bound"}
98110
//.
111+
// OPT: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}
112+
// OPT: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"}
99113
// OPT: [[TBAA2]] = !{[[META3:![0-9]+]], [[META3]], i64 0}
100114
// OPT: [[META3]] = !{!"p1 int", [[META4:![0-9]+]], i64 0}
101115
// OPT: [[META4]] = !{!"any pointer", [[META5:![0-9]+]], i64 0}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// x86_64 and arm64 use preserve_all
2+
3+
// RUN: %clang_cc1 -O0 -fbounds-safety -triple arm64-apple-macos \
4+
// RUN: -emit-llvm %s -o - -fbounds-safety-soft-traps=call-minimal | \
5+
// RUN: FileCheck --check-prefixes=PRESERVE_ALL_CC,COMMON %s
6+
7+
// RUN: %clang_cc1 -O0 -fbounds-safety -triple x86_64-apple-macos \
8+
// RUN: -emit-llvm %s -o - -fbounds-safety-soft-traps=call-minimal | \
9+
// RUN: FileCheck --check-prefixes=PRESERVE_ALL_CC,COMMON %s
10+
11+
// Other targets use the normal calling convention
12+
13+
// RUN: %clang_cc1 -O0 -fbounds-safety -triple i686-apple-macos \
14+
// RUN: -emit-llvm %s -o - -fbounds-safety-soft-traps=call-minimal | \
15+
// RUN: FileCheck --check-prefixes=NORMAL_CC,COMMON %s
16+
17+
// Hidden flag can also switch off custom calling convention
18+
19+
// RUN: %clang_cc1 -O0 -fbounds-safety -triple arm64-apple-macos \
20+
// RUN: -emit-llvm %s -o - -fbounds-safety-soft-traps=call-minimal \
21+
// RUN: -mllvm -bounds-safety-soft-trap-preserve-all-cc=false | \
22+
// RUN: FileCheck --check-prefixes=NORMAL_CC,COMMON %s
23+
24+
#include <ptrcheck.h>
25+
26+
// PRESERVE_ALL_CC: call preserve_allcc void @__bounds_safety_soft_trap()
27+
// PRESERVE_ALL_CC: call preserve_allcc void @__bounds_safety_soft_trap()
28+
// PRESERVE_ALL_CC: call preserve_allcc void @__bounds_safety_soft_trap()
29+
// NORMAL_CC: call void @__bounds_safety_soft_trap()
30+
// NORMAL_CC: call void @__bounds_safety_soft_trap()
31+
// NORMAL_CC: call void @__bounds_safety_soft_trap()
32+
// COMMON-NOT: call {{.*}} void @__bounds_safety_soft_trap()
33+
int read(int* __bidi_indexable ptr, int idx) {
34+
return ptr[idx];
35+
}
36+
37+
// PRESERVE_ALL_CC: declare preserve_allcc void @__bounds_safety_soft_trap()
38+
// NORMAL_CC: declare void @__bounds_safety_soft_trap()

0 commit comments

Comments
 (0)