243 lines · cpp
1// REQUIRES: x86-registered-target2// RUN: %clang_cl -c --target=x86_64-windows-msvc -O2 -EHsc -GS- \3// RUN: -Xclang=-import-call-optimization \4// RUN: -clang:-S -clang:-o- -- %s 2>&1 \5// RUN: | FileCheck %s6 7#ifdef __clang__8#define NO_TAIL __attribute((disable_tail_calls))9#else10#define NO_TAIL11#endif12 13void might_throw();14void other_func(int x);15 16void does_not_throw() noexcept(true);17 18extern "C" void __declspec(dllimport) some_dll_import();19 20class HasDtor {21 int x;22 char foo[40];23 24public:25 explicit HasDtor(int x);26 ~HasDtor();27};28 29class BadError {30public:31 int errorCode;32};33 34// Verify that when NOP padding for IP2State is active *and* Import Call35// Optimization is active that we see both forms of NOP padding.36void case_calls_dll_import() NO_TAIL {37 some_dll_import();38}39// CHECK-LABEL: .def "?case_calls_dll_import@@YAXXZ"40// CHECK: .seh_endprologue41// CHECK: .Limpcall{{[0-9]+}}:42// CHECK-NEXT: rex6443// CHECK-NEXT: call __imp_some_dll_import44// CHECK-NEXT: nop dword ptr {{\[.*\]}}45// CHECK-NEXT: nop46// CHECK-NEXT: .seh_startepilogue47 48void normal_has_regions() {49 50 // <-- state -1 (none)51 {52 HasDtor hd{42};53 54 // <-- state goes from -1 to 055 // because state changes, we expect the HasDtor::HasDtor() call to have a NOP56 57 might_throw();58 59 // <-- state goes from 0 to -1 because we're about to call HasDtor::~HasDtor()60 // <-- state -161 }62 63 // <-- state -164 other_func(10);65 66 // <-- state -167}68// CHECK-LABEL: .def "?normal_has_regions@@YAXXZ"69// CHECK: .seh_endprologue70// CHECK: call "??0HasDtor@@QEAA@H@Z"71// CHECK-NEXT: nop72// CHECK: call "?might_throw@@YAXXZ"73// CHECK-NEXT: nop74// CHECK: call "??1HasDtor@@QEAA@XZ"75// CHECK: call "?other_func@@YAXH@Z"76// CHECK-NEXT: nop77// CHECK: .seh_startepilogue78 79// This tests a tail call to a destructor.80void case_dtor_arg_empty_body(HasDtor x)81{82}83// CHECK-LABEL: .def "?case_dtor_arg_empty_body@@YAXVHasDtor@@@Z"84// CHECK: jmp "??1HasDtor@@QEAA@XZ"85 86int case_dtor_arg_empty_with_ret(HasDtor x)87{88 // CHECK-LABEL: .def "?case_dtor_arg_empty_with_ret@@YAHVHasDtor@@@Z"89 // CHECK: .seh_endprologue90 91 // CHECK: call "??1HasDtor@@QEAA@XZ"92 // CHECK-NOT: nop93 94 // The call to HasDtor::~HasDtor() should NOT have a NOP because the95 // following "mov eax, 100" instruction is in the same EH state.96 97 return 100;98 99 // CHECK: mov eax, 100100 // CHECK: .seh_startepilogue101 // CHECK: .seh_endepilogue102 // CHECK: .seh_endproc103}104 105int case_noexcept_dtor(HasDtor x) noexcept(true)106{107 // CHECK: .def "?case_noexcept_dtor@@YAHVHasDtor@@@Z"108 // CHECK: call "??1HasDtor@@QEAA@XZ"109 // CHECK-NEXT: mov eax, 100110 // CHECK-NEXT: .seh_startepilogue111 return 100;112}113 114// Simple call of a function that can throw115void case_except_simple_call() NO_TAIL116{117 might_throw();118}119// CHECK-LABEL: .def "?case_except_simple_call@@YAXXZ"120// CHECK: .seh_endprologue121// CHECK-NEXT: call "?might_throw@@YAXXZ"122// CHECK-NEXT: nop123// CHECK-NEXT: .seh_startepilogue124 125// Simple call of a function that cannot throw, in a noexcept context.126void case_noexcept_simple_call() noexcept(true) NO_TAIL127{128 does_not_throw();129}130// CHECK-LABEL: .def "?case_noexcept_simple_call@@YAXXZ"131// CHECK: .seh_endprologue132// CHECK-NEXT: call "?does_not_throw@@YAXXZ"133// CHECK-NEXT: nop134// CHECK-NEXT: .seh_startepilogue135 136 137// This tests that the destructor is called right before SEH_BeginEpilogue,138// but in a function that has a return value.139int case_dtor_arg_calls_no_throw(HasDtor x)140{141 does_not_throw(); // no NOP expected142 return 100;143}144 145// Check the behavior of CALLs that are at the end of MBBs. If a CALL is within146// a non-null EH state (state -1) and is at the end of an MBB, then we expect147// to find an EH_LABEL after the CALL. This causes us to insert a NOP, which148// is the desired result.149void case_dtor_runs_after_join(int x) {150 // CHECK-LABEL: .def "?case_dtor_runs_after_join@@YAXH@Z"151 // CHECK: .seh_endprologue152 153 // <-- EH state -1154 155 // ctor call does not need a NOP, because it has real instructions after it156 HasDtor hd{42};157 // CHECK: call "??0HasDtor@@QEAA@H@Z"158 // CHECK-NEXT: test159 160 // <-- EH state transition from -1 0161 if (x) {162 might_throw(); // <-- NOP expected (at end of BB w/ EH_LABEL)163 // CHECK: call "?might_throw@@YAXXZ"164 // CHECK-NEXT: nop165 } else {166 other_func(10); // <-- NOP expected (at end of BB w/ EH_LABEL)167 // CHECK: call "?other_func@@YAXH@Z"168 // CHECK-NEXT: nop169 }170 does_not_throw();171 // <-- EH state transition 0 to -1172 // ~HasDtor() runs173 174 // CHECK: .seh_endproc175 176 // CHECK: "$ip2state$?case_dtor_runs_after_join@@YAXH@Z":177 // CHECK-NEXT: .long [[func_begin:.Lfunc_begin([0-9]+)@IMGREL]]178 // CHECK-NEXT: .long -1179 // CHECK-NEXT: .long [[tmp1:.Ltmp([0-9]+)]]@IMGREL180 // CHECK-NEXT: .long 0181 // CHECK-NEXT: .long [[tmp2:.Ltmp([0-9]+)]]@IMGREL182 // CHECK-NEXT: .long -1183}184 185 186// Check the behavior of NOP padding around tail calls.187// We do not expect to insert NOPs around tail calls.188// However, the first call (to other_func()) does get a NOP189// because it comes before .seh_startepilogue.190void case_tail_call_no_eh() {191 // CHECK-LABEL: .def "?case_tail_call_no_eh@@YAXXZ"192 // CHECK: .seh_endprologue193 194 // ordinary call195 other_func(10);196 // CHECK: call "?other_func@@YAXH@Z"197 // CHECK-NEXT: nop198 199 // tail call; no NOP padding after JMP200 does_not_throw();201 202 // CHECK: .seh_startepilogue203 // CHECK: .seh_endepilogue204 // CHECK: jmp "?does_not_throw@@YAXXZ"205 // CHECK-NOT: nop206 // CHECK: .seh_endproc207}208 209 210// Check the behavior of a try/catch211int case_try_catch() {212 // CHECK-LABEL: .def "?case_try_catch@@YAHXZ"213 // CHECK: .seh_endprologue214 215 // Because of the EH_LABELs, the ctor and other_func() get NOPs.216 217 int result = 0;218 try {219 // CHECK: call "??0HasDtor@@QEAA@H@Z"220 // CHECK-NEXT: nop221 HasDtor hd{20};222 223 // CHECK: call "?other_func@@YAXH@Z"224 // CHECK-NEXT: nop225 other_func(10);226 227 // CHECK: call "??1HasDtor@@QEAA@XZ"228 // CHECK: mov229 } catch (BadError& e) {230 result = 1;231 }232 return result;233 234 // CHECK: .seh_endproc235 236 // CHECK: .def "?dtor$4@?0??case_try_catch@@YAHXZ@4HA"237 // CHECK: .seh_endprologue238 // CHECK: call "??1HasDtor@@QEAA@XZ"239 // CHECK-NEXT: nop240 // CHECK: .seh_startepilogue241 // CHECK: .seh_endproc242}243