1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +01:00

Initial submission for the attribute group feature.

Attribute groups are of the form:

  #0 = attributes { noinline "no-sse" "cpu"="cortex-a8" alignstack=4 }

Target-dependent attributes are represented as strings. Attributes can have
optional values associated with them. E.g., the "cpu" attribute has the value
"cortex-a8".

Target-independent attributes are listed as enums inside the attribute classes.

Multiple attribute groups can be referenced by the same object. In that case,
the attributes are merged together.

llvm-svn: 174493
This commit is contained in:
Bill Wendling 2013-02-06 06:52:58 +00:00
parent 4ba9d33da9
commit 2da9899378
6 changed files with 197 additions and 41 deletions

View File

@ -737,6 +737,36 @@ The compiler declares the supported values of *name*. Specifying a
collector which will cause the compiler to alter its output in order to collector which will cause the compiler to alter its output in order to
support the named garbage collection algorithm. support the named garbage collection algorithm.
.. _attrgrp:
Attribute Groups
----------------
Attribute groups are groups of attributes that are referenced by objects within
the IR. They are important for keeping ``.ll`` files readable, because a lot of
functions will use the same set of attributes. In the degenerative case of a
``.ll`` file that corresponds to a single ``.c`` file, the single attribute
group will capture the important command line flags used to build that file.
An attribute group is a module-level object. To use an attribute group, an
object references the attribute group's ID (e.g. ``#37``). An object may refer
to more than one attribute group. In that situation, the attributes from the
different groups are merged.
Here is an example of attribute groups for a function that should always be
inlined, has a stack alignment of 4, and which shouldn't use SSE instructions:
.. code-block:: llvm
; Target-independent attributes:
#0 = attributes { alwaysinline alignstack=4 }
; Target-dependent attributes:
#1 = attributes { "no-sse" }
; Function @f has attributes: alwaysinline, alignstack=4, and "no-sse".
define void @f() #0 #1 { ... }
.. _fnattrs: .. _fnattrs:
Function Attributes Function Attributes

View File

@ -226,6 +226,7 @@ lltok::Kind LLLexer::LexToken() {
SkipLineComment(); SkipLineComment();
return LexToken(); return LexToken();
case '!': return LexExclaim(); case '!': return LexExclaim();
case '#': return LexHash();
case '0': case '1': case '2': case '3': case '4': case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': case '5': case '6': case '7': case '8': case '9':
case '-': case '-':
@ -394,6 +395,24 @@ lltok::Kind LLLexer::LexExclaim() {
return lltok::exclaim; return lltok::exclaim;
} }
/// LexHash - Lex all tokens that start with a # character:
/// AttrGrpID ::= #[0-9]+
lltok::Kind LLLexer::LexHash() {
// Handle AttrGrpID: #[0-9]+
if (isdigit(CurPtr[0])) {
for (++CurPtr; isdigit(CurPtr[0]); ++CurPtr)
/*empty*/;
uint64_t Val = atoull(TokStart+1, CurPtr);
if ((unsigned)Val != Val)
Error("invalid value number (too large)!");
UIntVal = unsigned(Val);
return lltok::AttrGrpID;
}
return lltok::Error;
}
/// LexIdentifier: Handle several related productions: /// LexIdentifier: Handle several related productions:
/// Label [-a-zA-Z$._0-9]+: /// Label [-a-zA-Z$._0-9]+:
/// IntegerType i[0-9]+ /// IntegerType i[0-9]+
@ -531,35 +550,36 @@ lltok::Kind LLLexer::LexIdentifier() {
KEYWORD(cc); KEYWORD(cc);
KEYWORD(c); KEYWORD(c);
KEYWORD(signext); KEYWORD(attributes);
KEYWORD(zeroext);
KEYWORD(address_safety);
KEYWORD(alwaysinline);
KEYWORD(byval);
KEYWORD(inlinehint);
KEYWORD(inreg); KEYWORD(inreg);
KEYWORD(sret); KEYWORD(minsize);
KEYWORD(nounwind); KEYWORD(naked);
KEYWORD(noreturn); KEYWORD(nest);
KEYWORD(noalias); KEYWORD(noalias);
KEYWORD(nocapture); KEYWORD(nocapture);
KEYWORD(byval); KEYWORD(noduplicate);
KEYWORD(nest); KEYWORD(noimplicitfloat);
KEYWORD(noinline);
KEYWORD(nonlazybind);
KEYWORD(noredzone);
KEYWORD(noreturn);
KEYWORD(nounwind);
KEYWORD(optsize);
KEYWORD(readnone); KEYWORD(readnone);
KEYWORD(readonly); KEYWORD(readonly);
KEYWORD(uwtable);
KEYWORD(returns_twice); KEYWORD(returns_twice);
KEYWORD(signext);
KEYWORD(inlinehint); KEYWORD(sret);
KEYWORD(noinline);
KEYWORD(alwaysinline);
KEYWORD(optsize);
KEYWORD(ssp); KEYWORD(ssp);
KEYWORD(sspreq); KEYWORD(sspreq);
KEYWORD(sspstrong); KEYWORD(sspstrong);
KEYWORD(noredzone); KEYWORD(uwtable);
KEYWORD(noimplicitfloat); KEYWORD(zeroext);
KEYWORD(naked);
KEYWORD(nonlazybind);
KEYWORD(address_safety);
KEYWORD(minsize);
KEYWORD(noduplicate);
KEYWORD(type); KEYWORD(type);
KEYWORD(opaque); KEYWORD(opaque);

View File

@ -81,6 +81,7 @@ namespace llvm {
lltok::Kind LexPercent(); lltok::Kind LexPercent();
lltok::Kind LexQuote(); lltok::Kind LexQuote();
lltok::Kind Lex0x(); lltok::Kind Lex0x();
lltok::Kind LexHash();
uint64_t atoull(const char *Buffer, const char *End); uint64_t atoull(const char *Buffer, const char *End);
uint64_t HexIntToVal(const char *Buffer, const char *End); uint64_t HexIntToVal(const char *Buffer, const char *End);

View File

@ -174,7 +174,8 @@ bool LLParser::ParseTopLevelEntities() {
case lltok::GlobalID: if (ParseUnnamedGlobal()) return true; break; case lltok::GlobalID: if (ParseUnnamedGlobal()) return true; break;
case lltok::GlobalVar: if (ParseNamedGlobal()) return true; break; case lltok::GlobalVar: if (ParseNamedGlobal()) return true; break;
case lltok::exclaim: if (ParseStandaloneMetadata()) return true; break; case lltok::exclaim: if (ParseStandaloneMetadata()) return true; break;
case lltok::MetadataVar: if (ParseNamedMetadata()) return true; break; case lltok::MetadataVar:if (ParseNamedMetadata()) return true; break;
case lltok::AttrGrpID: if (ParseUnnamedAttrGrp()) return true; break;
// The Global variable production with no name can have many different // The Global variable production with no name can have many different
// optional leading prefixes, the production is: // optional leading prefixes, the production is:
@ -740,6 +741,102 @@ bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc,
return false; return false;
} }
/// ParseUnnamedAttrGrp
/// ::= AttrGrpID '=' '{' AttrValPair+ '}'
bool LLParser::ParseUnnamedAttrGrp() {
assert(Lex.getKind() == lltok::AttrGrpID);
LocTy AttrGrpLoc = Lex.getLoc();
unsigned VarID = Lex.getUIntVal();
Lex.Lex();
if (ParseToken(lltok::equal, "expected '=' here") ||
ParseToken(lltok::kw_attributes, "expected 'attributes' keyword here") ||
ParseToken(lltok::lbrace, "expected '{' here") ||
ParseAttributeValuePairs(ForwardRefAttrBuilder[VarID]) ||
ParseToken(lltok::rbrace, "expected end of attribute group"))
return true;
if (!ForwardRefAttrBuilder[VarID].hasAttributes())
return Error(AttrGrpLoc, "attribute group has no attributes");
return false;
}
/// ParseAttributeValuePairs
/// ::= <attr> | <attr> '=' <value>
bool LLParser::ParseAttributeValuePairs(AttrBuilder &B) {
while (true) {
lltok::Kind Token = Lex.getKind();
switch (Token) {
default:
return Error(Lex.getLoc(), "unterminated attribute group");
case lltok::rbrace:
// Finished.
return false;
// Target-dependent attributes:
case lltok::StringConstant: {
std::string Attr = Lex.getStrVal();
Lex.Lex();
std::string Val;
if (EatIfPresent(lltok::equal) &&
ParseStringConstant(Val))
return true;
B.addAttribute(Attr, Val);
break;
}
// Target-independent attributes:
case lltok::kw_align: {
unsigned Alignment;
if (ParseToken(lltok::equal, "expected '=' here") ||
ParseUInt32(Alignment))
return true;
B.addAlignmentAttr(Alignment);
break;
}
case lltok::kw_alignstack: {
unsigned Alignment;
if (ParseToken(lltok::equal, "expected '=' here") ||
ParseUInt32(Alignment))
return true;
B.addStackAlignmentAttr(Alignment);
break;
}
case lltok::kw_address_safety: B.addAttribute(Attribute::AddressSafety); break;
case lltok::kw_alwaysinline: B.addAttribute(Attribute::AlwaysInline); break;
case lltok::kw_byval: B.addAttribute(Attribute::ByVal); break;
case lltok::kw_inlinehint: B.addAttribute(Attribute::InlineHint); break;
case lltok::kw_inreg: B.addAttribute(Attribute::InReg); break;
case lltok::kw_minsize: B.addAttribute(Attribute::MinSize); break;
case lltok::kw_naked: B.addAttribute(Attribute::Naked); break;
case lltok::kw_nest: B.addAttribute(Attribute::Nest); break;
case lltok::kw_noalias: B.addAttribute(Attribute::NoAlias); break;
case lltok::kw_nocapture: B.addAttribute(Attribute::NoCapture); break;
case lltok::kw_noduplicate: B.addAttribute(Attribute::NoDuplicate); break;
case lltok::kw_noimplicitfloat: B.addAttribute(Attribute::NoImplicitFloat); break;
case lltok::kw_noinline: B.addAttribute(Attribute::NoInline); break;
case lltok::kw_nonlazybind: B.addAttribute(Attribute::NonLazyBind); break;
case lltok::kw_noredzone: B.addAttribute(Attribute::NoRedZone); break;
case lltok::kw_noreturn: B.addAttribute(Attribute::NoReturn); break;
case lltok::kw_nounwind: B.addAttribute(Attribute::NoUnwind); break;
case lltok::kw_optsize: B.addAttribute(Attribute::OptimizeForSize); break;
case lltok::kw_readnone: B.addAttribute(Attribute::ReadNone); break;
case lltok::kw_readonly: B.addAttribute(Attribute::ReadOnly); break;
case lltok::kw_returns_twice: B.addAttribute(Attribute::ReturnsTwice); break;
case lltok::kw_signext: B.addAttribute(Attribute::SExt); break;
case lltok::kw_sret: B.addAttribute(Attribute::StructRet); break;
case lltok::kw_ssp: B.addAttribute(Attribute::StackProtect); break;
case lltok::kw_sspreq: B.addAttribute(Attribute::StackProtectReq); break;
case lltok::kw_sspstrong: B.addAttribute(Attribute::StackProtectStrong); break;
case lltok::kw_uwtable: B.addAttribute(Attribute::UWTable); break;
case lltok::kw_zeroext: B.addAttribute(Attribute::ZExt); break;
}
Lex.Lex();
}
}
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// GlobalValue Reference/Resolution Routines. // GlobalValue Reference/Resolution Routines.

View File

@ -125,6 +125,9 @@ namespace llvm {
std::map<ValID, std::vector<std::pair<ValID, GlobalValue*> > > std::map<ValID, std::vector<std::pair<ValID, GlobalValue*> > >
ForwardRefBlockAddresses; ForwardRefBlockAddresses;
// Attribute builder reference information.
std::map<unsigned, AttrBuilder> ForwardRefAttrBuilder;
public: public:
LLParser(MemoryBuffer *F, SourceMgr &SM, SMDiagnostic &Err, Module *m) : LLParser(MemoryBuffer *F, SourceMgr &SM, SMDiagnostic &Err, Module *m) :
Context(m->getContext()), Lex(F, SM, Err, m->getContext()), Context(m->getContext()), Lex(F, SM, Err, m->getContext()),
@ -236,6 +239,8 @@ namespace llvm {
bool ParseMDString(MDString *&Result); bool ParseMDString(MDString *&Result);
bool ParseMDNodeID(MDNode *&Result); bool ParseMDNodeID(MDNode *&Result);
bool ParseMDNodeID(MDNode *&Result, unsigned &SlotNo); bool ParseMDNodeID(MDNode *&Result, unsigned &SlotNo);
bool ParseUnnamedAttrGrp();
bool ParseAttributeValuePairs(AttrBuilder &B);
// Type Parsing. // Type Parsing.
bool ParseType(Type *&Result, bool AllowVoid = false); bool ParseType(Type *&Result, bool AllowVoid = false);

View File

@ -30,6 +30,7 @@ namespace lltok {
lparen, rparen, // ( ) lparen, rparen, // ( )
backslash, // \ (not /) backslash, // \ (not /)
exclaim, // ! exclaim, // !
hash, // #
kw_x, kw_x,
kw_true, kw_false, kw_true, kw_false,
@ -90,35 +91,36 @@ namespace lltok {
kw_ptx_kernel, kw_ptx_device, kw_ptx_kernel, kw_ptx_device,
kw_spir_kernel, kw_spir_func, kw_spir_kernel, kw_spir_func,
kw_signext, // Attributes:
kw_zeroext, kw_attributes,
kw_alwaysinline,
kw_address_safety,
kw_byval,
kw_inlinehint,
kw_inreg, kw_inreg,
kw_sret, kw_minsize,
kw_nounwind, kw_naked,
kw_noreturn, kw_nest,
kw_noalias, kw_noalias,
kw_nocapture, kw_nocapture,
kw_byval, kw_noduplicate,
kw_nest, kw_noimplicitfloat,
kw_noinline,
kw_nonlazybind,
kw_noredzone,
kw_noreturn,
kw_nounwind,
kw_optsize,
kw_readnone, kw_readnone,
kw_readonly, kw_readonly,
kw_uwtable,
kw_returns_twice, kw_returns_twice,
kw_signext,
kw_inlinehint,
kw_noinline,
kw_alwaysinline,
kw_optsize,
kw_ssp, kw_ssp,
kw_sspreq, kw_sspreq,
kw_sspstrong, kw_sspstrong,
kw_noredzone, kw_sret,
kw_noimplicitfloat, kw_uwtable,
kw_naked, kw_zeroext,
kw_nonlazybind,
kw_address_safety,
kw_minsize,
kw_noduplicate,
kw_type, kw_type,
kw_opaque, kw_opaque,
@ -155,6 +157,7 @@ namespace lltok {
// Unsigned Valued tokens (UIntVal). // Unsigned Valued tokens (UIntVal).
GlobalID, // @42 GlobalID, // @42
LocalVarID, // %42 LocalVarID, // %42
AttrGrpID, // #42
// String valued tokens (StrVal). // String valued tokens (StrVal).
LabelStr, // foo: LabelStr, // foo: