-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[AllocToken, Clang] Implement __builtin_infer_alloc_token() and llvm.alloc.token.id #156842
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: users/melver/spr/main.alloctoken-clang-implement-__builtin_alloc_token_infer-and-llvmalloctokenid
Are you sure you want to change the base?
Changes from 6 commits
a5dccd9
131332f
f2ca41f
48227c8
b7f4c7f
548eba5
3aa00d1
72f662e
7a33b73
ba5bb6e
3bad95e
5fb8572
80f47ce
5db2e34
28f29d9
a09fc1e
dacf09a
a2df6e7
ee0275d
ab980ba
e94eeee
d3e693f
00bf24a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -794,16 +794,6 @@ static void addSanitizers(const Triple &TargetTriple, | |
if (LangOpts.Sanitize.has(SanitizerKind::DataFlow)) { | ||
MPM.addPass(DataFlowSanitizerPass(LangOpts.NoSanitizeFiles)); | ||
} | ||
|
||
if (LangOpts.Sanitize.has(SanitizerKind::AllocToken)) { | ||
if (Level == OptimizationLevel::O0) { | ||
// The default pass builder only infers libcall function attrs when | ||
// optimizing, so we insert it here because we need it for accurate | ||
// memory allocation function detection. | ||
MPM.addPass(InferFunctionAttrsPass()); | ||
} | ||
MPM.addPass(AllocTokenPass(getAllocTokenOptions(CodeGenOpts))); | ||
} | ||
}; | ||
if (ClSanitizeOnOptimizerEarlyEP) { | ||
PB.registerOptimizerEarlyEPCallback( | ||
|
@@ -846,6 +836,22 @@ static void addSanitizers(const Triple &TargetTriple, | |
} | ||
} | ||
|
||
static void addAllocTokenPass(const Triple &TargetTriple, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd rather separate sema changes from codegen There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Separate llvm/.. from clang/.. changes? One is useless without the other, and at least this way, if there's a problem, we can atomically revert one commit instead of several or partially reverting one or several commits. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Clang part looks deppends on LLVM but can be separated. |
||
const CodeGenOptions &CodeGenOpts, | ||
const LangOptions &LangOpts, PassBuilder &PB) { | ||
PB.registerOptimizerLastEPCallback( | ||
[&](ModulePassManager &MPM, OptimizationLevel Level, ThinOrFullLTOPhase) { | ||
if (Level == OptimizationLevel::O0 && | ||
LangOpts.Sanitize.has(SanitizerKind::AllocToken)) { | ||
// The default pass builder only infers libcall function attrs when | ||
// optimizing, so we insert it here because we need it for accurate | ||
// memory allocation function detection with -fsanitize=alloc-token. | ||
MPM.addPass(InferFunctionAttrsPass()); | ||
} | ||
MPM.addPass(AllocTokenPass(getAllocTokenOptions(CodeGenOpts))); | ||
}); | ||
} | ||
|
||
void EmitAssemblyHelper::RunOptimizationPipeline( | ||
BackendAction Action, std::unique_ptr<raw_pwrite_stream> &OS, | ||
std::unique_ptr<llvm::ToolOutputFile> &ThinLinkOS, BackendConsumer *BC) { | ||
|
@@ -1101,6 +1107,7 @@ void EmitAssemblyHelper::RunOptimizationPipeline( | |
if (!IsThinLTOPostLink) { | ||
addSanitizers(TargetTriple, CodeGenOpts, LangOpts, PB); | ||
addKCFIPass(TargetTriple, LangOpts, PB); | ||
addAllocTokenPass(TargetTriple, CodeGenOpts, LangOpts, PB); | ||
} | ||
|
||
if (std::optional<GCOVOptions> Options = | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
// Test IR generation of the builtin without evaluating the LLVM intrinsic. | ||
// RUN: %clang_cc1 -triple x86_64-linux-gnu -Werror -std=c++20 -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-CODEGEN | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. backendutils and CG* changes also seems unrelated |
||
// RUN: %clang_cc1 -triple x86_64-linux-gnu -Werror -std=c++20 -emit-llvm -falloc-token-max=2 %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-LOWER | ||
|
||
extern "C" void *my_malloc(unsigned long, unsigned long); | ||
|
||
struct NoPtr { | ||
int x; | ||
long y; | ||
}; | ||
|
||
struct WithPtr { | ||
int a; | ||
char *buf; | ||
}; | ||
|
||
int unevaluated_fn(); | ||
|
||
// CHECK-LABEL: @_Z16test_builtin_intv( | ||
unsigned long long test_builtin_int() { | ||
// CHECK-CODEGEN: call i64 @llvm.alloc.token.id(metadata ![[MD_INT:[0-9]+]]) | ||
// CHECK-LOWER: ret i64 0 | ||
return __builtin_alloc_token_infer(sizeof(1)); | ||
} | ||
|
||
// CHECK-LABEL: @_Z16test_builtin_ptrv( | ||
unsigned long long test_builtin_ptr() { | ||
// CHECK-CODEGEN: call i64 @llvm.alloc.token.id(metadata ![[MD_PTR:[0-9]+]]) | ||
// CHECK-LOWER: ret i64 1 | ||
return __builtin_alloc_token_infer(sizeof(int *)); | ||
} | ||
|
||
// CHECK-LABEL: @_Z25test_builtin_struct_noptrv( | ||
unsigned long long test_builtin_struct_noptr() { | ||
// CHECK-CODEGEN: call i64 @llvm.alloc.token.id(metadata ![[MD_NOPTR:[0-9]+]]) | ||
// CHECK-LOWER: ret i64 0 | ||
return __builtin_alloc_token_infer(sizeof(NoPtr)); | ||
} | ||
|
||
// CHECK-LABEL: @_Z25test_builtin_struct_w_ptrv( | ||
unsigned long long test_builtin_struct_w_ptr() { | ||
// CHECK-CODEGEN: call i64 @llvm.alloc.token.id(metadata ![[MD_WITHPTR:[0-9]+]]) | ||
// CHECK-LOWER: ret i64 1 | ||
return __builtin_alloc_token_infer(sizeof(WithPtr), 123); | ||
} | ||
|
||
// CHECK-LABEL: @_Z24test_builtin_unevaluatedv( | ||
unsigned long long test_builtin_unevaluated() { | ||
// CHECK-NOT: call{{.*}}unevaluated_fn | ||
// CHECK-CODEGEN: call i64 @llvm.alloc.token.id(metadata ![[MD_INT:[0-9]+]]) | ||
// CHECK-LOWER: ret i64 0 | ||
return __builtin_alloc_token_infer(sizeof(int) * unevaluated_fn()); | ||
} | ||
|
||
// CHECK-LABEL: @_Z36test_builtin_unsequenced_unevaluatedi( | ||
void test_builtin_unsequenced_unevaluated(int x) { | ||
// CHECK: add nsw | ||
// CHECK-NOT: add nsw | ||
// CHECK-CODEGEN: %[[REG:[0-9]+]] = call i64 @llvm.alloc.token.id(metadata ![[MD_UNKNOWN:[0-9]+]]) | ||
// CHECK-CODEGEN: call{{.*}}@my_malloc({{.*}}, i64 noundef %[[REG]]) | ||
// CHECK-LOWER: call{{.*}}@my_malloc({{.*}}, i64 noundef 0) | ||
my_malloc(++x, __builtin_alloc_token_infer(++x)); | ||
} | ||
|
||
// CHECK-LABEL: @_Z20test_builtin_unknownv( | ||
unsigned long long test_builtin_unknown() { | ||
// CHECK-CODEGEN: call i64 @llvm.alloc.token.id(metadata ![[MD_UNKNOWN:[0-9]+]]) | ||
// CHECK-LOWER: ret i64 0 | ||
return __builtin_alloc_token_infer(4096); | ||
} | ||
|
||
// CHECK-CODEGEN: ![[MD_INT]] = !{!"int", i1 false} | ||
// CHECK-CODEGEN: ![[MD_PTR]] = !{!"int *", i1 true} | ||
// CHECK-CODEGEN: ![[MD_NOPTR]] = !{!"NoPtr", i1 false} | ||
// CHECK-CODEGEN: ![[MD_WITHPTR]] = !{!"WithPtr", i1 true} | ||
// CHECK-CODEGEN: ![[MD_UNKNOWN]] = !{} |
Uh oh!
There was an error while loading. Please reload this page.