aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Bitcode/Reader/BitcodeReader.cpp')
-rw-r--r--llvm/lib/Bitcode/Reader/BitcodeReader.cpp55
1 files changed, 55 insertions, 0 deletions
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 8d5a255..1d6c21b 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -5510,6 +5510,61 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
if (!OperandBundles.empty())
UpgradeOperandBundles(OperandBundles);
+ if (auto *IA = dyn_cast<InlineAsm>(Callee)) {
+ InlineAsm::ConstraintInfoVector ConstraintInfo = IA->ParseConstraints();
+ auto IsLabelConstraint = [](const InlineAsm::ConstraintInfo &CI) {
+ return CI.Type == InlineAsm::isLabel;
+ };
+ if (none_of(ConstraintInfo, IsLabelConstraint)) {
+ // Upgrade explicit blockaddress arguments to label constraints.
+ // Verify that the last arguments are blockaddress arguments that
+ // match the indirect destinations. Clang always generates callbr
+ // in this form. We could support reordering with more effort.
+ unsigned FirstBlockArg = Args.size() - IndirectDests.size();
+ for (unsigned ArgNo = FirstBlockArg; ArgNo < Args.size(); ++ArgNo) {
+ unsigned LabelNo = ArgNo - FirstBlockArg;
+ auto *BA = dyn_cast<BlockAddress>(Args[ArgNo]);
+ if (!BA || BA->getFunction() != F ||
+ LabelNo > IndirectDests.size() ||
+ BA->getBasicBlock() != IndirectDests[LabelNo])
+ return error("callbr argument does not match indirect dest");
+ }
+
+ // Remove blockaddress arguments.
+ Args.erase(Args.begin() + FirstBlockArg, Args.end());
+ ArgTyIDs.erase(ArgTyIDs.begin() + FirstBlockArg, ArgTyIDs.end());
+
+ // Recreate the function type with less arguments.
+ SmallVector<Type *> ArgTys;
+ for (Value *Arg : Args)
+ ArgTys.push_back(Arg->getType());
+ FTy =
+ FunctionType::get(FTy->getReturnType(), ArgTys, FTy->isVarArg());
+
+ // Update constraint string to use label constraints.
+ std::string Constraints = IA->getConstraintString();
+ unsigned ArgNo = 0;
+ size_t Pos = 0;
+ for (const auto &CI : ConstraintInfo) {
+ if (CI.hasArg()) {
+ if (ArgNo >= FirstBlockArg)
+ Constraints.insert(Pos, "!");
+ ++ArgNo;
+ }
+
+ // Go to next constraint in string.
+ Pos = Constraints.find(',', Pos);
+ if (Pos == std::string::npos)
+ break;
+ ++Pos;
+ }
+
+ Callee = InlineAsm::get(FTy, IA->getAsmString(), Constraints,
+ IA->hasSideEffects(), IA->isAlignStack(),
+ IA->getDialect(), IA->canThrow());
+ }
+ }
+
I = CallBrInst::Create(FTy, Callee, DefaultDest, IndirectDests, Args,
OperandBundles);
ResTypeID = getContainedTypeID(FTyID);