https://github.com/jryans updated https://github.com/llvm/llvm-project/pull/189969
>From 20b5e4c3a015bfef0f9f0b797c866b7d1fbbbb26 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" <[email protected]> Date: Wed, 1 Apr 2026 15:09:06 +0100 Subject: [PATCH 1/6] [clang][DebugInfo] Add inlined subprogram metadata for compiler built-ins This wraps compiler built-ins in an artificial inlined subprogram for debug info purposes. This makes compiler built-in usage legible to debug info consumers like profilers, which can then annotate time spent with the built-in function name. For example, calls to e.g. `__builtin_alloca` and `__builtin_memset` become visible to profilers and debuggers, improving the correspondence to the source program. --- clang/lib/CodeGen/CGBuiltin.cpp | 5 +++++ clang/lib/CodeGen/CGDebugInfo.cpp | 22 ++++++++++++++++++++++ clang/lib/CodeGen/CGDebugInfo.h | 16 ++++++++++++++++ clang/test/DebugInfo/Generic/builtin.c | 26 ++++++++++++++++++++++++++ 4 files changed, 69 insertions(+) create mode 100644 clang/test/DebugInfo/Generic/builtin.c diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 453db290243d2..3667e89aad6b2 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -2705,6 +2705,11 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, assert(!getContext().BuiltinInfo.isImmediate(BuiltinID) && "Should not codegen for consteval builtins"); + // Treat built-in as call to artificial inlined function in debug info. + // This enables e.g. profiling tools to annotate time spent in user-called + // built-ins with the built-in function name. + ApplyBuiltinDebugLocation DebugScope(*this, GD); + const FunctionDecl *FD = GD.getDecl()->getAsFunction(); // See if we can constant fold this builtin. If so, don't emit it at all. // TODO: Extend this handling to all builtin calls that we can constant-fold. diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index cdebf4ce232ea..3baff7517d5fc 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -347,6 +347,19 @@ ApplyInlineDebugLocation::~ApplyInlineDebugLocation() { DI.EmitLocation(CGF->Builder, SavedLocation); } +static llvm::DILocation *createBuiltinInlineAt(CodeGenFunction &CGF, + GlobalDecl GD) { + if (!CGF.getDebugInfo()) { + return nullptr; + } + auto &DI = *CGF.getDebugInfo(); + return DI.createBuiltinFunctionLocation(CGF.Builder, GD); +} + +ApplyBuiltinDebugLocation::ApplyBuiltinDebugLocation(CodeGenFunction &CGF, + GlobalDecl BuiltinFn) + : Apply(CGF, createBuiltinInlineAt(CGF, BuiltinFn)) {} + void CGDebugInfo::setLocation(SourceLocation Loc) { // If the new location isn't valid return. if (Loc.isInvalid()) @@ -5134,6 +5147,15 @@ void CGDebugInfo::EmitInlineFunctionEnd(CGBuilderTy &Builder) { setInlinedAt(llvm::DebugLoc(CurInlinedAt).getInlinedAt()); } +llvm::DILocation * +CGDebugInfo::createBuiltinFunctionLocation(CGBuilderTy &Builder, + GlobalDecl GD) { + const auto *FD = cast<FunctionDecl>(GD.getDecl()); + const auto Location = Builder.getCurrentDebugLocation(); + return CreateSyntheticInlineAt(Location, getFunctionName(FD), + Location->getFile()); +} + void CGDebugInfo::EmitLocation(CGBuilderTy &Builder, SourceLocation Loc) { // Update our current location setLocation(Loc); diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h index 0922c629afc46..c59495ebc6209 100644 --- a/clang/lib/CodeGen/CGDebugInfo.h +++ b/clang/lib/CodeGen/CGDebugInfo.h @@ -503,6 +503,10 @@ class CGDebugInfo { /// End an inlined function scope. void EmitInlineFunctionEnd(CGBuilderTy &Builder); + /// Create location for an inlined built-in function. + llvm::DILocation *createBuiltinFunctionLocation(CGBuilderTy &Builder, + GlobalDecl GD); + /// Emit debug info for a function declaration. /// \p Fn is set only when a declaration for a debug call site gets created. void EmitFunctionDecl(GlobalDecl GD, SourceLocation Loc, @@ -999,6 +1003,18 @@ class ApplyInlineDebugLocation { ApplyInlineDebugLocation &operator=(ApplyInlineDebugLocation &) = delete; }; +/// A scoped helper to set the current debug location to a inlined location for +/// a built-in function. The function is marked as artificial in debug info to +/// convey the built-in aspect. +class ApplyBuiltinDebugLocation { + ApplyDebugLocation Apply; + +public: + ApplyBuiltinDebugLocation(CodeGenFunction &CGF, GlobalDecl BuiltinFn); + ApplyBuiltinDebugLocation(const ApplyBuiltinDebugLocation &) = delete; + ApplyBuiltinDebugLocation &operator=(ApplyBuiltinDebugLocation &) = delete; +}; + class SanitizerDebugLocation { CodeGenFunction *CGF; ApplyDebugLocation Apply; diff --git a/clang/test/DebugInfo/Generic/builtin.c b/clang/test/DebugInfo/Generic/builtin.c new file mode 100644 index 0000000000000..396b8024e8566 --- /dev/null +++ b/clang/test/DebugInfo/Generic/builtin.c @@ -0,0 +1,26 @@ + +// RUN: %clang_cc1 -triple x86_64-linux-gnu %s -debug-info-kind=limited -emit-llvm -disable-llvm-passes -o - | FileCheck %s + +void fun() { + // CHECK: %0 = alloca i8, i64 4{{.*}}, !dbg [[B1:!.*]] + void *a = __builtin_alloca(4); + + // CHECK: %1 = alloca i8, i64 4{{.*}}, !dbg [[B2:!.*]] + // Ensure calling same built-in twice only produces one `DISubprogram` entry + void *b = __builtin_alloca(4); + + // CHECK: call void @llvm.memset{{.*}}, !dbg [[B3:!.*]] + __builtin_memset(a, 0, 4); +} + +// CHECK: [[B1]] = !DILocation(line: 0, scope: [[S1:!.*]], inlinedAt: [[I1:!.*]]) +// CHECK: [[S1]] = distinct !DISubprogram(name: "__builtin_alloca"{{.*}}, flags: DIFlagArtificial +// CHECK: [[I1]] = !DILocation(line: 6, + +// Second call should reuse same `DISubprogram` scope +// CHECK: [[B2]] = !DILocation(line: 0, scope: [[S1:!.*]], inlinedAt: [[I2:!.*]]) +// CHECK: [[I2]] = !DILocation(line: 10, + +// CHECK: [[B3]] = !DILocation(line: 0, scope: [[S3:!.*]], inlinedAt: [[I3:!.*]]) +// CHECK: [[S3]] = distinct !DISubprogram(name: "__builtin_memset"{{.*}}, flags: DIFlagArtificial +// CHECK: [[I3]] = !DILocation(line: 13, >From 65c86634efb1c7f1c0883e9718b1cc67dd5a2a1e Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" <[email protected]> Date: Wed, 8 Apr 2026 15:03:55 +0100 Subject: [PATCH 2/6] Exclude various non-call-like built-ins Several categories of built-ins should not be part of the artificial inlined function debug info treatment: - target-specific built-ins - library functions emitted as direct calls - optimisation hint built-ins - trap and exception built-ins - annotation built-ins --- clang/lib/CodeGen/CGBuiltin.cpp | 73 +++++++++++++++++++++++++- clang/lib/CodeGen/CGDebugInfo.h | 2 - clang/test/DebugInfo/Generic/builtin.c | 35 ++++++++++-- 3 files changed, 102 insertions(+), 8 deletions(-) diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 3667e89aad6b2..94f6344249851 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -2699,6 +2699,65 @@ RValue CodeGenFunction::emitStdcFirstBit(const CallExpr *E, Intrinsic::ID IntID, return RValue::get(Result); } +/// Determines whether we should treat a given built-in as a call to an +/// artificial inlined function in debug info. +static bool shouldUseBuiltinDebugLocation(unsigned BuiltinID) { + switch (BuiltinID) { + case Builtin::BI__builtin_unpredictable: + case Builtin::BI__builtin_expect: + case Builtin::BI__builtin_expect_with_probability: + case Builtin::BI__builtin_assume_aligned: + case Builtin::BI__builtin_assume_dereferenceable: + case Builtin::BI__assume: + case Builtin::BI__builtin_assume: + case Builtin::BI__builtin_assume_separate_storage: + case Builtin::BI__builtin_allow_runtime_check: + case Builtin::BI__builtin_allow_sanitize_check: + case Builtin::BI__builtin_constant_p: + case Builtin::BI__builtin_prefetch: + case Builtin::BI__builtin___clear_cache: + case Builtin::BI__builtin_unreachable: { + // Exclude optimisation hint built-ins. These are a form of communicating + // additional constraints to the compiler. + return false; + } + case Builtin::BI__builtin_trap: + case Builtin::BI__builtin_verbose_trap: + case Builtin::BI__debugbreak: + case Builtin::BI__builtin_eh_return: + case Builtin::BI__builtin_unwind_init: + case Builtin::BI__exception_code: + case Builtin::BI_exception_code: + case Builtin::BI__exception_info: + case Builtin::BI_exception_info: + case Builtin::BI__abnormal_termination: + case Builtin::BI_abnormal_termination: { + // Exclude trap and exception built-ins. These may use their own debug + // location handling, so we avoid making debug changes so they may inspect + // the caller as-is without additional debug info layers. + return false; + } + case Builtin::BI__annotation: + case Builtin::BI__builtin_annotation: { + // Exclude annotation built-ins. These attach debug-time information. + return false; + } + case Builtin::BI__builtin_operator_new: + case Builtin::BI__builtin_operator_delete: { + // Exclude C++ operator built-ins. These are emitted as normal calls. + return false; + } + } + + // Most generic (non-target-specific) built-ins are call-like, so we default + // to enabling this debug info treatment. + return true; + + // See also further exclusions of library functions emitted as normal calls + // and target-specific built-ins towards the end of `EmitBuiltinExpr` which + // overrides the value returned here. +} + RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, const CallExpr *E, ReturnValueSlot ReturnValue) { @@ -2708,7 +2767,11 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, // Treat built-in as call to artificial inlined function in debug info. // This enables e.g. profiling tools to annotate time spent in user-called // built-ins with the built-in function name. - ApplyBuiltinDebugLocation DebugScope(*this, GD); + // See `useBuiltinDebugLocation` for cases where this treatment is disabled. + auto DebugScope = + shouldUseBuiltinDebugLocation(BuiltinID) + ? std::make_optional<ApplyBuiltinDebugLocation>(*this, GD) + : std::nullopt; const FunctionDecl *FD = GD.getDecl()->getAsFunction(); // See if we can constant fold this builtin. If so, don't emit it at all. @@ -6641,6 +6704,14 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, } } + // All cases beyond this point are excluded from the artificial inlined + // function in debug info treatment: + // - library functions handled below are emitted as normal calls, so an + // inlined wrapper of the same function is redundant + // - target-specific built-ins are mainly assembly-like concepts, so they + // should not be recorded in debug info as if they were calls + DebugScope = std::nullopt; + // If this is an alias for a lib function (e.g. __builtin_sin), emit // the call using the normal call path, but using the unmangled // version of the function name. diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h index c59495ebc6209..af92273020963 100644 --- a/clang/lib/CodeGen/CGDebugInfo.h +++ b/clang/lib/CodeGen/CGDebugInfo.h @@ -1011,8 +1011,6 @@ class ApplyBuiltinDebugLocation { public: ApplyBuiltinDebugLocation(CodeGenFunction &CGF, GlobalDecl BuiltinFn); - ApplyBuiltinDebugLocation(const ApplyBuiltinDebugLocation &) = delete; - ApplyBuiltinDebugLocation &operator=(ApplyBuiltinDebugLocation &) = delete; }; class SanitizerDebugLocation { diff --git a/clang/test/DebugInfo/Generic/builtin.c b/clang/test/DebugInfo/Generic/builtin.c index 396b8024e8566..f6aa94de53f21 100644 --- a/clang/test/DebugInfo/Generic/builtin.c +++ b/clang/test/DebugInfo/Generic/builtin.c @@ -2,25 +2,50 @@ // RUN: %clang_cc1 -triple x86_64-linux-gnu %s -debug-info-kind=limited -emit-llvm -disable-llvm-passes -o - | FileCheck %s void fun() { + // Most call-like built-ins are wrapped in an artificial inlined function in + // debug info, making them visible to e.g. profiling tools. // CHECK: %0 = alloca i8, i64 4{{.*}}, !dbg [[B1:!.*]] void *a = __builtin_alloca(4); + // Ensure calling same built-in only produces one `DISubprogram` entry. // CHECK: %1 = alloca i8, i64 4{{.*}}, !dbg [[B2:!.*]] - // Ensure calling same built-in twice only produces one `DISubprogram` entry void *b = __builtin_alloca(4); // CHECK: call void @llvm.memset{{.*}}, !dbg [[B3:!.*]] __builtin_memset(a, 0, 4); + + // Ensure certain built-ins like optimisation hints are excluded. + // CHECK: call void @llvm.assume{{.*}}, !dbg [[B4:!.*]] + __builtin_assume(a != 0); + + // Ensure target-specific built-ins are excluded. + // CHECK: call i64 @llvm.x86.rdtsc(), !dbg [[B5:!.*]] + __builtin_ia32_rdtsc(); + + // Ensure library functions emitted as normal calls are excluded. + // CHECK: call ptr @malloc{{.*}}, !dbg [[B6:!.*]] + void *c = __builtin_malloc(4); } // CHECK: [[B1]] = !DILocation(line: 0, scope: [[S1:!.*]], inlinedAt: [[I1:!.*]]) // CHECK: [[S1]] = distinct !DISubprogram(name: "__builtin_alloca"{{.*}}, flags: DIFlagArtificial -// CHECK: [[I1]] = !DILocation(line: 6, +// CHECK: [[I1]] = !DILocation(line: 8, -// Second call should reuse same `DISubprogram` scope +// Second call should reuse same `DISubprogram` scope. // CHECK: [[B2]] = !DILocation(line: 0, scope: [[S1:!.*]], inlinedAt: [[I2:!.*]]) -// CHECK: [[I2]] = !DILocation(line: 10, +// CHECK: [[I2]] = !DILocation(line: 12, // CHECK: [[B3]] = !DILocation(line: 0, scope: [[S3:!.*]], inlinedAt: [[I3:!.*]]) // CHECK: [[S3]] = distinct !DISubprogram(name: "__builtin_memset"{{.*}}, flags: DIFlagArtificial -// CHECK: [[I3]] = !DILocation(line: 13, +// CHECK: [[I3]] = !DILocation(line: 15, + +// Excluded built-ins should use location without inlined function wrapper. + +// CHECK: [[B4]] = !DILocation(line: 19, +// CHECK-NOT: distinct !DISubprogram(name: "__builtin_assume"{{.*}}, flags: DIFlagArtificial + +// CHECK: [[B5]] = !DILocation(line: 23, +// CHECK-NOT: distinct !DISubprogram(name: "__builtin_ia32_rdtsc"{{.*}}, flags: DIFlagArtificial + +// CHECK: [[B6]] = !DILocation(line: 27, +// CHECK-NOT: distinct !DISubprogram(name: "__builtin_malloc"{{.*}}, flags: DIFlagArtificial >From 1346aea036249a1e333b44742cb6b0067a9e0d8e Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" <[email protected]> Date: Wed, 1 Apr 2026 15:26:16 +0100 Subject: [PATCH 3/6] Adjust test KeyInstructions/builtin.c for inlined compiler built-ins --- .../test/DebugInfo/KeyInstructions/builtin.c | 102 +++++++++++------- 1 file changed, 65 insertions(+), 37 deletions(-) diff --git a/clang/test/DebugInfo/KeyInstructions/builtin.c b/clang/test/DebugInfo/KeyInstructions/builtin.c index ce8c6124fe923..c7f63ff8420df 100644 --- a/clang/test/DebugInfo/KeyInstructions/builtin.c +++ b/clang/test/DebugInfo/KeyInstructions/builtin.c @@ -13,78 +13,106 @@ int v = 3; void fun() { // CHECK: %a = alloca ptr, align 8 -// CHECK: %0 = alloca i8, i64 4{{.*}}, !dbg [[G1R2:!.*]] -// CHECK: call void @llvm.memset{{.*}}, !dbg [[G1R1:!.*]], !annotation +// CHECK: %0 = alloca i8, i64 4{{.*}}, !dbg [[B1:!.*]] +// CHECK: call void @llvm.memset{{.*}}, !dbg [[B1:!.*]], !annotation // CHECK: store ptr %0, ptr %a{{.*}}, !dbg [[G1R1:!.*]] void *a = __builtin_alloca(4); -// CHECK: %1 = alloca i8, i64 4{{.*}}, !dbg [[G2R2:!.*]] -// CHECK: call void @llvm.memset{{.*}}, !dbg [[G2R1:!.*]], !annotation +// CHECK: %1 = alloca i8, i64 4{{.*}}, !dbg [[B2:!.*]] +// CHECK: call void @llvm.memset{{.*}}, !dbg [[B2:!.*]], !annotation // CHECK: store ptr %1, ptr %b{{.*}}, !dbg [[G2R1:!.*]] void *b = __builtin_alloca_with_align(4, 8); // CHECK: %2 = load <4 x float>, ptr @mat{{.*}}, !dbg [[G3R2:!.*]] -// CHECK: call void @llvm.matrix.column.major.store.v4f32{{.*}}, !dbg [[G3R1:!.*]] +// CHECK: call void @llvm.matrix.column.major.store.v4f32{{.*}}, !dbg [[B3:!.*]] __builtin_matrix_column_major_store(mat, f4, sizeof(float) * 2); -// CHECK: call void @llvm.memset{{.*}}, !dbg [[G4R1:!.*]] +// CHECK: call void @llvm.memset{{.*}}, !dbg [[B4:!.*]] __builtin_bzero(f4, sizeof(float) * 2); -// CHECK: call void @llvm.memmove{{.*}}, !dbg [[G5R1:!.*]] +// CHECK: call void @llvm.memmove{{.*}}, !dbg [[B5:!.*]] __builtin_bcopy(f4, f8, sizeof(float) * 4); -// CHECK: call void @llvm.memcpy{{.*}}, !dbg [[G6R1:!.*]] +// CHECK: call void @llvm.memcpy{{.*}}, !dbg [[B6:!.*]] __builtin_memcpy(f4, f8, sizeof(float) * 4); -// CHECK: call void @llvm.memcpy{{.*}}, !dbg [[G7R1:!.*]] +// CHECK: call void @llvm.memcpy{{.*}}, !dbg [[B7:!.*]] __builtin_mempcpy(f4, f8, sizeof(float) * 4); -// CHECK: call void @llvm.memcpy{{.*}}, !dbg [[G8R1:!.*]] +// CHECK: call void @llvm.memcpy{{.*}}, !dbg [[B8:!.*]] __builtin_memcpy_inline(f4, f8, sizeof(float) * 4); -// CHECK: call void @llvm.memcpy{{.*}}, !dbg [[G9R1:!.*]] +// CHECK: call void @llvm.memcpy{{.*}}, !dbg [[B9:!.*]] __builtin___memcpy_chk(f4, f8, sizeof(float) * 4, -1); -// CHECK: call void @llvm.memmove{{.*}}, !dbg [[G10R1:!.*]] +// CHECK: call void @llvm.memmove{{.*}}, !dbg [[B10:!.*]] __builtin___memmove_chk(f4, f8, sizeof(float) * 4, -1); -// CHECK: call void @llvm.memmove{{.*}}, !dbg [[G11R1:!.*]] +// CHECK: call void @llvm.memmove{{.*}}, !dbg [[B11:!.*]] __builtin_memmove(f4, f8, sizeof(float) * 4); -// CHECK: call void @llvm.memset{{.*}}, !dbg [[G12R1:!.*]] +// CHECK: call void @llvm.memset{{.*}}, !dbg [[B12:!.*]] __builtin_memset(f4, 0, sizeof(float) * 4); -// CHECK: call void @llvm.memset{{.*}}, !dbg [[G13R1:!.*]] +// CHECK: call void @llvm.memset{{.*}}, !dbg [[B13:!.*]] __builtin_memset_inline(f4, 0, sizeof(float) * 4); -// CHECK: call void @llvm.memset{{.*}}, !dbg [[G14R1:!.*]] +// CHECK: call void @llvm.memset{{.*}}, !dbg [[B14:!.*]] __builtin___memset_chk(f4, 0, sizeof(float), -1); -// CHECK: %3 = load i32, ptr @v{{.*}}, !dbg [[G15R3:!.*]] -// CHECK-NEXT: %4 = trunc i32 %3 to i8, !dbg [[G15R2:!.*]] -// CHECK-NEXT: call void @llvm.memset{{.*}}, !dbg [[G15R1:!.*]] +// CHECK: %3 = load i32, ptr @v{{.*}}, !dbg [[G4R3:!.*]] +// CHECK-NEXT: %4 = trunc i32 %3 to i8, !dbg [[B15:!.*]] +// CHECK-NEXT: call void @llvm.memset{{.*}}, !dbg [[B15:!.*]] __builtin_memset(f4, v, sizeof(float) * 4); -// CHECK: ret{{.*}}, !dbg [[RET:!.*]] +// CHECK: ret{{.*}}, !dbg [[G5R1:!.*]] } -// CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2) +// CHECK: [[B1]] = !DILocation(line: 0, scope: [[S1:!.*]], inlinedAt: [[I1:!.*]]) +// CHECK: [[S1]] = distinct !DISubprogram(name: "__builtin_alloca"{{.*}}, flags: DIFlagArtificial +// CHECK: [[I1]] = !DILocation(line: 19, // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1) -// CHECK: [[G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2) +// CHECK: [[B2]] = !DILocation(line: 0, scope: [[S2:!.*]], inlinedAt: [[I2:!.*]]) +// CHECK: [[S2]] = distinct !DISubprogram(name: "__builtin_alloca_with_align"{{.*}}, flags: DIFlagArtificial +// CHECK: [[I2]] = !DILocation(line: 24, // CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1) // CHECK: [[G3R2]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 2) -// CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1) -// CHECK: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1) +// CHECK: [[B3]] = !DILocation(line: 0, scope: [[S3:!.*]], inlinedAt: [[I3:!.*]]) +// CHECK: [[S3]] = distinct !DISubprogram(name: "__builtin_matrix_column_major_store"{{.*}}, flags: DIFlagArtificial +// CHECK: [[I3]] = !DILocation(line: 28, +// CHECK: [[B4]] = !DILocation(line: 0, scope: [[S4:!.*]], inlinedAt: [[I4:!.*]]) +// CHECK: [[S4]] = distinct !DISubprogram(name: "__builtin_bzero"{{.*}}, flags: DIFlagArtificial +// CHECK: [[I4]] = !DILocation(line: 31, +// CHECK: [[B5]] = !DILocation(line: 0, scope: [[S5:!.*]], inlinedAt: [[I5:!.*]]) +// CHECK: [[S5]] = distinct !DISubprogram(name: "__builtin_bcopy"{{.*}}, flags: DIFlagArtificial +// CHECK: [[I5]] = !DILocation(line: 34, +// CHECK: [[B6]] = !DILocation(line: 0, scope: [[S6:!.*]], inlinedAt: [[I6:!.*]]) +// CHECK: [[S6]] = distinct !DISubprogram(name: "__builtin_memcpy"{{.*}}, flags: DIFlagArtificial +// CHECK: [[I6]] = !DILocation(line: 37, +// CHECK: [[B7]] = !DILocation(line: 0, scope: [[S7:!.*]], inlinedAt: [[I7:!.*]]) +// CHECK: [[S7]] = distinct !DISubprogram(name: "__builtin_mempcpy"{{.*}}, flags: DIFlagArtificial +// CHECK: [[I7]] = !DILocation(line: 40, +// CHECK: [[B8]] = !DILocation(line: 0, scope: [[S8:!.*]], inlinedAt: [[I8:!.*]]) +// CHECK: [[S8]] = distinct !DISubprogram(name: "__builtin_memcpy_inline"{{.*}}, flags: DIFlagArtificial +// CHECK: [[I8]] = !DILocation(line: 43, +// CHECK: [[B9]] = !DILocation(line: 0, scope: [[S9:!.*]], inlinedAt: [[I9:!.*]]) +// CHECK: [[S9]] = distinct !DISubprogram(name: "__builtin___memcpy_chk"{{.*}}, flags: DIFlagArtificial +// CHECK: [[I9]] = !DILocation(line: 46, +// CHECK: [[B10]] = !DILocation(line: 0, scope: [[S10:!.*]], inlinedAt: [[I10:!.*]]) +// CHECK: [[S10]] = distinct !DISubprogram(name: "__builtin___memmove_chk"{{.*}}, flags: DIFlagArtificial +// CHECK: [[I10]] = !DILocation(line: 49, +// CHECK: [[B11]] = !DILocation(line: 0, scope: [[S11:!.*]], inlinedAt: [[I11:!.*]]) +// CHECK: [[S11]] = distinct !DISubprogram(name: "__builtin_memmove"{{.*}}, flags: DIFlagArtificial +// CHECK: [[I11]] = !DILocation(line: 52, +// CHECK: [[B12]] = !DILocation(line: 0, scope: [[S12:!.*]], inlinedAt: [[I12:!.*]]) +// CHECK: [[S12]] = distinct !DISubprogram(name: "__builtin_memset"{{.*}}, flags: DIFlagArtificial +// CHECK: [[I12]] = !DILocation(line: 55, +// CHECK: [[B13]] = !DILocation(line: 0, scope: [[S13:!.*]], inlinedAt: [[I13:!.*]]) +// CHECK: [[S13]] = distinct !DISubprogram(name: "__builtin_memset_inline"{{.*}}, flags: DIFlagArtificial +// CHECK: [[I13]] = !DILocation(line: 58, +// CHECK: [[B14]] = !DILocation(line: 0, scope: [[S14:!.*]], inlinedAt: [[I14:!.*]]) +// CHECK: [[S14]] = distinct !DISubprogram(name: "__builtin___memset_chk"{{.*}}, flags: DIFlagArtificial +// CHECK: [[I14]] = !DILocation(line: 61, +// CHECK: [[G4R3]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 3) +// CHECK: [[B15]] = !DILocation(line: 0, scope: [[S12]], inlinedAt: [[I15:!.*]]) +// CHECK: [[I15]] = !DILocation(line: 66, // CHECK: [[G5R1]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 1) -// CHECK: [[G6R1]] = !DILocation({{.*}}, atomGroup: 6, atomRank: 1) -// CHECK: [[G7R1]] = !DILocation({{.*}}, atomGroup: 7, atomRank: 1) -// CHECK: [[G8R1]] = !DILocation({{.*}}, atomGroup: 8, atomRank: 1) -// CHECK: [[G9R1]] = !DILocation({{.*}}, atomGroup: 9, atomRank: 1) -// CHECK: [[G10R1]] = !DILocation({{.*}}, atomGroup: 10, atomRank: 1) -// CHECK: [[G11R1]] = !DILocation({{.*}}, atomGroup: 11, atomRank: 1) -// CHECK: [[G12R1]] = !DILocation({{.*}}, atomGroup: 12, atomRank: 1) -// CHECK: [[G13R1]] = !DILocation({{.*}}, atomGroup: 13, atomRank: 1) -// CHECK: [[G14R1]] = !DILocation({{.*}}, atomGroup: 14, atomRank: 1) -// CHECK: [[G15R3]] = !DILocation({{.*}}, atomGroup: 15, atomRank: 3) -// CHECK: [[G15R2]] = !DILocation({{.*}}, atomGroup: 15, atomRank: 2) -// CHECK: [[G15R1]] = !DILocation({{.*}}, atomGroup: 15, atomRank: 1) -// CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 16, atomRank: 1) >From 96ff6144a1f250d02dc0f8b23069a8c9a7ac6846 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" <[email protected]> Date: Thu, 2 Apr 2026 14:37:51 +0100 Subject: [PATCH 4/6] Adjust test CodeGenOpenCL/enqueue-kernel-non-entry-block.cl for inlined compiler built-ins --- clang/test/CodeGenOpenCL/enqueue-kernel-non-entry-block.cl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/clang/test/CodeGenOpenCL/enqueue-kernel-non-entry-block.cl b/clang/test/CodeGenOpenCL/enqueue-kernel-non-entry-block.cl index 8e970f121bca8..e927a188afc13 100644 --- a/clang/test/CodeGenOpenCL/enqueue-kernel-non-entry-block.cl +++ b/clang/test/CodeGenOpenCL/enqueue-kernel-non-entry-block.cl @@ -18,7 +18,7 @@ kernel void test(int i) { // SPIR64: %block_sizes = alloca [1 x i64] // COMMON-LABEL: if.then: // COMMON-NOT: alloca -// CHECK-DEBUG: getelementptr {{.*}} %block_sizes{{.*}}, {{.*}} !dbg ![[TEMPLOCATION:[0-9]+]] +// CHECK-DEBUG: getelementptr {{.*}} %block_sizes{{.*}}, {{.*}} !dbg ![[BUILTINLOCATION:[0-9]+]] // COMMON-LABEL: if.end queue_t default_queue; unsigned flags = 0; @@ -38,4 +38,6 @@ kernel void test(int i) { // CHECK-DEBUG: ![[TESTFILE:[0-9]+]] = !DIFile(filename: "<stdin>" // CHECK-DEBUG: ![[TESTSCOPE:[0-9]+]] = distinct !DISubprogram(name: "test", linkageName: "__clang_ocl_kern_imp_test", {{.*}} file: ![[TESTFILE]] // CHECK-DEBUG: ![[IFSCOPE:[0-9]+]] = distinct !DILexicalBlock(scope: ![[TESTSCOPE]], file: ![[TESTFILE]], line: 26) -// CHECK-DEBUG: ![[TEMPLOCATION]] = !DILocation(line: 27, scope: ![[IFSCOPE]]) +// CHECK-DEBUG: ![[TEMPLOCATION:[0-9]+]] = !DILocation(line: 27, scope: ![[IFSCOPE]]) +// CHECK-DEBUG: ![[BUILTINLOCATION]] = !DILocation(line: 0, scope: ![[BUILTINSCOPE:[0-9]+]], inlinedAt: ![[TEMPLOCATION]]) +// CHECK-DEBUG: ![[BUILTINSCOPE]] = distinct !DISubprogram(name: "enqueue_kernel"{{.*}}, flags: DIFlagArtificial >From bd262ad4d5b8f99a32fa7610c947061e02db6f59 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" <[email protected]> Date: Wed, 6 May 2026 16:47:22 +0100 Subject: [PATCH 5/6] Adjust compiler-rt tests for inlined compiler built-ins --- compiler-rt/test/dfsan/origin_memcpy.c | 26 +++++++------- compiler-rt/test/dfsan/origin_memmove.c | 26 +++++++------- .../test/dfsan/origin_unaligned_memtrans.c | 36 ++++++++++--------- compiler-rt/test/dfsan/pthread.c | 7 ++-- .../test/msan/chained_origin_memcpy.cpp | 13 +++---- .../test/msan/chained_origin_memmove.cpp | 13 +++---- 6 files changed, 66 insertions(+), 55 deletions(-) diff --git a/compiler-rt/test/dfsan/origin_memcpy.c b/compiler-rt/test/dfsan/origin_memcpy.c index 5632f259ead86..03250baced10a 100644 --- a/compiler-rt/test/dfsan/origin_memcpy.c +++ b/compiler-rt/test/dfsan/origin_memcpy.c @@ -42,26 +42,28 @@ int main(int argc, char *argv[]) { // CHECK0: Taint value 0x8 {{.*}} origin tracking () // CHECK0: Origin value: {{.*}}, Taint value was stored to memory at -// CHECK0: #0 {{.*}} in fn_h.dfsan {{.*}}origin_memcpy.c:[[@LINE-16]] -// CHECK0: #1 {{.*}} in main {{.*}}origin_memcpy.c:[[@LINE-8]] +// CHECK0: #0 {{.*}} in memcpy {{.*}}origin_memcpy.c:[[@LINE-17]] +// CHECK0: #1 {{.*}} in fn_h.dfsan {{.*}}origin_memcpy.c:[[@LINE-17]] +// CHECK0: #2 {{.*}} in main {{.*}}origin_memcpy.c:[[@LINE-9]] // CHECK0: Origin value: {{.*}}, Taint value was stored to memory at -// CHECK0: #0 {{.*}} in fn_g.dfsan {{.*}}origin_memcpy.c:[[@LINE-30]] -// CHECK0: #1 {{.*}} in fn_f.dfsan {{.*}}origin_memcpy.c:[[@LINE-26]] -// CHECK0: #2 {{.*}} in main {{.*}}origin_memcpy.c:[[@LINE-14]] +// CHECK0: #0 {{.*}} in fn_g.dfsan {{.*}}origin_memcpy.c:[[@LINE-31]] +// CHECK0: #1 {{.*}} in fn_f.dfsan {{.*}}origin_memcpy.c:[[@LINE-27]] +// CHECK0: #2 {{.*}} in main {{.*}}origin_memcpy.c:[[@LINE-15]] // CHECK0: Origin value: {{.*}}, Taint value was created at -// CHECK0: #0 {{.*}} in main {{.*}}origin_memcpy.c:[[@LINE-19]] +// CHECK0: #0 {{.*}} in main {{.*}}origin_memcpy.c:[[@LINE-20]] // CHECK10: Taint value 0x10 {{.*}} origin tracking () // CHECK10: Origin value: {{.*}}, Taint value was stored to memory at -// CHECK10: #0 {{.*}} in fn_h.dfsan {{.*}}origin_memcpy.c:[[@LINE-29]] -// CHECK10: #1 {{.*}} in main {{.*}}origin_memcpy.c:[[@LINE-21]] +// CHECK10: #0 {{.*}} in memcpy {{.*}}origin_memcpy.c:[[@LINE-31]] +// CHECK10: #1 {{.*}} in fn_h.dfsan {{.*}}origin_memcpy.c:[[@LINE-31]] +// CHECK10: #2 {{.*}} in main {{.*}}origin_memcpy.c:[[@LINE-23]] // CHECK10: Origin value: {{.*}}, Taint value was stored to memory at -// CHECK10: #0 {{.*}} in fn_g.dfsan {{.*}}origin_memcpy.c:[[@LINE-43]] -// CHECK10: #1 {{.*}} in fn_f.dfsan {{.*}}origin_memcpy.c:[[@LINE-39]] -// CHECK10: #2 {{.*}} in main {{.*}}origin_memcpy.c:[[@LINE-27]] +// CHECK10: #0 {{.*}} in fn_g.dfsan {{.*}}origin_memcpy.c:[[@LINE-45]] +// CHECK10: #1 {{.*}} in fn_f.dfsan {{.*}}origin_memcpy.c:[[@LINE-41]] +// CHECK10: #2 {{.*}} in main {{.*}}origin_memcpy.c:[[@LINE-29]] // CHECK10: Origin value: {{.*}}, Taint value was created at -// CHECK10: #0 {{.*}} in main {{.*}}origin_memcpy.c:[[@LINE-31]] +// CHECK10: #0 {{.*}} in main {{.*}}origin_memcpy.c:[[@LINE-33]] diff --git a/compiler-rt/test/dfsan/origin_memmove.c b/compiler-rt/test/dfsan/origin_memmove.c index 9ec050428c69a..38a6d02302175 100644 --- a/compiler-rt/test/dfsan/origin_memmove.c +++ b/compiler-rt/test/dfsan/origin_memmove.c @@ -42,26 +42,28 @@ int main(int argc, char *argv[]) { // CHECK0: Taint value 0x8 {{.*}} origin tracking () // CHECK0: Origin value: {{.*}}, Taint value was stored to memory at -// CHECK0: #0 {{.*}} in fn_h.dfsan {{.*}}origin_memmove.c:[[@LINE-16]] -// CHECK0: #1 {{.*}} in main {{.*}}origin_memmove.c:[[@LINE-8]] +// CHECK0: #0 {{.*}} in memmove {{.*}}origin_memmove.c:[[@LINE-17]] +// CHECK0: #1 {{.*}} in fn_h.dfsan {{.*}}origin_memmove.c:[[@LINE-17]] +// CHECK0: #2 {{.*}} in main {{.*}}origin_memmove.c:[[@LINE-9]] // CHECK0: Origin value: {{.*}}, Taint value was stored to memory at -// CHECK0: #0 {{.*}} in fn_g.dfsan {{.*}}origin_memmove.c:[[@LINE-30]] -// CHECK0: #1 {{.*}} in fn_f.dfsan {{.*}}origin_memmove.c:[[@LINE-26]] -// CHECK0: #2 {{.*}} in main {{.*}}origin_memmove.c:[[@LINE-14]] +// CHECK0: #0 {{.*}} in fn_g.dfsan {{.*}}origin_memmove.c:[[@LINE-31]] +// CHECK0: #1 {{.*}} in fn_f.dfsan {{.*}}origin_memmove.c:[[@LINE-27]] +// CHECK0: #2 {{.*}} in main {{.*}}origin_memmove.c:[[@LINE-15]] // CHECK0: Origin value: {{.*}}, Taint value was created at -// CHECK0: #0 {{.*}} in main {{.*}}origin_memmove.c:[[@LINE-19]] +// CHECK0: #0 {{.*}} in main {{.*}}origin_memmove.c:[[@LINE-20]] // CHECK10: Taint value 0x10 {{.*}} origin tracking () // CHECK10: Origin value: {{.*}}, Taint value was stored to memory at -// CHECK10: #0 {{.*}} in fn_h.dfsan {{.*}}origin_memmove.c:[[@LINE-29]] -// CHECK10: #1 {{.*}} in main {{.*}}origin_memmove.c:[[@LINE-21]] +// CHECK10: #0 {{.*}} in memmove {{.*}}origin_memmove.c:[[@LINE-31]] +// CHECK10: #1 {{.*}} in fn_h.dfsan {{.*}}origin_memmove.c:[[@LINE-31]] +// CHECK10: #2 {{.*}} in main {{.*}}origin_memmove.c:[[@LINE-23]] // CHECK10: Origin value: {{.*}}, Taint value was stored to memory at -// CHECK10: #0 {{.*}} in fn_g.dfsan {{.*}}origin_memmove.c:[[@LINE-43]] -// CHECK10: #1 {{.*}} in fn_f.dfsan {{.*}}origin_memmove.c:[[@LINE-39]] -// CHECK10: #2 {{.*}} in main {{.*}}origin_memmove.c:[[@LINE-27]] +// CHECK10: #0 {{.*}} in fn_g.dfsan {{.*}}origin_memmove.c:[[@LINE-45]] +// CHECK10: #1 {{.*}} in fn_f.dfsan {{.*}}origin_memmove.c:[[@LINE-41]] +// CHECK10: #2 {{.*}} in main {{.*}}origin_memmove.c:[[@LINE-29]] // CHECK10: Origin value: {{.*}}, Taint value was created at -// CHECK10: #0 {{.*}} in main {{.*}}origin_memmove.c:[[@LINE-31]] +// CHECK10: #0 {{.*}} in main {{.*}}origin_memmove.c:[[@LINE-33]] diff --git a/compiler-rt/test/dfsan/origin_unaligned_memtrans.c b/compiler-rt/test/dfsan/origin_unaligned_memtrans.c index b465af1474fa3..35181b4254812 100644 --- a/compiler-rt/test/dfsan/origin_unaligned_memtrans.c +++ b/compiler-rt/test/dfsan/origin_unaligned_memtrans.c @@ -45,34 +45,38 @@ int main(int argc, char *argv[]) { // CHECK0: Taint value 0x8 {{.*}} origin tracking () // CHECK0: Origin value: {{.*}}, Taint value was stored to memory at -// CHECK0: #0 {{.*}} in fn_i.dfsan {{.*}}origin_unaligned_memtrans.c:[[@LINE-18]] -// CHECK0: #1 {{.*}} in main {{.*}}origin_unaligned_memtrans.c:[[@LINE-8]] +// CHECK0: #0 {{.*}} in memmove {{.*}}origin_unaligned_memtrans.c:[[@LINE-19]] +// CHECK0: #1 {{.*}} in fn_i.dfsan {{.*}}origin_unaligned_memtrans.c:[[@LINE-19]] +// CHECK0: #2 {{.*}} in main {{.*}}origin_unaligned_memtrans.c:[[@LINE-9]] // CHECK0: Origin value: {{.*}}, Taint value was stored to memory at -// CHECK0: #0 {{.*}} in fn_h.dfsan {{.*}}origin_unaligned_memtrans.c:[[@LINE-26]] -// CHECK0: #1 {{.*}} in main {{.*}}origin_unaligned_memtrans.c:[[@LINE-13]] +// CHECK0: #0 {{.*}} in memcpy {{.*}}origin_unaligned_memtrans.c:[[@LINE-28]] +// CHECK0: #1 {{.*}} in fn_h.dfsan {{.*}}origin_unaligned_memtrans.c:[[@LINE-28]] +// CHECK0: #2 {{.*}} in main {{.*}}origin_unaligned_memtrans.c:[[@LINE-15]] // CHECK0: Origin value: {{.*}}, Taint value was stored to memory at -// CHECK0: #0 {{.*}} in fn_g.dfsan {{.*}}origin_unaligned_memtrans.c:[[@LINE-38]] -// CHECK0: #1 {{.*}} in fn_f.dfsan {{.*}}origin_unaligned_memtrans.c:[[@LINE-35]] -// CHECK0: #2 {{.*}} in main {{.*}}origin_unaligned_memtrans.c:[[@LINE-19]] +// CHECK0: #0 {{.*}} in fn_g.dfsan {{.*}}origin_unaligned_memtrans.c:[[@LINE-40]] +// CHECK0: #1 {{.*}} in fn_f.dfsan {{.*}}origin_unaligned_memtrans.c:[[@LINE-37]] +// CHECK0: #2 {{.*}} in main {{.*}}origin_unaligned_memtrans.c:[[@LINE-21]] // CHECK0: Origin value: {{.*}}, Taint value was created at -// CHECK0: #0 {{.*}} in main {{.*}}origin_unaligned_memtrans.c:[[@LINE-24]] +// CHECK0: #0 {{.*}} in main {{.*}}origin_unaligned_memtrans.c:[[@LINE-26]] // CHECK10: Taint value 0x10 {{.*}} origin tracking // CHECK10: Origin value: {{.*}}, Taint value was stored to memory at -// CHECK10: #0 {{.*}} in fn_i.dfsan {{.*}}origin_unaligned_memtrans.c:[[@LINE-35]] -// CHECK10: #1 {{.*}} in main {{.*}}origin_unaligned_memtrans.c:[[@LINE-25]] +// CHECK10: #0 {{.*}} in memmove {{.*}}origin_unaligned_memtrans.c:[[@LINE-38]] +// CHECK10: #1 {{.*}} in fn_i.dfsan {{.*}}origin_unaligned_memtrans.c:[[@LINE-38]] +// CHECK10: #2 {{.*}} in main {{.*}}origin_unaligned_memtrans.c:[[@LINE-28]] // CHECK10: Origin value: {{.*}}, Taint value was stored to memory at -// CHECK10: #0 {{.*}} in fn_h.dfsan {{.*}}origin_unaligned_memtrans.c:[[@LINE-43]] -// CHECK10: #1 {{.*}} in main {{.*}}origin_unaligned_memtrans.c:[[@LINE-30]] +// CHECK10: #0 {{.*}} in memcpy {{.*}}origin_unaligned_memtrans.c:[[@LINE-47]] +// CHECK10: #1 {{.*}} in fn_h.dfsan {{.*}}origin_unaligned_memtrans.c:[[@LINE-47]] +// CHECK10: #2 {{.*}} in main {{.*}}origin_unaligned_memtrans.c:[[@LINE-34]] // CHECK10: Origin value: {{.*}}, Taint value was stored to memory at -// CHECK10: #0 {{.*}} in fn_g.dfsan {{.*}}origin_unaligned_memtrans.c:[[@LINE-55]] -// CHECK10: #1 {{.*}} in fn_f.dfsan {{.*}}origin_unaligned_memtrans.c:[[@LINE-52]] -// CHECK10: #2 {{.*}} in main {{.*}}origin_unaligned_memtrans.c:[[@LINE-36]] +// CHECK10: #0 {{.*}} in fn_g.dfsan {{.*}}origin_unaligned_memtrans.c:[[@LINE-59]] +// CHECK10: #1 {{.*}} in fn_f.dfsan {{.*}}origin_unaligned_memtrans.c:[[@LINE-56]] +// CHECK10: #2 {{.*}} in main {{.*}}origin_unaligned_memtrans.c:[[@LINE-40]] // CHECK10: Origin value: {{.*}}, Taint value was created at -// CHECK10: #0 {{.*}} in main {{.*}}origin_unaligned_memtrans.c:[[@LINE-40]] +// CHECK10: #0 {{.*}} in main {{.*}}origin_unaligned_memtrans.c:[[@LINE-44]] diff --git a/compiler-rt/test/dfsan/pthread.c b/compiler-rt/test/dfsan/pthread.c index c5b195c76998d..6db6a3342b144 100644 --- a/compiler-rt/test/dfsan/pthread.c +++ b/compiler-rt/test/dfsan/pthread.c @@ -42,10 +42,11 @@ int main(void) { // CHECK: Taint value 0x8 {{.*}} origin tracking () // CHECK: Origin value: {{.*}}, Taint value was stored to memory at -// CHECK: #0 {{.*}} in ThreadFn.dfsan {{.*}}pthread.c:[[@LINE-21]] +// CHECK: #0 {{.*}} in memcpy {{.*}}pthread.c +// CHECK: #1 {{.*}} in ThreadFn.dfsan {{.*}}pthread.c:[[@LINE-22]] // CHECK: Origin value: {{.*}}, Taint value was stored to memory at -// CHECK: #0 {{.*}} in ThreadFn.dfsan {{.*}}pthread.c:[[@LINE-26]] +// CHECK: #0 {{.*}} in ThreadFn.dfsan {{.*}}pthread.c:[[@LINE-27]] // CHECK: Origin value: {{.*}}, Taint value was created at -// CHECK: #0 {{.*}} in main {{.*}}pthread.c:[[@LINE-20]] +// CHECK: #0 {{.*}} in main {{.*}}pthread.c:[[@LINE-21]] diff --git a/compiler-rt/test/msan/chained_origin_memcpy.cpp b/compiler-rt/test/msan/chained_origin_memcpy.cpp index 8961b4cd64da6..1195df9fedc5a 100644 --- a/compiler-rt/test/msan/chained_origin_memcpy.cpp +++ b/compiler-rt/test/msan/chained_origin_memcpy.cpp @@ -48,15 +48,16 @@ int main(int argc, char *argv[]) { // CHECK: {{#0 .* in main .*chained_origin_memcpy.cpp:}}[[@LINE-4]] // CHECK: Uninitialized value was stored to memory at -// CHECK-FULL-STACK: {{#1 .* in fn_h.*chained_origin_memcpy.cpp:}}[[@LINE-15]] +// CHECK-FULL-STACK: {{#1 .* in memcpy.*chained_origin_memcpy.cpp:}}[[@LINE-16]] +// CHECK-FULL-STACK: {{#2 .* in fn_h.*chained_origin_memcpy.cpp:}}[[@LINE-16]] // CHECK-SHORT-STACK: {{#0 .* in __msan_memcpy.*msan_interceptors.cpp:}} // CHECK: Uninitialized value was stored to memory at -// CHECK-FULL-STACK: {{#0 .* in fn_g.*chained_origin_memcpy.cpp:}}[[@LINE-29]] -// CHECK-FULL-STACK: {{#1 .* in fn_f.*chained_origin_memcpy.cpp:}}[[@LINE-25]] -// CHECK-SHORT-STACK: {{#0 .* in fn_g.*chained_origin_memcpy.cpp:}}[[@LINE-31]] +// CHECK-FULL-STACK: {{#0 .* in fn_g.*chained_origin_memcpy.cpp:}}[[@LINE-30]] +// CHECK-FULL-STACK: {{#1 .* in fn_f.*chained_origin_memcpy.cpp:}}[[@LINE-26]] +// CHECK-SHORT-STACK: {{#0 .* in fn_g.*chained_origin_memcpy.cpp:}}[[@LINE-32]] // CHECK-Z1: Uninitialized value was created by an allocation of 'z1' in the stack frame // CHECK-Z2: Uninitialized value was created by an allocation of 'z2' in the stack frame -// CHECK-Z1: {{#0 .* in main.*chained_origin_memcpy.cpp:}}[[@LINE-21]] -// CHECK-Z2: {{#0 .* in main.*chained_origin_memcpy.cpp:}}[[@LINE-21]] +// CHECK-Z1: {{#0 .* in main.*chained_origin_memcpy.cpp:}}[[@LINE-22]] +// CHECK-Z2: {{#0 .* in main.*chained_origin_memcpy.cpp:}}[[@LINE-22]] diff --git a/compiler-rt/test/msan/chained_origin_memmove.cpp b/compiler-rt/test/msan/chained_origin_memmove.cpp index fcaf3735bd9d1..8fa5f3b5fb439 100644 --- a/compiler-rt/test/msan/chained_origin_memmove.cpp +++ b/compiler-rt/test/msan/chained_origin_memmove.cpp @@ -44,15 +44,16 @@ int main(int argc, char *argv[]) { // CHECK: {{#0 .* in main .*chained_origin_memmove.cpp:}}[[@LINE-4]] // CHECK: Uninitialized value was stored to memory at -// CHECK-FULL-STACK: {{#1 .* in fn_h.*chained_origin_memmove.cpp:}}[[@LINE-15]] +// CHECK-FULL-STACK: {{#1 .* in memmove.*chained_origin_memmove.cpp:}}[[@LINE-16]] +// CHECK-FULL-STACK: {{#2 .* in fn_h.*chained_origin_memmove.cpp:}}[[@LINE-16]] // CHECK-SHORT-STACK: {{#0 .* in __msan_memmove.*msan_interceptors.cpp:}} // CHECK: Uninitialized value was stored to memory at -// CHECK-FULL-STACK: {{#0 .* in fn_g.*chained_origin_memmove.cpp:}}[[@LINE-27]] -// CHECK-FULL-STACK: {{#1 .* in fn_f.*chained_origin_memmove.cpp:}}[[@LINE-24]] -// CHECK-SHORT-STACK: {{#0 .* in fn_g.*chained_origin_memmove.cpp:}}[[@LINE-29]] +// CHECK-FULL-STACK: {{#0 .* in fn_g.*chained_origin_memmove.cpp:}}[[@LINE-28]] +// CHECK-FULL-STACK: {{#1 .* in fn_f.*chained_origin_memmove.cpp:}}[[@LINE-25]] +// CHECK-SHORT-STACK: {{#0 .* in fn_g.*chained_origin_memmove.cpp:}}[[@LINE-30]] // CHECK-Z1: Uninitialized value was created by an allocation of 'z1' in the stack frame // CHECK-Z2: Uninitialized value was created by an allocation of 'z2' in the stack frame -// CHECK-Z1: {{#0 .* in main.*chained_origin_memmove.cpp:}}[[@LINE-21]] -// CHECK-Z2: {{#0 .* in main.*chained_origin_memmove.cpp:}}[[@LINE-21]] +// CHECK-Z1: {{#0 .* in main.*chained_origin_memmove.cpp:}}[[@LINE-22]] +// CHECK-Z2: {{#0 .* in main.*chained_origin_memmove.cpp:}}[[@LINE-22]] >From f7d0d469bb8d39e680d63efc3378b86809050f29 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" <[email protected]> Date: Thu, 7 May 2026 15:10:01 +0100 Subject: [PATCH 6/6] Add enabled-by-default flag for inlined compiler built-ins --- clang/include/clang/Basic/DebugOptions.def | 5 +++++ clang/include/clang/Options/Options.td | 8 ++++++++ clang/lib/CodeGen/CGBuiltin.cpp | 3 ++- clang/lib/Driver/ToolChains/Clang.cpp | 4 ++++ clang/test/DebugInfo/Generic/builtin.c | 16 ++++++++++------ clang/test/Driver/debug-options.c | 5 +++++ 6 files changed, 34 insertions(+), 7 deletions(-) diff --git a/clang/include/clang/Basic/DebugOptions.def b/clang/include/clang/Basic/DebugOptions.def index 604e87e615a69..f9366a22b5f05 100644 --- a/clang/include/clang/Basic/DebugOptions.def +++ b/clang/include/clang/Basic/DebugOptions.def @@ -68,6 +68,11 @@ DEBUGOPT(DebugColumnInfo, 1, 0, Compatible) ///< Whether or not to use column in /// Whether or not to include call site information in debug info. DEBUGOPT(DebugCallSiteInfo, 1, 1, Benign) +/// Whether to represent built-ins as calls to artificial inlined functions in +/// debug info. This enables e.g. profiling tools to annotate time spent in +/// user-called built-ins with the built-in function name. +DEBUGOPT(DebugInlinedBuiltins, 1, 1, Benign) + DEBUGOPT(DebugTypeExtRefs, 1, 0, Compatible) ///< Whether or not debug info should contain ///< external references to a PCH or module. diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td index 46e97256a9e77..68593a19513fc 100644 --- a/clang/include/clang/Options/Options.td +++ b/clang/include/clang/Options/Options.td @@ -5174,6 +5174,14 @@ def gembed_source : Flag<["-"], "gembed-source">, Group<g_flags_Group>, def gno_embed_source : Flag<["-"], "gno-embed-source">, Group<g_flags_Group>, Flags<[NoXarchOption]>, HelpText<"Restore the default behavior of not embedding source text in DWARF debug sections">; +defm inlined_builtins : BoolOption<"g", "inlined-builtins", + CodeGenOpts<"DebugInlinedBuiltins">, + DefaultTrue, + PosFlag<SetTrue, [], [], "Enable">, + NegFlag<SetFalse, [], [], "Disable">, + BothFlags<[], [ClangOption, CC1Option], " inlined compiler built-ins in debug info">>, + Group<g_flags_Group>, + DocBrief<[{Treats built-ins as calls to artificial inlined functions in debug info. This enables e.g. profiling tools to annotate time spent in user-called built-ins with the built-in function name.}]>; defm structor_decl_linkage_names : BoolGOption<"structor-decl-linkage-names", CodeGenOpts<"DebugStructorDeclLinkageNames">, DefaultTrue, diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 94f6344249851..5de8c0046d915 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -2769,7 +2769,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, // built-ins with the built-in function name. // See `useBuiltinDebugLocation` for cases where this treatment is disabled. auto DebugScope = - shouldUseBuiltinDebugLocation(BuiltinID) + CGM.getCodeGenOpts().DebugInlinedBuiltins && + shouldUseBuiltinDebugLocation(BuiltinID) ? std::make_optional<ApplyBuiltinDebugLocation>(*this, GD) : std::nullopt; diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 99f511df9e8a1..a356c062f4d0a 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4599,6 +4599,10 @@ renderDebugOptions(const ToolChain &TC, const Driver &D, const llvm::Triple &T, options::OPT_gno_call_site_info, true)) CmdArgs.push_back("-gno-call-site-info"); + if (!Args.hasFlag(options::OPT_ginlined_builtins, + options::OPT_gno_inlined_builtins, true)) + CmdArgs.push_back("-gno-inlined-builtins"); + // FIXME: Move backend command line options to the module. if (Args.hasFlag(options::OPT_gmodules, options::OPT_gno_modules, false)) { // If -gline-tables-only or -gline-directives-only is the last option it diff --git a/clang/test/DebugInfo/Generic/builtin.c b/clang/test/DebugInfo/Generic/builtin.c index f6aa94de53f21..c885302b20e48 100644 --- a/clang/test/DebugInfo/Generic/builtin.c +++ b/clang/test/DebugInfo/Generic/builtin.c @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -triple x86_64-linux-gnu %s -debug-info-kind=limited -emit-llvm -disable-llvm-passes -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu %s -debug-info-kind=limited -gno-inlined-builtins -emit-llvm -disable-llvm-passes -o - | FileCheck %s --check-prefix=CHECK-DISABLED void fun() { // Most call-like built-ins are wrapped in an artificial inlined function in @@ -29,23 +30,26 @@ void fun() { // CHECK: [[B1]] = !DILocation(line: 0, scope: [[S1:!.*]], inlinedAt: [[I1:!.*]]) // CHECK: [[S1]] = distinct !DISubprogram(name: "__builtin_alloca"{{.*}}, flags: DIFlagArtificial -// CHECK: [[I1]] = !DILocation(line: 8, +// CHECK: [[I1]] = !DILocation(line: 9, // Second call should reuse same `DISubprogram` scope. // CHECK: [[B2]] = !DILocation(line: 0, scope: [[S1:!.*]], inlinedAt: [[I2:!.*]]) -// CHECK: [[I2]] = !DILocation(line: 12, +// CHECK: [[I2]] = !DILocation(line: 13, // CHECK: [[B3]] = !DILocation(line: 0, scope: [[S3:!.*]], inlinedAt: [[I3:!.*]]) // CHECK: [[S3]] = distinct !DISubprogram(name: "__builtin_memset"{{.*}}, flags: DIFlagArtificial -// CHECK: [[I3]] = !DILocation(line: 15, +// CHECK: [[I3]] = !DILocation(line: 16, // Excluded built-ins should use location without inlined function wrapper. -// CHECK: [[B4]] = !DILocation(line: 19, +// CHECK: [[B4]] = !DILocation(line: 20, // CHECK-NOT: distinct !DISubprogram(name: "__builtin_assume"{{.*}}, flags: DIFlagArtificial -// CHECK: [[B5]] = !DILocation(line: 23, +// CHECK: [[B5]] = !DILocation(line: 24, // CHECK-NOT: distinct !DISubprogram(name: "__builtin_ia32_rdtsc"{{.*}}, flags: DIFlagArtificial -// CHECK: [[B6]] = !DILocation(line: 27, +// CHECK: [[B6]] = !DILocation(line: 28, // CHECK-NOT: distinct !DISubprogram(name: "__builtin_malloc"{{.*}}, flags: DIFlagArtificial + +// When disabled, there should not be any artificial subprograms +// CHECK-DISABLED-NOT: distinct !DISubprogram({{.*}}, flags: DIFlagArtificial diff --git a/clang/test/Driver/debug-options.c b/clang/test/Driver/debug-options.c index 92179ff9421ad..155dc273fecb9 100644 --- a/clang/test/Driver/debug-options.c +++ b/clang/test/Driver/debug-options.c @@ -300,6 +300,9 @@ // RUN: %clang -### -g -gno-call-site-info %s 2>&1 \ // RUN: | FileCheck -check-prefix=NOCALLSITE %s // +// RUN: %clang -### -g -gno-inlined-builtins %s 2>&1 \ +// RUN: | FileCheck -check-prefix=NOINLINEDBUILTINS %s +// // RUN: %clang -### -g -target x86_64-unknown-unknown %s 2>&1 \ // | FileCheck -check-prefix=CI %s // @@ -431,6 +434,8 @@ // // NOCALLSITE: "-gno-call-site-info" // +// NOINLINEDBUILTINS: "-gno-inlined-builtins" +// // GEXTREFS: "-dwarf-ext-refs" "-fmodule-format=obj" // GEXTREFS: "-debug-info-kind={{standalone|constructor}}" // NOGEXTREFS-NOT: -dwarf-ext-refs _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
