rnk updated this revision to Diff 192223. rnk added a comment. Herald added a project: clang. Herald added a subscriber: cfe-commits.
- replace struct with current size Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D59797/new/ https://reviews.llvm.org/D59797 Files: clang/include/clang/Basic/Attr.td clang/include/clang/Basic/AttrDocs.td clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/SemaDeclAttr.cpp clang/test/SemaCXX/declspec-allocator.cpp lld/COFF/Chunks.cpp lld/COFF/Chunks.h llvm/include/llvm/BinaryFormat/COFF.h
Index: llvm/include/llvm/BinaryFormat/COFF.h =================================================================== --- llvm/include/llvm/BinaryFormat/COFF.h +++ llvm/include/llvm/BinaryFormat/COFF.h @@ -402,7 +402,7 @@ IMAGE_REL_ARM64_REL32 = 0x0011, }; -enum COMDATType : unsigned { +enum COMDATType : uint8_t { IMAGE_COMDAT_SELECT_NODUPLICATES = 1, IMAGE_COMDAT_SELECT_ANY, IMAGE_COMDAT_SELECT_SAME_SIZE, Index: lld/COFF/Chunks.h =================================================================== --- lld/COFF/Chunks.h +++ lld/COFF/Chunks.h @@ -50,7 +50,7 @@ // doesn't even have actual data (if common or bss). class Chunk { public: - enum Kind { SectionKind, OtherKind }; + enum Kind : uint8_t { SectionKind, OtherKind }; Kind kind() const { return ChunkKind; } virtual ~Chunk() = default; @@ -114,6 +114,12 @@ Chunk(Kind K = OtherKind) : ChunkKind(K) {} const Kind ChunkKind; +public: + // Whether this section needs to be kept distinct from other sections during + // ICF. This is set by the driver using address-significance tables. + bool KeepUnique = false; + +protected: // The RVA of this chunk in the output. The writer sets a value. uint64_t RVA = 0; @@ -123,10 +129,6 @@ public: // The offset from beginning of the output section. The writer sets a value. uint64_t OutputSectionOff = 0; - - // Whether this section needs to be kept distinct from other sections during - // ICF. This is set by the driver using address-significance tables. - bool KeepUnique = false; }; // A chunk corresponding a section of an input file. @@ -217,36 +219,41 @@ bool isHotPatchable() const override { return File->HotPatchable; } - // A pointer pointing to a replacement for this chunk. - // Initially it points to "this" object. If this chunk is merged - // with other chunk by ICF, it points to another chunk, - // and this chunk is considered as dead. - SectionChunk *Repl; - - // The CRC of the contents as described in the COFF spec 4.5.5. - // Auxiliary Format 5: Section Definitions. Used for ICF. - uint32_t Checksum = 0; - - const coff_section *Header; - // The file that this chunk was created from. ObjFile *File; + // Pointer to the COFF section header in the input file. + const coff_section *Header; + // The COMDAT leader symbol if this is a COMDAT chunk. DefinedRegular *Sym = nullptr; - // The COMDAT selection if this is a COMDAT chunk. - llvm::COFF::COMDATType Selection = (llvm::COFF::COMDATType)0; - + // Relocations for this section. ArrayRef<coff_relocation> Relocs; - // Used by the garbage collector. - bool Live; - // When inserting a thunk, we need to adjust a relocation to point to // the thunk instead of the actual original target Symbol. std::vector<Symbol *> RelocTargets; + // The CRC of the contents as described in the COFF spec 4.5.5. + // Auxiliary Format 5: Section Definitions. Used for ICF. + uint32_t Checksum = 0; + + // Indicates whether the section should be included in the output file. + // Sections may become dead if the garbage collector discards them, if ICF + // replaces them, or if they are associated with a non-prevailing comdat + // section. + bool Live; + + // The COMDAT selection if this is a COMDAT chunk. + llvm::COFF::COMDATType Selection = (llvm::COFF::COMDATType)0; + + // A pointer pointing to a replacement for this chunk. + // Initially it points to "this" object. If this chunk is merged + // with other chunk by ICF, it points to another chunk, + // and this chunk is considered as dead. + SectionChunk *Repl; + private: StringRef SectionName; std::vector<SectionChunk *> AssocChildren; Index: lld/COFF/Chunks.cpp =================================================================== --- lld/COFF/Chunks.cpp +++ lld/COFF/Chunks.cpp @@ -30,8 +30,8 @@ namespace coff { SectionChunk::SectionChunk(ObjFile *F, const coff_section *H) - : Chunk(SectionKind), Repl(this), Header(H), File(F), - Relocs(File->getCOFFObj()->getRelocations(Header)) { + : Chunk(SectionKind), File(F), Header(H), + Relocs(File->getCOFFObj()->getRelocations(Header)), Repl(this) { // Initialize SectionName. File->getCOFFObj()->getSectionName(Header, SectionName); @@ -44,6 +44,11 @@ Live = !Config->DoGC || !isCOMDAT(); } +// SectionChunk is one of the most frequently allocated classes, so it is +// important to keep it as compact as possible. 168 happens to be the size of +// the class on x64 as of this writing. +static_assert(sizeof(SectionChunk) <= 168, "SectionChunk grew unexpectedly"); + // Initialize the RelocTargets vector, to allow redirecting certain relocations // to a thunk instead of the actual symbol the relocation's symbol table index // indicates. Index: clang/test/SemaCXX/declspec-allocator.cpp =================================================================== --- /dev/null +++ clang/test/SemaCXX/declspec-allocator.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fms-compatibility -triple x86_64-windows-msvc -std=c++14 -fms-extensions -fms-compatibility-version=19.00 -verify %s + +__declspec(allocator) int err_on_data; // expected-warning {{'allocator' attribute only applies to functions}} +__declspec(allocator) struct ErrOnStruct1; // expected-warning {{place it after "struct" to apply attribute}} +struct __declspec(allocator) ErrOnStruct2 {}; // expected-warning {{'allocator' attribute only applies to functions}} +__declspec(allocator) void err_on_ret_void(); // expected-warning {{not a pointer or reference type}} +__declspec(allocator) int err_on_ret_int(); // expected-warning {{not a pointer or reference type}} +__declspec(allocator) void *accept_on_ptr1(); +__declspec(allocator) void *accept_on_ptr2(size_t); +void * __declspec(allocator) accept_on_ptr3(size_t); // expected-error {{expected unqualified-id}} + +struct Foo { int x; }; +__declspec(allocator) Foo *accept_nonvoid_ptr(size_t); Index: clang/lib/Sema/SemaDeclAttr.cpp =================================================================== --- clang/lib/Sema/SemaDeclAttr.cpp +++ clang/lib/Sema/SemaDeclAttr.cpp @@ -6548,6 +6548,20 @@ handleSimpleAttribute<MIGServerRoutineAttr>(S, D, AL); } +static void handleMSAllocatorAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + // Warn if the return type is not a pointer or reference type. + if (auto *FD = dyn_cast<FunctionDecl>(D)) { + QualType RetTy = FD->getReturnType(); + if (!RetTy->isPointerType() && !RetTy->isReferenceType()) { + S.Diag(AL.getLoc(), diag::warn_declspec_allocator_nonpointer) + << AL.getRange() << RetTy; + return; + } + } + + handleSimpleAttribute<MSAllocatorAttr>(S, D, AL); +} + //===----------------------------------------------------------------------===// // Top Level Sema Entry Points //===----------------------------------------------------------------------===// @@ -7281,6 +7295,10 @@ case ParsedAttr::AT_MIGServerRoutine: handleMIGServerRoutineAttr(S, D, AL); break; + + case ParsedAttr::AT_MSAllocator: + handleMSAllocatorAttr(S, D, AL); + break; } } Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2956,6 +2956,9 @@ "%0 attribute cannot be applied to a base specifier">; def err_invalid_attribute_on_virtual_function : Error< "%0 attribute cannot be applied to virtual functions">; +def warn_declspec_allocator_nonpointer : Warning< + "ignoring __declspec(allocator) because the function return type %0 is not " + "a pointer or reference type">, InGroup<IgnoredAttributes>; def ext_cannot_use_trivial_abi : ExtWarn< "'trivial_abi' cannot be applied to %0">, InGroup<IgnoredAttributes>; Index: clang/include/clang/Basic/AttrDocs.td =================================================================== --- clang/include/clang/Basic/AttrDocs.td +++ clang/include/clang/Basic/AttrDocs.td @@ -4089,3 +4089,20 @@ attribute can also be written using C++11 syntax: ``[[mig::server_routine]]``. }]; } + +def MSAllocatorDocs : Documentation { + let Category = DocCatType; + let Content = [{ +The ``__declspec(allocator)`` attribute is applied to functions that allocate +memory, such as operator new in C++. When CodeView debug information is emitted +(enabled by ``clang -gcodeview`` or ``clang-cl /Z7``), Clang will attempt to +record the code offset of heap allocation call sites in the debug info. It will +also record the type being allocated using some local heuristics. The Visual +Studio debugger uses this information to `profile memory usage`_. + +.. _profile memory usage: https://docs.microsoft.com/en-us/visualstudio/profiling/memory-usage + +This attribute does not affect optimizations in any way, unlike GCC's +``__attribute__((malloc))``. +}]; +} Index: clang/include/clang/Basic/Attr.td =================================================================== --- clang/include/clang/Basic/Attr.td +++ clang/include/clang/Basic/Attr.td @@ -2757,6 +2757,12 @@ let Spellings = [Declspec<"property">]; } +def MSAllocator : InheritableAttr { + let Spellings = [Declspec<"allocator">]; + let Subjects = SubjectList<[Function]>; + let Documentation = [MSAllocatorDocs]; +} + def MSStruct : InheritableAttr { let Spellings = [GCC<"ms_struct">]; let Subjects = SubjectList<[Record]>;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits