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:
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
|
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
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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.
|
||||||
|
@ -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);
|
||||||
|
@ -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:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user