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
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 '-':
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]+
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);
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:
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.
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()),
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);