llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
29.17k stars 12.04k forks source link

Musttail calls do not work when compiling to x86 Windows #53271

Open ngg opened 2 years ago

ngg commented 2 years ago

Clang version in use: 13.0.0 (installed from Gentoo's package manager), but the problem is not Gentoo-specific and I could reproduce with current trunk as well. (Godbolt: https://gcc.godbolt.org/z/boxqK5r6d)

Compiling the following C++ code with clang++ -c -target i386-windows x.cpp fails with error in backend: failed to perform tail call elimination on a call site marked musttail error. When clang is compiled with assertions, the error message is musttail call must precede a ret with an optional bitcast.

// x.cpp
// clang++ -c -target i386-windows x.cpp
struct X {
  ~X();
  void f();
};

void g();

template <typename T>
struct Y {
  static void h()
  {
    X().f();
    [[clang::musttail]] return g();
  }
};

template struct Y<void>;

The reduced bugpoint-reduced-simplified.bc from running bugpoint -run-llc x.bc is uploaded here: https://web.tresorit.com/l/VVWGy#E9cy7Z9o6YakdQ_jmTsPPw

What happens is that the x86-winehstate LLVM pass inserts instructions between the musttail call and the ret instructions, which makes the code invalid.

IR dump before and after the x86-winehstate pass ``` *** IR Dump Before Windows 32-bit x86 EH state insertion (x86-winehstate) *** define dso_local void @"?h@?$Y@X@@SAXXZ"() #0 comdat align 2 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { invoke x86_thiscallcc void @"?f@X@@QAEXXZ"() to label %1 unwind label %2 1: ; preds = %0 musttail call void @"?g@@YAXXZ"() ret void 2: ; preds = %0 %3 = cleanuppad within none [] cleanupret from %3 unwind to caller } *** IR Dump After Windows 32-bit x86 EH state insertion (x86-winehstate) *** define dso_local void @"?h@?$Y@X@@SAXXZ"() #0 comdat align 2 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { %1 = alloca %CXXExceptionRegistration, align 4 %2 = bitcast %CXXExceptionRegistration* %1 to i8* call void @llvm.x86.seh.ehregnode(i8* %2) %3 = call i8* @llvm.stacksave() %4 = getelementptr inbounds %CXXExceptionRegistration, %CXXExceptionRegistration* %1, i32 0, i32 0 store i8* %3, i8** %4, align 4 %5 = getelementptr inbounds %CXXExceptionRegistration, %CXXExceptionRegistration* %1, i32 0, i32 2 store i32 -1, i32* %5, align 4 %6 = getelementptr inbounds %CXXExceptionRegistration, %CXXExceptionRegistration* %1, i32 0, i32 1 %7 = getelementptr inbounds %EHRegistrationNode, %EHRegistrationNode* %6, i32 0, i32 1 store i8* bitcast (i32 (i8*, i8*, i8*, i8*)* @"__ehhandler$?h@?$Y@X@@SAXXZ" to i8*), i8** %7, align 4 %8 = load %EHRegistrationNode*, %EHRegistrationNode* addrspace(257)* null, align 4 %9 = getelementptr inbounds %EHRegistrationNode, %EHRegistrationNode* %6, i32 0, i32 0 store %EHRegistrationNode* %8, %EHRegistrationNode** %9, align 4 store %EHRegistrationNode* %6, %EHRegistrationNode* addrspace(257)* null, align 4 %10 = getelementptr inbounds %CXXExceptionRegistration, %CXXExceptionRegistration* %1, i32 0, i32 2 store i32 0, i32* %10, align 4 invoke x86_thiscallcc void @"?f@X@@QAEXXZ"() to label %11 unwind label %16 11: ; preds = %0 %12 = getelementptr inbounds %CXXExceptionRegistration, %CXXExceptionRegistration* %1, i32 0, i32 2 store i32 -1, i32* %12, align 4 musttail call void @"?g@@YAXXZ"() %13 = getelementptr inbounds %CXXExceptionRegistration, %CXXExceptionRegistration* %1, i32 0, i32 1 %14 = getelementptr inbounds %EHRegistrationNode, %EHRegistrationNode* %13, i32 0, i32 0 %15 = load %EHRegistrationNode*, %EHRegistrationNode** %14, align 4 store %EHRegistrationNode* %15, %EHRegistrationNode* addrspace(257)* null, align 4 ret void 16: ; preds = %0 %17 = cleanuppad within none [] cleanupret from %17 unwind to caller } ```
llvmbot commented 2 years ago

@llvm/issue-subscribers-backend-x86

Chilledheart commented 2 years ago

BTW It doesn't compile with mips/mipsel/mips64el backend as well.