diff options
author | David Majnemer <david.majnemer@gmail.com> | 2015-07-10 07:00:44 +0000 |
---|---|---|
committer | David Majnemer <david.majnemer@gmail.com> | 2015-07-10 07:00:44 +0000 |
commit | ae2ffc8a8c825acf46f58f20dc7d0ae5fecbdd0b (patch) | |
tree | bba694cd7ab6a7a5eb4aca757ebfc3b38b1e949d /llvm/lib/AsmParser | |
parent | 83505347724a3eeb42f66a0b58fb8ff5c4c9ea4c (diff) | |
download | bcm5719-llvm-ae2ffc8a8c825acf46f58f20dc7d0ae5fecbdd0b.tar.gz bcm5719-llvm-ae2ffc8a8c825acf46f58f20dc7d0ae5fecbdd0b.zip |
New EH representation for MSVC compatibility
Summary:
This introduces new instructions neccessary to implement MSVC-compatible
exception handling support. Most of the middle-end and none of the
back-end haven't been audited or updated to take them into account.
Reviewers: rnk, JosephTremoulet, reames, nlewycky, rjmccall
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D11041
llvm-svn: 241888
Diffstat (limited to 'llvm/lib/AsmParser')
-rw-r--r-- | llvm/lib/AsmParser/LLLexer.cpp | 7 | ||||
-rw-r--r-- | llvm/lib/AsmParser/LLParser.cpp | 161 | ||||
-rw-r--r-- | llvm/lib/AsmParser/LLParser.h | 9 | ||||
-rw-r--r-- | llvm/lib/AsmParser/LLToken.h | 4 |
4 files changed, 180 insertions, 1 deletions
diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp index 88f359d4fd5..69c2048aae2 100644 --- a/llvm/lib/AsmParser/LLLexer.cpp +++ b/llvm/lib/AsmParser/LLLexer.cpp @@ -524,6 +524,7 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(undef); KEYWORD(null); KEYWORD(to); + KEYWORD(caller); KEYWORD(tail); KEYWORD(musttail); KEYWORD(target); @@ -748,6 +749,12 @@ lltok::Kind LLLexer::LexIdentifier() { INSTKEYWORD(extractvalue, ExtractValue); INSTKEYWORD(insertvalue, InsertValue); INSTKEYWORD(landingpad, LandingPad); + INSTKEYWORD(cleanupret, CleanupRet); + INSTKEYWORD(catchret, CatchRet); + INSTKEYWORD(catchblock, CatchBlock); + INSTKEYWORD(terminateblock, TerminateBlock); + INSTKEYWORD(cleanupblock, CleanupBlock); + INSTKEYWORD(catchendblock, CatchEndBlock); #undef INSTKEYWORD #define DWKEYWORD(TYPE, TOKEN) \ diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 91a88bc91fd..4e28410abdc 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -4489,6 +4489,12 @@ int LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB, 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_catchblock: return ParseCatchBlock(Inst, PFS); + case lltok::kw_terminateblock: return ParseTerminateBlock(Inst, PFS); + case lltok::kw_cleanupblock: return ParseCleanupBlock(Inst, PFS); + case lltok::kw_catchendblock: return ParseCatchEndBlock(Inst, PFS); // Binary Operators. case lltok::kw_add: case lltok::kw_sub: @@ -4882,6 +4888,161 @@ bool LLParser::ParseResume(Instruction *&Inst, PerFunctionState &PFS) { return false; } +bool LLParser::ParseExceptionArgs(SmallVectorImpl<Value *> &Args, + PerFunctionState &PFS) { + if (ParseToken(lltok::lsquare, "expected '[' in cleanupblock")) + 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; +} + +/// ParseCatchBlock +/// ::= 'catchblock' Type ParamList 'to' TypeAndValue 'unwind' TypeAndValue +bool LLParser::ParseCatchBlock(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 catchblock") || + ParseTypeAndBasicBlock(NormalBB, PFS) || + ParseToken(lltok::kw_unwind, "expected 'unwind' in catchblock") || + ParseTypeAndBasicBlock(UnwindBB, PFS)) + return true; + + Inst = CatchBlockInst::Create(RetType, NormalBB, UnwindBB, Args); + return false; +} + +/// ParseTerminateBlock +/// ::= 'terminateblock' ParamList 'to' TypeAndValue +bool LLParser::ParseTerminateBlock(Instruction *&Inst, PerFunctionState &PFS) { + SmallVector<Value *, 8> Args; + if (ParseExceptionArgs(Args, PFS)) + return true; + + if (ParseToken(lltok::kw_unwind, "expected 'unwind' in terminateblock")) + 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 = TerminateBlockInst::Create(Context, UnwindBB, Args); + return false; +} + +/// ParseCleanupBlock +/// ::= 'cleanupblock' ParamList +bool LLParser::ParseCleanupBlock(Instruction *&Inst, PerFunctionState &PFS) { + Type *RetType = nullptr; + + SmallVector<Value *, 8> Args; + if (ParseType(RetType, /*AllowVoid=*/true) || ParseExceptionArgs(Args, PFS)) + return true; + + Inst = CleanupBlockInst::Create(RetType, Args); + return false; +} + +/// ParseCatchEndBlock +/// ::= 'catchendblock' unwind ('to' 'caller' | TypeAndValue) +bool LLParser::ParseCatchEndBlock(Instruction *&Inst, PerFunctionState &PFS) { + if (ParseToken(lltok::kw_unwind, "expected 'unwind' in cleanupret")) + 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 = CatchEndBlockInst::Create(Context, UnwindBB); + return false; +} + //===----------------------------------------------------------------------===// // Binary Operators. //===----------------------------------------------------------------------===// diff --git a/llvm/lib/AsmParser/LLParser.h b/llvm/lib/AsmParser/LLParser.h index 6e57b3e0667..2a39b6d364d 100644 --- a/llvm/lib/AsmParser/LLParser.h +++ b/llvm/lib/AsmParser/LLParser.h @@ -381,6 +381,9 @@ namespace llvm { bool IsMustTailCall = false, bool InVarArgsFunc = false); + bool ParseExceptionArgs(SmallVectorImpl<Value *> &Args, + PerFunctionState &PFS); + // Constant Parsing. bool ParseValID(ValID &ID, PerFunctionState *PFS = nullptr); bool ParseGlobalValue(Type *Ty, Constant *&V); @@ -441,6 +444,12 @@ namespace llvm { bool ParseIndirectBr(Instruction *&Inst, PerFunctionState &PFS); bool ParseInvoke(Instruction *&Inst, PerFunctionState &PFS); bool ParseResume(Instruction *&Inst, PerFunctionState &PFS); + bool ParseCleanupRet(Instruction *&Inst, PerFunctionState &PFS); + bool ParseCatchRet(Instruction *&Inst, PerFunctionState &PFS); + bool ParseCatchBlock(Instruction *&Inst, PerFunctionState &PFS); + bool ParseTerminateBlock(Instruction *&Inst, PerFunctionState &PFS); + bool ParseCleanupBlock(Instruction *&Inst, PerFunctionState &PFS); + bool ParseCatchEndBlock(Instruction *&Inst, PerFunctionState &PFS); bool ParseArithmetic(Instruction *&I, PerFunctionState &PFS, unsigned Opc, unsigned OperandType); diff --git a/llvm/lib/AsmParser/LLToken.h b/llvm/lib/AsmParser/LLToken.h index 2487d120813..6e24224978e 100644 --- a/llvm/lib/AsmParser/LLToken.h +++ b/llvm/lib/AsmParser/LLToken.h @@ -51,6 +51,7 @@ namespace lltok { kw_zeroinitializer, kw_undef, kw_null, kw_to, + kw_caller, kw_tail, kw_musttail, kw_target, @@ -176,7 +177,8 @@ namespace lltok { kw_landingpad, kw_personality, kw_cleanup, kw_catch, kw_filter, kw_ret, kw_br, kw_switch, kw_indirectbr, kw_invoke, kw_resume, - kw_unreachable, + kw_unreachable, kw_cleanupret, kw_catchret, kw_catchblock, + kw_terminateblock, kw_cleanupblock, kw_catchendblock, kw_alloca, kw_load, kw_store, kw_fence, kw_cmpxchg, kw_atomicrmw, kw_getelementptr, |