diff options
Diffstat (limited to 'lib/AsmParser')
-rw-r--r-- | lib/AsmParser/LLLexer.cpp | 190 | ||||
-rw-r--r-- | lib/AsmParser/LLLexer.h | 1 | ||||
-rw-r--r-- | lib/AsmParser/LLParser.cpp | 502 | ||||
-rw-r--r-- | lib/AsmParser/LLParser.h | 27 | ||||
-rw-r--r-- | lib/AsmParser/LLToken.h | 47 | ||||
-rw-r--r-- | lib/AsmParser/Parser.cpp | 2 |
6 files changed, 500 insertions, 269 deletions
diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp index 350eef2b19..f46383be7e 100644 --- a/lib/AsmParser/LLLexer.cpp +++ b/lib/AsmParser/LLLexer.cpp @@ -12,11 +12,12 @@ //===----------------------------------------------------------------------===// #include "LLLexer.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" #include "llvm/Assembly/Parser.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Instruction.h" -#include "llvm/LLVMContext.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/MemoryBuffer.h" @@ -55,22 +56,12 @@ uint64_t LLLexer::atoull(const char *Buffer, const char *End) { return Result; } -static char parseHexChar(char C) { - if (C >= '0' && C <= '9') - return C-'0'; - if (C >= 'A' && C <= 'F') - return C-'A'+10; - if (C >= 'a' && C <= 'f') - return C-'a'+10; - return 0; -} - uint64_t LLLexer::HexIntToVal(const char *Buffer, const char *End) { uint64_t Result = 0; for (; Buffer != End; ++Buffer) { uint64_t OldRes = Result; Result *= 16; - Result += parseHexChar(*Buffer); + Result += hexDigitValue(*Buffer); if (Result < OldRes) { // Uh, oh, overflow detected!!! Error("constant bigger than 64 bits detected!"); @@ -86,12 +77,12 @@ void LLLexer::HexToIntPair(const char *Buffer, const char *End, for (int i=0; i<16; i++, Buffer++) { assert(Buffer != End); Pair[0] *= 16; - Pair[0] += parseHexChar(*Buffer); + Pair[0] += hexDigitValue(*Buffer); } Pair[1] = 0; for (int i=0; i<16 && Buffer != End; i++, Buffer++) { Pair[1] *= 16; - Pair[1] += parseHexChar(*Buffer); + Pair[1] += hexDigitValue(*Buffer); } if (Buffer != End) Error("constant bigger than 128 bits detected!"); @@ -105,12 +96,12 @@ void LLLexer::FP80HexToIntPair(const char *Buffer, const char *End, for (int i=0; i<4 && Buffer != End; i++, Buffer++) { assert(Buffer != End); Pair[1] *= 16; - Pair[1] += parseHexChar(*Buffer); + Pair[1] += hexDigitValue(*Buffer); } Pair[0] = 0; for (int i=0; i<16; i++, Buffer++) { Pair[0] *= 16; - Pair[0] += parseHexChar(*Buffer); + Pair[0] += hexDigitValue(*Buffer); } if (Buffer != End) Error("constant bigger than 128 bits detected!"); @@ -128,8 +119,10 @@ static void UnEscapeLexed(std::string &Str) { if (BIn < EndBuffer-1 && BIn[1] == '\\') { *BOut++ = '\\'; // Two \ becomes one BIn += 2; - } else if (BIn < EndBuffer-2 && isxdigit(BIn[1]) && isxdigit(BIn[2])) { - *BOut = parseHexChar(BIn[1]) * 16 + parseHexChar(BIn[2]); + } else if (BIn < EndBuffer-2 && + isxdigit(static_cast<unsigned char>(BIn[1])) && + isxdigit(static_cast<unsigned char>(BIn[2]))) { + *BOut = hexDigitValue(BIn[1]) * 16 + hexDigitValue(BIn[2]); BIn += 3; // Skip over handled chars ++BOut; } else { @@ -144,7 +137,8 @@ static void UnEscapeLexed(std::string &Str) { /// isLabelChar - Return true for [-a-zA-Z$._0-9]. static bool isLabelChar(char C) { - return isalnum(C) || C == '-' || C == '$' || C == '.' || C == '_'; + return isalnum(static_cast<unsigned char>(C)) || C == '-' || C == '$' || + C == '.' || C == '_'; } @@ -197,7 +191,7 @@ lltok::Kind LLLexer::LexToken() { switch (CurChar) { default: // Handle letters: [a-zA-Z_] - if (isalpha(CurChar) || CurChar == '_') + if (isalpha(static_cast<unsigned char>(CurChar)) || CurChar == '_') return LexIdentifier(); return lltok::Error; @@ -235,6 +229,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 '-': @@ -290,8 +285,8 @@ lltok::Kind LLLexer::LexAt() { return lltok::GlobalVar; // Handle GlobalVarID: @[0-9]+ - if (isdigit(CurPtr[0])) { - for (++CurPtr; isdigit(CurPtr[0]); ++CurPtr) + if (isdigit(static_cast<unsigned char>(CurPtr[0]))) { + for (++CurPtr; isdigit(static_cast<unsigned char>(CurPtr[0])); ++CurPtr) /*empty*/; uint64_t Val = atoull(TokStart+1, CurPtr); @@ -325,10 +320,12 @@ lltok::Kind LLLexer::ReadString(lltok::Kind kind) { /// ReadVarName - Read the rest of a token containing a variable name. bool LLLexer::ReadVarName() { const char *NameStart = CurPtr; - if (isalpha(CurPtr[0]) || CurPtr[0] == '-' || CurPtr[0] == '$' || + if (isalpha(static_cast<unsigned char>(CurPtr[0])) || + CurPtr[0] == '-' || CurPtr[0] == '$' || CurPtr[0] == '.' || CurPtr[0] == '_') { ++CurPtr; - while (isalnum(CurPtr[0]) || CurPtr[0] == '-' || CurPtr[0] == '$' || + while (isalnum(static_cast<unsigned char>(CurPtr[0])) || + CurPtr[0] == '-' || CurPtr[0] == '$' || CurPtr[0] == '.' || CurPtr[0] == '_') ++CurPtr; @@ -354,8 +351,8 @@ lltok::Kind LLLexer::LexPercent() { return lltok::LocalVar; // Handle LocalVarID: %[0-9]+ - if (isdigit(CurPtr[0])) { - for (++CurPtr; isdigit(CurPtr[0]); ++CurPtr) + if (isdigit(static_cast<unsigned char>(CurPtr[0]))) { + for (++CurPtr; isdigit(static_cast<unsigned char>(CurPtr[0])); ++CurPtr) /*empty*/; uint64_t Val = atoull(TokStart+1, CurPtr); @@ -389,10 +386,12 @@ lltok::Kind LLLexer::LexQuote() { /// ! lltok::Kind LLLexer::LexExclaim() { // Lex a metadata name as a MetadataVar. - if (isalpha(CurPtr[0]) || CurPtr[0] == '-' || CurPtr[0] == '$' || + if (isalpha(static_cast<unsigned char>(CurPtr[0])) || + CurPtr[0] == '-' || CurPtr[0] == '$' || CurPtr[0] == '.' || CurPtr[0] == '_' || CurPtr[0] == '\\') { ++CurPtr; - while (isalnum(CurPtr[0]) || CurPtr[0] == '-' || CurPtr[0] == '$' || + while (isalnum(static_cast<unsigned char>(CurPtr[0])) || + CurPtr[0] == '-' || CurPtr[0] == '$' || CurPtr[0] == '.' || CurPtr[0] == '_' || CurPtr[0] == '\\') ++CurPtr; @@ -403,6 +402,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(static_cast<unsigned char>(CurPtr[0]))) { + for (++CurPtr; isdigit(static_cast<unsigned char>(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]+ @@ -415,8 +432,11 @@ lltok::Kind LLLexer::LexIdentifier() { for (; isLabelChar(*CurPtr); ++CurPtr) { // If we decide this is an integer, remember the end of the sequence. - if (!IntEnd && !isdigit(*CurPtr)) IntEnd = CurPtr; - if (!KeywordEnd && !isalnum(*CurPtr) && *CurPtr != '_') KeywordEnd = CurPtr; + if (!IntEnd && !isdigit(static_cast<unsigned char>(*CurPtr))) + IntEnd = CurPtr; + if (!KeywordEnd && !isalnum(static_cast<unsigned char>(*CurPtr)) && + *CurPtr != '_') + KeywordEnd = CurPtr; } // If we stopped due to a colon, this really is a label. @@ -445,9 +465,11 @@ lltok::Kind LLLexer::LexIdentifier() { CurPtr = KeywordEnd; --StartChar; unsigned Len = CurPtr-StartChar; -#define KEYWORD(STR) \ - if (Len == strlen(#STR) && !memcmp(StartChar, #STR, strlen(#STR))) \ - return lltok::kw_##STR; +#define KEYWORD(STR) \ + do { \ + if (Len == strlen(#STR) && !memcmp(StartChar, #STR, strlen(#STR))) \ + return lltok::kw_##STR; \ + } while (0) KEYWORD(true); KEYWORD(false); KEYWORD(declare); KEYWORD(define); @@ -472,6 +494,7 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(hidden); KEYWORD(protected); KEYWORD(unnamed_addr); + KEYWORD(externally_initialized); KEYWORD(extern_weak); KEYWORD(external); KEYWORD(thread_local); @@ -498,11 +521,11 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(seq_cst); KEYWORD(singlethread); - KEYWORD(nnan) - KEYWORD(ninf) - KEYWORD(nsz) - KEYWORD(arcp) - KEYWORD(fast) + KEYWORD(nnan); + KEYWORD(ninf); + KEYWORD(nsz); + KEYWORD(arcp); + KEYWORD(fast); KEYWORD(nuw); KEYWORD(nsw); KEYWORD(exact); @@ -537,33 +560,39 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(cc); KEYWORD(c); - KEYWORD(signext); - KEYWORD(zeroext); + KEYWORD(attributes); + + KEYWORD(alwaysinline); + KEYWORD(byval); + KEYWORD(inlinehint); KEYWORD(inreg); - KEYWORD(sret); - KEYWORD(nounwind); - KEYWORD(noreturn); + KEYWORD(minsize); + KEYWORD(naked); + KEYWORD(nest); KEYWORD(noalias); + KEYWORD(nobuiltin); 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(noredzone); - KEYWORD(noimplicitfloat); - KEYWORD(naked); - KEYWORD(nonlazybind); - KEYWORD(address_safety); - KEYWORD(minsize); + KEYWORD(sspstrong); + KEYWORD(sanitize_address); + KEYWORD(sanitize_thread); + KEYWORD(sanitize_memory); + KEYWORD(uwtable); + KEYWORD(zeroext); KEYWORD(type); KEYWORD(opaque); @@ -658,7 +687,8 @@ lltok::Kind LLLexer::LexIdentifier() { // Check for [us]0x[0-9A-Fa-f]+ which are Hexadecimal constant generated by // the CFE to avoid forcing it to deal with 64-bit numbers. if ((TokStart[0] == 'u' || TokStart[0] == 's') && - TokStart[1] == '0' && TokStart[2] == 'x' && isxdigit(TokStart[3])) { + TokStart[1] == '0' && TokStart[2] == 'x' && + isxdigit(static_cast<unsigned char>(TokStart[3]))) { int len = CurPtr-TokStart-3; uint32_t bits = len * 4; APInt Tmp(bits, StringRef(TokStart+3, len), 16); @@ -698,13 +728,13 @@ lltok::Kind LLLexer::Lex0x() { Kind = 'J'; } - if (!isxdigit(CurPtr[0])) { + if (!isxdigit(static_cast<unsigned char>(CurPtr[0]))) { // Bad token, return it as an error. CurPtr = TokStart+1; return lltok::Error; } - while (isxdigit(CurPtr[0])) + while (isxdigit(static_cast<unsigned char>(CurPtr[0]))) ++CurPtr; if (Kind == 'J') { @@ -721,20 +751,21 @@ lltok::Kind LLLexer::Lex0x() { case 'K': // F80HexFPConstant - x87 long double in hexadecimal format (10 bytes) FP80HexToIntPair(TokStart+3, CurPtr, Pair); - APFloatVal = APFloat(APInt(80, Pair)); + APFloatVal = APFloat(APFloat::x87DoubleExtended, APInt(80, Pair)); return lltok::APFloat; case 'L': // F128HexFPConstant - IEEE 128-bit in hexadecimal format (16 bytes) HexToIntPair(TokStart+3, CurPtr, Pair); - APFloatVal = APFloat(APInt(128, Pair), true); + APFloatVal = APFloat(APFloat::IEEEquad, APInt(128, Pair)); return lltok::APFloat; case 'M': // PPC128HexFPConstant - PowerPC 128-bit in hexadecimal format (16 bytes) HexToIntPair(TokStart+3, CurPtr, Pair); - APFloatVal = APFloat(APInt(128, Pair)); + APFloatVal = APFloat(APFloat::PPCDoubleDouble, APInt(128, Pair)); return lltok::APFloat; case 'H': - APFloatVal = APFloat(APInt(16,HexIntToVal(TokStart+3, CurPtr))); + APFloatVal = APFloat(APFloat::IEEEhalf, + APInt(16,HexIntToVal(TokStart+3, CurPtr))); return lltok::APFloat; } } @@ -750,7 +781,8 @@ lltok::Kind LLLexer::Lex0x() { /// HexPPC128Constant 0xM[0-9A-Fa-f]+ lltok::Kind LLLexer::LexDigitOrNegative() { // If the letter after the negative is not a number, this is probably a label. - if (!isdigit(TokStart[0]) && !isdigit(CurPtr[0])) { + if (!isdigit(static_cast<unsigned char>(TokStart[0])) && + !isdigit(static_cast<unsigned char>(CurPtr[0]))) { // Okay, this is not a number after the -, it's probably a label. if (const char *End = isLabelTail(CurPtr)) { StrVal.assign(TokStart, End-1); @@ -764,7 +796,7 @@ lltok::Kind LLLexer::LexDigitOrNegative() { // At this point, it is either a label, int or fp constant. // Skip digits, we have at least one. - for (; isdigit(CurPtr[0]); ++CurPtr) + for (; isdigit(static_cast<unsigned char>(CurPtr[0])); ++CurPtr) /*empty*/; // Check to see if this really is a label afterall, e.g. "-1:". @@ -801,13 +833,14 @@ lltok::Kind LLLexer::LexDigitOrNegative() { ++CurPtr; // Skip over [0-9]*([eE][-+]?[0-9]+)? - while (isdigit(CurPtr[0])) ++CurPtr; + while (isdigit(static_cast<unsigned char>(CurPtr[0]))) ++CurPtr; if (CurPtr[0] == 'e' || CurPtr[0] == 'E') { - if (isdigit(CurPtr[1]) || - ((CurPtr[1] == '-' || CurPtr[1] == '+') && isdigit(CurPtr[2]))) { + if (isdigit(static_cast<unsigned char>(CurPtr[1])) || + ((CurPtr[1] == '-' || CurPtr[1] == '+') && + isdigit(static_cast<unsigned char>(CurPtr[2])))) { CurPtr += 2; - while (isdigit(CurPtr[0])) ++CurPtr; + while (isdigit(static_cast<unsigned char>(CurPtr[0]))) ++CurPtr; } } @@ -819,11 +852,11 @@ lltok::Kind LLLexer::LexDigitOrNegative() { lltok::Kind LLLexer::LexPositive() { // If the letter after the negative is a number, this is probably not a // label. - if (!isdigit(CurPtr[0])) + if (!isdigit(static_cast<unsigned char>(CurPtr[0]))) return lltok::Error; // Skip digits. - for (++CurPtr; isdigit(CurPtr[0]); ++CurPtr) + for (++CurPtr; isdigit(static_cast<unsigned char>(CurPtr[0])); ++CurPtr) /*empty*/; // At this point, we need a '.'. @@ -835,13 +868,14 @@ lltok::Kind LLLexer::LexPositive() { ++CurPtr; // Skip over [0-9]*([eE][-+]?[0-9]+)? - while (isdigit(CurPtr[0])) ++CurPtr; + while (isdigit(static_cast<unsigned char>(CurPtr[0]))) ++CurPtr; if (CurPtr[0] == 'e' || CurPtr[0] == 'E') { - if (isdigit(CurPtr[1]) || - ((CurPtr[1] == '-' || CurPtr[1] == '+') && isdigit(CurPtr[2]))) { + if (isdigit(static_cast<unsigned char>(CurPtr[1])) || + ((CurPtr[1] == '-' || CurPtr[1] == '+') && + isdigit(static_cast<unsigned char>(CurPtr[2])))) { CurPtr += 2; - while (isdigit(CurPtr[0])) ++CurPtr; + while (isdigit(static_cast<unsigned char>(CurPtr[0]))) ++CurPtr; } } 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 16b955d58f..c8da1f8bc6 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -14,16 +14,16 @@ #include "LLParser.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/AutoUpgrade.h" -#include "llvm/CallingConv.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/InlineAsm.h" -#include "llvm/Instructions.h" -#include "llvm/Module.h" -#include "llvm/Operator.h" +#include "llvm/IR/CallingConv.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/InlineAsm.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Operator.h" +#include "llvm/IR/ValueSymbolTable.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/ValueSymbolTable.h" using namespace llvm; static std::string getTypeString(Type *T) { @@ -65,6 +65,64 @@ bool LLParser::ValidateEndOfModule() { ForwardRefInstMetadata.clear(); } + // Handle any function attribute group forward references. + for (std::map<Value*, std::vector<unsigned> >::iterator + I = ForwardRefAttrGroups.begin(), E = ForwardRefAttrGroups.end(); + I != E; ++I) { + Value *V = I->first; + std::vector<unsigned> &Vec = I->second; + AttrBuilder B; + + for (std::vector<unsigned>::iterator VI = Vec.begin(), VE = Vec.end(); + VI != VE; ++VI) + B.merge(NumberedAttrBuilders[*VI]); + + if (Function *Fn = dyn_cast<Function>(V)) { + AttributeSet AS = Fn->getAttributes(); + AttrBuilder FnAttrs(AS.getFnAttributes(), AttributeSet::FunctionIndex); + AS = AS.removeAttributes(Context, AttributeSet::FunctionIndex, + AS.getFnAttributes()); + + FnAttrs.merge(B); + + // If the alignment was parsed as an attribute, move to the alignment + // field. + if (FnAttrs.hasAlignmentAttr()) { + Fn->setAlignment(FnAttrs.getAlignment()); + FnAttrs.removeAttribute(Attribute::Alignment); + } + + AS = AS.addAttributes(Context, AttributeSet::FunctionIndex, + AttributeSet::get(Context, + AttributeSet::FunctionIndex, + FnAttrs)); + Fn->setAttributes(AS); + } else if (CallInst *CI = dyn_cast<CallInst>(V)) { + AttributeSet AS = CI->getAttributes(); + AttrBuilder FnAttrs(AS.getFnAttributes(), AttributeSet::FunctionIndex); + AS = AS.removeAttributes(Context, AttributeSet::FunctionIndex, + AS.getFnAttributes()); + FnAttrs.merge(B); + AS = AS.addAttributes(Context, AttributeSet::FunctionIndex, + AttributeSet::get(Context, + AttributeSet::FunctionIndex, + FnAttrs)); + CI->setAttributes(AS); + } else if (InvokeInst *II = dyn_cast<InvokeInst>(V)) { + AttributeSet AS = II->getAttributes(); + AttrBuilder FnAttrs(AS.getFnAttributes(), AttributeSet::FunctionIndex); + AS = AS.removeAttributes(Context, AttributeSet::FunctionIndex, + AS.getFnAttributes()); + FnAttrs.merge(B); + AS = AS.addAttributes(Context, AttributeSet::FunctionIndex, + AttributeSet::get(Context, + AttributeSet::FunctionIndex, + FnAttrs)); + II->setAttributes(AS); + } else { + llvm_unreachable("invalid object with forward attribute group reference"); + } + } // If there are entries in ForwardRefBlockAddresses at this point, they are // references after the function was defined. Resolve those now. @@ -174,7 +232,7 @@ 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; // The Global variable production with no name can have many different // optional leading prefixes, the production is: @@ -220,6 +278,8 @@ bool LLParser::ParseTopLevelEntities() { case lltok::kw_global: // GlobalType if (ParseGlobal("", SMLoc(), 0, false, 0)) return true; break; + + case lltok::kw_attributes: if (ParseUnnamedAttrGrp()) return true; break; } } } @@ -632,9 +692,11 @@ bool LLParser::ParseAlias(const std::string &Name, LocTy NameLoc, /// ParseGlobal /// ::= GlobalVar '=' OptionalLinkage OptionalVisibility OptionalThreadLocal -/// OptionalAddrSpace OptionalUnNammedAddr GlobalType Type Const +/// OptionalAddrSpace OptionalUnNammedAddr +/// OptionalExternallyInitialized GlobalType Type Const /// ::= OptionalLinkage OptionalVisibility OptionalThreadLocal -/// OptionalAddrSpace OptionalUnNammedAddr GlobalType Type Const +/// OptionalAddrSpace OptionalUnNammedAddr +/// OptionalExternallyInitialized GlobalType Type Const /// /// Everything through visibility has been parsed already. /// @@ -642,9 +704,10 @@ bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc, unsigned Linkage, bool HasLinkage, unsigned Visibility) { unsigned AddrSpace; - bool IsConstant, UnnamedAddr; + bool IsConstant, UnnamedAddr, IsExternallyInitialized; GlobalVariable::ThreadLocalMode TLM; LocTy UnnamedAddrLoc; + LocTy IsExternallyInitializedLoc; LocTy TyLoc; Type *Ty = 0; @@ -652,6 +715,9 @@ bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc, ParseOptionalAddrSpace(AddrSpace) || ParseOptionalToken(lltok::kw_unnamed_addr, UnnamedAddr, &UnnamedAddrLoc) || + ParseOptionalToken(lltok::kw_externally_initialized, + IsExternallyInitialized, + &IsExternallyInitializedLoc) || ParseGlobalType(IsConstant) || ParseType(Ty, TyLoc)) return true; @@ -709,6 +775,7 @@ bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc, GV->setConstant(IsConstant); GV->setLinkage((GlobalValue::LinkageTypes)Linkage); GV->setVisibility((GlobalValue::VisibilityTypes)Visibility); + GV->setExternallyInitialized(IsExternallyInitialized); GV->setThreadLocalMode(TLM); GV->setUnnamedAddr(UnnamedAddr); @@ -733,6 +800,159 @@ bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc, return false; } +/// ParseUnnamedAttrGrp +/// ::= 'attributes' AttrGrpID '=' '{' AttrValPair+ '}' +bool LLParser::ParseUnnamedAttrGrp() { + assert(Lex.getKind() == lltok::kw_attributes); + LocTy AttrGrpLoc = Lex.getLoc(); + Lex.Lex(); + + assert(Lex.getKind() == lltok::AttrGrpID); + unsigned VarID = Lex.getUIntVal(); + std::vector<unsigned> unused; + LocTy NoBuiltinLoc; + Lex.Lex(); + + if (ParseToken(lltok::equal, "expected '=' here") || + ParseToken(lltok::lbrace, "expected '{' here") || + ParseFnAttributeValuePairs(NumberedAttrBuilders[VarID], unused, true, + NoBuiltinLoc) || + ParseToken(lltok::rbrace, "expected end of attribute group")) + return true; + + if (!NumberedAttrBuilders[VarID].hasAttributes()) + return Error(AttrGrpLoc, "attribute group has no attributes"); + + return false; +} + +/// ParseFnAttributeValuePairs +/// ::= <attr> | <attr> '=' <value> +bool LLParser::ParseFnAttributeValuePairs(AttrBuilder &B, + std::vector<unsigned> &FwdRefAttrGrps, + bool inAttrGrp, LocTy &NoBuiltinLoc) { + bool HaveError = false; + + B.clear(); + + while (true) { + lltok::Kind Token = Lex.getKind(); + if (Token == lltok::kw_nobuiltin) + NoBuiltinLoc = Lex.getLoc(); + switch (Token) { + default: + if (!inAttrGrp) return HaveError; + return Error(Lex.getLoc(), "unterminated attribute group"); + case lltok::rbrace: + // Finished. + return false; + + case lltok::AttrGrpID: { + // Allow a function to reference an attribute group: + // + // define void @foo() #1 { ... } + if (inAttrGrp) + HaveError |= + Error(Lex.getLoc(), + "cannot have an attribute group reference in an attribute group"); + + unsigned AttrGrpNum = Lex.getUIntVal(); + if (inAttrGrp) break; + + // Save the reference to the attribute group. We'll fill it in later. + FwdRefAttrGrps.push_back(AttrGrpNum); + break; + } + // 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); + continue; + } + + // Target-independent attributes: + case lltok::kw_align: { + // As a hack, we allow "align 2" on functions as a synonym for "alignstack + // 2". + unsigned Alignment; + if (inAttrGrp) { + Lex.Lex(); + if (ParseToken(lltok::equal, "expected '=' here") || + ParseUInt32(Alignment)) + return true; + } else { + if (ParseOptionalAlignment(Alignment)) + return true; + } + B.addAlignmentAttr(Alignment); + continue; + } + case lltok::kw_alignstack: { + unsigned Alignment; + if (inAttrGrp) { + Lex.Lex(); + if (ParseToken(lltok::equal, "expected '=' here") || + ParseUInt32(Alignment)) + return true; + } else { + if (ParseOptionalStackAlignment(Alignment)) + return true; + } + B.addStackAlignmentAttr(Alignment); + continue; + } + case lltok::kw_alwaysinline: B.addAttribute(Attribute::AlwaysInline); break; + case lltok::kw_inlinehint: B.addAttribute(Attribute::InlineHint); break; + case lltok::kw_minsize: B.addAttribute(Attribute::MinSize); break; + case lltok::kw_naked: B.addAttribute(Attribute::Naked); break; + case lltok::kw_nobuiltin: B.addAttribute(Attribute::NoBuiltin); 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_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_sanitize_address: B.addAttribute(Attribute::SanitizeAddress); break; + case lltok::kw_sanitize_thread: B.addAttribute(Attribute::SanitizeThread); break; + case lltok::kw_sanitize_memory: B.addAttribute(Attribute::SanitizeMemory); break; + case lltok::kw_uwtable: B.addAttribute(Attribute::UWTable); break; + + // Error handling. + case lltok::kw_inreg: + case lltok::kw_signext: + case lltok::kw_zeroext: + HaveError |= + Error(Lex.getLoc(), + "invalid use of attribute on a function"); + break; + case lltok::kw_byval: + case lltok::kw_nest: + case lltok::kw_noalias: + case lltok::kw_nocapture: + case lltok::kw_sret: + HaveError |= + Error(Lex.getLoc(), + "invalid use of parameter-only attribute on a function"); + break; + } + + Lex.Lex(); + } +} //===----------------------------------------------------------------------===// // GlobalValue Reference/Resolution Routines. @@ -912,70 +1132,6 @@ bool LLParser::ParseOptionalAddrSpace(unsigned &AddrSpace) { ParseToken(lltok::rparen, "expected ')' in address space"); } -/// ParseOptionalFuncAttrs - Parse a potentially empty list of function attributes. -bool LLParser::ParseOptionalFuncAttrs(AttrBuilder &B) { - bool HaveError = false; - - B.clear(); - - while (1) { - lltok::Kind Token = Lex.getKind(); - switch (Token) { - default: // End of attributes. - return HaveError; - case lltok::kw_alignstack: { - unsigned Alignment; - if (ParseOptionalStackAlignment(Alignment)) - return true; - B.addStackAlignmentAttr(Alignment); - continue; - } - case lltok::kw_align: { - // As a hack, we allow "align 2" on functions as a synonym for "alignstack - // 2". - unsigned Alignment; - if (ParseOptionalAlignment(Alignment)) - return true; - B.addAlignmentAttr(Alignment); - continue; - } - case lltok::kw_address_safety: B.addAttribute(Attributes::AddressSafety); break; - case lltok::kw_alwaysinline: B.addAttribute(Attributes::AlwaysInline); break; - case lltok::kw_inlinehint: B.addAttribute(Attributes::InlineHint); break; - case lltok::kw_minsize: B.addAttribute(Attributes::MinSize); break; - case lltok::kw_naked: B.addAttribute(Attributes::Naked); break; - case lltok::kw_noinline: B.addAttribute(Attributes::NoInline); break; - case lltok::kw_nonlazybind: B.addAttribute(Attributes::NonLazyBind); break; - case lltok::kw_noredzone: B.addAttribute(Attributes::NoRedZone); break; - case lltok::kw_noimplicitfloat: B.addAttribute(Attributes::NoImplicitFloat); break; - case lltok::kw_noreturn: B.addAttribute(Attributes::NoReturn); break; - case lltok::kw_nounwind: B.addAttribute(Attributes::NoUnwind); break; - case lltok::kw_optsize: B.addAttribute(Attributes::OptimizeForSize); break; - case lltok::kw_readnone: B.addAttribute(Attributes::ReadNone); break; - case lltok::kw_readonly: B.addAttribute(Attributes::ReadOnly); break; - case lltok::kw_returns_twice: B.addAttribute(Attributes::ReturnsTwice); break; - case lltok::kw_ssp: B.addAttribute(Attributes::StackProtect); break; - case lltok::kw_sspreq: B.addAttribute(Attributes::StackProtectReq); break; - case lltok::kw_uwtable: B.addAttribute(Attributes::UWTable); break; - - // Error handling. - case lltok::kw_zeroext: - case lltok::kw_signext: - case lltok::kw_inreg: - HaveError |= Error(Lex.getLoc(), "invalid use of attribute on a function"); - break; - case lltok::kw_sret: case lltok::kw_noalias: - case lltok::kw_nocapture: case lltok::kw_byval: - case lltok::kw_nest: - HaveError |= - Error(Lex.getLoc(), "invalid use of parameter-only attribute on a function"); - break; - } - - Lex.Lex(); - } -} - /// ParseOptionalParamAttrs - Parse a potentially empty list of parameter attributes. bool LLParser::ParseOptionalParamAttrs(AttrBuilder &B) { bool HaveError = false; @@ -994,25 +1150,26 @@ bool LLParser::ParseOptionalParamAttrs(AttrBuilder &B) { B.addAlignmentAttr(Alignment); continue; } - case lltok::kw_byval: B.addAttribute(Attributes::ByVal); break; - case lltok::kw_inreg: B.addAttribute(Attributes::InReg); break; - case lltok::kw_nest: B.addAttribute(Attributes::Nest); break; - case lltok::kw_noalias: B.addAttribute(Attributes::NoAlias); break; - case lltok::kw_nocapture: B.addAttribute(Attributes::NoCapture); break; - case lltok::kw_signext: B.addAttribute(Attributes::SExt); break; - case lltok::kw_sret: B.addAttribute(Attributes::StructRet); break; - case lltok::kw_zeroext: B.addAttribute(Attributes::ZExt); break; - - case lltok::kw_noreturn: case lltok::kw_nounwind: - case lltok::kw_uwtable: case lltok::kw_returns_twice: - case lltok::kw_noinline: case lltok::kw_readnone: - case lltok::kw_readonly: case lltok::kw_inlinehint: - case lltok::kw_alwaysinline: case lltok::kw_optsize: - case lltok::kw_ssp: case lltok::kw_sspreq: - case lltok::kw_noredzone: case lltok::kw_noimplicitfloat: - case lltok::kw_naked: case lltok::kw_nonlazybind: - case lltok::kw_address_safety: case lltok::kw_minsize: - case lltok::kw_alignstack: + case lltok::kw_byval: B.addAttribute(Attribute::ByVal); break; + case lltok::kw_inreg: B.addAttribute(Attribute::InReg); 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_signext: B.addAttribute(Attribute::SExt); break; + case lltok::kw_sret: B.addAttribute(Attribute::StructRet); break; + case lltok::kw_zeroext: B.addAttribute(Attribute::ZExt); break; + + case lltok::kw_alignstack: case lltok::kw_nounwind: + case lltok::kw_alwaysinline: case lltok::kw_optsize: + case lltok::kw_inlinehint: case lltok::kw_readnone: + case lltok::kw_minsize: case lltok::kw_readonly: + case lltok::kw_naked: case lltok::kw_returns_twice: + case lltok::kw_nobuiltin: case lltok::kw_sanitize_address: + case lltok::kw_noimplicitfloat: case lltok::kw_sanitize_memory: + case lltok::kw_noinline: case lltok::kw_sanitize_thread: + case lltok::kw_nonlazybind: case lltok::kw_ssp: + case lltok::kw_noredzone: case lltok::kw_sspreq: + case lltok::kw_noreturn: case lltok::kw_uwtable: HaveError |= Error(Lex.getLoc(), "invalid use of function-only attribute"); break; } @@ -1032,26 +1189,30 @@ bool LLParser::ParseOptionalReturnAttrs(AttrBuilder &B) { switch (Token) { default: // End of attributes. return HaveError; - case lltok::kw_inreg: B.addAttribute(Attributes::InReg); break; - case lltok::kw_noalias: B.addAttribute(Attributes::NoAlias); break; - case lltok::kw_signext: B.addAttribute(Attributes::SExt); break; - case lltok::kw_zeroext: B.addAttribute(Attributes::ZExt); break; + case lltok::kw_inreg: B.addAttribute(Attribute::InReg); break; + case lltok::kw_noalias: B.addAttribute(Attribute::NoAlias); break; + case lltok::kw_signext: B.addAttribute(Attribute::SExt); break; + case lltok::kw_zeroext: B.addAttribute(Attribute::ZExt); break; // Error handling. case lltok::kw_sret: case lltok::kw_nocapture: case lltok::kw_byval: case lltok::kw_nest: HaveError |= Error(Lex.getLoc(), "invalid use of parameter-only attribute"); break; - case lltok::kw_noreturn: case lltok::kw_nounwind: - case lltok::kw_uwtable: case lltok::kw_returns_twice: - case lltok::kw_noinline: case lltok::kw_readnone: - case lltok::kw_readonly: case lltok::kw_inlinehint: - case lltok::kw_alwaysinline: case lltok::kw_optsize: - case lltok::kw_ssp: case lltok::kw_sspreq: - case lltok::kw_noredzone: case lltok::kw_noimplicitfloat: - case lltok::kw_naked: case lltok::kw_nonlazybind: - case lltok::kw_address_safety: case lltok::kw_minsize: - case lltok::kw_alignstack: case lltok::kw_align: + + case lltok::kw_align: case lltok::kw_noreturn: + case lltok::kw_alignstack: case lltok::kw_nounwind: + case lltok::kw_alwaysinline: case lltok::kw_optsize: + case lltok::kw_inlinehint: case lltok::kw_readnone: + case lltok::kw_minsize: case lltok::kw_readonly: + case lltok::kw_naked: case lltok::kw_returns_twice: + case lltok::kw_nobuiltin: case lltok::kw_sanitize_address: + case lltok::kw_noduplicate: case lltok::kw_sanitize_memory: + case lltok::kw_noimplicitfloat: case lltok::kw_sanitize_thread: + case lltok::kw_noinline: case lltok::kw_ssp: + case lltok::kw_nonlazybind: case lltok::kw_sspreq: + case lltok::kw_noredzone: case lltok::kw_sspstrong: + case lltok::kw_uwtable: HaveError |= Error(Lex.getLoc(), "invalid use of function-only attribute"); break; } @@ -1468,6 +1629,7 @@ bool LLParser::ParseParameterList(SmallVectorImpl<ParamInfo> &ArgList, if (ParseToken(lltok::lparen, "expected '(' in call")) return true; + unsigned AttrIndex = 1; while (Lex.getKind() != lltok::rparen) { // If this isn't the first argument, we need a comma. if (!ArgList.empty() && @@ -1485,8 +1647,9 @@ bool LLParser::ParseParameterList(SmallVectorImpl<ParamInfo> &ArgList, // Otherwise, handle normal operands. if (ParseOptionalParamAttrs(ArgAttrs) || ParseValue(ArgTy, V, PFS)) return true; - ArgList.push_back(ParamInfo(ArgLoc, V, Attributes::get(V->getContext(), - ArgAttrs))); + ArgList.push_back(ParamInfo(ArgLoc, V, AttributeSet::get(V->getContext(), + AttrIndex++, + ArgAttrs))); } Lex.Lex(); // Lex the ')'. @@ -1535,9 +1698,10 @@ bool LLParser::ParseArgumentList(SmallVectorImpl<ArgInfo> &ArgList, if (!FunctionType::isValidArgumentType(ArgTy)) return Error(TypeLoc, "invalid type for function argument"); + unsigned AttrIndex = 1; ArgList.push_back(ArgInfo(TypeLoc, ArgTy, - Attributes::get(ArgTy->getContext(), - Attrs), Name)); + AttributeSet::get(ArgTy->getContext(), + AttrIndex++, Attrs), Name)); while (EatIfPresent(lltok::comma)) { // Handle ... at end of arg list. @@ -1564,7 +1728,8 @@ bool LLParser::ParseArgumentList(SmallVectorImpl<ArgInfo> &ArgList, return Error(TypeLoc, "invalid type for function argument"); ArgList.push_back(ArgInfo(TypeLoc, ArgTy, - Attributes::get(ArgTy->getContext(), Attrs), + AttributeSet::get(ArgTy->getContext(), + AttrIndex++, Attrs), Name)); } } @@ -1589,7 +1754,7 @@ bool LLParser::ParseFunctionType(Type *&Result) { for (unsigned i = 0, e = ArgList.size(); i != e; ++i) { if (!ArgList[i].Name.empty()) return Error(ArgList[i].Loc, "argument name invalid in function type"); - if (ArgList[i].Attrs.hasAttributes()) + if (ArgList[i].Attrs.hasAttributes(i + 1)) return Error(ArgList[i].Loc, "argument attributes invalid in function type"); } @@ -2153,7 +2318,8 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) { return false; case lltok::kw_asm: { - // ValID ::= 'asm' SideEffect? AlignStack? STRINGCONSTANT ',' STRINGCONSTANT + // ValID ::= 'asm' SideEffect? AlignStack? IntelDialect? STRINGCONSTANT ',' + // STRINGCONSTANT bool HasSideEffect, AlignStack, AsmDialect; Lex.Lex(); if (ParseOptionalToken(lltok::kw_sideeffect, HasSideEffect) || @@ -2783,6 +2949,8 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) { SmallVector<ArgInfo, 8> ArgList; bool isVarArg; AttrBuilder FuncAttrs; + std::vector<unsigned> FwdRefAttrGrps; + LocTy NoBuiltinLoc; std::string Section; unsigned Alignment; std::string GC; @@ -2792,7 +2960,8 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) { if (ParseArgumentList(ArgList, isVarArg) || ParseOptionalToken(lltok::kw_unnamed_addr, UnnamedAddr, &UnnamedAddrLoc) || - ParseOptionalFuncAttrs(FuncAttrs) || + ParseFnAttributeValuePairs(FuncAttrs, FwdRefAttrGrps, false, + NoBuiltinLoc) || (EatIfPresent(lltok::kw_section) && ParseStringConstant(Section)) || ParseOptionalAlignment(Alignment) || @@ -2800,39 +2969,41 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) { ParseStringConstant(GC))) return true; + if (FuncAttrs.contains(Attribute::NoBuiltin)) + return Error(NoBuiltinLoc, "'nobuiltin' attribute not valid on function"); + // If the alignment was parsed as an attribute, move to the alignment field. if (FuncAttrs.hasAlignmentAttr()) { Alignment = FuncAttrs.getAlignment(); - FuncAttrs.removeAttribute(Attributes::Alignment); + FuncAttrs.removeAttribute(Attribute::Alignment); } // Okay, if we got here, the function is syntactically valid. Convert types // and do semantic checks. std::vector<Type*> ParamTypeList; - SmallVector<AttributeWithIndex, 8> Attrs; + SmallVector<AttributeSet, 8> Attrs; if (RetAttrs.hasAttributes()) - Attrs.push_back( - AttributeWithIndex::get(AttributeSet::ReturnIndex, - Attributes::get(RetType->getContext(), - RetAttrs))); + Attrs.push_back(AttributeSet::get(RetType->getContext(), + AttributeSet::ReturnIndex, + RetAttrs)); for (unsigned i = 0, e = ArgList.size(); i != e; ++i) { ParamTypeList.push_back(ArgList[i].Ty); - if (ArgList[i].Attrs.hasAttributes()) - Attrs.push_back(AttributeWithIndex::get(i+1, ArgList[i].Attrs)); + if (ArgList[i].Attrs.hasAttributes(i + 1)) { + AttrBuilder B(ArgList[i].Attrs, i + 1); + Attrs.push_back(AttributeSet::get(RetType->getContext(), i + 1, B)); + } } if (FuncAttrs.hasAttributes()) - Attrs.push_back( - AttributeWithIndex::get(AttributeSet::FunctionIndex, - Attributes::get(RetType->getContext(), - FuncAttrs))); + Attrs.push_back(AttributeSet::get(RetType->getContext(), + AttributeSet::FunctionIndex, + FuncAttrs)); AttributeSet PAL = AttributeSet::get(Context, Attrs); - if (PAL.getParamAttributes(1).hasAttribute(Attributes::StructRet) && - !RetType->isVoidTy()) + if (PAL.hasAttribute(1, Attribute::StructRet) && !RetType->isVoidTy()) return Error(RetTypeLoc, "functions with 'sret' argument must return void"); FunctionType *FT = @@ -2893,6 +3064,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) { Fn->setAlignment(Alignment); Fn->setSection(Section); if (!GC.empty()) Fn->setGC(GC.c_str()); + ForwardRefAttrGroups[Fn] = FwdRefAttrGrps; // Add all of the arguments we parsed to the function. Function::arg_iterator ArgIt = Fn->arg_begin(); @@ -3118,7 +3290,7 @@ int LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB, bool LLParser::ParseCmpPredicate(unsigned &P, unsigned Opc) { if (Opc == Instruction::FCmp) { switch (Lex.getKind()) { - default: TokError("expected fcmp predicate (e.g. 'oeq')"); + default: return TokError("expected fcmp predicate (e.g. 'oeq')"); case lltok::kw_oeq: P = CmpInst::FCMP_OEQ; break; case lltok::kw_one: P = CmpInst::FCMP_ONE; break; case lltok::kw_olt: P = CmpInst::FCMP_OLT; break; @@ -3138,7 +3310,7 @@ bool LLParser::ParseCmpPredicate(unsigned &P, unsigned Opc) { } } else { switch (Lex.getKind()) { - default: TokError("expected icmp predicate (e.g. 'eq')"); + default: return TokError("expected icmp predicate (e.g. 'eq')"); case lltok::kw_eq: P = CmpInst::ICMP_EQ; break; case lltok::kw_ne: P = CmpInst::ICMP_NE; break; case lltok::kw_slt: P = CmpInst::ICMP_SLT; break; @@ -3312,6 +3484,8 @@ bool LLParser::ParseIndirectBr(Instruction *&Inst, PerFunctionState &PFS) { bool LLParser::ParseInvoke(Instruction *&Inst, PerFunctionState &PFS) { LocTy CallLoc = Lex.getLoc(); AttrBuilder RetAttrs, FnAttrs; + std::vector<unsigned> FwdRefAttrGrps; + LocTy NoBuiltinLoc; CallingConv::ID CC; Type *RetType = 0; LocTy RetTypeLoc; @@ -3324,7 +3498,8 @@ bool LLParser::ParseInvoke(Instruction *&Inst, PerFunctionState &PFS) { ParseType(RetType, RetTypeLoc, true /*void allowed*/) || ParseValID(CalleeID) || ParseParameterList(ArgList, PFS) || - ParseOptionalFuncAttrs(FnAttrs) || + ParseFnAttributeValuePairs(FnAttrs, FwdRefAttrGrps, false, + NoBuiltinLoc) || ParseToken(lltok::kw_to, "expected 'to' in invoke") || ParseTypeAndBasicBlock(NormalBB, PFS) || ParseToken(lltok::kw_unwind, "expected 'unwind' in invoke") || @@ -3354,13 +3529,12 @@ bool LLParser::ParseInvoke(Instruction *&Inst, PerFunctionState &PFS) { Value *Callee; if (ConvertValIDToValue(PFTy, CalleeID, Callee, &PFS)) return true; - // Set up the Attributes for the function. - SmallVector<AttributeWithIndex, 8> Attrs; + // Set up the Attribute for the function. + SmallVector<AttributeSet, 8> Attrs; if (RetAttrs.hasAttributes()) - Attrs.push_back( - AttributeWithIndex::get(AttributeSet::ReturnIndex, - Attributes::get(Callee->getContext(), - RetAttrs))); + Attrs.push_back(AttributeSet::get(RetType->getContext(), + AttributeSet::ReturnIndex, + RetAttrs)); SmallVector<Value*, 8> Args; @@ -3380,25 +3554,27 @@ bool LLParser::ParseInvoke(Instruction *&Inst, PerFunctionState &PFS) { return Error(ArgList[i].Loc, "argument is not of expected type '" + getTypeString(ExpectedTy) + "'"); Args.push_back(ArgList[i].V); - if (ArgList[i].Attrs.hasAttributes()) - Attrs.push_back(AttributeWithIndex::get(i+1, ArgList[i].Attrs)); + if (ArgList[i].Attrs.hasAttributes(i + 1)) { + AttrBuilder B(ArgList[i].Attrs, i + 1); + Attrs.push_back(AttributeSet::get(RetType->getContext(), i + 1, B)); + } } if (I != E) return Error(CallLoc, "not enough parameters specified for call"); if (FnAttrs.hasAttributes()) - Attrs.push_back( - AttributeWithIndex::get(AttributeSet::FunctionIndex, - Attributes::get(Callee->getContext(), - FnAttrs))); + Attrs.push_back(AttributeSet::get(RetType->getContext(), + AttributeSet::FunctionIndex, + FnAttrs)); - // Finish off the Attributes and check them + // Finish off the Attribute and check them AttributeSet PAL = AttributeSet::get(Context, Attrs); InvokeInst *II = InvokeInst::Create(Callee, NormalBB, UnwindBB, Args); II->setCallingConv(CC); II->setAttributes(PAL); + ForwardRefAttrGroups[II] = FwdRefAttrGrps; Inst = II; return false; } @@ -3717,6 +3893,8 @@ bool LLParser::ParseLandingPad(Instruction *&Inst, PerFunctionState &PFS) { bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS, bool isTail) { AttrBuilder RetAttrs, FnAttrs; + std::vector<unsigned> FwdRefAttrGrps; + LocTy NoBuiltinLoc; CallingConv::ID CC; Type *RetType = 0; LocTy RetTypeLoc; @@ -3730,7 +3908,8 @@ bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS, ParseType(RetType, RetTypeLoc, true /*void allowed*/) || ParseValID(CalleeID) || ParseParameterList(ArgList, PFS) || - ParseOptionalFuncAttrs(FnAttrs)) + ParseFnAttributeValuePairs(FnAttrs, FwdRefAttrGrps, false, + NoBuiltinLoc)) return true; // If RetType is a non-function pointer type, then this is the short syntax @@ -3756,13 +3935,12 @@ bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS, Value *Callee; if (ConvertValIDToValue(PFTy, CalleeID, Callee, &PFS)) return true; - // Set up the Attributes for the function. - SmallVector<AttributeWithIndex, 8> Attrs; + // Set up the Attribute for the function. + SmallVector<AttributeSet, 8> Attrs; if (RetAttrs.hasAttributes()) - Attrs.push_back( - AttributeWithIndex::get(AttributeSet::ReturnIndex, - Attributes::get(Callee->getContext(), - RetAttrs))); + Attrs.push_back(AttributeSet::get(RetType->getContext(), + AttributeSet::ReturnIndex, + RetAttrs)); SmallVector<Value*, 8> Args; @@ -3782,26 +3960,28 @@ bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS, return Error(ArgList[i].Loc, "argument is not of expected type '" + getTypeString(ExpectedTy) + "'"); Args.push_back(ArgList[i].V); - if (ArgList[i].Attrs.hasAttributes()) - Attrs.push_back(AttributeWithIndex::get(i+1, ArgList[i].Attrs)); + if (ArgList[i].Attrs.hasAttributes(i + 1)) { + AttrBuilder B(ArgList[i].Attrs, i + 1); + Attrs.push_back(AttributeSet::get(RetType->getContext(), i + 1, B)); + } } if (I != E) return Error(CallLoc, "not enough parameters specified for call"); if (FnAttrs.hasAttributes()) - Attrs.push_back( - AttributeWithIndex::get(AttributeSet::FunctionIndex, - Attributes::get(Callee->getContext(), - FnAttrs))); + Attrs.push_back(AttributeSet::get(RetType->getContext(), + AttributeSet::FunctionIndex, + FnAttrs)); - // Finish off the Attributes and check them + // Finish off the Attribute and check them AttributeSet PAL = AttributeSet::get(Context, Attrs); CallInst *CI = CallInst::Create(Callee, Args); CI->setTailCall(isTail); CI->setCallingConv(CC); CI->setAttributes(PAL); + ForwardRefAttrGroups[CI] = FwdRefAttrGrps; Inst = CI; return false; } diff --git a/lib/AsmParser/LLParser.h b/lib/AsmParser/LLParser.h index 3a38159d80..1f2879e948 100644 --- a/lib/AsmParser/LLParser.h +++ b/lib/AsmParser/LLParser.h @@ -17,12 +17,12 @@ #include "LLLexer.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" -#include "llvm/Attributes.h" -#include "llvm/Instructions.h" -#include "llvm/Module.h" -#include "llvm/Operator.h" +#include "llvm/IR/Attributes.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Operator.h" +#include "llvm/IR/Type.h" #include "llvm/Support/ValueHandle.h" -#include "llvm/Type.h" #include <map> namespace llvm { @@ -125,6 +125,10 @@ namespace llvm { std::map<ValID, std::vector<std::pair<ValID, GlobalValue*> > > ForwardRefBlockAddresses; + // Attribute builder reference information. + std::map<Value*, std::vector<unsigned> > ForwardRefAttrGroups; + std::map<unsigned, AttrBuilder> NumberedAttrBuilders; + public: LLParser(MemoryBuffer *F, SourceMgr &SM, SMDiagnostic &Err, Module *m) : Context(m->getContext()), Lex(F, SM, Err, m->getContext()), @@ -191,7 +195,6 @@ namespace llvm { bool ParseTLSModel(GlobalVariable::ThreadLocalMode &TLM); bool ParseOptionalThreadLocal(GlobalVariable::ThreadLocalMode &TLM); bool ParseOptionalAddrSpace(unsigned &AddrSpace); - bool ParseOptionalFuncAttrs(AttrBuilder &B); bool ParseOptionalParamAttrs(AttrBuilder &B); bool ParseOptionalReturnAttrs(AttrBuilder &B); bool ParseOptionalLinkage(unsigned &Linkage, bool &HasLinkage); @@ -236,6 +239,10 @@ namespace llvm { bool ParseMDString(MDString *&Result); bool ParseMDNodeID(MDNode *&Result); bool ParseMDNodeID(MDNode *&Result, unsigned &SlotNo); + bool ParseUnnamedAttrGrp(); + bool ParseFnAttributeValuePairs(AttrBuilder &B, + std::vector<unsigned> &FwdRefAttrGrps, + bool inAttrGrp, LocTy &NoBuiltinLoc); // Type Parsing. bool ParseType(Type *&Result, bool AllowVoid = false); @@ -326,8 +333,8 @@ namespace llvm { struct ParamInfo { LocTy Loc; Value *V; - Attributes Attrs; - ParamInfo(LocTy loc, Value *v, Attributes attrs) + AttributeSet Attrs; + ParamInfo(LocTy loc, Value *v, AttributeSet attrs) : Loc(loc), V(v), Attrs(attrs) {} }; bool ParseParameterList(SmallVectorImpl<ParamInfo> &ArgList, @@ -347,9 +354,9 @@ namespace llvm { struct ArgInfo { LocTy Loc; Type *Ty; - Attributes Attrs; + AttributeSet Attrs; std::string Name; - ArgInfo(LocTy L, Type *ty, Attributes Attr, const std::string &N) + ArgInfo(LocTy L, Type *ty, AttributeSet Attr, const std::string &N) : Loc(L), Ty(ty), Attrs(Attr), Name(N) {} }; bool ParseArgumentList(SmallVectorImpl<ArgInfo> &ArgList, bool &isVarArg); diff --git a/lib/AsmParser/LLToken.h b/lib/AsmParser/LLToken.h index 2ed2c221a8..cd25ba3000 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, @@ -44,6 +45,7 @@ namespace lltok { kw_dllimport, kw_dllexport, kw_common, kw_available_externally, kw_default, kw_hidden, kw_protected, kw_unnamed_addr, + kw_externally_initialized, kw_extern_weak, kw_external, kw_thread_local, kw_localdynamic, kw_initialexec, kw_localexec, @@ -89,33 +91,39 @@ namespace lltok { kw_ptx_kernel, kw_ptx_device, kw_spir_kernel, kw_spir_func, - kw_signext, - kw_zeroext, + // Attributes: + kw_attributes, + kw_alwaysinline, + kw_sanitize_address, + kw_byval, + kw_inlinehint, kw_inreg, - kw_sret, - kw_nounwind, - kw_noreturn, + kw_minsize, + kw_naked, + kw_nest, kw_noalias, + kw_nobuiltin, 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_noredzone, - kw_noimplicitfloat, - kw_naked, - kw_nonlazybind, - kw_address_safety, - kw_minsize, + kw_sspstrong, + kw_sret, + kw_sanitize_thread, + kw_sanitize_memory, + kw_uwtable, + kw_zeroext, kw_type, kw_opaque, @@ -152,6 +160,7 @@ namespace lltok { // Unsigned Valued tokens (UIntVal). GlobalID, // @42 LocalVarID, // %42 + AttrGrpID, // #42 // String valued tokens (StrVal). LabelStr, // foo: diff --git a/lib/AsmParser/Parser.cpp b/lib/AsmParser/Parser.cpp index a473e6b713..bb4f03bacc 100644 --- a/lib/AsmParser/Parser.cpp +++ b/lib/AsmParser/Parser.cpp @@ -14,7 +14,7 @@ #include "llvm/Assembly/Parser.h" #include "LLParser.h" #include "llvm/ADT/OwningPtr.h" -#include "llvm/Module.h" +#include "llvm/IR/Module.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/raw_ostream.h" |