diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2010-07-16 00:55:21 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2010-07-16 00:55:21 +0000 |
commit | 6d7cfd7ef82e42ff30ee1dafd2883fd94e9f8294 (patch) | |
tree | 7c8957fc0290c36a3379d4c9ae5f31e71207edd2 | |
parent | 1058253c364b2c98e6cecfe15d18d3562db245f4 (diff) |
Fix for PR3800: make sure not to evaluate the expression for a read-write
asm operand twice.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@108489 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/CGStmt.cpp | 43 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 5 | ||||
-rw-r--r-- | test/CodeGen/asm-inout.c | 19 |
3 files changed, 51 insertions, 16 deletions
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index b72725edca..29b426cd12 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -888,40 +888,50 @@ SimplifyConstraint(const char *Constraint, const TargetInfo &Target, return Result; } -llvm::Value* CodeGenFunction::EmitAsmInput(const AsmStmt &S, - const TargetInfo::ConstraintInfo &Info, - const Expr *InputExpr, - std::string &ConstraintStr) { +llvm::Value* +CodeGenFunction::EmitAsmInputLValue(const AsmStmt &S, + const TargetInfo::ConstraintInfo &Info, + LValue InputValue, QualType InputType, + std::string &ConstraintStr) { llvm::Value *Arg; if (Info.allowsRegister() || !Info.allowsMemory()) { - if (!CodeGenFunction::hasAggregateLLVMType(InputExpr->getType())) { - Arg = EmitScalarExpr(InputExpr); + if (!CodeGenFunction::hasAggregateLLVMType(InputType)) { + Arg = EmitLoadOfLValue(InputValue, InputType).getScalarVal(); } else { - InputExpr = InputExpr->IgnoreParenNoopCasts(getContext()); - LValue Dest = EmitLValue(InputExpr); - - const llvm::Type *Ty = ConvertType(InputExpr->getType()); + const llvm::Type *Ty = ConvertType(InputType); uint64_t Size = CGM.getTargetData().getTypeSizeInBits(Ty); if (Size <= 64 && llvm::isPowerOf2_64(Size)) { Ty = llvm::IntegerType::get(VMContext, Size); Ty = llvm::PointerType::getUnqual(Ty); - Arg = Builder.CreateLoad(Builder.CreateBitCast(Dest.getAddress(), Ty)); + Arg = Builder.CreateLoad(Builder.CreateBitCast(InputValue.getAddress(), + Ty)); } else { - Arg = Dest.getAddress(); + Arg = InputValue.getAddress(); ConstraintStr += '*'; } } } else { - InputExpr = InputExpr->IgnoreParenNoopCasts(getContext()); - LValue Dest = EmitLValue(InputExpr); - Arg = Dest.getAddress(); + Arg = InputValue.getAddress(); ConstraintStr += '*'; } return Arg; } +llvm::Value* CodeGenFunction::EmitAsmInput(const AsmStmt &S, + const TargetInfo::ConstraintInfo &Info, + const Expr *InputExpr, + std::string &ConstraintStr) { + if (Info.allowsRegister() || !Info.allowsMemory()) + if (!CodeGenFunction::hasAggregateLLVMType(InputExpr->getType())) + return EmitScalarExpr(InputExpr); + + InputExpr = InputExpr->IgnoreParenNoopCasts(getContext()); + LValue Dest = EmitLValue(InputExpr); + return EmitAsmInputLValue(S, Info, Dest, InputExpr->getType(), ConstraintStr); +} + void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { // Analyze the asm string to decompose it into its pieces. We know that Sema // has already done this, so it is guaranteed to be successful. @@ -1031,7 +1041,8 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { InOutConstraints += ','; const Expr *InputExpr = S.getOutputExpr(i); - llvm::Value *Arg = EmitAsmInput(S, Info, InputExpr, InOutConstraints); + llvm::Value *Arg = EmitAsmInputLValue(S, Info, Dest, InputExpr->getType(), + InOutConstraints); if (Info.allowsRegister()) InOutConstraints += llvm::utostr(i); diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 5ee3db08ee..778604b217 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -1575,6 +1575,11 @@ private: const TargetInfo::ConstraintInfo &Info, const Expr *InputExpr, std::string &ConstraintStr); + llvm::Value* EmitAsmInputLValue(const AsmStmt &S, + const TargetInfo::ConstraintInfo &Info, + LValue InputValue, QualType InputType, + std::string &ConstraintStr); + /// EmitCallArgs - Emit call arguments for a function. /// The CallArgTypeInfo parameter is used for iterating over the known /// argument types of the function being called. diff --git a/test/CodeGen/asm-inout.c b/test/CodeGen/asm-inout.c new file mode 100644 index 0000000000..f04276693e --- /dev/null +++ b/test/CodeGen/asm-inout.c @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s +// PR3800 +int *foo(void); + +// CHECK: @test1 +void test1() { + // CHECK: [[REGCALLRESULT:%[a-zA-Z0-9\.]+]] = call i32* @foo() + // CHECK: call void asm "foobar", "=*m,*m,~{dirflag},~{fpsr},~{flags}"(i32* [[REGCALLRESULT]], i32* [[REGCALLRESULT]]) + asm ("foobar" : "+m"(*foo())); +} + +// CHECK: @test2 +void test2() { + // CHECK: [[REGCALLRESULT:%[a-zA-Z0-9\.]+]] = call i32* @foo() + // CHECK: load i32* [[REGCALLRESULT]] + // CHECK: call i32 asm + // CHECK: store i32 {{%[a-zA-Z0-9\.]+}}, i32* [[REGCALLRESULT]] + asm ("foobar" : "+r"(*foo())); +} |