From b5a79d0eaa83baf7c73f89fedef4f865de0208d2 Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Mon, 17 Dec 2007 18:08:19 +0000 Subject: [PATCH] Make invokes of inline asm legal. Teach codegen how to lower them (with no attempt made to be efficient, since they should only occur for unoptimized code). llvm-svn: 45108 --- .../CodeGen/SelectionDAG/SelectionDAGISel.cpp | 37 ++++++++++--------- llvm/lib/Transforms/Utils/InlineFunction.cpp | 5 +-- llvm/lib/VMCore/Verifier.cpp | 2 +- .../CodeGen/Generic/2007-12-17-InvokeAsm.ll | 15 ++++++++ .../Transforms/Inline/2007-04-15-InlineEH.ll | 2 +- 5 files changed, 39 insertions(+), 22 deletions(-) create mode 100644 llvm/test/CodeGen/Generic/2007-12-17-InvokeAsm.ll diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index ed89878a0d89..bc336d206975 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -597,7 +597,7 @@ public: void visitStore(StoreInst &I); void visitPHI(PHINode &I) { } // PHI nodes are handled specially. void visitCall(CallInst &I); - void visitInlineAsm(CallInst &I); + void visitInlineAsm(CallSite CS); const char *visitIntrinsicCall(CallInst &I, unsigned Intrinsic); void visitTargetIntrinsic(CallInst &I, unsigned Intrinsic); @@ -1449,11 +1449,14 @@ void SelectionDAGLowering::visitInvoke(InvokeInst &I) { MachineBasicBlock *Return = FuncInfo.MBBMap[I.getSuccessor(0)]; MachineBasicBlock *LandingPad = FuncInfo.MBBMap[I.getSuccessor(1)]; - LowerCallTo(I, I.getCalledValue()->getType(), I.getParamAttrs(), - I.getCallingConv(), - false, - getValue(I.getOperand(0)), - 3, LandingPad); + if (isa(I.getCalledValue())) + visitInlineAsm(&I); + else + LowerCallTo(I, I.getCalledValue()->getType(), I.getParamAttrs(), + I.getCallingConv(), + false, + getValue(I.getOperand(0)), + 3, LandingPad); // If the value of the invoke is used outside of its defining block, make it // available as a virtual register. @@ -3044,7 +3047,7 @@ void SelectionDAGLowering::visitCall(CallInst &I) { } } } else if (isa(I.getOperand(0))) { - visitInlineAsm(I); + visitInlineAsm(&I); return; } @@ -3425,8 +3428,8 @@ GetRegistersForValue(AsmOperandInfo &OpInfo, bool HasEarlyClobber, /// visitInlineAsm - Handle a call to an InlineAsm object. /// -void SelectionDAGLowering::visitInlineAsm(CallInst &I) { - InlineAsm *IA = cast(I.getOperand(0)); +void SelectionDAGLowering::visitInlineAsm(CallSite CS) { + InlineAsm *IA = cast(CS.getCalledValue()); /// ConstraintOperands - Information about all of the constraints. std::vector ConstraintOperands; @@ -3446,7 +3449,7 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) { // registers, because it will not know to avoid the earlyclobbered output reg. bool SawEarlyClobber = false; - unsigned OpNo = 1; // OpNo - The operand of the CallInst. + unsigned ArgNo = 0; // ArgNo - The argument of the CallInst. for (unsigned i = 0, e = ConstraintInfos.size(); i != e; ++i) { ConstraintOperands.push_back(AsmOperandInfo(ConstraintInfos[i])); AsmOperandInfo &OpInfo = ConstraintOperands.back(); @@ -3459,14 +3462,14 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) { if (!OpInfo.isIndirect) { // The return value of the call is this value. As such, there is no // corresponding argument. - assert(I.getType() != Type::VoidTy && "Bad inline asm!"); - OpVT = TLI.getValueType(I.getType()); + assert(CS.getType() != Type::VoidTy && "Bad inline asm!"); + OpVT = TLI.getValueType(CS.getType()); } else { - OpInfo.CallOperandVal = I.getOperand(OpNo++); + OpInfo.CallOperandVal = CS.getArgument(ArgNo++); } break; case InlineAsm::isInput: - OpInfo.CallOperandVal = I.getOperand(OpNo++); + OpInfo.CallOperandVal = CS.getArgument(ArgNo++); break; case InlineAsm::isClobber: // Nothing to do. @@ -3617,7 +3620,7 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) { // This is the result value of the call. assert(RetValRegs.Regs.empty() && "Cannot have multiple output constraints yet!"); - assert(I.getType() != Type::VoidTy && "Bad inline asm!"); + assert(CS.getType() != Type::VoidTy && "Bad inline asm!"); RetValRegs = OpInfo.AssignedRegs; } else { IndirectStoresToEmit.push_back(std::make_pair(OpInfo.AssignedRegs, @@ -3751,13 +3754,13 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) { // width/num elts. Make sure to convert it to the right type with // bit_convert. if (MVT::isVector(Val.getValueType())) { - const VectorType *VTy = cast(I.getType()); + const VectorType *VTy = cast(CS.getType()); MVT::ValueType DesiredVT = TLI.getValueType(VTy); Val = DAG.getNode(ISD::BIT_CONVERT, DesiredVT, Val); } - setValue(&I, Val); + setValue(CS.getInstruction(), Val); } std::vector > StoresToEmit; diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp index e88eb9428268..69d0e12a37cd 100644 --- a/llvm/lib/Transforms/Utils/InlineFunction.cpp +++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp @@ -69,9 +69,8 @@ static void HandleInlinedInvoke(InvokeInst *II, BasicBlock *FirstNewBlock, if (!isa(I)) continue; CallInst *CI = cast(I); - // If this call cannot unwind or is an inline asm, don't - // convert it to an invoke. - if (CI->isNoUnwind() || isa(CI->getCalledValue())) + // If this call cannot unwind, don't convert it to an invoke. + if (CI->isNoUnwind()) continue; // Convert this function call into an invoke instruction. diff --git a/llvm/lib/VMCore/Verifier.cpp b/llvm/lib/VMCore/Verifier.cpp index 08f031f40ed6..c083fe78107a 100644 --- a/llvm/lib/VMCore/Verifier.cpp +++ b/llvm/lib/VMCore/Verifier.cpp @@ -1123,7 +1123,7 @@ void Verifier::visitInstruction(Instruction &I) { "Instruction does not dominate all uses!", Op, &I); } } else if (isa(I.getOperand(i))) { - Assert1(i == 0 && isa(I), + Assert1(i == 0 && (isa(I) || isa(I)), "Cannot take the address of an inline asm!", &I); } } diff --git a/llvm/test/CodeGen/Generic/2007-12-17-InvokeAsm.ll b/llvm/test/CodeGen/Generic/2007-12-17-InvokeAsm.ll new file mode 100644 index 000000000000..98871d0e3a45 --- /dev/null +++ b/llvm/test/CodeGen/Generic/2007-12-17-InvokeAsm.ll @@ -0,0 +1,15 @@ +; RUN: llvm-as < %s | llc -enable-eh + +target triple = "i686-pc-linux-gnu" + +define fastcc void @bc__support__high_resolution_time__initialize_clock_rate() { +entry: + invoke void asm "rdtsc\0A\09movl %eax, $0\0A\09movl %edx, $1", "=*imr,=*imr,~{dirflag},~{fpsr},~{flags},~{dx},~{ax}"( i32* null, i32* null ) + to label %.noexc unwind label %cleanup144 + +.noexc: ; preds = %entry + ret void + +cleanup144: ; preds = %entry + unwind +} diff --git a/llvm/test/Transforms/Inline/2007-04-15-InlineEH.ll b/llvm/test/Transforms/Inline/2007-04-15-InlineEH.ll index 9d28755d2890..083a328ae673 100644 --- a/llvm/test/Transforms/Inline/2007-04-15-InlineEH.ll +++ b/llvm/test/Transforms/Inline/2007-04-15-InlineEH.ll @@ -1,4 +1,4 @@ -; RUN: llvm-as < %s | opt -inline -disable-output +; RUN: llvm-as < %s | opt -inline | llvm-dis | not grep {invoke void asm} ; PR1335 target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64"