brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.6 KiB · 744f863 Raw
141 lines · cpp
1// REQUIRES: x86-registered-target2// RUN: %clang_cl -c --target=x86_64-windows-msvc -EHs-c- -O2 -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 29void normal_has_regions() {30    {31        HasDtor hd{42};32 33        // because state changes, we expect the HasDtor::HasDtor() call to have a NOP34        might_throw();35    }36 37    other_func(10);38}39// CHECK-LABEL: .def "?normal_has_regions@@YAXXZ"40// CHECK: .seh_endprologue41// CHECK: call "??0HasDtor@@QEAA@H@Z"42// CHECK-NEXT: call "?might_throw@@YAXXZ"43// CHECK-NEXT: mov44// CHECK: call "??1HasDtor@@QEAA@XZ"45// CHECK-NEXT: mov ecx, 1046// CHECK-NEXT: call "?other_func@@YAXH@Z"47// CHECK-NEXT: nop48// CHECK-NEXT: .seh_startepilogue49// CHECK-NOT: "$ip2state$?normal_has_regions@@YAXXZ"50 51// This tests a tail call to a destructor.52void case_dtor_arg_empty_body(HasDtor x)53{54}55// CHECK-LABEL: .def "?case_dtor_arg_empty_body@@YAXVHasDtor@@@Z"56// CHECK: jmp "??1HasDtor@@QEAA@XZ"57 58int case_dtor_arg_empty_with_ret(HasDtor x)59{60    // The call to HasDtor::~HasDtor() should NOT have a NOP because the61    // following "mov eax, 100" instruction is in the same EH state.62    return 100;63}64// CHECK-LABEL: .def "?case_dtor_arg_empty_with_ret@@YAHVHasDtor@@@Z"65// CHECK: .seh_endprologue66// CHECK: call "??1HasDtor@@QEAA@XZ"67// CHECK-NOT: nop68// CHECK: mov eax, 10069// CHECK: .seh_startepilogue70// CHECK: .seh_endepilogue71// CHECK: .seh_endproc72 73void case_except_simple_call() NO_TAIL74{75    does_not_throw();76}77 78// This tests that the destructor is called right before SEH_BeginEpilogue,79// but in a function that has a return value.80int case_dtor_arg_calls_no_throw(HasDtor x)81{82    does_not_throw(); // no NOP expected83    return 100;84}85 86// Check the behavior of CALLs that are at the end of MBBs. If a CALL is within87// a non-null EH state (state -1) and is at the end of an MBB, then we expect88// to find an EH_LABEL after the CALL. This causes us to insert a NOP, which89// is the desired result.90void case_dtor_runs_after_join(int x) {91 92    // ctor call does not need a NOP, because it has real instructions after it93    HasDtor hd{42};94 95    if (x) {96        might_throw();97    } else {98        other_func(10);99    }100    does_not_throw();101    // ~HasDtor() runs102}103 104// CHECK-LABEL: .def "?case_dtor_runs_after_join@@YAXH@Z"105// CHECK: .seh_endprologue106// CHECK: call "??0HasDtor@@QEAA@H@Z"107// CHECK-NEXT: test108// CHECK: call "?might_throw@@YAXXZ"109// CHECK-NEXT: jmp110// CHECK: call "?other_func@@YAXH@Z"111// CHECK-NEXT: .LBB112// CHECK: call "?does_not_throw@@YAXXZ"113// CHECK-NEXT: lea114// CHECK-NEXT: call "??1HasDtor@@QEAA@XZ"115// CHECK-NEXT: nop116// CHECK-NEXT: .seh_startepilogue117// CHECK-NOT: "$ip2state$?case_dtor_runs_after_join@@YAXH@Z":118 119 120// Check the behavior of NOP padding around tail calls.121// We do not expect to insert NOPs around tail calls.122// However, the first call (to other_func()) does get a NOP123// because it comes before .seh_startepilogue.124void case_tail_call_no_eh() {125    // ordinary call126    other_func(10);127 128    // tail call; no NOP padding after JMP129    does_not_throw();130}131 132// CHECK-LABEL: .def "?case_tail_call_no_eh@@YAXXZ"133// CHECK: .seh_endprologue134// CHECK: call "?other_func@@YAXH@Z"135// CHECK-NEXT: nop136// CHECK-NEXT: .seh_startepilogue137// CHECK: .seh_endepilogue138// CHECK: jmp "?does_not_throw@@YAXXZ"139// CHECK-NOT: nop140// CHECK: .seh_endproc141