diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 93b3dbf525f1..879ebfbd2979 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -3923,6 +3923,25 @@ void BitcodeReader::propagateAttributeTypes(CallBase *CB, } } + if (CB->isInlineAsm()) { + const InlineAsm *IA = cast(CB->getCalledOperand()); + unsigned ArgNo = 0; + for (const InlineAsm::ConstraintInfo &CI : IA->ParseConstraints()) { + bool HasArg = CI.Type == InlineAsm::isInput || + (CI.Type == InlineAsm::isOutput && CI.isIndirect); + if (!HasArg) + continue; + + if (CI.isIndirect && !CB->getAttributes().getParamElementType(ArgNo)) { + Type *ElemTy = ArgsTys[ArgNo]->getPointerElementType(); + CB->addParamAttr( + ArgNo, Attribute::get(Context, Attribute::ElementType, ElemTy)); + } + + ArgNo++; + } + } + switch (CB->getIntrinsicID()) { case Intrinsic::preserve_array_access_index: case Intrinsic::preserve_struct_access_index: @@ -4826,15 +4845,18 @@ Error BitcodeReader::parseFunctionBody(Function *F) { return error("Insufficient operands to call"); SmallVector Args; + SmallVector ArgsTys; // Read the fixed params. for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i, ++OpNum) { + Value *Arg; if (FTy->getParamType(i)->isLabelTy()) - Args.push_back(getBasicBlock(Record[OpNum])); + Arg = getBasicBlock(Record[OpNum]); else - Args.push_back(getValue(Record, OpNum, NextValueNo, - FTy->getParamType(i))); - if (!Args.back()) + Arg = getValue(Record, OpNum, NextValueNo, FTy->getParamType(i)); + if (!Arg) return error("Invalid record"); + Args.push_back(Arg); + ArgsTys.push_back(Arg->getType()); } // Read type/value pairs for varargs params. @@ -4847,6 +4869,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) { if (getValueTypePair(Record, OpNum, NextValueNo, Op)) return error("Invalid record"); Args.push_back(Op); + ArgsTys.push_back(Op->getType()); } } @@ -4857,6 +4880,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) { cast(I)->setCallingConv( static_cast((0x7ff & CCInfo) >> bitc::CALL_CCONV)); cast(I)->setAttributes(PAL); + propagateAttributeTypes(cast(I), ArgsTys); break; } case bitc::FUNC_CODE_INST_UNREACHABLE: // UNREACHABLE diff --git a/llvm/test/Bitcode/upgrade-inline-asm-elementtype.ll b/llvm/test/Bitcode/upgrade-inline-asm-elementtype.ll new file mode 100644 index 000000000000..5658103fbc80 --- /dev/null +++ b/llvm/test/Bitcode/upgrade-inline-asm-elementtype.ll @@ -0,0 +1,30 @@ +; RUN: llvm-dis < %s.bc | FileCheck %s + +; CHECK: call void asm "", "=*rm,r"(i32* elementtype(i32) %p1, i32* %p2) +define void @test_call(i32* %p1, i32* %p2) { + call void asm "", "=*rm,r"(i32* %p1, i32* %p2) + ret void +} + +; CHECK: invoke void asm "", "=*rm,r"(i32* elementtype(i32) %p1, i32* %p2) +define void @test_invoke(i32* %p1, i32* %p2) personality i8* null { + invoke void asm "", "=*rm,r"(i32* %p1, i32* %p2) + to label %cont unwind label %lpad + +lpad: + %lp = landingpad i32 + cleanup + ret void + +cont: + ret void +} + +; CHECK: callbr void asm "", "=*rm,r"(i32* elementtype(i32) %p1, i32* %p2) +define void @test_callbr(i32* %p1, i32* %p2) { + callbr void asm "", "=*rm,r"(i32* %p1, i32* %p2) + to label %cont [] + +cont: + ret void +} diff --git a/llvm/test/Bitcode/upgrade-inline-asm-elementtype.ll.bc b/llvm/test/Bitcode/upgrade-inline-asm-elementtype.ll.bc new file mode 100644 index 000000000000..db0c3c33f113 Binary files /dev/null and b/llvm/test/Bitcode/upgrade-inline-asm-elementtype.ll.bc differ