diff options
author | Craig Topper <craig.topper@intel.com> | 2019-02-08 20:48:56 +0000 |
---|---|---|
committer | Craig Topper <craig.topper@intel.com> | 2019-02-08 20:48:56 +0000 |
commit | 784929d0454c4df6a98ef6fbbd1d30a6f71f9c16 (patch) | |
tree | ee2091fd647c20c3279800a14f7ce36c85b8c00b /llvm/lib/Bitcode/Reader/BitcodeReader.cpp | |
parent | 0e5dd512aae057aeceb34089c93a380f8edd37da (diff) | |
download | bcm5719-llvm-784929d0454c4df6a98ef6fbbd1d30a6f71f9c16.tar.gz bcm5719-llvm-784929d0454c4df6a98ef6fbbd1d30a6f71f9c16.zip |
Implementation of asm-goto support in LLVM
This patch accompanies the RFC posted here:
http://lists.llvm.org/pipermail/llvm-dev/2018-October/127239.html
This patch adds a new CallBr IR instruction to support asm-goto
inline assembly like gcc as used by the linux kernel. This
instruction is both a call instruction and a terminator
instruction with multiple successors. Only inline assembly
usage is supported today.
This also adds a new INLINEASM_BR opcode to SelectionDAG and
MachineIR to represent an INLINEASM block that is also
considered a terminator instruction.
There will likely be more bug fixes and optimizations to follow
this, but we felt it had reached a point where we would like to
switch to an incremental development model.
Patch by Craig Topper, Alexander Ivchenko, Mikhail Dvoretckii
Differential Revision: https://reviews.llvm.org/D53765
llvm-svn: 353563
Diffstat (limited to 'llvm/lib/Bitcode/Reader/BitcodeReader.cpp')
-rw-r--r-- | llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 61bc031026b..b94bb66a0d6 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -4231,6 +4231,74 @@ Error BitcodeReader::parseFunctionBody(Function *F) { InstructionList.push_back(I); break; } + case bitc::FUNC_CODE_INST_CALLBR: { + // CALLBR: [attr, cc, norm, transfs, fty, fnid, args] + unsigned OpNum = 0; + AttributeList PAL = getAttributes(Record[OpNum++]); + unsigned CCInfo = Record[OpNum++]; + + BasicBlock *DefaultDest = getBasicBlock(Record[OpNum++]); + unsigned NumIndirectDests = Record[OpNum++]; + SmallVector<BasicBlock *, 16> IndirectDests; + for (unsigned i = 0, e = NumIndirectDests; i != e; ++i) + IndirectDests.push_back(getBasicBlock(Record[OpNum++])); + + FunctionType *FTy = nullptr; + if (CCInfo >> bitc::CALL_EXPLICIT_TYPE & 1 && + !(FTy = dyn_cast<FunctionType>(getTypeByID(Record[OpNum++])))) + return error("Explicit call type is not a function type"); + + Value *Callee; + if (getValueTypePair(Record, OpNum, NextValueNo, Callee)) + return error("Invalid record"); + + PointerType *OpTy = dyn_cast<PointerType>(Callee->getType()); + if (!OpTy) + return error("Callee is not a pointer type"); + if (!FTy) { + FTy = dyn_cast<FunctionType>(OpTy->getElementType()); + if (!FTy) + return error("Callee is not of pointer to function type"); + } else if (OpTy->getElementType() != FTy) + return error("Explicit call type does not match pointee type of " + "callee operand"); + if (Record.size() < FTy->getNumParams() + OpNum) + return error("Insufficient operands to call"); + + SmallVector<Value*, 16> Args; + // Read the fixed params. + for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i, ++OpNum) { + if (FTy->getParamType(i)->isLabelTy()) + Args.push_back(getBasicBlock(Record[OpNum])); + else + Args.push_back(getValue(Record, OpNum, NextValueNo, + FTy->getParamType(i))); + if (!Args.back()) + return error("Invalid record"); + } + + // Read type/value pairs for varargs params. + if (!FTy->isVarArg()) { + if (OpNum != Record.size()) + return error("Invalid record"); + } else { + while (OpNum != Record.size()) { + Value *Op; + if (getValueTypePair(Record, OpNum, NextValueNo, Op)) + return error("Invalid record"); + Args.push_back(Op); + } + } + + I = CallBrInst::Create(FTy, Callee, DefaultDest, IndirectDests, Args, + OperandBundles); + OperandBundles.clear(); + InstructionList.push_back(I); + cast<CallBrInst>(I)->setCallingConv( + static_cast<CallingConv::ID>((0x7ff & CCInfo) >> bitc::CALL_CCONV)); + cast<CallBrInst>(I)->setAttributes(PAL); + break; + } case bitc::FUNC_CODE_INST_UNREACHABLE: // UNREACHABLE I = new UnreachableInst(Context); InstructionList.push_back(I); |