Index: lib/Target/ARM/ARMAsmPrinter.cpp =================================================================== --- lib/Target/ARM/ARMAsmPrinter.cpp +++ lib/Target/ARM/ARMAsmPrinter.cpp @@ -1102,7 +1102,11 @@ if (MO.isUndef()) { assert(RegList.empty() && "Pad registers must come before restored ones"); - Pad += 4; + const MachineFunction &MF = *MI->getParent()->getParent(); + const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); + const MachineRegisterInfo &MRI = MF.getRegInfo(); + unsigned Width = TRI->getRegSizeInBits(MO.getReg(), MRI) / 8; + Pad += Width; continue; } RegList.push_back(MO.getReg()); Index: test/CodeGen/ARM/unwind-fp.ll =================================================================== --- /dev/null +++ test/CodeGen/ARM/unwind-fp.ll @@ -0,0 +1,119 @@ +; RUN: llc < %s -mtriple=armv7a-arm-none-eabi | FileCheck %s +; CHECK: pad #8 + +; Source code: +;#include +;#include +;#include +;#include +; +;struct Cplx { +; double r, i; +;}; +; +;void foo(struct Cplx P0, __fp16 P1, int P2, ...) { +; assert(P0.r == 1.0); +; assert(P0.i == 2.0); +; assert(P1 == 1.5); +; std::va_list vl; +; va_start(vl, P2); +; throw 42; +;} + + +%"struct.std::__va_list" = type { i8* } + +@_ZTIi = external dso_local constant i8* + +; Function Attrs: minsize noinline noreturn nounwind optsize +define dso_local void @__assert_fail(i8* nocapture readnone %assertion, i8* nocapture readnone %file, i32 %line, i8* nocapture readnone %function) local_unnamed_addr #0 { +entry: + tail call void @abort() #7 + unreachable +} + +; Function Attrs: minsize noreturn nounwind optsize +declare dso_local void @abort() local_unnamed_addr #1 + +; Function Attrs: minsize noreturn optsize +define dso_local void @_Z3foo4CplxDhiz([2 x i64] %P0.coerce, i32 %P1.coerce, i32 %P2, ...) local_unnamed_addr #2 { +entry: + %vl = alloca %"struct.std::__va_list", align 4 + %P0.coerce.fca.0.extract = extractvalue [2 x i64] %P0.coerce, 0 + %tmp.0.extract.trunc = trunc i32 %P1.coerce to i16 + %0 = bitcast i16 %tmp.0.extract.trunc to half + %1 = bitcast i64 %P0.coerce.fca.0.extract to double + %cmp = fcmp oeq double %1, 1.000000e+00 + br i1 %cmp, label %cond.end, label %cond.false + +cond.false: ; preds = %entry + tail call void @__assert_fail(i8* undef, i8* undef, i32 undef, i8* undef) #7 + unreachable + +cond.end: ; preds = %entry + %P0.coerce.fca.1.extract = extractvalue [2 x i64] %P0.coerce, 1 + %2 = bitcast i64 %P0.coerce.fca.1.extract to double + %cmp2 = fcmp oeq double %2, 2.000000e+00 + br i1 %cmp2, label %cond.end5, label %cond.false4 + +cond.false4: ; preds = %cond.end + tail call void @__assert_fail(i8* undef, i8* undef, i32 undef, i8* undef) #7 + unreachable + +cond.end5: ; preds = %cond.end + %cmp6 = fcmp oeq half %0, 0xH3E00 + br i1 %cmp6, label %cond.end9, label %cond.false8 + +cond.false8: ; preds = %cond.end5 + tail call void @__assert_fail(i8* undef, i8* undef, i32 undef, i8* undef) #7 + unreachable + +cond.end9: ; preds = %cond.end5 + %3 = bitcast %"struct.std::__va_list"* %vl to i8* + call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %3) #4 + call void @llvm.va_start(i8* nonnull %3) + %exception = call i8* @__cxa_allocate_exception(i32 4) #4 + %4 = bitcast i8* %exception to i32* + store i32 42, i32* %4, align 16, !tbaa !3 + call void @__cxa_throw(i8* %exception, i8* bitcast (i8** @_ZTIi to i8*), i8* null) #8 + unreachable +} + +; Function Attrs: argmemonly nounwind +declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #3 + +; Function Attrs: nounwind +declare void @llvm.va_start(i8*) #4 + +declare dso_local i8* @__cxa_allocate_exception(i32) local_unnamed_addr + +declare dso_local void @__cxa_throw(i8*, i8*, i8*) local_unnamed_addr + +; Function Attrs: minsize norecurse optsize + +declare dso_local i32 @__gxx_personality_v0(...) + +; Function Attrs: nounwind readnone +declare i32 @llvm.eh.typeid.for(i8*) #6 + +declare dso_local i8* @__cxa_begin_catch(i8*) local_unnamed_addr + +declare dso_local void @__cxa_end_catch() local_unnamed_addr + +attributes #0 = { minsize noinline noreturn nounwind optsize "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="generic" "target-features"="+armv7-a,+dsp,+neon,+strict-align,+vfp3,-thumb-mode" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { minsize noreturn nounwind optsize "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="generic" "target-features"="+armv7-a,+dsp,+neon,+strict-align,+vfp3,-thumb-mode" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #2 = { minsize noreturn optsize "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="generic" "target-features"="+armv7-a,+dsp,+neon,+strict-align,+vfp3,-thumb-mode" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #3 = { argmemonly nounwind } +attributes #4 = { nounwind } +attributes #5 = { minsize norecurse optsize "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="generic" "target-features"="+armv7-a,+dsp,+neon,+strict-align,+vfp3,-thumb-mode" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #6 = { nounwind readnone } +attributes #7 = { minsize noreturn nounwind optsize } +attributes #8 = { noreturn } +attributes #9 = { minsize optsize } + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{i32 1, !"min_enum_size", i32 4} +!3 = !{!4, !4, i64 0} +!4 = !{!"int", !5, i64 0} +!5 = !{!"omnipotent char", !6, i64 0} +!6 = !{!"Simple C++ TBAA"}