#include "LLParser.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/AsmParser/SlotMapping.h"
#include "llvm/IR/AutoUpgrade.h"
#include "llvm/IR/CallingConv.h"
ValidateEndOfModule();
}
+bool LLParser::parseStandaloneConstantValue(Constant *&C) {
+ Lex.Lex();
+
+ Type *Ty = nullptr;
+ if (ParseType(Ty) || parseConstantValue(Ty, C))
+ return true;
+ if (Lex.getKind() != lltok::Eof)
+ return Error(Lex.getLoc(), "expected end of string");
+ return false;
+}
+
/// ValidateEndOfModule - Do final validity and sanity checks at the end of the
/// module.
bool LLParser::ValidateEndOfModule() {
ParseToken(lltok::rbrace, "expected end of struct constant"))
return true;
- ID.ConstantStructElts = new Constant*[Elts.size()];
+ ID.ConstantStructElts = make_unique<Constant *[]>(Elts.size());
ID.UIntVal = Elts.size();
- memcpy(ID.ConstantStructElts, Elts.data(), Elts.size()*sizeof(Elts[0]));
+ memcpy(ID.ConstantStructElts.get(), Elts.data(),
+ Elts.size() * sizeof(Elts[0]));
ID.Kind = ValID::t_ConstantStruct;
return false;
}
return true;
if (isPackedStruct) {
- ID.ConstantStructElts = new Constant*[Elts.size()];
- memcpy(ID.ConstantStructElts, Elts.data(), Elts.size()*sizeof(Elts[0]));
+ ID.ConstantStructElts = make_unique<Constant *[]>(Elts.size());
+ memcpy(ID.ConstantStructElts.get(), Elts.data(),
+ Elts.size() * sizeof(Elts[0]));
ID.UIntVal = Elts.size();
ID.Kind = ValID::t_PackedConstantStruct;
return false;
}
/// ParseDILocalVariable:
-/// ::= !DILocalVariable(tag: DW_TAG_arg_variable, scope: !0, name: "foo",
+/// ::= !DILocalVariable(arg: 7, scope: !0, name: "foo",
+/// file: !1, line: 7, type: !2, arg: 2, flags: 7)
+/// ::= !DILocalVariable(scope: !0, name: "foo",
/// file: !1, line: 7, type: !2, arg: 2, flags: 7)
bool LLParser::ParseDILocalVariable(MDNode *&Result, bool IsDistinct) {
#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \
- REQUIRED(tag, DwarfTagField, ); \
REQUIRED(scope, MDField, (/* AllowNull */ false)); \
OPTIONAL(name, MDStringField, ); \
+ OPTIONAL(arg, MDUnsignedField, (0, UINT16_MAX)); \
OPTIONAL(file, MDField, ); \
OPTIONAL(line, LineField, ); \
OPTIONAL(type, MDField, ); \
- OPTIONAL(arg, MDUnsignedField, (0, UINT16_MAX)); \
OPTIONAL(flags, DIFlagField, );
PARSE_MD_FIELDS();
#undef VISIT_MD_FIELDS
Result = GET_OR_DISTINCT(DILocalVariable,
- (Context, tag.Val, scope.Val, name.Val, file.Val,
- line.Val, type.Val, arg.Val, flags.Val));
+ (Context, scope.Val, name.Val, file.Val, line.Val,
+ type.Val, arg.Val, flags.Val));
return false;
}
V = PFS->GetVal(ID.StrVal, Ty, ID.Loc);
return V == nullptr;
case ValID::t_InlineAsm: {
- PointerType *PTy = dyn_cast<PointerType>(Ty);
- FunctionType *FTy =
- PTy ? dyn_cast<FunctionType>(PTy->getElementType()) : nullptr;
- if (!FTy || !InlineAsm::Verify(FTy, ID.StrVal2))
+ assert(ID.FTy);
+ if (!InlineAsm::Verify(ID.FTy, ID.StrVal2))
return Error(ID.Loc, "invalid type for inline asm constraint string");
- V = InlineAsm::get(FTy, ID.StrVal, ID.StrVal2, ID.UIntVal&1,
- (ID.UIntVal>>1)&1, (InlineAsm::AsmDialect(ID.UIntVal>>2)));
+ V = InlineAsm::get(ID.FTy, ID.StrVal, ID.StrVal2, ID.UIntVal & 1,
+ (ID.UIntVal >> 1) & 1,
+ (InlineAsm::AsmDialect(ID.UIntVal >> 2)));
return false;
}
case ValID::t_GlobalName:
return Error(ID.Loc, "element " + Twine(i) +
" of struct initializer doesn't match struct element type");
- V = ConstantStruct::get(ST, makeArrayRef(ID.ConstantStructElts,
- ID.UIntVal));
+ V = ConstantStruct::get(
+ ST, makeArrayRef(ID.ConstantStructElts.get(), ID.UIntVal));
} else
return Error(ID.Loc, "constant expression type mismatch");
return false;
llvm_unreachable("Invalid ValID");
}
+bool LLParser::parseConstantValue(Type *Ty, Constant *&C) {
+ C = nullptr;
+ ValID ID;
+ auto Loc = Lex.getLoc();
+ if (ParseValID(ID, /*PFS=*/nullptr))
+ return true;
+ switch (ID.Kind) {
+ case ValID::t_APSInt:
+ case ValID::t_APFloat:
+ case ValID::t_Constant:
+ case ValID::t_ConstantStruct:
+ case ValID::t_PackedConstantStruct: {
+ Value *V;
+ if (ConvertValIDToValue(Ty, ID, V, /*PFS=*/nullptr))
+ return true;
+ assert(isa<Constant>(V) && "Expected a constant value");
+ C = cast<Constant>(V);
+ return false;
+ }
+ default:
+ return Error(Loc, "expected a constant value");
+ }
+}
+
bool LLParser::ParseValue(Type *Ty, Value *&V, PerFunctionState *PFS) {
V = nullptr;
ValID ID;
case lltok::kw_indirectbr: return ParseIndirectBr(Inst, PFS);
case lltok::kw_invoke: return ParseInvoke(Inst, 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);
// Binary Operators.
case lltok::kw_add:
case lltok::kw_sub:
Ty = FunctionType::get(RetType, ParamTypes, false);
}
+ CalleeID.FTy = Ty;
+
// Look up the callee.
Value *Callee;
if (ConvertValIDToValue(PointerType::getUnqual(Ty), CalleeID, Callee, &PFS))
return false;
}
+bool LLParser::ParseExceptionArgs(SmallVectorImpl<Value *> &Args,
+ PerFunctionState &PFS) {
+ if (ParseToken(lltok::lsquare, "expected '[' in cleanuppad"))
+ return true;
+
+ while (Lex.getKind() != lltok::rsquare) {
+ // If this isn't the first argument, we need a comma.
+ if (!Args.empty() &&
+ ParseToken(lltok::comma, "expected ',' in argument list"))
+ return true;
+
+ // Parse the argument.
+ LocTy ArgLoc;
+ Type *ArgTy = nullptr;
+ if (ParseType(ArgTy, ArgLoc))
+ return true;
+
+ Value *V;
+ if (ArgTy->isMetadataTy()) {
+ if (ParseMetadataAsValue(V, PFS))
+ return true;
+ } else {
+ if (ParseValue(ArgTy, V, PFS))
+ return true;
+ }
+ Args.push_back(V);
+ }
+
+ Lex.Lex(); // Lex the ']'.
+ return false;
+}
+
+/// ParseCleanupRet
+/// ::= 'cleanupret' ('void' | TypeAndValue) unwind ('to' 'caller' | TypeAndValue)
+bool LLParser::ParseCleanupRet(Instruction *&Inst, PerFunctionState &PFS) {
+ Type *RetTy = nullptr;
+ Value *RetVal = nullptr;
+ if (ParseType(RetTy, /*AllowVoid=*/true))
+ return true;
+
+ if (!RetTy->isVoidTy())
+ if (ParseValue(RetTy, RetVal, PFS))
+ return true;
+
+ if (ParseToken(lltok::kw_unwind, "expected 'unwind' in cleanupret"))
+ return true;
+
+ BasicBlock *UnwindBB = nullptr;
+ if (Lex.getKind() == lltok::kw_to) {
+ Lex.Lex();
+ if (ParseToken(lltok::kw_caller, "expected 'caller' in cleanupret"))
+ return true;
+ } else {
+ if (ParseTypeAndBasicBlock(UnwindBB, PFS)) {
+ return true;
+ }
+ }
+
+ Inst = CleanupReturnInst::Create(Context, RetVal, UnwindBB);
+ return false;
+}
+
+/// ParseCatchRet
+/// ::= 'catchret' TypeAndValue
+bool LLParser::ParseCatchRet(Instruction *&Inst, PerFunctionState &PFS) {
+ BasicBlock *BB;
+ if (ParseTypeAndBasicBlock(BB, PFS))
+ return true;
+
+ Inst = CatchReturnInst::Create(BB);
+ return false;
+}
+
+/// ParseCatchPad
+/// ::= 'catchpad' Type ParamList 'to' TypeAndValue 'unwind' TypeAndValue
+bool LLParser::ParseCatchPad(Instruction *&Inst, PerFunctionState &PFS) {
+ Type *RetType = nullptr;
+
+ SmallVector<Value *, 8> Args;
+ if (ParseType(RetType, /*AllowVoid=*/true) || ParseExceptionArgs(Args, PFS))
+ 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))
+ return true;
+
+ Inst = CatchPadInst::Create(RetType, NormalBB, UnwindBB, Args);
+ return false;
+}
+
+/// ParseTerminatePad
+/// ::= 'terminatepad' ParamList 'to' TypeAndValue
+bool LLParser::ParseTerminatePad(Instruction *&Inst, PerFunctionState &PFS) {
+ SmallVector<Value *, 8> Args;
+ if (ParseExceptionArgs(Args, PFS))
+ return true;
+
+ if (ParseToken(lltok::kw_unwind, "expected 'unwind' in terminatepad"))
+ return true;
+
+ BasicBlock *UnwindBB = nullptr;
+ if (Lex.getKind() == lltok::kw_to) {
+ Lex.Lex();
+ if (ParseToken(lltok::kw_caller, "expected 'caller' in terminatepad"))
+ return true;
+ } else {
+ if (ParseTypeAndBasicBlock(UnwindBB, PFS)) {
+ return true;
+ }
+ }
+
+ Inst = TerminatePadInst::Create(Context, UnwindBB, Args);
+ return false;
+}
+
+/// ParseCleanupPad
+/// ::= 'cleanuppad' ParamList
+bool LLParser::ParseCleanupPad(Instruction *&Inst, PerFunctionState &PFS) {
+ Type *RetType = nullptr;
+
+ SmallVector<Value *, 8> Args;
+ if (ParseType(RetType, /*AllowVoid=*/true) || ParseExceptionArgs(Args, PFS))
+ return true;
+
+ Inst = CleanupPadInst::Create(RetType, Args);
+ return false;
+}
+
+/// ParseCatchEndPad
+/// ::= 'catchendpad' unwind ('to' 'caller' | TypeAndValue)
+bool LLParser::ParseCatchEndPad(Instruction *&Inst, PerFunctionState &PFS) {
+ if (ParseToken(lltok::kw_unwind, "expected 'unwind' in catchendpad"))
+ 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;
+ }
+ }
+
+ Inst = CatchEndPadInst::Create(Context, UnwindBB);
+ return false;
+}
+
//===----------------------------------------------------------------------===//
// Binary Operators.
//===----------------------------------------------------------------------===//
Ty = FunctionType::get(RetType, ParamTypes, false);
}
+ CalleeID.FTy = Ty;
+
// Look up the callee.
Value *Callee;
if (ConvertValIDToValue(PointerType::getUnqual(Ty), CalleeID, Callee, &PFS))