forked from OSchip/llvm-project
Add support for #pragma clang section
This patch provides a means to specify section-names for global variables, functions and static variables, using #pragma directives. This feature is only defined to work sensibly for ELF targets. One can specify section names as: #pragma clang section bss="myBSS" data="myData" rodata="myRodata" text="myText" One can "unspecify" a section name with empty string e.g. #pragma clang section bss="" data="" text="" rodata="" Reviewers: Roger Ferrer, Jonathan Roelofs, Reid Kleckner Differential Revision: https://reviews.llvm.org/D33412 llvm-svn: 304705
This commit is contained in:
parent
b16d146838
commit
2a67c9ee39
|
@ -2521,3 +2521,45 @@ whether or not an attribute is supported by the pragma by referring to the
|
|||
The attributes are applied to all matching declarations individually, even when
|
||||
the attribute is semantically incorrect. The attributes that aren't applied to
|
||||
any declaration are not verified semantically.
|
||||
|
||||
Specifying section names for global objects (#pragma clang section)
|
||||
===================================================================
|
||||
|
||||
The ``#pragma clang section`` directive provides a means to assign section-names
|
||||
to global variables, functions and static variables.
|
||||
|
||||
The section names can be specified as:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
#pragma clang section bss="myBSS" data="myData" rodata="myRodata" text="myText"
|
||||
|
||||
The section names can be reverted back to default name by supplying an empty
|
||||
string to the section kind, for example:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
#pragma clang section bss="" data="" text="" rodata=""
|
||||
|
||||
The ``#pragma clang section`` directive obeys the following rules:
|
||||
|
||||
* The pragma applies to all global variable, statics and function declarations
|
||||
from the pragma to the end of the translation unit.
|
||||
|
||||
* The pragma clang section is enabled automatically, without need of any flags.
|
||||
|
||||
* This feature is only defined to work sensibly for ELF targets.
|
||||
|
||||
* If section name is specified through _attribute_((section("myname"))), then
|
||||
the attribute name gains precedence.
|
||||
|
||||
* Global variables that are initialized to zero will be placed in the named
|
||||
bss section, if one is present.
|
||||
|
||||
* The ``#pragma clang section`` directive does not does try to infer section-kind
|
||||
from the name. For example, naming a section "``.bss.mySec``" does NOT mean
|
||||
it will be a bss section name.
|
||||
|
||||
* The decision about which section-kind applies to each global is taken in the back-end.
|
||||
Once the section-kind is known, appropriate section name, as specified by the user using
|
||||
``#pragma clang section`` directive, is applied to that global.
|
||||
|
|
|
@ -1683,6 +1683,42 @@ def Section : InheritableAttr {
|
|||
let Documentation = [SectionDocs];
|
||||
}
|
||||
|
||||
def PragmaClangBSSSection : InheritableAttr {
|
||||
// This attribute has no spellings as it is only ever created implicitly.
|
||||
let Spellings = [];
|
||||
let Args = [StringArgument<"Name">];
|
||||
let Subjects = SubjectList<[GlobalVar], ErrorDiag,
|
||||
"ExpectedFunctionMethodOrGlobalVar">;
|
||||
let Documentation = [Undocumented];
|
||||
}
|
||||
|
||||
def PragmaClangDataSection : InheritableAttr {
|
||||
// This attribute has no spellings as it is only ever created implicitly.
|
||||
let Spellings = [];
|
||||
let Args = [StringArgument<"Name">];
|
||||
let Subjects = SubjectList<[GlobalVar], ErrorDiag,
|
||||
"ExpectedFunctionMethodOrGlobalVar">;
|
||||
let Documentation = [Undocumented];
|
||||
}
|
||||
|
||||
def PragmaClangRodataSection : InheritableAttr {
|
||||
// This attribute has no spellings as it is only ever created implicitly.
|
||||
let Spellings = [];
|
||||
let Args = [StringArgument<"Name">];
|
||||
let Subjects = SubjectList<[GlobalVar], ErrorDiag,
|
||||
"ExpectedFunctionMethodOrGlobalVar">;
|
||||
let Documentation = [Undocumented];
|
||||
}
|
||||
|
||||
def PragmaClangTextSection : InheritableAttr {
|
||||
// This attribute has no spellings as it is only ever created implicitly.
|
||||
let Spellings = [];
|
||||
let Args = [StringArgument<"Name">];
|
||||
let Subjects = SubjectList<[Function], ErrorDiag,
|
||||
"ExpectedFunctionMethodOrGlobalVar">;
|
||||
let Documentation = [Undocumented];
|
||||
}
|
||||
|
||||
def Sentinel : InheritableAttr {
|
||||
let Spellings = [GCC<"sentinel">];
|
||||
let Args = [DefaultIntArgument<"Sentinel", 0>,
|
||||
|
|
|
@ -887,9 +887,18 @@ def warn_pragma_expected_rparen : Warning<
|
|||
"missing ')' after '#pragma %0' - ignoring">, InGroup<IgnoredPragmas>;
|
||||
def warn_pragma_expected_identifier : Warning<
|
||||
"expected identifier in '#pragma %0' - ignored">, InGroup<IgnoredPragmas>;
|
||||
|
||||
// '#pragma clang section' related errors
|
||||
def err_pragma_expected_clang_section_name : Error<
|
||||
"expected one of [bss|data|rodata|text] section kind in '#pragma %0'">;
|
||||
def err_pragma_clang_section_expected_equal : Error<
|
||||
"expected '=' following '#pragma clang section %select{invalid|bss|data|rodata|text}0'">;
|
||||
def err_pragma_clang_section_expected_name_or_clear : Error<
|
||||
"expected section name or '\"\"' following '#pragma clang section %select{invalid|bss|data|rodata|text}0'">;
|
||||
def warn_pragma_expected_section_name : Warning<
|
||||
"expected a string literal for the section name in '#pragma %0' - ignored">,
|
||||
InGroup<IgnoredPragmas>;
|
||||
|
||||
def warn_pragma_expected_section_push_pop_or_name : Warning<
|
||||
"expected push, pop or a string literal for the section name in '#pragma %0' - ignored">,
|
||||
InGroup<IgnoredPragmas>;
|
||||
|
|
|
@ -166,6 +166,7 @@ class Parser : public CodeCompletionHandler {
|
|||
std::unique_ptr<PragmaHandler> FPContractHandler;
|
||||
std::unique_ptr<PragmaHandler> OpenCLExtensionHandler;
|
||||
std::unique_ptr<PragmaHandler> OpenMPHandler;
|
||||
std::unique_ptr<PragmaHandler> PCSectionHandler;
|
||||
std::unique_ptr<PragmaHandler> MSCommentHandler;
|
||||
std::unique_ptr<PragmaHandler> MSDetectMismatchHandler;
|
||||
std::unique_ptr<PragmaHandler> MSPointersToMembers;
|
||||
|
|
|
@ -336,6 +336,35 @@ public:
|
|||
/// \brief Source location for newly created implicit MSInheritanceAttrs
|
||||
SourceLocation ImplicitMSInheritanceAttrLoc;
|
||||
|
||||
/// \brief pragma clang section kind
|
||||
enum PragmaClangSectionKind {
|
||||
PCSK_Invalid = 0,
|
||||
PCSK_BSS = 1,
|
||||
PCSK_Data = 2,
|
||||
PCSK_Rodata = 3,
|
||||
PCSK_Text = 4
|
||||
};
|
||||
|
||||
enum PragmaClangSectionAction {
|
||||
PCSA_Set = 0,
|
||||
PCSA_Clear = 1
|
||||
};
|
||||
|
||||
struct PragmaClangSection {
|
||||
std::string SectionName;
|
||||
bool Valid = false;
|
||||
SourceLocation PragmaLocation;
|
||||
|
||||
void Act(SourceLocation PragmaLocation,
|
||||
PragmaClangSectionAction Action,
|
||||
StringLiteral* Name);
|
||||
};
|
||||
|
||||
PragmaClangSection PragmaClangBSSSection;
|
||||
PragmaClangSection PragmaClangDataSection;
|
||||
PragmaClangSection PragmaClangRodataSection;
|
||||
PragmaClangSection PragmaClangTextSection;
|
||||
|
||||
enum PragmaMsStackAction {
|
||||
PSK_Reset = 0x0, // #pragma ()
|
||||
PSK_Set = 0x1, // #pragma (value)
|
||||
|
@ -8117,6 +8146,11 @@ public:
|
|||
POAK_Reset // #pragma options align=reset
|
||||
};
|
||||
|
||||
/// ActOnPragmaClangSection - Called on well formed \#pragma clang section
|
||||
void ActOnPragmaClangSection(SourceLocation PragmaLoc,
|
||||
PragmaClangSectionAction Action,
|
||||
PragmaClangSectionKind SecKind, StringRef SecName);
|
||||
|
||||
/// ActOnPragmaOptionsAlign - Called on well formed \#pragma options align.
|
||||
void ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
|
||||
SourceLocation PragmaLoc);
|
||||
|
|
|
@ -406,6 +406,13 @@ void CodeGenFunction::EmitStaticVarDecl(const VarDecl &D,
|
|||
if (D.hasAttr<AnnotateAttr>())
|
||||
CGM.AddGlobalAnnotations(&D, var);
|
||||
|
||||
if (auto *SA = D.getAttr<PragmaClangBSSSectionAttr>())
|
||||
var->addAttribute("bss-section", SA->getName());
|
||||
if (auto *SA = D.getAttr<PragmaClangDataSectionAttr>())
|
||||
var->addAttribute("data-section", SA->getName());
|
||||
if (auto *SA = D.getAttr<PragmaClangRodataSectionAttr>())
|
||||
var->addAttribute("rodata-section", SA->getName());
|
||||
|
||||
if (const SectionAttr *SA = D.getAttr<SectionAttr>())
|
||||
var->setSection(SA->getName());
|
||||
|
||||
|
|
|
@ -1026,9 +1026,25 @@ void CodeGenModule::setNonAliasAttributes(const Decl *D,
|
|||
llvm::GlobalObject *GO) {
|
||||
SetCommonAttributes(D, GO);
|
||||
|
||||
if (D)
|
||||
if (D) {
|
||||
if (auto *GV = dyn_cast<llvm::GlobalVariable>(GO)) {
|
||||
if (auto *SA = D->getAttr<PragmaClangBSSSectionAttr>())
|
||||
GV->addAttribute("bss-section", SA->getName());
|
||||
if (auto *SA = D->getAttr<PragmaClangDataSectionAttr>())
|
||||
GV->addAttribute("data-section", SA->getName());
|
||||
if (auto *SA = D->getAttr<PragmaClangRodataSectionAttr>())
|
||||
GV->addAttribute("rodata-section", SA->getName());
|
||||
}
|
||||
|
||||
if (auto *F = dyn_cast<llvm::Function>(GO)) {
|
||||
if (auto *SA = D->getAttr<PragmaClangTextSectionAttr>())
|
||||
if (!D->getAttr<SectionAttr>())
|
||||
F->addFnAttr("implicit-section-name", SA->getName());
|
||||
}
|
||||
|
||||
if (const SectionAttr *SA = D->getAttr<SectionAttr>())
|
||||
GO->setSection(SA->getName());
|
||||
}
|
||||
|
||||
getTargetCodeGenInfo().setTargetAttributes(D, GO, *this);
|
||||
}
|
||||
|
@ -1127,6 +1143,10 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
|
|||
|
||||
setLinkageAndVisibilityForGV(F, FD);
|
||||
|
||||
if (FD->getAttr<PragmaClangTextSectionAttr>()) {
|
||||
F->addFnAttr("implicit-section-name");
|
||||
}
|
||||
|
||||
if (const SectionAttr *SA = FD->getAttr<SectionAttr>())
|
||||
F->setSection(SA->getName());
|
||||
|
||||
|
@ -2828,6 +2848,14 @@ static bool isVarDeclStrongDefinition(const ASTContext &Context,
|
|||
if (D->hasAttr<SectionAttr>())
|
||||
return true;
|
||||
|
||||
// A variable cannot be both common and exist in a section.
|
||||
// We dont try to determine which is the right section in the front-end.
|
||||
// If no specialized section name is applicable, it will resort to default.
|
||||
if (D->hasAttr<PragmaClangBSSSectionAttr>() ||
|
||||
D->hasAttr<PragmaClangDataSectionAttr>() ||
|
||||
D->hasAttr<PragmaClangRodataSectionAttr>())
|
||||
return true;
|
||||
|
||||
// Thread local vars aren't considered common linkage.
|
||||
if (D->getTLSKind())
|
||||
return true;
|
||||
|
|
|
@ -49,6 +49,15 @@ struct PragmaPackHandler : public PragmaHandler {
|
|||
Token &FirstToken) override;
|
||||
};
|
||||
|
||||
struct PragmaClangSectionHandler : public PragmaHandler {
|
||||
explicit PragmaClangSectionHandler(Sema &S)
|
||||
: PragmaHandler("section"), Actions(S) {}
|
||||
void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
|
||||
Token &FirstToken) override;
|
||||
private:
|
||||
Sema &Actions;
|
||||
};
|
||||
|
||||
struct PragmaMSStructHandler : public PragmaHandler {
|
||||
explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
|
||||
void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
|
||||
|
@ -224,6 +233,9 @@ void Parser::initializePragmaHandlers() {
|
|||
FPContractHandler.reset(new PragmaFPContractHandler());
|
||||
PP.AddPragmaHandler("STDC", FPContractHandler.get());
|
||||
|
||||
PCSectionHandler.reset(new PragmaClangSectionHandler(Actions));
|
||||
PP.AddPragmaHandler("clang", PCSectionHandler.get());
|
||||
|
||||
if (getLangOpts().OpenCL) {
|
||||
OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler());
|
||||
PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
|
||||
|
@ -323,6 +335,9 @@ void Parser::resetPragmaHandlers() {
|
|||
MSCommentHandler.reset();
|
||||
}
|
||||
|
||||
PP.RemovePragmaHandler("clang", PCSectionHandler.get());
|
||||
PCSectionHandler.reset();
|
||||
|
||||
if (getLangOpts().MicrosoftExt) {
|
||||
PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
|
||||
MSDetectMismatchHandler.reset();
|
||||
|
@ -1614,6 +1629,51 @@ void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
|
|||
PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
|
||||
}
|
||||
|
||||
// #pragma clang section bss="abc" data="" rodata="def" text=""
|
||||
void PragmaClangSectionHandler::HandlePragma(Preprocessor &PP,
|
||||
PragmaIntroducerKind Introducer, Token &FirstToken) {
|
||||
|
||||
Token Tok;
|
||||
auto SecKind = Sema::PragmaClangSectionKind::PCSK_Invalid;
|
||||
|
||||
PP.Lex(Tok); // eat 'section'
|
||||
while (Tok.isNot(tok::eod)) {
|
||||
if (Tok.isNot(tok::identifier)) {
|
||||
PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
|
||||
return;
|
||||
}
|
||||
|
||||
const IdentifierInfo *SecType = Tok.getIdentifierInfo();
|
||||
if (SecType->isStr("bss"))
|
||||
SecKind = Sema::PragmaClangSectionKind::PCSK_BSS;
|
||||
else if (SecType->isStr("data"))
|
||||
SecKind = Sema::PragmaClangSectionKind::PCSK_Data;
|
||||
else if (SecType->isStr("rodata"))
|
||||
SecKind = Sema::PragmaClangSectionKind::PCSK_Rodata;
|
||||
else if (SecType->isStr("text"))
|
||||
SecKind = Sema::PragmaClangSectionKind::PCSK_Text;
|
||||
else {
|
||||
PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
|
||||
return;
|
||||
}
|
||||
|
||||
PP.Lex(Tok); // eat ['bss'|'data'|'rodata'|'text']
|
||||
if (Tok.isNot(tok::equal)) {
|
||||
PP.Diag(Tok.getLocation(), diag::err_pragma_clang_section_expected_equal) << SecKind;
|
||||
return;
|
||||
}
|
||||
|
||||
std::string SecName;
|
||||
if (!PP.LexStringLiteral(Tok, SecName, "pragma clang section", false))
|
||||
return;
|
||||
|
||||
Actions.ActOnPragmaClangSection(Tok.getLocation(),
|
||||
(SecName.size()? Sema::PragmaClangSectionAction::PCSA_Set :
|
||||
Sema::PragmaClangSectionAction::PCSA_Clear),
|
||||
SecKind, SecName);
|
||||
}
|
||||
}
|
||||
|
||||
// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
|
||||
// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
|
||||
static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
|
||||
|
|
|
@ -126,6 +126,36 @@ void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
|
|||
PackStack.Act(PragmaLoc, Action, StringRef(), Alignment);
|
||||
}
|
||||
|
||||
void Sema::ActOnPragmaClangSection(SourceLocation PragmaLoc, PragmaClangSectionAction Action,
|
||||
PragmaClangSectionKind SecKind, StringRef SecName) {
|
||||
PragmaClangSection *CSec;
|
||||
switch (SecKind) {
|
||||
case PragmaClangSectionKind::PCSK_BSS:
|
||||
CSec = &PragmaClangBSSSection;
|
||||
break;
|
||||
case PragmaClangSectionKind::PCSK_Data:
|
||||
CSec = &PragmaClangDataSection;
|
||||
break;
|
||||
case PragmaClangSectionKind::PCSK_Rodata:
|
||||
CSec = &PragmaClangRodataSection;
|
||||
break;
|
||||
case PragmaClangSectionKind::PCSK_Text:
|
||||
CSec = &PragmaClangTextSection;
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("invalid clang section kind");
|
||||
}
|
||||
|
||||
if (Action == PragmaClangSectionAction::PCSA_Clear) {
|
||||
CSec->Valid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
CSec->Valid = true;
|
||||
CSec->SectionName = SecName;
|
||||
CSec->PragmaLocation = PragmaLoc;
|
||||
}
|
||||
|
||||
void Sema::ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action,
|
||||
StringRef SlotLabel, Expr *alignment) {
|
||||
Expr *Alignment = static_cast<Expr *>(alignment);
|
||||
|
|
|
@ -8651,6 +8651,14 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
NewFD->setInvalidDecl();
|
||||
}
|
||||
|
||||
// Apply an implicit SectionAttr if '#pragma clang section text' is active
|
||||
if (PragmaClangTextSection.Valid && D.isFunctionDefinition() &&
|
||||
!NewFD->hasAttr<SectionAttr>()) {
|
||||
NewFD->addAttr(PragmaClangTextSectionAttr::CreateImplicit(Context,
|
||||
PragmaClangTextSection.SectionName,
|
||||
PragmaClangTextSection.PragmaLocation));
|
||||
}
|
||||
|
||||
// Apply an implicit SectionAttr if #pragma code_seg is active.
|
||||
if (CodeSegStack.CurrentValue && D.isFunctionDefinition() &&
|
||||
!NewFD->hasAttr<SectionAttr>()) {
|
||||
|
@ -11175,6 +11183,23 @@ void Sema::FinalizeDeclaration(Decl *ThisDecl) {
|
|||
if (!VD)
|
||||
return;
|
||||
|
||||
// Apply an implicit SectionAttr if '#pragma clang section bss|data|rodata' is active
|
||||
if (VD->hasGlobalStorage() && VD->isThisDeclarationADefinition() &&
|
||||
!inTemplateInstantiation() && !VD->hasAttr<SectionAttr>()) {
|
||||
if (PragmaClangBSSSection.Valid)
|
||||
VD->addAttr(PragmaClangBSSSectionAttr::CreateImplicit(Context,
|
||||
PragmaClangBSSSection.SectionName,
|
||||
PragmaClangBSSSection.PragmaLocation));
|
||||
if (PragmaClangDataSection.Valid)
|
||||
VD->addAttr(PragmaClangDataSectionAttr::CreateImplicit(Context,
|
||||
PragmaClangDataSection.SectionName,
|
||||
PragmaClangDataSection.PragmaLocation));
|
||||
if (PragmaClangRodataSection.Valid)
|
||||
VD->addAttr(PragmaClangRodataSectionAttr::CreateImplicit(Context,
|
||||
PragmaClangRodataSection.SectionName,
|
||||
PragmaClangRodataSection.PragmaLocation));
|
||||
}
|
||||
|
||||
if (auto *DD = dyn_cast<DecompositionDecl>(ThisDecl)) {
|
||||
for (auto *BD : DD->bindings()) {
|
||||
FinalizeDeclaration(BD);
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
// RUN: %clang_cc1 -x c -emit-llvm -triple arm-none-eabi -o - %s | FileCheck %s
|
||||
|
||||
// Test that section attributes are attached to C tentative definitions as per
|
||||
// '#pragma clang section' directives.
|
||||
|
||||
#pragma clang section bss = ".bss.1"
|
||||
int x; // bss.1
|
||||
|
||||
#pragma clang section bss = ""
|
||||
int x; // stays in .bss.1
|
||||
int y; // not assigned a section attribute
|
||||
int z; // not assigned a section attribute
|
||||
|
||||
#pragma clang section bss = ".bss.2"
|
||||
int x; // stays in .bss.1
|
||||
int y; // .bss.2
|
||||
|
||||
// Test the same for `const` declarations.
|
||||
#pragma clang section rodata = ".rodata.1"
|
||||
const int cx; // rodata.1
|
||||
|
||||
#pragma clang section rodata = ""
|
||||
const int cx; // stays in .rodata.1
|
||||
const int cy; // not assigned a section attribute
|
||||
const int cz; // not assigned a rodata section attribute
|
||||
|
||||
#pragma clang section rodata = ".rodata.2"
|
||||
const int cx; // stays in .rodata.1
|
||||
const int cy; // .rodata.2
|
||||
|
||||
// CHECK: @x = global i32 0, align 4 #0
|
||||
// CHECK: @y = global i32 0, align 4 #1
|
||||
// CHECK: @z = common global i32 0, align 4
|
||||
// CHECK: @cx = constant i32 0, align 4 #2
|
||||
// CHECK: @cy = constant i32 0, align 4 #3
|
||||
// CHECK: @cz = constant i32 0, align 4 #1
|
||||
|
||||
// CHECK: attributes #0 = { "bss-section"=".bss.1" }
|
||||
// CHECK: attributes #1 = { "bss-section"=".bss.2" }
|
||||
// CHECK: attributes #2 = { "bss-section"=".bss.2" "rodata-section"=".rodata.1" }
|
||||
// CHECK: attributes #3 = { "bss-section"=".bss.2" "rodata-section"=".rodata.2" }
|
|
@ -0,0 +1,78 @@
|
|||
// RUN: %clang_cc1 -emit-llvm -triple arm-none-eabi -o - %s | FileCheck %s
|
||||
// Test that global variables, statics and functions are attached section-attributes
|
||||
// as per '#pragma clang section' directives.
|
||||
|
||||
extern "C" {
|
||||
// test with names for each section
|
||||
#pragma clang section bss="my_bss.1" data="my_data.1" rodata="my_rodata.1"
|
||||
#pragma clang section text="my_text.1"
|
||||
int a; // my_bss.1
|
||||
int b = 1; // my_data.1
|
||||
int c[4]; // my_bss.1
|
||||
short d[5] = {0}; // my_bss.1
|
||||
short e[6] = {0, 0, 1}; // my_data.1
|
||||
extern const int f;
|
||||
const int f = 2; // my_rodata.1
|
||||
int foo(void) { // my_text.1
|
||||
return b;
|
||||
}
|
||||
static int g[2]; // my_bss.1
|
||||
#pragma clang section bss=""
|
||||
int h; // default - .bss
|
||||
#pragma clang section data="" bss="my_bss.2" text="my_text.2"
|
||||
int i = 0; // my_bss.2
|
||||
extern const int j;
|
||||
const int j = 4; // default - .rodata
|
||||
int k; // my_bss.2
|
||||
extern int zoo(int *x, int *y);
|
||||
int goo(void) { // my_text.2
|
||||
static int lstat_h; // my_bss.2
|
||||
return zoo(g, &lstat_h);
|
||||
}
|
||||
#pragma clang section rodata="my_rodata.2" data="my_data.2"
|
||||
int l = 5; // my_data.2
|
||||
extern const int m;
|
||||
const int m = 6; // my_rodata.2
|
||||
#pragma clang section rodata="" data="" bss="" text=""
|
||||
int n; // default
|
||||
int o = 6; // default
|
||||
extern const int p;
|
||||
const int p = 7; // default
|
||||
int hoo(void) {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
//CHECK: @a = global i32 0, align 4 #0
|
||||
//CHECK: @b = global i32 1, align 4 #0
|
||||
//CHECK: @c = global [4 x i32] zeroinitializer, align 4 #0
|
||||
//CHECK: @d = global [5 x i16] zeroinitializer, align 2 #0
|
||||
//CHECK: @e = global [6 x i16] [i16 0, i16 0, i16 1, i16 0, i16 0, i16 0], align 2 #0
|
||||
//CHECK: @f = constant i32 2, align 4 #0
|
||||
|
||||
//CHECK: @h = global i32 0, align 4 #1
|
||||
//CHECK: @i = global i32 0, align 4 #2
|
||||
//CHECK: @j = constant i32 4, align 4 #2
|
||||
//CHECK: @k = global i32 0, align 4 #2
|
||||
//CHECK: @_ZZ3gooE7lstat_h = internal global i32 0, align 4 #2
|
||||
//CHECK: @_ZL1g = internal global [2 x i32] zeroinitializer, align 4 #0
|
||||
|
||||
//CHECK: @l = global i32 5, align 4 #3
|
||||
//CHECK: @m = constant i32 6, align 4 #3
|
||||
|
||||
//CHECK: @n = global i32 0, align 4
|
||||
//CHECK: @o = global i32 6, align 4
|
||||
//CHECK: @p = constant i32 7, align 4
|
||||
|
||||
//CHECK: define i32 @foo() #4 {
|
||||
//CHECK: define i32 @goo() #5 {
|
||||
//CHECK: declare i32 @zoo(i32*, i32*) #6
|
||||
//CHECK: define i32 @hoo() #7 {
|
||||
|
||||
//CHECK: attributes #0 = { "bss-section"="my_bss.1" "data-section"="my_data.1" "rodata-section"="my_rodata.1" }
|
||||
//CHECK: attributes #1 = { "data-section"="my_data.1" "rodata-section"="my_rodata.1" }
|
||||
//CHECK: attributes #2 = { "bss-section"="my_bss.2" "rodata-section"="my_rodata.1" }
|
||||
//CHECK: attributes #3 = { "bss-section"="my_bss.2" "data-section"="my_data.2" "rodata-section"="my_rodata.2" }
|
||||
//CHECK: attributes #4 = { {{.*"implicit-section-name"="my_text.1".*}} }
|
||||
//CHECK: attributes #5 = { {{.*"implicit-section-name"="my_text.2".*}} }
|
||||
//CHECK-NOT: attributes #6 = { {{.*"implicit-section-name".*}} }
|
||||
//CHECK-NOT: attributes #7 = { {{.*"implicit-section-name".*}} }
|
|
@ -0,0 +1,17 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s -triple arm-none-eabi
|
||||
#pragma clang section bss="mybss.1" data="mydata.1" rodata="myrodata.1" text="mytext.1"
|
||||
#pragma clang section bss="" data="" rodata="" text=""
|
||||
#pragma clang section
|
||||
|
||||
#pragma clang section dss="mybss.2" // expected-error {{expected one of [bss|data|rodata|text] section kind in '#pragma clang section'}}
|
||||
#pragma clang section deta="mydata.2" // expected-error {{expected one of [bss|data|rodata|text] section kind in '#pragma clang section'}}
|
||||
#pragma clang section rodeta="rodata.2" // expected-error {{expected one of [bss|data|rodata|text] section kind in '#pragma clang section'}}
|
||||
#pragma clang section taxt="text.2" // expected-error {{expected one of [bss|data|rodata|text] section kind in '#pragma clang section'}}
|
||||
|
||||
#pragma clang section section bss="mybss.2" // expected-error {{expected one of [bss|data|rodata|text] section kind in '#pragma clang section'}}
|
||||
|
||||
#pragma clang section bss "mybss.2" // expected-error {{expected '=' following '#pragma clang section bss'}}
|
||||
#pragma clang section data "mydata.2" // expected-error {{expected '=' following '#pragma clang section data'}}
|
||||
#pragma clang section rodata "myrodata.2" // expected-error {{expected '=' following '#pragma clang section rodata'}}
|
||||
#pragma clang section bss="" data="" rodata="" text="" more //expected-error {{expected one of [bss|data|rodata|text] section kind in '#pragma clang section'}}
|
||||
int a;
|
Loading…
Reference in New Issue