mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-02 16:36:40 +00: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:
parent
4ba9d33da9
commit
2da9899378
@ -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
|
||||
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:
|
||||
|
||||
Function Attributes
|
||||
|
@ -226,6 +226,7 @@ lltok::Kind LLLexer::LexToken() {
|
||||
SkipLineComment();
|
||||
return LexToken();
|
||||
case '!': return LexExclaim();
|
||||
case '#': return LexHash();
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
case '-':
|
||||
@ -394,6 +395,24 @@ lltok::Kind LLLexer::LexExclaim() {
|
||||
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:
|
||||
/// Label [-a-zA-Z$._0-9]+:
|
||||
/// IntegerType i[0-9]+
|
||||
@ -531,35 +550,36 @@ lltok::Kind LLLexer::LexIdentifier() {
|
||||
KEYWORD(cc);
|
||||
KEYWORD(c);
|
||||
|
||||
KEYWORD(signext);
|
||||
KEYWORD(zeroext);
|
||||
KEYWORD(attributes);
|
||||
|
||||
KEYWORD(address_safety);
|
||||
KEYWORD(alwaysinline);
|
||||
KEYWORD(byval);
|
||||
KEYWORD(inlinehint);
|
||||
KEYWORD(inreg);
|
||||
KEYWORD(sret);
|
||||
KEYWORD(nounwind);
|
||||
KEYWORD(noreturn);
|
||||
KEYWORD(minsize);
|
||||
KEYWORD(naked);
|
||||
KEYWORD(nest);
|
||||
KEYWORD(noalias);
|
||||
KEYWORD(nocapture);
|
||||
KEYWORD(byval);
|
||||
KEYWORD(nest);
|
||||
KEYWORD(noduplicate);
|
||||
KEYWORD(noimplicitfloat);
|
||||
KEYWORD(noinline);
|
||||
KEYWORD(nonlazybind);
|
||||
KEYWORD(noredzone);
|
||||
KEYWORD(noreturn);
|
||||
KEYWORD(nounwind);
|
||||
KEYWORD(optsize);
|
||||
KEYWORD(readnone);
|
||||
KEYWORD(readonly);
|
||||
KEYWORD(uwtable);
|
||||
KEYWORD(returns_twice);
|
||||
|
||||
KEYWORD(inlinehint);
|
||||
KEYWORD(noinline);
|
||||
KEYWORD(alwaysinline);
|
||||
KEYWORD(optsize);
|
||||
KEYWORD(signext);
|
||||
KEYWORD(sret);
|
||||
KEYWORD(ssp);
|
||||
KEYWORD(sspreq);
|
||||
KEYWORD(sspstrong);
|
||||
KEYWORD(noredzone);
|
||||
KEYWORD(noimplicitfloat);
|
||||
KEYWORD(naked);
|
||||
KEYWORD(nonlazybind);
|
||||
KEYWORD(address_safety);
|
||||
KEYWORD(minsize);
|
||||
KEYWORD(noduplicate);
|
||||
KEYWORD(uwtable);
|
||||
KEYWORD(zeroext);
|
||||
|
||||
KEYWORD(type);
|
||||
KEYWORD(opaque);
|
||||
|
@ -81,6 +81,7 @@ namespace llvm {
|
||||
lltok::Kind LexPercent();
|
||||
lltok::Kind LexQuote();
|
||||
lltok::Kind Lex0x();
|
||||
lltok::Kind LexHash();
|
||||
|
||||
uint64_t atoull(const char *Buffer, const char *End);
|
||||
uint64_t HexIntToVal(const char *Buffer, const char *End);
|
||||
|
@ -174,7 +174,8 @@ bool LLParser::ParseTopLevelEntities() {
|
||||
case lltok::GlobalID: if (ParseUnnamedGlobal()) return true; break;
|
||||
case lltok::GlobalVar: if (ParseNamedGlobal()) 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
|
||||
// optional leading prefixes, the production is:
|
||||
@ -740,6 +741,102 @@ bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc,
|
||||
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.
|
||||
|
@ -125,6 +125,9 @@ namespace llvm {
|
||||
std::map<ValID, std::vector<std::pair<ValID, GlobalValue*> > >
|
||||
ForwardRefBlockAddresses;
|
||||
|
||||
// Attribute builder reference information.
|
||||
std::map<unsigned, AttrBuilder> ForwardRefAttrBuilder;
|
||||
|
||||
public:
|
||||
LLParser(MemoryBuffer *F, SourceMgr &SM, SMDiagnostic &Err, Module *m) :
|
||||
Context(m->getContext()), Lex(F, SM, Err, m->getContext()),
|
||||
@ -236,6 +239,8 @@ namespace llvm {
|
||||
bool ParseMDString(MDString *&Result);
|
||||
bool ParseMDNodeID(MDNode *&Result);
|
||||
bool ParseMDNodeID(MDNode *&Result, unsigned &SlotNo);
|
||||
bool ParseUnnamedAttrGrp();
|
||||
bool ParseAttributeValuePairs(AttrBuilder &B);
|
||||
|
||||
// Type Parsing.
|
||||
bool ParseType(Type *&Result, bool AllowVoid = false);
|
||||
|
@ -30,6 +30,7 @@ namespace lltok {
|
||||
lparen, rparen, // ( )
|
||||
backslash, // \ (not /)
|
||||
exclaim, // !
|
||||
hash, // #
|
||||
|
||||
kw_x,
|
||||
kw_true, kw_false,
|
||||
@ -90,35 +91,36 @@ namespace lltok {
|
||||
kw_ptx_kernel, kw_ptx_device,
|
||||
kw_spir_kernel, kw_spir_func,
|
||||
|
||||
kw_signext,
|
||||
kw_zeroext,
|
||||
// Attributes:
|
||||
kw_attributes,
|
||||
kw_alwaysinline,
|
||||
kw_address_safety,
|
||||
kw_byval,
|
||||
kw_inlinehint,
|
||||
kw_inreg,
|
||||
kw_sret,
|
||||
kw_nounwind,
|
||||
kw_noreturn,
|
||||
kw_minsize,
|
||||
kw_naked,
|
||||
kw_nest,
|
||||
kw_noalias,
|
||||
kw_nocapture,
|
||||
kw_byval,
|
||||
kw_nest,
|
||||
kw_noduplicate,
|
||||
kw_noimplicitfloat,
|
||||
kw_noinline,
|
||||
kw_nonlazybind,
|
||||
kw_noredzone,
|
||||
kw_noreturn,
|
||||
kw_nounwind,
|
||||
kw_optsize,
|
||||
kw_readnone,
|
||||
kw_readonly,
|
||||
kw_uwtable,
|
||||
kw_returns_twice,
|
||||
|
||||
kw_inlinehint,
|
||||
kw_noinline,
|
||||
kw_alwaysinline,
|
||||
kw_optsize,
|
||||
kw_signext,
|
||||
kw_ssp,
|
||||
kw_sspreq,
|
||||
kw_sspstrong,
|
||||
kw_noredzone,
|
||||
kw_noimplicitfloat,
|
||||
kw_naked,
|
||||
kw_nonlazybind,
|
||||
kw_address_safety,
|
||||
kw_minsize,
|
||||
kw_noduplicate,
|
||||
kw_sret,
|
||||
kw_uwtable,
|
||||
kw_zeroext,
|
||||
|
||||
kw_type,
|
||||
kw_opaque,
|
||||
@ -155,6 +157,7 @@ namespace lltok {
|
||||
// Unsigned Valued tokens (UIntVal).
|
||||
GlobalID, // @42
|
||||
LocalVarID, // %42
|
||||
AttrGrpID, // #42
|
||||
|
||||
// String valued tokens (StrVal).
|
||||
LabelStr, // foo:
|
||||
|
Loading…
Reference in New Issue
Block a user