Skip to content

[MS ABI]: Support preserve_none in MS ABI #96487

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 51 additions & 19 deletions clang/lib/AST/MicrosoftMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -447,8 +447,8 @@ class MicrosoftCXXNameMangler {
void mangleDecayedArrayType(const ArrayType *T);
void mangleArrayType(const ArrayType *T);
void mangleFunctionClass(const FunctionDecl *FD);
void mangleCallingConvention(CallingConv CC);
void mangleCallingConvention(const FunctionType *T);
void mangleCallingConvention(CallingConv CC, SourceRange Range);
void mangleCallingConvention(const FunctionType *T, SourceRange Range);
void mangleIntegerLiteral(const llvm::APSInt &Number,
const NonTypeTemplateParmDecl *PD = nullptr,
QualType TemplateArgType = QualType());
Expand Down Expand Up @@ -888,7 +888,8 @@ void MicrosoftCXXNameMangler::mangleVirtualMemPtrThunk(
Out << "$B";
mangleNumber(OffsetInVFTable);
Out << 'A';
mangleCallingConvention(MD->getType()->castAs<FunctionProtoType>());
mangleCallingConvention(MD->getType()->castAs<FunctionProtoType>(),
MD->getSourceRange());
}

void MicrosoftCXXNameMangler::mangleName(GlobalDecl GD) {
Expand Down Expand Up @@ -2768,7 +2769,7 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
mangleQualifiers(Quals, /*IsMember=*/false);
}

mangleCallingConvention(CC);
mangleCallingConvention(CC, Range);

// <return-type> ::= <type>
// ::= @ # structors (they have no declared return type)
Expand Down Expand Up @@ -2949,7 +2950,8 @@ void MicrosoftCXXNameMangler::mangleFunctionClass(const FunctionDecl *FD) {
Out << 'Y';
}
}
void MicrosoftCXXNameMangler::mangleCallingConvention(CallingConv CC) {
void MicrosoftCXXNameMangler::mangleCallingConvention(CallingConv CC,
SourceRange Range) {
// <calling-convention> ::= A # __cdecl
// ::= B # __export __cdecl
// ::= C # __pascal
Expand All @@ -2962,7 +2964,10 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(CallingConv CC) {
// ::= J # __export __fastcall
// ::= Q # __vectorcall
// ::= S # __attribute__((__swiftcall__)) // Clang-only
// ::= T # __attribute__((__swiftasynccall__))
// ::= W # __attribute__((__swiftasynccall__))
// ::= U # __attribute__((__preserve_most__))
// ::= V # __attribute__((__preserve_none__)) //
// Clang-only
// // Clang-only
// ::= w # __regcall
// ::= x # __regcall4
Expand All @@ -2974,28 +2979,55 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(CallingConv CC) {

switch (CC) {
default:
llvm_unreachable("Unsupported CC for mangling");
break;
case CC_Win64:
case CC_X86_64SysV:
case CC_C: Out << 'A'; break;
case CC_X86Pascal: Out << 'C'; break;
case CC_X86ThisCall: Out << 'E'; break;
case CC_X86StdCall: Out << 'G'; break;
case CC_X86FastCall: Out << 'I'; break;
case CC_X86VectorCall: Out << 'Q'; break;
case CC_Swift: Out << 'S'; break;
case CC_SwiftAsync: Out << 'W'; break;
case CC_PreserveMost: Out << 'U'; break;
case CC_C:
Out << 'A';
return;
case CC_X86Pascal:
Out << 'C';
return;
case CC_X86ThisCall:
Out << 'E';
return;
case CC_X86StdCall:
Out << 'G';
return;
case CC_X86FastCall:
Out << 'I';
return;
case CC_X86VectorCall:
Out << 'Q';
return;
case CC_Swift:
Out << 'S';
return;
case CC_SwiftAsync:
Out << 'W';
return;
case CC_PreserveMost:
Out << 'U';
return;
case CC_PreserveNone:
Out << 'V';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not a good long term solution. I emailed the relevant external Microsoft mailing list for discussing these issues and CC'd some folks to inquire about a better long term solution, but we can continue with this approach for now.

return;
case CC_X86RegCall:
if (getASTContext().getLangOpts().RegCall4)
Out << "x";
else
Out << "w";
break;
return;
}

DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(
DiagnosticsEngine::Error, "cannot mangle this calling convention yet");
Diags.Report(Range.getBegin(), DiagID) << Range;
}
void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) {
mangleCallingConvention(T->getCallConv());
void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T,
SourceRange Range) {
mangleCallingConvention(T->getCallConv(), Range);
}

void MicrosoftCXXNameMangler::mangleThrowSpecification(
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Basic/Targets/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1536,6 +1536,7 @@ WindowsARM64TargetInfo::checkCallingConvention(CallingConv CC) const {
case CC_OpenCLKernel:
case CC_PreserveMost:
case CC_PreserveAll:
case CC_PreserveNone:
case CC_Swift:
case CC_SwiftAsync:
case CC_Win64:
Expand Down
28 changes: 28 additions & 0 deletions clang/test/CodeGenCXX/msabi-preserve-none-cc.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -fdeclspec -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -triple aarch64-unknown-windows-msvc -fdeclspec -emit-llvm %s -o - | FileCheck %s

void __attribute__((__preserve_none__)) f() {}
// CHECK-DAG: @"?f@@YVXXZ"

void (__attribute__((__preserve_none__)) *p)();
// CHECK-DAG: @"?p@@3P6VXXZEA

namespace {
void __attribute__((__preserve_none__)) __attribute__((__used__)) f() { }
}
// CHECK-DAG: @"?f@?A0x{{[^@]*}}@@YVXXZ"

namespace n {
void __attribute__((__preserve_none__)) f() {}
}
// CHECK-DAG: @"?f@n@@YVXXZ"

struct __declspec(dllexport) S {
S(const S &) = delete;
S & operator=(const S &) = delete;
void __attribute__((__preserve_none__)) m() { }
};
// CHECK-DAG: @"?m@S@@QEAVXXZ"

void f(void (__attribute__((__preserve_none__))())) {}
// CHECK-DAG: @"?f@@YAXP6VXXZ@Z"
1 change: 1 addition & 0 deletions clang/test/Sema/preserve-none-call-conv.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 %s -fsyntax-only -triple x86_64-unknown-unknown -verify
// RUN: %clang_cc1 %s -fsyntax-only -triple aarch64-unknown-unknown -verify

typedef void typedef_fun_t(int);

Expand Down
Loading