https://github.com/dpaoliello updated https://github.com/llvm/llvm-project/pull/116847
>From d97c75c91d5b4a8b6c490ce125f3c7cf0f62b234 Mon Sep 17 00:00:00 2001 From: "Daniel Paoliello (HE/HIM)" <dan...@microsoft.com> Date: Tue, 19 Nov 2024 09:34:51 -0800 Subject: [PATCH] [clang] Add support for __declspec(no_init_all) --- clang/include/clang/Basic/Attr.td | 7 +++ clang/include/clang/Basic/AttrDocs.td | 12 ++++ clang/lib/CodeGen/CGDecl.cpp | 22 ++++---- clang/test/CodeGenCXX/auto-var-init-attr.cpp | 59 ++++++++++++++++++++ 4 files changed, 90 insertions(+), 10 deletions(-) create mode 100644 clang/test/CodeGenCXX/auto-var-init-attr.cpp diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 6035a563d5fce7..634253d0032560 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -4888,3 +4888,10 @@ def ClspvLibclcBuiltin: InheritableAttr { let Documentation = [ClspvLibclcBuiltinDoc]; let SimpleHandler = 1; } + +def NoTrivialAutoVarInit: InheritableAttr { + let Spellings = [Declspec<"no_init_all">]; + let Subjects = SubjectList<[Function, Tag]>; + let Documentation = [NoTrivialAutoVarInitDocs]; + let SimpleHandler = 1; +} diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 2fdceca163ee63..8d727ac7bb4210 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -8719,6 +8719,18 @@ Attribute used by `clspv`_ (OpenCL-C to Vulkan SPIR-V compiler) to identify func }]; } +def NoTrivialAutoVarInitDocs : Documentation { + let Category = DocCatDecl; + let Content = [{ +The ``__declspec(no_init_all)`` attribute disables the automatic initialization that the +`-ftrivial-auto-var-init`_ flag would have applied to locals in a marked function, or instances of +a marked type. Note that this attribute has no effect for locals that are automatically initialized +without the `-ftrivial-auto-var-init`_ flag. + +.. _`-ftrivial-auto-var-init`: https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-ftrivial-auto-var-init +}]; +} + def DocCatNonBlockingNonAllocating : DocumentationCategory<"Performance Constraint Attributes"> { let Content = [{ The ``nonblocking``, ``blocking``, ``nonallocating`` and ``allocating`` attributes can be attached diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 6e9d28cea28e79..47b21bc9f63f04 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -1899,13 +1899,16 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { const Address Loc = locIsByrefHeader ? emission.getObjectAddress(*this) : emission.Addr; + auto hasNoTrivialAutoVarInitAttr = [&](const Decl *D) { + return D && D->hasAttr<NoTrivialAutoVarInitAttr>(); + }; // Note: constexpr already initializes everything correctly. LangOptions::TrivialAutoVarInitKind trivialAutoVarInit = - (D.isConstexpr() + ((D.isConstexpr() || D.getAttr<UninitializedAttr>() || + hasNoTrivialAutoVarInitAttr(type->getAsTagDecl()) || + hasNoTrivialAutoVarInitAttr(CurFuncDecl)) ? LangOptions::TrivialAutoVarInitKind::Uninitialized - : (D.getAttr<UninitializedAttr>() - ? LangOptions::TrivialAutoVarInitKind::Uninitialized - : getContext().getLangOpts().getTrivialAutoVarInit())); + : getContext().getLangOpts().getTrivialAutoVarInit()); auto initializeWhatIsTechnicallyUninitialized = [&](Address Loc) { if (trivialAutoVarInit == @@ -1944,13 +1947,13 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { replaceUndef(CGM, isPattern, constant)); } - if (constant && D.getType()->isBitIntType() && - CGM.getTypes().typeRequiresSplitIntoByteArray(D.getType())) { + if (constant && type->isBitIntType() && + CGM.getTypes().typeRequiresSplitIntoByteArray(type)) { // Constants for long _BitInt types are split into individual bytes. // Try to fold these back into an integer constant so it can be stored // properly. - llvm::Type *LoadType = CGM.getTypes().convertTypeForLoadStore( - D.getType(), constant->getType()); + llvm::Type *LoadType = + CGM.getTypes().convertTypeForLoadStore(type, constant->getType()); constant = llvm::ConstantFoldLoadFromConst( constant, LoadType, llvm::APInt::getZero(32), CGM.getDataLayout()); } @@ -1967,8 +1970,7 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { // It may be that the Init expression uses other uninitialized memory, // but auto-var-init here would not help, as auto-init would get // overwritten by Init. - if (!D.getType()->isScalarType() || capturedByInit || - isAccessedBy(D, Init)) { + if (!type->isScalarType() || capturedByInit || isAccessedBy(D, Init)) { initializeWhatIsTechnicallyUninitialized(Loc); } } diff --git a/clang/test/CodeGenCXX/auto-var-init-attr.cpp b/clang/test/CodeGenCXX/auto-var-init-attr.cpp new file mode 100644 index 00000000000000..5481c6e8613c56 --- /dev/null +++ b/clang/test/CodeGenCXX/auto-var-init-attr.cpp @@ -0,0 +1,59 @@ +// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown -fblocks -fdeclspec -ftrivial-auto-var-init=zero %s -emit-llvm -o - | FileCheck %s + +struct S { char c; }; +class C { char c; }; +enum class E { ZERO }; +union U { char c; int i; }; + +struct __declspec(no_init_all) NoInitS { char c; }; +class __declspec(no_init_all) NoInitC { char c; }; +enum class __declspec(no_init_all) NoInitE { ZERO }; +union __declspec(no_init_all) NoInitU { char c; int i; }; + +extern "C" { + void test_no_attr() { + // CHECK-LABEL: @test_no_attr() + // CHECK-NEXT: entry: + // CHECK-NEXT: %s = alloca %struct.S, align 1 + // CHECK-NEXT: %c = alloca %class.C, align 1 + // CHECK-NEXT: %e = alloca i32, align 4 + // CHECK-NEXT: %u = alloca %union.U, align 4 + // CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 %s, i8 0, i64 1, i1 false) + // CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 %c, i8 0, i64 1, i1 false) + // CHECK-NEXT: store i32 0, ptr %e, align 4 + // CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 4 %u, i8 0, i64 4, i1 false) + // CHECK-NEXT ret void + S s; + C c; + E e; + U u; + } + + void __declspec(no_init_all) test_attr_on_function() { + // CHECK-LABEL: @test_attr_on_function() + // CHECK-NEXT: entry: + // CHECK-NEXT: %s = alloca %struct.S, align 1 + // CHECK-NEXT: %c = alloca %class.C, align 1 + // CHECK-NEXT: %e = alloca i32, align 4 + // CHECK-NEXT: %u = alloca %union.U, align 4 + // CHECK-NEXT: ret void + S s; + C c; + E e; + U u; + } + + void test_attr_on_decl() { + // CHECK-LABEL: @test_attr_on_decl() + // CHECK-NEXT: entry: + // CHECK-NEXT: %s = alloca %struct.NoInitS, align 1 + // CHECK-NEXT: %c = alloca %class.NoInitC, align 1 + // CHECK-NEXT: %e = alloca i32, align 4 + // CHECK-NEXT: %u = alloca %union.NoInitU, align 4 + // CHECK-NEXT: ret void + NoInitS s; + NoInitC c; + NoInitE e; + NoInitU u; + } +} \ No newline at end of file _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits