summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/LangRef.rst30
-rw-r--r--lib/AsmParser/LLLexer.cpp60
-rw-r--r--lib/AsmParser/LLLexer.h1
-rw-r--r--lib/AsmParser/LLParser.cpp99
-rw-r--r--lib/AsmParser/LLParser.h5
-rw-r--r--lib/AsmParser/LLToken.h43
6 files changed, 197 insertions, 41 deletions
diff --git a/docs/LangRef.rst b/docs/LangRef.rst
index 8fd92f97f4..d702cfb02c 100644
--- a/docs/LangRef.rst
+++ b/docs/LangRef.rst
@@ -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
diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp
index 72136d058e..2256124043 100644
--- a/lib/AsmParser/LLLexer.cpp
+++ b/lib/AsmParser/LLLexer.cpp
@@ -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);
diff --git a/lib/AsmParser/LLLexer.h b/lib/AsmParser/LLLexer.h
index 1a307a8bec..85703c766b 100644
--- a/lib/AsmParser/LLLexer.h
+++ b/lib/AsmParser/LLLexer.h
@@ -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);
diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp
index 2b6b165837..22c21c62b9 100644
--- a/lib/AsmParser/LLParser.cpp
+++ b/lib/AsmParser/LLParser.cpp
@@ -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.
diff --git a/lib/AsmParser/LLParser.h b/lib/AsmParser/LLParser.h
index d8de77908c..131331a5bc 100644
--- a/lib/AsmParser/LLParser.h
+++ b/lib/AsmParser/LLParser.h
@@ -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);
diff --git a/lib/AsmParser/LLToken.h b/lib/AsmParser/LLToken.h
index c9ecd21470..8c18a3be60 100644
--- a/lib/AsmParser/LLToken.h
+++ b/lib/AsmParser/LLToken.h
@@ -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: