зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
1058253c36
Коммит
6d7cfd7ef8
|
@ -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.
|
||||
|
|
|
@ -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()));
|
||||
}
|
Загрузка…
Ссылка в новой задаче