ExplicitTypeLoc,
"explicit pointee type doesn't match operand's pointee type");
+ GlobalValue *GVal = nullptr;
+
+ // See if the alias was forward referenced, if so, prepare to replace the
+ // forward reference.
+ if (!Name.empty()) {
+ GVal = M->getNamedValue(Name);
+ if (GVal) {
+ if (!ForwardRefVals.erase(Name))
+ return Error(NameLoc, "redefinition of global '@" + Name + "'");
+ }
+ } else {
+ auto I = ForwardRefValIDs.find(NumberedVals.size());
+ if (I != ForwardRefValIDs.end()) {
+ GVal = I->second.first;
+ ForwardRefValIDs.erase(I);
+ }
+ }
+
// Okay, create the alias but do not insert it into the module yet.
std::unique_ptr<GlobalAlias> GA(
GlobalAlias::create(Ty, AddrSpace, (GlobalValue::LinkageTypes)Linkage,
if (Name.empty())
NumberedVals.push_back(GA.get());
- // See if this value already exists in the symbol table. If so, it is either
- // a redefinition or a definition of a forward reference.
- if (GlobalValue *Val = M->getNamedValue(Name)) {
- // See if this was a redefinition. If so, there is no entry in
- // ForwardRefVals.
- auto I = ForwardRefVals.find(Name);
- if (I == ForwardRefVals.end())
- return Error(NameLoc, "redefinition of global named '@" + Name + "'");
-
- // Otherwise, this was a definition of forward ref. Verify that types
- // agree.
- if (Val->getType() != GA->getType())
- return Error(NameLoc,
- "forward reference and definition of alias have different types");
+ if (GVal) {
+ // Verify that types agree.
+ if (GVal->getType() != GA->getType())
+ return Error(
+ ExplicitTypeLoc,
+ "forward reference and definition of alias have different types");
// If they agree, just RAUW the old value with the alias and remove the
// forward ref info.
- Val->replaceAllUsesWith(GA.get());
- Val->eraseFromParent();
- ForwardRefVals.erase(I);
+ GVal->replaceAllUsesWith(GA.get());
+ GVal->eraseFromParent();
}
// Insert into the module, we know its name won't collide now.
if (!Name.empty()) {
GVal = M->getNamedValue(Name);
if (GVal) {
- if (!ForwardRefVals.erase(Name) || !isa<GlobalValue>(GVal))
+ if (!ForwardRefVals.erase(Name))
return Error(NameLoc, "redefinition of global '@" + Name + "'");
}
} else {
case lltok::kw_builtin: B.addAttribute(Attribute::Builtin); break;
case lltok::kw_cold: B.addAttribute(Attribute::Cold); break;
case lltok::kw_convergent: B.addAttribute(Attribute::Convergent); break;
+ case lltok::kw_inaccessiblememonly:
+ B.addAttribute(Attribute::InaccessibleMemOnly); break;
+ case lltok::kw_inaccessiblemem_or_argmemonly:
+ B.addAttribute(Attribute::InaccessibleMemOrArgMemOnly); break;
case lltok::kw_inlinehint: B.addAttribute(Attribute::InlineHint); break;
case lltok::kw_jumptable: B.addAttribute(Attribute::JumpTable); break;
case lltok::kw_minsize: B.addAttribute(Attribute::MinSize); break;
/// ::= 'preserve_mostcc'
/// ::= 'preserve_allcc'
/// ::= 'ghccc'
+/// ::= 'x86_intrcc'
/// ::= 'hhvmcc'
/// ::= 'hhvm_ccc'
+/// ::= 'cxx_fast_tlscc'
/// ::= 'cc' UINT
///
bool LLParser::ParseOptionalCallingConv(unsigned &CC) {
case lltok::kw_preserve_mostcc:CC = CallingConv::PreserveMost; break;
case lltok::kw_preserve_allcc: CC = CallingConv::PreserveAll; break;
case lltok::kw_ghccc: CC = CallingConv::GHC; break;
+ case lltok::kw_x86_intrcc: CC = CallingConv::X86_INTR; break;
case lltok::kw_hhvmcc: CC = CallingConv::HHVM; break;
case lltok::kw_hhvm_ccc: CC = CallingConv::HHVM_C; break;
+ case lltok::kw_cxx_fast_tlscc: CC = CallingConv::CXX_FAST_TLS; break;
case lltok::kw_cc: {
Lex.Lex();
return ParseUInt32(CC);
if (ParseStringConstant(Tag))
return true;
- BundleList.emplace_back();
- auto &OBI = BundleList.back();
-
- OBI.Tag = std::move(Tag);
-
if (ParseToken(lltok::lparen, "expected '(' in operand bundle"))
return true;
+ std::vector<Value *> Inputs;
while (Lex.getKind() != lltok::rparen) {
// If this isn't the first input, we need a comma.
- if (!OBI.Inputs.empty() &&
+ if (!Inputs.empty() &&
ParseToken(lltok::comma, "expected ',' in input list"))
return true;
Value *Input = nullptr;
if (ParseType(Ty) || ParseValue(Ty, Input, PFS))
return true;
- OBI.Inputs.push_back(Input);
+ Inputs.push_back(Input);
}
+ BundleList.emplace_back(std::move(Tag), std::move(Inputs));
+
Lex.Lex(); // Lex the ')'.
}
/// forward reference record if needed. This can return null if the value
/// exists but does not have the right type.
Value *LLParser::PerFunctionState::GetVal(const std::string &Name, Type *Ty,
- LocTy Loc, OperatorConstraint OC) {
+ LocTy Loc) {
// Look this name up in the normal function symbol table.
Value *Val = F.getValueSymbolTable().lookup(Name);
// If we have the value in the symbol table or fwd-ref table, return it.
if (Val) {
- // Check operator constraints.
- switch (OC) {
- case OC_None:
- // no constraint
- break;
- case OC_CatchPad:
- if (!isa<CatchPadInst>(Val)) {
- P.Error(Loc, "'%" + Name + "' is not a catchpad");
- return nullptr;
- }
- break;
- case OC_CleanupPad:
- if (!isa<CleanupPadInst>(Val)) {
- P.Error(Loc, "'%" + Name + "' is not a cleanuppad");
- return nullptr;
- }
- break;
- }
if (Val->getType() == Ty) return Val;
if (Ty->isLabelTy())
P.Error(Loc, "'%" + Name + "' is not a basic block");
// Otherwise, create a new forward reference for this value and remember it.
Value *FwdVal;
if (Ty->isLabelTy()) {
- assert(!OC);
FwdVal = BasicBlock::Create(F.getContext(), Name, &F);
- } else if (!OC) {
- FwdVal = new Argument(Ty, Name);
} else {
- switch (OC) {
- case OC_CatchPad:
- FwdVal = CatchPadInst::Create(&F.getEntryBlock(), &F.getEntryBlock(), {},
- Name);
- break;
- case OC_CleanupPad:
- FwdVal = CleanupPadInst::Create(F.getContext(), {}, Name);
- break;
- default:
- llvm_unreachable("unexpected constraint");
- }
+ FwdVal = new Argument(Ty, Name);
}
ForwardRefVals[Name] = std::make_pair(FwdVal, Loc);
return FwdVal;
}
-Value *LLParser::PerFunctionState::GetVal(unsigned ID, Type *Ty, LocTy Loc,
- OperatorConstraint OC) {
+Value *LLParser::PerFunctionState::GetVal(unsigned ID, Type *Ty, LocTy Loc) {
// Look this name up in the normal function symbol table.
Value *Val = ID < NumberedVals.size() ? NumberedVals[ID] : nullptr;
// If we have the value in the symbol table or fwd-ref table, return it.
if (Val) {
- // Check operator constraint.
- switch (OC) {
- case OC_None:
- // no constraint
- break;
- case OC_CatchPad:
- if (!isa<CatchPadInst>(Val)) {
- P.Error(Loc, "'%" + Twine(ID) + "' is not a catchpad");
- return nullptr;
- }
- break;
- case OC_CleanupPad:
- if (!isa<CleanupPadInst>(Val)) {
- P.Error(Loc, "'%" + Twine(ID) + "' is not a cleanuppad");
- return nullptr;
- }
- break;
- }
if (Val->getType() == Ty) return Val;
if (Ty->isLabelTy())
P.Error(Loc, "'%" + Twine(ID) + "' is not a basic block");
// Otherwise, create a new forward reference for this value and remember it.
Value *FwdVal;
if (Ty->isLabelTy()) {
- assert(!OC);
FwdVal = BasicBlock::Create(F.getContext(), "", &F);
- } else if (!OC) {
- FwdVal = new Argument(Ty);
} else {
- switch (OC) {
- case OC_CatchPad:
- FwdVal = CatchPadInst::Create(&F.getEntryBlock(), &F.getEntryBlock(), {});
- break;
- case OC_CleanupPad:
- FwdVal = CleanupPadInst::Create(F.getContext(), {});
- break;
- default:
- llvm_unreachable("unexpected constraint");
- }
+ FwdVal = new Argument(Ty);
}
ForwardRefValIDs[ID] = std::make_pair(FwdVal, Loc);
if (Sentinel->getType() != Inst->getType())
return P.Error(NameLoc, "instruction forward referenced with type '" +
getTypeString(FI->second.first->getType()) + "'");
- // Check operator constraints. We only put cleanuppads or catchpads in
- // the forward value map if the value is constrained to match.
- if (isa<CatchPadInst>(Sentinel)) {
- if (!isa<CatchPadInst>(Inst))
- return P.Error(FI->second.second,
- "'%" + Twine(NameID) + "' is not a catchpad");
- } else if (isa<CleanupPadInst>(Sentinel)) {
- if (!isa<CleanupPadInst>(Inst))
- return P.Error(FI->second.second,
- "'%" + Twine(NameID) + "' is not a cleanuppad");
- }
Sentinel->replaceAllUsesWith(Inst);
delete Sentinel;
if (Sentinel->getType() != Inst->getType())
return P.Error(NameLoc, "instruction forward referenced with type '" +
getTypeString(FI->second.first->getType()) + "'");
- // Check operator constraints. We only put cleanuppads or catchpads in
- // the forward value map if the value is constrained to match.
- if (isa<CatchPadInst>(Sentinel)) {
- if (!isa<CatchPadInst>(Inst))
- return P.Error(FI->second.second,
- "'%" + NameStr + "' is not a catchpad");
- } else if (isa<CleanupPadInst>(Sentinel)) {
- if (!isa<CleanupPadInst>(Inst))
- return P.Error(FI->second.second,
- "'%" + NameStr + "' is not a cleanuppad");
- }
Sentinel->replaceAllUsesWith(Inst);
delete Sentinel;
case lltok::kw_null: ID.Kind = ValID::t_Null; break;
case lltok::kw_undef: ID.Kind = ValID::t_Undef; break;
case lltok::kw_zeroinitializer: ID.Kind = ValID::t_Zero; break;
+ case lltok::kw_none: ID.Kind = ValID::t_None; break;
case lltok::lbrace: {
// ValID ::= '{' ConstVector '}'
DwarfTagField(dwarf::Tag DefaultTag)
: MDUnsignedField(DefaultTag, dwarf::DW_TAG_hi_user) {}
};
+struct DwarfMacinfoTypeField : public MDUnsignedField {
+ DwarfMacinfoTypeField() : MDUnsignedField(0, dwarf::DW_MACINFO_vendor_ext) {}
+ DwarfMacinfoTypeField(dwarf::MacinfoRecordType DefaultType)
+ : MDUnsignedField(DefaultType, dwarf::DW_MACINFO_vendor_ext) {}
+};
struct DwarfAttEncodingField : public MDUnsignedField {
DwarfAttEncodingField() : MDUnsignedField(0, dwarf::DW_ATE_hi_user) {}
};
return false;
}
+template <>
+bool LLParser::ParseMDField(LocTy Loc, StringRef Name,
+ DwarfMacinfoTypeField &Result) {
+ if (Lex.getKind() == lltok::APSInt)
+ return ParseMDField(Loc, Name, static_cast<MDUnsignedField &>(Result));
+
+ if (Lex.getKind() != lltok::DwarfMacinfo)
+ return TokError("expected DWARF macinfo type");
+
+ unsigned Macinfo = dwarf::getMacinfo(Lex.getStrVal());
+ if (Macinfo == dwarf::DW_MACINFO_invalid)
+ return TokError(
+ "invalid DWARF macinfo type" + Twine(" '") + Lex.getStrVal() + "'");
+ assert(Macinfo <= Result.Max && "Expected valid DWARF macinfo type");
+
+ Result.assign(Macinfo);
+ Lex.Lex();
+ return false;
+}
+
template <>
bool LLParser::ParseMDField(LocTy Loc, StringRef Name,
DwarfVirtualityField &Result) {
/// isOptimized: true, flags: "-O2", runtimeVersion: 1,
/// splitDebugFilename: "abc.debug", emissionKind: 1,
/// enums: !1, retainedTypes: !2, subprograms: !3,
-/// globals: !4, imports: !5, dwoId: 0x0abcd)
+/// globals: !4, imports: !5, macros: !6, dwoId: 0x0abcd)
bool LLParser::ParseDICompileUnit(MDNode *&Result, bool IsDistinct) {
if (!IsDistinct)
return Lex.Error("missing 'distinct', required for !DICompileUnit");
OPTIONAL(subprograms, MDField, ); \
OPTIONAL(globals, MDField, ); \
OPTIONAL(imports, MDField, ); \
+ OPTIONAL(macros, MDField, ); \
OPTIONAL(dwoId, MDUnsignedField, );
PARSE_MD_FIELDS();
#undef VISIT_MD_FIELDS
Result = DICompileUnit::getDistinct(
Context, language.Val, file.Val, producer.Val, isOptimized.Val, flags.Val,
runtimeVersion.Val, splitDebugFilename.Val, emissionKind.Val, enums.Val,
- retainedTypes.Val, subprograms.Val, globals.Val, imports.Val, dwoId.Val);
+ retainedTypes.Val, subprograms.Val, globals.Val, imports.Val, macros.Val,
+ dwoId.Val);
return false;
}
return false;
}
+/// ParseDIMacro:
+/// ::= !DIMacro(macinfo: type, line: 9, name: "SomeMacro", value: "SomeValue")
+bool LLParser::ParseDIMacro(MDNode *&Result, bool IsDistinct) {
+#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \
+ REQUIRED(type, DwarfMacinfoTypeField, ); \
+ REQUIRED(line, LineField, ); \
+ REQUIRED(name, MDStringField, ); \
+ OPTIONAL(value, MDStringField, );
+ PARSE_MD_FIELDS();
+#undef VISIT_MD_FIELDS
+
+ Result = GET_OR_DISTINCT(DIMacro,
+ (Context, type.Val, line.Val, name.Val, value.Val));
+ return false;
+}
+
+/// ParseDIMacroFile:
+/// ::= !DIMacroFile(line: 9, file: !2, nodes: !3)
+bool LLParser::ParseDIMacroFile(MDNode *&Result, bool IsDistinct) {
+#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \
+ OPTIONAL(type, DwarfMacinfoTypeField, (dwarf::DW_MACINFO_start_file)); \
+ REQUIRED(line, LineField, ); \
+ REQUIRED(file, MDField, ); \
+ OPTIONAL(nodes, MDField, );
+ PARSE_MD_FIELDS();
+#undef VISIT_MD_FIELDS
+
+ Result = GET_OR_DISTINCT(DIMacroFile,
+ (Context, type.Val, line.Val, file.Val, nodes.Val));
+ return false;
+}
+
+
/// ParseDIModule:
/// ::= !DIModule(scope: !0, name: "SomeModule", configMacros: "-DNDEBUG",
/// includePath: "/usr/include", isysroot: "/")
//===----------------------------------------------------------------------===//
bool LLParser::ConvertValIDToValue(Type *Ty, ValID &ID, Value *&V,
- PerFunctionState *PFS,
- OperatorConstraint OC) {
+ PerFunctionState *PFS) {
if (Ty->isFunctionTy())
return Error(ID.Loc, "functions are not values, refer to them as pointers");
- if (OC && ID.Kind != ValID::t_LocalID && ID.Kind != ValID::t_LocalName) {
- switch (OC) {
- case OC_CatchPad:
- return Error(ID.Loc, "Catchpad value required in this position");
- case OC_CleanupPad:
- return Error(ID.Loc, "Cleanuppad value required in this position");
- default:
- llvm_unreachable("Unexpected constraint kind");
- }
- }
-
switch (ID.Kind) {
case ValID::t_LocalID:
if (!PFS) return Error(ID.Loc, "invalid use of function-local name");
- V = PFS->GetVal(ID.UIntVal, Ty, ID.Loc, OC);
+ V = PFS->GetVal(ID.UIntVal, Ty, ID.Loc);
return V == nullptr;
case ValID::t_LocalName:
if (!PFS) return Error(ID.Loc, "invalid use of function-local name");
- V = PFS->GetVal(ID.StrVal, Ty, ID.Loc, OC);
+ V = PFS->GetVal(ID.StrVal, Ty, ID.Loc);
return V == nullptr;
case ValID::t_InlineAsm: {
if (!ID.FTy || !InlineAsm::Verify(ID.FTy, ID.StrVal2))
return Error(ID.Loc, "invalid type for null constant");
V = Constant::getNullValue(Ty);
return false;
+ case ValID::t_None:
+ if (!Ty->isTokenTy())
+ return Error(ID.Loc, "invalid type for none constant");
+ V = Constant::getNullValue(Ty);
+ return false;
case ValID::t_Constant:
if (ID.ConstantVal->getType() != Ty)
return Error(ID.Loc, "constant expression type mismatch");
}
}
-bool LLParser::ParseValue(Type *Ty, Value *&V, PerFunctionState *PFS,
- OperatorConstraint OC) {
+bool LLParser::ParseValue(Type *Ty, Value *&V, PerFunctionState *PFS) {
V = nullptr;
ValID ID;
- return ParseValID(ID, PFS) || ConvertValIDToValue(Ty, ID, V, PFS, OC);
+ return ParseValID(ID, PFS) || ConvertValIDToValue(Ty, ID, V, PFS);
}
bool LLParser::ParseTypeAndValue(Value *&V, PerFunctionState *PFS) {
case lltok::kw_resume: return ParseResume(Inst, PFS);
case lltok::kw_cleanupret: return ParseCleanupRet(Inst, PFS);
case lltok::kw_catchret: return ParseCatchRet(Inst, PFS);
- case lltok::kw_catchpad: return ParseCatchPad(Inst, PFS);
- case lltok::kw_terminatepad: return ParseTerminatePad(Inst, PFS);
- case lltok::kw_cleanuppad: return ParseCleanupPad(Inst, PFS);
- case lltok::kw_catchendpad: return ParseCatchEndPad(Inst, PFS);
- case lltok::kw_cleanupendpad: return ParseCleanupEndPad(Inst, PFS);
+ case lltok::kw_catchswitch: return ParseCatchSwitch(Inst, PFS);
+ case lltok::kw_catchpad: return ParseCatchPad(Inst, PFS);
+ case lltok::kw_cleanuppad: return ParseCleanupPad(Inst, PFS);
// Binary Operators.
case lltok::kw_add:
case lltok::kw_sub:
case lltok::kw_call: return ParseCall(Inst, PFS, CallInst::TCK_None);
case lltok::kw_tail: return ParseCall(Inst, PFS, CallInst::TCK_Tail);
case lltok::kw_musttail: return ParseCall(Inst, PFS, CallInst::TCK_MustTail);
+ case lltok::kw_notail: return ParseCall(Inst, PFS, CallInst::TCK_NoTail);
// Memory.
case lltok::kw_alloca: return ParseAlloc(Inst, PFS);
case lltok::kw_load: return ParseLoad(Inst, PFS);
}
/// ParseCleanupRet
-/// ::= 'cleanupret' Value unwind ('to' 'caller' | TypeAndValue)
+/// ::= 'cleanupret' from Value unwind ('to' 'caller' | TypeAndValue)
bool LLParser::ParseCleanupRet(Instruction *&Inst, PerFunctionState &PFS) {
Value *CleanupPad = nullptr;
- if (ParseValue(Type::getTokenTy(Context), CleanupPad, PFS, OC_CleanupPad))
+ if (ParseToken(lltok::kw_from, "expected 'from' after cleanupret"))
+ return true;
+
+ if (ParseValue(Type::getTokenTy(Context), CleanupPad, PFS))
return true;
if (ParseToken(lltok::kw_unwind, "expected 'unwind' in cleanupret"))
}
}
- Inst = CleanupReturnInst::Create(cast<CleanupPadInst>(CleanupPad), UnwindBB);
+ Inst = CleanupReturnInst::Create(CleanupPad, UnwindBB);
return false;
}
/// ParseCatchRet
-/// ::= 'catchret' Value 'to' TypeAndValue
+/// ::= 'catchret' from Parent Value 'to' TypeAndValue
bool LLParser::ParseCatchRet(Instruction *&Inst, PerFunctionState &PFS) {
Value *CatchPad = nullptr;
- if (ParseValue(Type::getTokenTy(Context), CatchPad, PFS, OC_CatchPad))
+ if (ParseToken(lltok::kw_from, "expected 'from' after catchret"))
+ return true;
+
+ if (ParseValue(Type::getTokenTy(Context), CatchPad, PFS))
return true;
BasicBlock *BB;
ParseTypeAndBasicBlock(BB, PFS))
return true;
- Inst = CatchReturnInst::Create(cast<CatchPadInst>(CatchPad), BB);
+ Inst = CatchReturnInst::Create(CatchPad, BB);
return false;
}
-/// ParseCatchPad
-/// ::= 'catchpad' ParamList 'to' TypeAndValue 'unwind' TypeAndValue
-bool LLParser::ParseCatchPad(Instruction *&Inst, PerFunctionState &PFS) {
- SmallVector<Value *, 8> Args;
- if (ParseExceptionArgs(Args, PFS))
+/// ParseCatchSwitch
+/// ::= 'catchswitch' within Parent
+bool LLParser::ParseCatchSwitch(Instruction *&Inst, PerFunctionState &PFS) {
+ Value *ParentPad;
+ LocTy BBLoc;
+
+ if (ParseToken(lltok::kw_within, "expected 'within' after catchswitch"))
return true;
- BasicBlock *NormalBB, *UnwindBB;
- if (ParseToken(lltok::kw_to, "expected 'to' in catchpad") ||
- ParseTypeAndBasicBlock(NormalBB, PFS) ||
- ParseToken(lltok::kw_unwind, "expected 'unwind' in catchpad") ||
- ParseTypeAndBasicBlock(UnwindBB, PFS))
+ if (Lex.getKind() != lltok::kw_none && Lex.getKind() != lltok::LocalVar &&
+ Lex.getKind() != lltok::LocalVarID)
+ return TokError("expected scope value for catchswitch");
+
+ if (ParseValue(Type::getTokenTy(Context), ParentPad, PFS))
return true;
- Inst = CatchPadInst::Create(NormalBB, UnwindBB, Args);
- return false;
-}
+ if (ParseToken(lltok::lsquare, "expected '[' with catchswitch labels"))
+ return true;
-/// ParseTerminatePad
-/// ::= 'terminatepad' ParamList 'to' TypeAndValue
-bool LLParser::ParseTerminatePad(Instruction *&Inst, PerFunctionState &PFS) {
- SmallVector<Value *, 8> Args;
- if (ParseExceptionArgs(Args, PFS))
+ SmallVector<BasicBlock *, 32> Table;
+ do {
+ BasicBlock *DestBB;
+ if (ParseTypeAndBasicBlock(DestBB, PFS))
+ return true;
+ Table.push_back(DestBB);
+ } while (EatIfPresent(lltok::comma));
+
+ if (ParseToken(lltok::rsquare, "expected ']' after catchswitch labels"))
return true;
- if (ParseToken(lltok::kw_unwind, "expected 'unwind' in terminatepad"))
+ if (ParseToken(lltok::kw_unwind,
+ "expected 'unwind' after catchswitch scope"))
return true;
BasicBlock *UnwindBB = nullptr;
- if (Lex.getKind() == lltok::kw_to) {
- Lex.Lex();
- if (ParseToken(lltok::kw_caller, "expected 'caller' in terminatepad"))
+ if (EatIfPresent(lltok::kw_to)) {
+ if (ParseToken(lltok::kw_caller, "expected 'caller' in catchswitch"))
return true;
} else {
- if (ParseTypeAndBasicBlock(UnwindBB, PFS)) {
+ if (ParseTypeAndBasicBlock(UnwindBB, PFS))
return true;
- }
}
- Inst = TerminatePadInst::Create(Context, UnwindBB, Args);
+ auto *CatchSwitch =
+ CatchSwitchInst::Create(ParentPad, UnwindBB, Table.size());
+ for (BasicBlock *DestBB : Table)
+ CatchSwitch->addHandler(DestBB);
+ Inst = CatchSwitch;
return false;
}
-/// ParseCleanupPad
-/// ::= 'cleanuppad' ParamList
-bool LLParser::ParseCleanupPad(Instruction *&Inst, PerFunctionState &PFS) {
- SmallVector<Value *, 8> Args;
- if (ParseExceptionArgs(Args, PFS))
+/// ParseCatchPad
+/// ::= 'catchpad' ParamList 'to' TypeAndValue 'unwind' TypeAndValue
+bool LLParser::ParseCatchPad(Instruction *&Inst, PerFunctionState &PFS) {
+ Value *CatchSwitch = nullptr;
+
+ if (ParseToken(lltok::kw_within, "expected 'within' after catchpad"))
return true;
- Inst = CleanupPadInst::Create(Context, Args);
- return false;
-}
+ if (Lex.getKind() != lltok::LocalVar && Lex.getKind() != lltok::LocalVarID)
+ return TokError("expected scope value for catchpad");
-/// ParseCatchEndPad
-/// ::= 'catchendpad' unwind ('to' 'caller' | TypeAndValue)
-bool LLParser::ParseCatchEndPad(Instruction *&Inst, PerFunctionState &PFS) {
- if (ParseToken(lltok::kw_unwind, "expected 'unwind' in catchendpad"))
+ if (ParseValue(Type::getTokenTy(Context), CatchSwitch, PFS))
return true;
- BasicBlock *UnwindBB = nullptr;
- if (Lex.getKind() == lltok::kw_to) {
- Lex.Lex();
- if (Lex.getKind() == lltok::kw_caller) {
- Lex.Lex();
- } else {
- return true;
- }
- } else {
- if (ParseTypeAndBasicBlock(UnwindBB, PFS)) {
- return true;
- }
- }
+ SmallVector<Value *, 8> Args;
+ if (ParseExceptionArgs(Args, PFS))
+ return true;
- Inst = CatchEndPadInst::Create(Context, UnwindBB);
+ Inst = CatchPadInst::Create(CatchSwitch, Args);
return false;
}
-/// ParseCatchEndPad
-/// ::= 'cleanupendpad' Value unwind ('to' 'caller' | TypeAndValue)
-bool LLParser::ParseCleanupEndPad(Instruction *&Inst, PerFunctionState &PFS) {
- Value *CleanupPad = nullptr;
+/// ParseCleanupPad
+/// ::= 'cleanuppad' within Parent ParamList
+bool LLParser::ParseCleanupPad(Instruction *&Inst, PerFunctionState &PFS) {
+ Value *ParentPad = nullptr;
- if (ParseValue(Type::getTokenTy(Context), CleanupPad, PFS, OC_CleanupPad))
+ if (ParseToken(lltok::kw_within, "expected 'within' after cleanuppad"))
return true;
- if (ParseToken(lltok::kw_unwind, "expected 'unwind' in catchendpad"))
+ if (Lex.getKind() != lltok::kw_none && Lex.getKind() != lltok::LocalVar &&
+ Lex.getKind() != lltok::LocalVarID)
+ return TokError("expected scope value for cleanuppad");
+
+ if (ParseValue(Type::getTokenTy(Context), ParentPad, PFS))
return true;
- BasicBlock *UnwindBB = nullptr;
- if (Lex.getKind() == lltok::kw_to) {
- Lex.Lex();
- if (Lex.getKind() == lltok::kw_caller) {
- Lex.Lex();
- } else {
- return true;
- }
- } else {
- if (ParseTypeAndBasicBlock(UnwindBB, PFS)) {
- return true;
- }
- }
+ SmallVector<Value *, 8> Args;
+ if (ParseExceptionArgs(Args, PFS))
+ return true;
- Inst = CleanupEndPadInst::Create(cast<CleanupPadInst>(CleanupPad), UnwindBB);
+ Inst = CleanupPadInst::Create(ParentPad, Args);
return false;
}
}
/// ParseCall
-/// ::= 'call' OptionalCallingConv OptionalAttrs Type Value
-/// ParameterList OptionalAttrs
-/// ::= 'tail' 'call' OptionalCallingConv OptionalAttrs Type Value
-/// ParameterList OptionalAttrs
-/// ::= 'musttail' 'call' OptionalCallingConv OptionalAttrs Type Value
-/// ParameterList OptionalAttrs
+/// ::= 'call' OptionalFastMathFlags OptionalCallingConv
+/// OptionalAttrs Type Value ParameterList OptionalAttrs
+/// ::= 'tail' 'call' OptionalFastMathFlags OptionalCallingConv
+/// OptionalAttrs Type Value ParameterList OptionalAttrs
+/// ::= 'musttail' 'call' OptionalFastMathFlags OptionalCallingConv
+/// OptionalAttrs Type Value ParameterList OptionalAttrs
+/// ::= 'notail' 'call' OptionalFastMathFlags OptionalCallingConv
+/// OptionalAttrs Type Value ParameterList OptionalAttrs
bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS,
CallInst::TailCallKind TCK) {
AttrBuilder RetAttrs, FnAttrs;
SmallVector<OperandBundleDef, 2> BundleList;
LocTy CallLoc = Lex.getLoc();
- if ((TCK != CallInst::TCK_None &&
- ParseToken(lltok::kw_call, "expected 'tail call'")) ||
- ParseOptionalCallingConv(CC) || ParseOptionalReturnAttrs(RetAttrs) ||
+ if (TCK != CallInst::TCK_None &&
+ ParseToken(lltok::kw_call,
+ "expected 'tail call', 'musttail call', or 'notail call'"))
+ return true;
+
+ FastMathFlags FMF = EatFastMathFlagsIfPresent();
+
+ if (ParseOptionalCallingConv(CC) || ParseOptionalReturnAttrs(RetAttrs) ||
ParseType(RetType, RetTypeLoc, true /*void allowed*/) ||
ParseValID(CalleeID) ||
ParseParameterList(ArgList, PFS, TCK == CallInst::TCK_MustTail,
ParseOptionalOperandBundles(BundleList, PFS))
return true;
+ if (FMF.any() && !RetType->isFPOrFPVectorTy())
+ return Error(CallLoc, "fast-math-flags specified for call without "
+ "floating-point scalar or vector return type");
+
// If RetType is a non-function pointer type, then this is the short syntax
// for the call, which means that RetType is just the return type. Infer the
// rest of the function argument types from the arguments that are present.
CallInst *CI = CallInst::Create(Ty, Callee, Args, BundleList);
CI->setTailCallKind(TCK);
CI->setCallingConv(CC);
+ if (FMF.any())
+ CI->setFastMathFlags(FMF);
CI->setAttributes(PAL);
ForwardRefAttrGroups[CI] = FwdRefAttrGrps;
Inst = CI;