From 677c6ecd0804c247eb727a830b50cd6537a6c12c Mon Sep 17 00:00:00 2001 From: Dale Johannesen Date: Thu, 16 Sep 2010 18:30:55 +0000 Subject: [PATCH] When substituting sunkaddrs into indirect arguments an asm, we were walking the asm arguments once and stashing their Values. This is wrong because the same memory location can be in the list twice, and if the first one has a sunkaddr substituted, the stashed value for the second one will be wrong (use-after-free). PR 8154. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@114104 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/CodeGenPrepare.cpp | 6 ++- test/CodeGen/X86/2010-09-16-asmcrash.ll | 56 ++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 test/CodeGen/X86/2010-09-16-asmcrash.ll diff --git a/lib/Transforms/Scalar/CodeGenPrepare.cpp b/lib/Transforms/Scalar/CodeGenPrepare.cpp index 02282820fc9..437de38131c 100644 --- a/lib/Transforms/Scalar/CodeGenPrepare.cpp +++ b/lib/Transforms/Scalar/CodeGenPrepare.cpp @@ -738,6 +738,7 @@ bool CodeGenPrepare::OptimizeInlineAsmInst(Instruction *I, CallSite CS, bool MadeChange = false; std::vector TargetConstraints = TLI->ParseConstraints(CS); + unsigned ArgNo = 0; for (unsigned i = 0, e = TargetConstraints.size(); i != e; ++i) { TargetLowering::AsmOperandInfo &OpInfo = TargetConstraints[i]; @@ -746,9 +747,10 @@ bool CodeGenPrepare::OptimizeInlineAsmInst(Instruction *I, CallSite CS, if (OpInfo.ConstraintType == TargetLowering::C_Memory && OpInfo.isIndirect) { - Value *OpVal = OpInfo.CallOperandVal; + Value *OpVal = const_cast(CS.getArgument(ArgNo++)); MadeChange |= OptimizeMemoryInst(I, OpVal, OpVal->getType(), SunkAddrs); - } + } else if (OpInfo.Type == InlineAsm::isInput) + ArgNo++; } return MadeChange; diff --git a/test/CodeGen/X86/2010-09-16-asmcrash.ll b/test/CodeGen/X86/2010-09-16-asmcrash.ll new file mode 100644 index 00000000000..9bbd6919421 --- /dev/null +++ b/test/CodeGen/X86/2010-09-16-asmcrash.ll @@ -0,0 +1,56 @@ +; RUN: llc < %s -mtriple=x86_64-unknown-freebsd8.1 -o /dev/null +; This formerly crashed, PR 8154. + +module asm ".weak sem_close" +module asm ".equ sem_close, _sem_close" +module asm ".weak sem_destroy" +module asm ".equ sem_destroy, _sem_destroy" +module asm ".weak sem_getvalue" +module asm ".equ sem_getvalue, _sem_getvalue" +module asm ".weak sem_init" +module asm ".equ sem_init, _sem_init" +module asm ".weak sem_open" +module asm ".equ sem_open, _sem_open" +module asm ".weak sem_post" +module asm ".equ sem_post, _sem_post" +module asm ".weak sem_timedwait" +module asm ".equ sem_timedwait, _sem_timedwait" +module asm ".weak sem_trywait" +module asm ".equ sem_trywait, _sem_trywait" +module asm ".weak sem_unlink" +module asm ".equ sem_unlink, _sem_unlink" +module asm ".weak sem_wait" +module asm ".equ sem_wait, _sem_wait" + +%struct._sem = type { i32, %struct._usem } +%struct._usem = type { i32, i32, i32 } + +define void @_sem_timedwait(%struct._sem* noalias %sem) nounwind ssp { +entry: + br i1 undef, label %while.cond.preheader, label %sem_check_validity.exit + +while.cond.preheader: ; preds = %entry + %tmp4 = getelementptr inbounds %struct._sem* %sem, i64 0, i32 1, i32 1 + br label %while.cond + +sem_check_validity.exit: ; preds = %entry + ret void + +while.cond: ; preds = %while.body, %while.cond.preheader + br i1 undef, label %while.body, label %while.end + +while.body: ; preds = %while.cond + %0 = call i8 asm sideeffect "\09lock ; \09\09\09cmpxchgl $2,$1 ;\09 sete\09$0 ;\09\091:\09\09\09\09# atomic_cmpset_int", "={ax},=*m,r,{ax},*m,~{memory},~{dirflag},~{fpsr},~{flags}"(i32* %tmp4, i32 undef, i32 undef, i32* %tmp4) nounwind, !srcloc !0 + br i1 undef, label %while.cond, label %return + +while.end: ; preds = %while.cond + br i1 undef, label %if.end18, label %return + +if.end18: ; preds = %while.end + unreachable + +return: ; preds = %while.end, %while.body + ret void +} + +!0 = metadata !{i32 158484}