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
This commit is contained in:
Eli Friedman 2010-07-16 00:55:21 +00:00
Родитель 1058253c36
Коммит 6d7cfd7ef8
3 изменённых файлов: 51 добавлений и 16 удалений

Просмотреть файл

@ -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);

Просмотреть файл

@ -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.

19
test/CodeGen/asm-inout.c Normal file
Просмотреть файл

@ -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()));
}