mirror of
https://github.com/intel/llvm.git
synced 2026-02-01 08:56:15 +08:00
MS Compat: mark globals emitted in read-only sections const
They cannot be written to, so marking them const makes sense and may improve optimisation. As a side-effect, SectionInfos has to be moved from Sema to ASTContext. It also fixes this problem, that occurs when compiling ATL: warning LNK4254: section 'ATL' (C0000040) merged into '.rdata' (40000040) with different attributes The ATL headers are putting variables in a special section that's marked read-only. However, Clang currently can't model that read-onlyness in the IR. But, by making the variables const, the section does become read-only, and the linker warning is avoided. Differential Revision: http://reviews.llvm.org/D5812 llvm-svn: 219960
This commit is contained in:
@@ -2328,6 +2328,31 @@ private:
|
||||
std::unique_ptr<ParentMap> AllParents;
|
||||
|
||||
std::unique_ptr<VTableContextBase> VTContext;
|
||||
|
||||
public:
|
||||
enum PragmaSectionFlag : unsigned {
|
||||
PSF_None = 0,
|
||||
PSF_Read = 0x1,
|
||||
PSF_Write = 0x2,
|
||||
PSF_Execute = 0x4,
|
||||
PSF_Implicit = 0x8,
|
||||
PSF_Invalid = 0x80000000U,
|
||||
};
|
||||
|
||||
struct SectionInfo {
|
||||
DeclaratorDecl *Decl;
|
||||
SourceLocation PragmaSectionLocation;
|
||||
int SectionFlags;
|
||||
SectionInfo() {}
|
||||
SectionInfo(DeclaratorDecl *Decl,
|
||||
SourceLocation PragmaSectionLocation,
|
||||
int SectionFlags)
|
||||
: Decl(Decl),
|
||||
PragmaSectionLocation(PragmaSectionLocation),
|
||||
SectionFlags(SectionFlags) {}
|
||||
};
|
||||
|
||||
llvm::StringMap<SectionInfo> SectionInfos;
|
||||
};
|
||||
|
||||
/// \brief Utility function for constructing a nullary selector.
|
||||
|
||||
@@ -7218,29 +7218,6 @@ public:
|
||||
PSK_CodeSeg,
|
||||
};
|
||||
|
||||
enum PragmaSectionFlag : unsigned {
|
||||
PSF_None = 0,
|
||||
PSF_Read = 0x1,
|
||||
PSF_Write = 0x2,
|
||||
PSF_Execute = 0x4,
|
||||
PSF_Implicit = 0x8,
|
||||
PSF_Invalid = 0x80000000U,
|
||||
};
|
||||
|
||||
struct SectionInfo {
|
||||
DeclaratorDecl *Decl;
|
||||
SourceLocation PragmaSectionLocation;
|
||||
int SectionFlags;
|
||||
SectionInfo() {}
|
||||
SectionInfo(DeclaratorDecl *Decl,
|
||||
SourceLocation PragmaSectionLocation,
|
||||
int SectionFlags)
|
||||
: Decl(Decl),
|
||||
PragmaSectionLocation(PragmaSectionLocation),
|
||||
SectionFlags(SectionFlags) {}
|
||||
};
|
||||
|
||||
llvm::StringMap<SectionInfo> SectionInfos;
|
||||
bool UnifySection(StringRef SectionName,
|
||||
int SectionFlags,
|
||||
DeclaratorDecl *TheDecl);
|
||||
|
||||
@@ -1931,6 +1931,13 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
|
||||
GV->setConstant(!NeedsGlobalCtor && !NeedsGlobalDtor &&
|
||||
isTypeConstant(D->getType(), true));
|
||||
|
||||
// If it is in a read-only section, mark it 'constant'.
|
||||
if (const SectionAttr *SA = D->getAttr<SectionAttr>()) {
|
||||
const ASTContext::SectionInfo &SI = Context.SectionInfos[SA->getName()];
|
||||
if ((SI.SectionFlags & ASTContext::PSF_Write) == 0)
|
||||
GV->setConstant(true);
|
||||
}
|
||||
|
||||
GV->setAlignment(getContext().getDeclAlign(D).getQuantity());
|
||||
|
||||
// Set the llvm linkage type as appropriate.
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "RAIIObjectsForParser.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
#include "clang/Lex/Preprocessor.h"
|
||||
#include "clang/Parse/ParseDiagnostic.h"
|
||||
@@ -539,20 +540,20 @@ bool Parser::HandlePragmaMSSection(StringRef PragmaName,
|
||||
<< PragmaName;
|
||||
return false;
|
||||
}
|
||||
Sema::PragmaSectionFlag Flag =
|
||||
llvm::StringSwitch<Sema::PragmaSectionFlag>(
|
||||
ASTContext::PragmaSectionFlag Flag =
|
||||
llvm::StringSwitch<ASTContext::PragmaSectionFlag>(
|
||||
Tok.getIdentifierInfo()->getName())
|
||||
.Case("read", Sema::PSF_Read)
|
||||
.Case("write", Sema::PSF_Write)
|
||||
.Case("execute", Sema::PSF_Execute)
|
||||
.Case("shared", Sema::PSF_Invalid)
|
||||
.Case("nopage", Sema::PSF_Invalid)
|
||||
.Case("nocache", Sema::PSF_Invalid)
|
||||
.Case("discard", Sema::PSF_Invalid)
|
||||
.Case("remove", Sema::PSF_Invalid)
|
||||
.Default(Sema::PSF_None);
|
||||
if (Flag == Sema::PSF_None || Flag == Sema::PSF_Invalid) {
|
||||
PP.Diag(PragmaLocation, Flag == Sema::PSF_None
|
||||
.Case("read", ASTContext::PSF_Read)
|
||||
.Case("write", ASTContext::PSF_Write)
|
||||
.Case("execute", ASTContext::PSF_Execute)
|
||||
.Case("shared", ASTContext::PSF_Invalid)
|
||||
.Case("nopage", ASTContext::PSF_Invalid)
|
||||
.Case("nocache", ASTContext::PSF_Invalid)
|
||||
.Case("discard", ASTContext::PSF_Invalid)
|
||||
.Case("remove", ASTContext::PSF_Invalid)
|
||||
.Default(ASTContext::PSF_None);
|
||||
if (Flag == ASTContext::PSF_None || Flag == ASTContext::PSF_Invalid) {
|
||||
PP.Diag(PragmaLocation, Flag == ASTContext::PSF_None
|
||||
? diag::warn_pragma_invalid_specific_action
|
||||
: diag::warn_pragma_unsupported_action)
|
||||
<< PragmaName << Tok.getIdentifierInfo()->getName();
|
||||
|
||||
@@ -363,15 +363,15 @@ void Sema::PragmaStack<ValueType>::Act(SourceLocation PragmaLocation,
|
||||
bool Sema::UnifySection(StringRef SectionName,
|
||||
int SectionFlags,
|
||||
DeclaratorDecl *Decl) {
|
||||
auto Section = SectionInfos.find(SectionName);
|
||||
if (Section == SectionInfos.end()) {
|
||||
SectionInfos[SectionName] =
|
||||
SectionInfo(Decl, SourceLocation(), SectionFlags);
|
||||
auto Section = Context.SectionInfos.find(SectionName);
|
||||
if (Section == Context.SectionInfos.end()) {
|
||||
Context.SectionInfos[SectionName] =
|
||||
ASTContext::SectionInfo(Decl, SourceLocation(), SectionFlags);
|
||||
return false;
|
||||
}
|
||||
// A pre-declared section takes precedence w/o diagnostic.
|
||||
if (Section->second.SectionFlags == SectionFlags ||
|
||||
!(Section->second.SectionFlags & PSF_Implicit))
|
||||
!(Section->second.SectionFlags & ASTContext::PSF_Implicit))
|
||||
return false;
|
||||
auto OtherDecl = Section->second.Decl;
|
||||
Diag(Decl->getLocation(), diag::err_section_conflict)
|
||||
@@ -390,11 +390,11 @@ bool Sema::UnifySection(StringRef SectionName,
|
||||
bool Sema::UnifySection(StringRef SectionName,
|
||||
int SectionFlags,
|
||||
SourceLocation PragmaSectionLocation) {
|
||||
auto Section = SectionInfos.find(SectionName);
|
||||
if (Section != SectionInfos.end()) {
|
||||
auto Section = Context.SectionInfos.find(SectionName);
|
||||
if (Section != Context.SectionInfos.end()) {
|
||||
if (Section->second.SectionFlags == SectionFlags)
|
||||
return false;
|
||||
if (!(Section->second.SectionFlags & PSF_Implicit)) {
|
||||
if (!(Section->second.SectionFlags & ASTContext::PSF_Implicit)) {
|
||||
Diag(PragmaSectionLocation, diag::err_section_conflict)
|
||||
<< "this" << "a prior #pragma section";
|
||||
Diag(Section->second.PragmaSectionLocation,
|
||||
@@ -402,8 +402,8 @@ bool Sema::UnifySection(StringRef SectionName,
|
||||
return true;
|
||||
}
|
||||
}
|
||||
SectionInfos[SectionName] =
|
||||
SectionInfo(nullptr, PragmaSectionLocation, SectionFlags);
|
||||
Context.SectionInfos[SectionName] =
|
||||
ASTContext::SectionInfo(nullptr, PragmaSectionLocation, SectionFlags);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -7334,7 +7334,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
||||
CodeSegStack.CurrentValue->getString(),
|
||||
CodeSegStack.CurrentPragmaLocation));
|
||||
if (UnifySection(CodeSegStack.CurrentValue->getString(),
|
||||
PSF_Implicit | PSF_Execute | PSF_Read, NewFD))
|
||||
ASTContext::PSF_Implicit | ASTContext::PSF_Execute |
|
||||
ASTContext::PSF_Read,
|
||||
NewFD))
|
||||
NewFD->dropAttr<SectionAttr>();
|
||||
}
|
||||
|
||||
@@ -9403,15 +9405,15 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
|
||||
if (var->isThisDeclarationADefinition() &&
|
||||
ActiveTemplateInstantiations.empty()) {
|
||||
PragmaStack<StringLiteral *> *Stack = nullptr;
|
||||
int SectionFlags = PSF_Implicit | PSF_Read;
|
||||
int SectionFlags = ASTContext::PSF_Implicit | ASTContext::PSF_Read;
|
||||
if (var->getType().isConstQualified())
|
||||
Stack = &ConstSegStack;
|
||||
else if (!var->getInit()) {
|
||||
Stack = &BSSSegStack;
|
||||
SectionFlags |= PSF_Write;
|
||||
SectionFlags |= ASTContext::PSF_Write;
|
||||
} else {
|
||||
Stack = &DataSegStack;
|
||||
SectionFlags |= PSF_Write;
|
||||
SectionFlags |= ASTContext::PSF_Write;
|
||||
}
|
||||
if (!var->hasAttr<SectionAttr>() && Stack->CurrentValue)
|
||||
var->addAttr(
|
||||
|
||||
@@ -31,6 +31,14 @@ int i;
|
||||
int TEST1;
|
||||
#pragma bss_seg(pop)
|
||||
int TEST2;
|
||||
|
||||
#pragma section("read_flag_section", read)
|
||||
// Even though they are not declared const, these become constant since they are
|
||||
// in a read-only section.
|
||||
__declspec(allocate("read_flag_section")) int unreferenced = 0;
|
||||
extern __declspec(allocate("read_flag_section")) int referenced = 42;
|
||||
int *user() { return &referenced; }
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -47,5 +55,7 @@ int TEST2;
|
||||
//CHECK: @i = global i32 0
|
||||
//CHECK: @TEST1 = global i32 0
|
||||
//CHECK: @TEST2 = global i32 0, section ".bss1"
|
||||
//CHECK: @unreferenced = constant i32 0, section "read_flag_section"
|
||||
//CHECK: @referenced = constant i32 42, section "read_flag_section"
|
||||
//CHECK: define void @g()
|
||||
//CHECK: define void @h() {{.*}} section ".my_code"
|
||||
|
||||
Reference in New Issue
Block a user