Index: lib/CodeGen/SjLjEHPrepare.cpp =================================================================== --- lib/CodeGen/SjLjEHPrepare.cpp +++ lib/CodeGen/SjLjEHPrepare.cpp @@ -249,18 +249,18 @@ ++AI) { Type *Ty = AI->getType(); - // Aggregate types can't be cast, but are legal argument types, so we have - // to handle them differently. We use an extract/insert pair as a - // lightweight method to achieve the same goal. if (isa(Ty) || isa(Ty)) { - Instruction *EI = ExtractValueInst::Create(AI, 0, "", AfterAllocaInsPt); - Instruction *NI = InsertValueInst::Create(AI, EI, 0); - NI->insertAfter(EI); - AI->replaceAllUsesWith(NI); - - // Set the operand of the instructions back to the AllocaInst. - EI->setOperand(0, AI); - NI->setOperand(0, AI); + // Aggregate types can't be cast, but are legal argument types, + // so we have to handle them differently. We use + // select i8 true, %arg, undef to achieve the same goal + Value *TrueValue = ConstantInt::getTrue(F.getContext()); + Value *UndefValue = UndefValue::get(Ty); + Instruction *SI = SelectInst::Create(TrueValue, AI, UndefValue, + AI->getName() + ".tmp", + AfterAllocaInsPt); + AI->replaceAllUsesWith(SI); + + SI->setOperand(1, AI); } else { // This is always a no-op cast because we're casting AI to AI->getType() // so src and destination types are identical. BitCast is the only Index: test/CodeGen/ARM/sjljehprepare-lower-empty-struct.ll =================================================================== --- /dev/null +++ test/CodeGen/ARM/sjljehprepare-lower-empty-struct.ll @@ -0,0 +1,31 @@ +; RUN: llc -mtriple=armv7-apple-ios -O0 < %s | FileCheck %s +; RUN: llc -mtriple=armv7-apple-ios -O1 < %s | FileCheck %s +; RUN: llc -mtriple=armv7-apple-ios -O2 < %s | FileCheck %s +; RUN: llc -mtriple=armv7-apple-ios -O3 < %s | FileCheck %s + +; SjLjEHPrepare shouldn't crash when lowering empty structs. +; +; Checks that between in case of empty structs used as arguments +; nothing happens, i.e. there are no instructions between +; __Unwind_SjLj_Register and actual @bar invocation + + +define i8* @foo({} %c) { +entry: +; CHECK: bl __Unwind_SjLj_Register +; CHECK-NEXT: {{[A-Z][a-zA-Z0-9]*}}: +; CHECK-NEXT: bl _bar + invoke void @bar () + to label %unreachable unwind label %handler + +unreachable: + unreachable + +handler: + %tmp = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @baz to i8*) + cleanup + resume { i8*, i32 } undef +} + +declare void @bar() +declare i32 @baz(...)