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.
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:
case lltok::kw_global: // GlobalType
if (ParseGlobal("", SMLoc(), 0, false, 0)) return true;
break;
+
+ case lltok::kw_attributes: if (ParseUnnamedAttrGrp()) return true; break;
}
}
}
if (Result) return false;
// Otherwise, create MDNode forward reference.
- MDNode *FwdNode = MDNode::getTemporary(Context, ArrayRef<Value*>());
+ MDNode *FwdNode = MDNode::getTemporary(Context, None);
ForwardRefMDNodes[MID] = std::make_pair(FwdNode, Lex.getLoc());
if (NumberedMetadata.size() <= MID)
/// 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.
///
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;
ParseOptionalAddrSpace(AddrSpace) ||
ParseOptionalToken(lltok::kw_unnamed_addr, UnnamedAddr,
&UnnamedAddrLoc) ||
+ ParseOptionalToken(lltok::kw_externally_initialized,
+ IsExternallyInitialized,
+ &IsExternallyInitializedLoc) ||
ParseGlobalType(IsConstant) ||
ParseType(Ty, TyLoc))
return true;
GV->setConstant(IsConstant);
GV->setLinkage((GlobalValue::LinkageTypes)Linkage);
GV->setVisibility((GlobalValue::VisibilityTypes)Visibility);
+ GV->setExternallyInitialized(IsExternallyInitialized);
GV->setThreadLocalMode(TLM);
GV->setUnnamedAddr(UnnamedAddr);
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 BuiltinLoc;
+ Lex.Lex();
+
+ if (ParseToken(lltok::equal, "expected '=' here") ||
+ ParseToken(lltok::lbrace, "expected '{' here") ||
+ ParseFnAttributeValuePairs(NumberedAttrBuilders[VarID], unused, true,
+ BuiltinLoc) ||
+ 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 &BuiltinLoc) {
+ bool HaveError = false;
+
+ B.clear();
+
+ while (true) {
+ lltok::Kind Token = Lex.getKind();
+ if (Token == lltok::kw_builtin)
+ BuiltinLoc = 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 function alignment to be initially parsed as an
+ // attribute on a function declaration/definition or added to an attribute
+ // group and later moved to the alignment field.
+ 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_builtin: B.addAttribute(Attribute::Builtin); break;
+ case lltok::kw_cold: B.addAttribute(Attribute::Cold); 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_returned:
+ case lltok::kw_sret:
+ HaveError |=
+ Error(Lex.getLoc(),
+ "invalid use of parameter-only attribute on a function");
+ break;
+ }
+
+ Lex.Lex();
+ }
+}
//===----------------------------------------------------------------------===//
// GlobalValue Reference/Resolution Routines.
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(Attribute::AddressSafety); break;
- 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_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_noimplicitfloat: B.addAttribute(Attribute::NoImplicitFloat); 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_uwtable: B.addAttribute(Attribute::UWTable); break;
- case lltok::kw_noduplicate: B.addAttribute(Attribute::NoDuplicate); 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;
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_readnone: B.addAttribute(Attribute::ReadNone); break;
+ case lltok::kw_readonly: B.addAttribute(Attribute::ReadOnly); break;
+ case lltok::kw_returned: B.addAttribute(Attribute::Returned); 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_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_alwaysinline:
+ case lltok::kw_builtin:
+ case lltok::kw_inlinehint:
+ case lltok::kw_minsize:
+ case lltok::kw_naked:
+ case lltok::kw_nobuiltin:
+ case lltok::kw_noduplicate:
+ case lltok::kw_noimplicitfloat:
+ case lltok::kw_noinline:
+ case lltok::kw_nonlazybind:
+ case lltok::kw_noredzone:
+ case lltok::kw_noreturn:
+ case lltok::kw_nounwind:
+ case lltok::kw_optsize:
+ case lltok::kw_returns_twice:
+ case lltok::kw_sanitize_address:
+ case lltok::kw_sanitize_memory:
+ case lltok::kw_sanitize_thread:
+ case lltok::kw_ssp:
+ case lltok::kw_sspreq:
+ case lltok::kw_sspstrong:
+ case lltok::kw_uwtable:
HaveError |= Error(Lex.getLoc(), "invalid use of function-only attribute");
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:
+ case lltok::kw_align:
+ case lltok::kw_byval:
+ case lltok::kw_nest:
+ case lltok::kw_nocapture:
+ case lltok::kw_returned:
+ case lltok::kw_sret:
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_alignstack:
+ case lltok::kw_alwaysinline:
+ case lltok::kw_builtin:
+ case lltok::kw_cold:
+ case lltok::kw_inlinehint:
+ case lltok::kw_minsize:
+ case lltok::kw_naked:
+ case lltok::kw_nobuiltin:
case lltok::kw_noduplicate:
+ case lltok::kw_noimplicitfloat:
+ case lltok::kw_noinline:
+ case lltok::kw_nonlazybind:
+ case lltok::kw_noredzone:
+ case lltok::kw_noreturn:
+ case lltok::kw_nounwind:
+ case lltok::kw_optsize:
+ case lltok::kw_returns_twice:
+ case lltok::kw_sanitize_address:
+ case lltok::kw_sanitize_memory:
+ case lltok::kw_sanitize_thread:
+ case lltok::kw_ssp:
+ case lltok::kw_sspreq:
+ case lltok::kw_sspstrong:
+ case lltok::kw_uwtable:
HaveError |= Error(Lex.getLoc(), "invalid use of function-only attribute");
break;
+
+ case lltok::kw_readnone:
+ case lltok::kw_readonly:
+ HaveError |= Error(Lex.getLoc(), "invalid use of attribute on return type");
}
Lex.Lex();
/// ::= 'ptx_device'
/// ::= 'spir_func'
/// ::= 'spir_kernel'
+/// ::= 'x86_64_sysvcc'
+/// ::= 'x86_64_win64cc'
/// ::= 'cc' UINT
///
bool LLParser::ParseOptionalCallingConv(CallingConv::ID &CC) {
case lltok::kw_spir_kernel: CC = CallingConv::SPIR_KERNEL; break;
case lltok::kw_spir_func: CC = CallingConv::SPIR_FUNC; break;
case lltok::kw_intel_ocl_bicc: CC = CallingConv::Intel_OCL_BI; break;
+ case lltok::kw_x86_64_sysvcc: CC = CallingConv::X86_64_SysV; break;
+ case lltok::kw_x86_64_win64cc: CC = CallingConv::X86_64_Win64; break;
case lltok::kw_cc: {
unsigned ArbitraryCC;
Lex.Lex();
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() &&
// Otherwise, handle normal operands.
if (ParseOptionalParamAttrs(ArgAttrs) || ParseValue(ArgTy, V, PFS))
return true;
- ArgList.push_back(ParamInfo(ArgLoc, V, Attribute::get(V->getContext(),
- ArgAttrs)));
+ ArgList.push_back(ParamInfo(ArgLoc, V, AttributeSet::get(V->getContext(),
+ AttrIndex++,
+ ArgAttrs)));
}
Lex.Lex(); // Lex the ')'.
if (!FunctionType::isValidArgumentType(ArgTy))
return Error(TypeLoc, "invalid type for function argument");
+ unsigned AttrIndex = 1;
ArgList.push_back(ArgInfo(TypeLoc, ArgTy,
- Attribute::get(ArgTy->getContext(),
- Attrs), Name));
+ AttributeSet::get(ArgTy->getContext(),
+ AttrIndex++, Attrs), Name));
while (EatIfPresent(lltok::comma)) {
// Handle ... at end of arg list.
return Error(TypeLoc, "invalid type for function argument");
ArgList.push_back(ArgInfo(TypeLoc, ArgTy,
- Attribute::get(ArgTy->getContext(), Attrs),
+ AttributeSet::get(ArgTy->getContext(),
+ AttrIndex++, Attrs),
Name));
}
}
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");
}
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) ||
SmallVector<ArgInfo, 8> ArgList;
bool isVarArg;
AttrBuilder FuncAttrs;
+ std::vector<unsigned> FwdRefAttrGrps;
+ LocTy BuiltinLoc;
std::string Section;
unsigned Alignment;
std::string GC;
if (ParseArgumentList(ArgList, isVarArg) ||
ParseOptionalToken(lltok::kw_unnamed_addr, UnnamedAddr,
&UnnamedAddrLoc) ||
- ParseOptionalFuncAttrs(FuncAttrs) ||
+ ParseFnAttributeValuePairs(FuncAttrs, FwdRefAttrGrps, false,
+ BuiltinLoc) ||
(EatIfPresent(lltok::kw_section) &&
ParseStringConstant(Section)) ||
ParseOptionalAlignment(Alignment) ||
ParseStringConstant(GC)))
return true;
+ if (FuncAttrs.contains(Attribute::Builtin))
+ return Error(BuiltinLoc, "'builtin' attribute not valid on function");
+
// If the alignment was parsed as an attribute, move to the alignment field.
if (FuncAttrs.hasAlignmentAttr()) {
Alignment = FuncAttrs.getAlignment();
// 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,
- Attribute::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,
- Attribute::get(RetType->getContext(),
- FuncAttrs)));
+ Attrs.push_back(AttributeSet::get(RetType->getContext(),
+ AttributeSet::FunctionIndex,
+ FuncAttrs));
AttributeSet PAL = AttributeSet::get(Context, Attrs);
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();
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;
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") ||
if (ConvertValIDToValue(PFTy, CalleeID, Callee, &PFS)) return true;
// Set up the Attribute for the function.
- SmallVector<AttributeWithIndex, 8> Attrs;
+ SmallVector<AttributeSet, 8> Attrs;
if (RetAttrs.hasAttributes())
- Attrs.push_back(
- AttributeWithIndex::get(AttributeSet::ReturnIndex,
- Attribute::get(Callee->getContext(),
- RetAttrs)));
+ Attrs.push_back(AttributeSet::get(RetType->getContext(),
+ AttributeSet::ReturnIndex,
+ RetAttrs));
SmallVector<Value*, 8> Args;
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,
- Attribute::get(Callee->getContext(),
- FnAttrs)));
+ Attrs.push_back(AttributeSet::get(RetType->getContext(),
+ AttributeSet::FunctionIndex,
+ FnAttrs));
// 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;
}
bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS,
bool isTail) {
AttrBuilder RetAttrs, FnAttrs;
+ std::vector<unsigned> FwdRefAttrGrps;
+ LocTy BuiltinLoc;
CallingConv::ID CC;
Type *RetType = 0;
LocTy RetTypeLoc;
ParseType(RetType, RetTypeLoc, true /*void allowed*/) ||
ParseValID(CalleeID) ||
ParseParameterList(ArgList, PFS) ||
- ParseOptionalFuncAttrs(FnAttrs))
+ ParseFnAttributeValuePairs(FnAttrs, FwdRefAttrGrps, false,
+ BuiltinLoc))
return true;
// If RetType is a non-function pointer type, then this is the short syntax
if (ConvertValIDToValue(PFTy, CalleeID, Callee, &PFS)) return true;
// Set up the Attribute for the function.
- SmallVector<AttributeWithIndex, 8> Attrs;
+ SmallVector<AttributeSet, 8> Attrs;
if (RetAttrs.hasAttributes())
- Attrs.push_back(
- AttributeWithIndex::get(AttributeSet::ReturnIndex,
- Attribute::get(Callee->getContext(),
- RetAttrs)));
+ Attrs.push_back(AttributeSet::get(RetType->getContext(),
+ AttributeSet::ReturnIndex,
+ RetAttrs));
SmallVector<Value*, 8> Args;
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,
- Attribute::get(Callee->getContext(),
- FnAttrs)));
+ Attrs.push_back(AttributeSet::get(RetType->getContext(),
+ AttributeSet::FunctionIndex,
+ FnAttrs));
// Finish off the Attribute and check them
AttributeSet PAL = AttributeSet::get(Context, Attrs);
CI->setTailCall(isTail);
CI->setCallingConv(CC);
CI->setAttributes(PAL);
+ ForwardRefAttrGroups[CI] = FwdRefAttrGrps;
Inst = CI;
return false;
}
if (ParseTypeAndValue(Ptr, Loc, PFS)) return true;
- if (!Ptr->getType()->getScalarType()->isPointerTy())
+ Type *BaseType = Ptr->getType();
+ PointerType *BasePointerType = dyn_cast<PointerType>(BaseType->getScalarType());
+ if (!BasePointerType)
return Error(Loc, "base of getelementptr must be a pointer");
SmallVector<Value*, 16> Indices;
Indices.push_back(Val);
}
- if (!GetElementPtrInst::getIndexedType(Ptr->getType(), Indices))
+ if (!Indices.empty() && !BasePointerType->getElementType()->isSized())
+ return Error(Loc, "base element of getelementptr must be sized");
+
+ if (!GetElementPtrInst::getIndexedType(BaseType, Indices))
return Error(Loc, "invalid getelementptr indices");
Inst = GetElementPtrInst::Create(Ptr, Indices);
if (InBounds)