brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.3 KiB · 0b7b406 Raw
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