diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 4e9b961688d55..bada8574e725e 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -3558,6 +3558,7 @@ OPT_LIST(V) PSF_Execute = 0x4, PSF_Implicit = 0x8, PSF_ZeroInit = 0x10, + PSF_Shared = 0x20, PSF_Invalid = 0x80000000U, }; diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index eb8d3ceeeba4c..58d965271604d 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -5696,6 +5696,10 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D, const ASTContext::SectionInfo &SI = Context.SectionInfos[SA->getName()]; if ((SI.SectionFlags & ASTContext::PSF_Write) == 0) GV->setConstant(true); + if ((SI.SectionFlags & ASTContext::PSF_Execute) != 0) + GV->setExecute(true); + if ((SI.SectionFlags & ASTContext::PSF_Shared) != 0) + GV->setShared(true); } CharUnits AlignVal = getContext().getDeclAlign(D); diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp index 21ebff1e50559..fe3267f530fe9 100644 --- a/clang/lib/Parse/ParsePragma.cpp +++ b/clang/lib/Parse/ParsePragma.cpp @@ -1108,7 +1108,7 @@ bool Parser::HandlePragmaMSSection(StringRef PragmaName, .Case("read", ASTContext::PSF_Read) .Case("write", ASTContext::PSF_Write) .Case("execute", ASTContext::PSF_Execute) - .Case("shared", ASTContext::PSF_Invalid) + .Case("shared", ASTContext::PSF_Shared) .Case("nopage", ASTContext::PSF_Invalid) .Case("nocache", ASTContext::PSF_Invalid) .Case("discard", ASTContext::PSF_Invalid) diff --git a/clang/test/CodeGenCXX/sections.cpp b/clang/test/CodeGenCXX/sections.cpp index c7fe4e45ea05a..9d03f84f7c939 100644 --- a/clang/test/CodeGenCXX/sections.cpp +++ b/clang/test/CodeGenCXX/sections.cpp @@ -102,6 +102,10 @@ __declspec(allocate("short_section")) short short_var = 42; struct t2 { t2(); }; extern const t2 non_trivial_ctor; __declspec(allocate("non_trivial_ctor_section")) const t2 non_trivial_ctor_var; +#pragma section("mysec", shared) + int j = 0; +__declspec(allocate("mysec")) int k = 0; +extern __declspec(allocate("mysec")) int var = 10; } @@ -130,6 +134,9 @@ __declspec(allocate("non_trivial_ctor_section")) const t2 non_trivial_ctor_var; //CHECK: @long_var = dso_local global i32 42, section "long_section" //CHECK: @short_var = dso_local global i16 42, section "short_section" //CHECK: @non_trivial_ctor_var = internal global %struct.t2 zeroinitializer, section "non_trivial_ctor_section" +//CHECK: @j = dso_local global i32 0, section ".data", align 4 +//CHECK: @k = dso_local constant i32 0, section "mysec", align 4 +//CHECK: @var = dso_local constant i32 10, section "mysec", align 4 //CHECK: define dso_local void @g() //CHECK: define dso_local void @h() {{.*}} section ".my_code" //CHECK: define dso_local void @h2() {{.*}} section ".my_code" diff --git a/llvm/include/llvm/IR/GlobalVariable.h b/llvm/include/llvm/IR/GlobalVariable.h index 83e484816d7d4..af7e49c2ce805 100644 --- a/llvm/include/llvm/IR/GlobalVariable.h +++ b/llvm/include/llvm/IR/GlobalVariable.h @@ -48,6 +48,8 @@ class GlobalVariable : public GlobalObject, public ilist_node { // Is this a global whose value can change from its initial value before // global initializers are run? bool isExternallyInitializedConstant : 1; + bool isExecuteGlobal : 1; + bool isSharedGlobal : 1; private: static const unsigned CodeModelBits = LastCodeModelBit - LastAlignmentBit; @@ -60,7 +62,8 @@ class GlobalVariable : public GlobalObject, public ilist_node { GlobalVariable(Type *Ty, bool isConstant, LinkageTypes Linkage, Constant *Initializer = nullptr, const Twine &Name = "", ThreadLocalMode = NotThreadLocal, unsigned AddressSpace = 0, - bool isExternallyInitialized = false); + bool isExternallyInitialized = false, bool isExecuteGlobal = false, + bool isSharedGlobal = false); /// GlobalVariable ctor - This creates a global and inserts it before the /// specified other global. GlobalVariable(Module &M, Type *Ty, bool isConstant, LinkageTypes Linkage, @@ -68,7 +71,8 @@ class GlobalVariable : public GlobalObject, public ilist_node { GlobalVariable *InsertBefore = nullptr, ThreadLocalMode = NotThreadLocal, std::optional AddressSpace = std::nullopt, - bool isExternallyInitialized = false); + bool isExternallyInitialized = false, + bool isExecuteGlobal = false, bool isSharedGlobal = false); GlobalVariable(const GlobalVariable &) = delete; GlobalVariable &operator=(const GlobalVariable &) = delete; @@ -179,6 +183,10 @@ class GlobalVariable : public GlobalObject, public ilist_node { void setExternallyInitialized(bool Val) { isExternallyInitializedConstant = Val; } + bool isExecute() const { return isExecuteGlobal; } + bool isShared() const { return isSharedGlobal; } + void setExecute(bool Val) { isExecuteGlobal = Val; } + void setShared(bool Val) { isSharedGlobal = Val; } /// copyAttributesFrom - copy all additional attributes (those not needed to /// create a GlobalVariable) from the GlobalVariable Src to this one. diff --git a/llvm/include/llvm/MC/SectionKind.h b/llvm/include/llvm/MC/SectionKind.h index 61e400fe9edee..0bc4f5ad9a1b6 100644 --- a/llvm/include/llvm/MC/SectionKind.h +++ b/llvm/include/llvm/MC/SectionKind.h @@ -23,7 +23,8 @@ class SectionKind { enum Kind { /// Metadata - Debug info sections or other metadata. Metadata, - + /// Shared + Shared, /// Exclude - This section will be excluded from the final executable or /// shared library. Only valid for ELF / COFF targets. Exclude, @@ -153,6 +154,7 @@ class SectionKind { bool isWriteable() const { return isThreadLocal() || isGlobalWriteableData(); } + bool isShared() const { return K == Shared; } bool isThreadLocal() const { return K == ThreadData || K == ThreadBSS || K == ThreadBSSLocal; @@ -190,6 +192,7 @@ class SectionKind { static SectionKind getText() { return get(Text); } static SectionKind getExecuteOnly() { return get(ExecuteOnly); } static SectionKind getReadOnly() { return get(ReadOnly); } + static SectionKind getShared() { return get(Shared); } static SectionKind getMergeable1ByteCString() { return get(Mergeable1ByteCString); } diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index fbbd92a2e0ca4..0215f0a7537a7 100644 --- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -1599,37 +1599,28 @@ getCOFFSectionFlags(SectionKind K, const TargetMachine &TM) { bool isThumb = TM.getTargetTriple().getArch() == Triple::thumb; if (K.isMetadata()) - Flags |= - COFF::IMAGE_SCN_MEM_DISCARDABLE; + Flags |= COFF::IMAGE_SCN_MEM_DISCARDABLE; else if (K.isExclude()) - Flags |= - COFF::IMAGE_SCN_LNK_REMOVE | COFF::IMAGE_SCN_MEM_DISCARDABLE; + Flags |= COFF::IMAGE_SCN_LNK_REMOVE | COFF::IMAGE_SCN_MEM_DISCARDABLE; else if (K.isText()) Flags |= - COFF::IMAGE_SCN_MEM_EXECUTE | - COFF::IMAGE_SCN_MEM_READ | - COFF::IMAGE_SCN_CNT_CODE | - (isThumb ? COFF::IMAGE_SCN_MEM_16BIT : (COFF::SectionCharacteristics)0); + COFF::IMAGE_SCN_MEM_EXECUTE | COFF::IMAGE_SCN_MEM_READ | + COFF::IMAGE_SCN_CNT_CODE | + (isThumb ? COFF::IMAGE_SCN_MEM_16BIT : (COFF::SectionCharacteristics)0); else if (K.isBSS()) - Flags |= - COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ | - COFF::IMAGE_SCN_MEM_WRITE; + Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ | + COFF::IMAGE_SCN_MEM_WRITE; else if (K.isThreadLocal()) - Flags |= - COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ | - COFF::IMAGE_SCN_MEM_WRITE; + Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ | + COFF::IMAGE_SCN_MEM_WRITE; else if (K.isReadOnly() || K.isReadOnlyWithRel()) - Flags |= - COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ; + Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ; else if (K.isWriteable()) - Flags |= - COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ | - COFF::IMAGE_SCN_MEM_WRITE; - + Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ | + COFF::IMAGE_SCN_MEM_WRITE; + else if (K.isShared()) + Flags |= COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_MEM_WRITE | + COFF::IMAGE_SCN_MEM_SHARED; return Flags; } diff --git a/llvm/lib/IR/Globals.cpp b/llvm/lib/IR/Globals.cpp index db5e1cb57b1ba..72f10c9504a1f 100644 --- a/llvm/lib/IR/Globals.cpp +++ b/llvm/lib/IR/Globals.cpp @@ -447,11 +447,13 @@ bool GlobalValue::canBeOmittedFromSymbolTable() const { GlobalVariable::GlobalVariable(Type *Ty, bool constant, LinkageTypes Link, Constant *InitVal, const Twine &Name, ThreadLocalMode TLMode, unsigned AddressSpace, - bool isExternallyInitialized) + bool isExternallyInitialized, bool isExecute, + bool isShared) : GlobalObject(Ty, Value::GlobalVariableVal, AllocMarker, Link, Name, AddressSpace), isConstantGlobal(constant), - isExternallyInitializedConstant(isExternallyInitialized) { + isExternallyInitializedConstant(isExternallyInitialized), + isExecuteGlobal(isExecute), isSharedGlobal(isShared) { assert(!Ty->isFunctionTy() && PointerType::isValidElementType(Ty) && "invalid type for global variable"); setThreadLocalMode(TLMode); @@ -469,12 +471,13 @@ GlobalVariable::GlobalVariable(Module &M, Type *Ty, bool constant, const Twine &Name, GlobalVariable *Before, ThreadLocalMode TLMode, std::optional AddressSpace, - bool isExternallyInitialized) + bool isExternallyInitialized, bool isExecute, + bool isShared) : GlobalVariable(Ty, constant, Link, InitVal, Name, TLMode, AddressSpace ? *AddressSpace : M.getDataLayout().getDefaultGlobalsAddressSpace(), - isExternallyInitialized) { + isExternallyInitialized, isExecute, isShared) { if (Before) Before->getParent()->insertGlobalVariable(Before->getIterator(), this); else diff --git a/llvm/lib/Target/TargetLoweringObjectFile.cpp b/llvm/lib/Target/TargetLoweringObjectFile.cpp index 4fe9d13d06226..8d9168e50d253 100644 --- a/llvm/lib/Target/TargetLoweringObjectFile.cpp +++ b/llvm/lib/Target/TargetLoweringObjectFile.cpp @@ -258,7 +258,11 @@ SectionKind TargetLoweringObjectFile::getKindForGlobal(const GlobalObject *GO, // into a mergable section: just drop it into the general read-only // section instead. if (!GVar->hasGlobalUnnamedAddr()) - return SectionKind::getReadOnly(); + if (GVar->isExecute()) + return SectionKind::getExecuteOnly(); + if (GVar->isShared()) + return SectionKind::getShared(); + return SectionKind::getReadOnly(); // If initializer is a null-terminated string, put it in a "cstring" // section of the right width.