зеркало из https://github.com/microsoft/clang-1.git
[Windows] Use thiscall as the default calling convention for class methods. PR12785
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@160121 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
9a50249cd3
Коммит
8f88a1dcc5
|
@ -1501,15 +1501,11 @@ public:
|
|||
|
||||
/// \brief Retrieves the default calling convention to use for
|
||||
/// C++ instance methods.
|
||||
CallingConv getDefaultMethodCallConv();
|
||||
CallingConv getDefaultCXXMethodCallConv(bool isVariadic);
|
||||
|
||||
/// \brief Retrieves the canonical representation of the given
|
||||
/// calling convention.
|
||||
CallingConv getCanonicalCallConv(CallingConv CC) const {
|
||||
if (!LangOpts.MRTD && CC == CC_C)
|
||||
return CC_Default;
|
||||
return CC;
|
||||
}
|
||||
CallingConv getCanonicalCallConv(CallingConv CC) const;
|
||||
|
||||
/// \brief Determines whether two calling conventions name the same
|
||||
/// calling convention.
|
||||
|
|
|
@ -7098,9 +7098,15 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
|
|||
return true;
|
||||
}
|
||||
|
||||
CallingConv ASTContext::getDefaultMethodCallConv() {
|
||||
CallingConv ASTContext::getDefaultCXXMethodCallConv(bool isVariadic) {
|
||||
// Pass through to the C++ ABI object
|
||||
return ABI->getDefaultMethodCallConv();
|
||||
return ABI->getDefaultMethodCallConv(isVariadic);
|
||||
}
|
||||
|
||||
CallingConv ASTContext::getCanonicalCallConv(CallingConv CC) const {
|
||||
if (CC == CC_C && !LangOpts.MRTD && getTargetInfo().getCXXABI() != CXXABI_Microsoft)
|
||||
return CC_Default;
|
||||
return CC;
|
||||
}
|
||||
|
||||
bool ASTContext::isNearlyEmpty(const CXXRecordDecl *RD) const {
|
||||
|
|
|
@ -32,7 +32,7 @@ public:
|
|||
virtual unsigned getMemberPointerSize(const MemberPointerType *MPT) const = 0;
|
||||
|
||||
/// Returns the default calling convention for C++ methods.
|
||||
virtual CallingConv getDefaultMethodCallConv() const = 0;
|
||||
virtual CallingConv getDefaultMethodCallConv(bool isVariadic) const = 0;
|
||||
|
||||
// Returns whether the given class is nearly empty, with just virtual pointers
|
||||
// and no data except possibly virtual bases.
|
||||
|
|
|
@ -39,7 +39,7 @@ public:
|
|||
return 1;
|
||||
}
|
||||
|
||||
CallingConv getDefaultMethodCallConv() const {
|
||||
CallingConv getDefaultMethodCallConv(bool isVariadic) const {
|
||||
return CC_C;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,8 +29,8 @@ public:
|
|||
|
||||
unsigned getMemberPointerSize(const MemberPointerType *MPT) const;
|
||||
|
||||
CallingConv getDefaultMethodCallConv() const {
|
||||
if (Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86)
|
||||
CallingConv getDefaultMethodCallConv(bool isVariadic) const {
|
||||
if (!isVariadic && Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86)
|
||||
return CC_X86ThisCall;
|
||||
else
|
||||
return CC_C;
|
||||
|
|
|
@ -1159,8 +1159,16 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T,
|
|||
// that they could be in a DLL and somebody from another module could call
|
||||
// them.)
|
||||
CallingConv CC = T->getCallConv();
|
||||
if (CC == CC_Default)
|
||||
CC = IsInstMethod ? getASTContext().getDefaultMethodCallConv() : CC_C;
|
||||
if (CC == CC_Default) {
|
||||
if (IsInstMethod) {
|
||||
const FunctionProtoType *FPT =
|
||||
T->getCanonicalTypeUnqualified().getAs<FunctionProtoType>();
|
||||
bool isVariadic = FPT->isVariadic();
|
||||
CC = getASTContext().getDefaultCXXMethodCallConv(isVariadic);
|
||||
} else {
|
||||
CC = CC_C;
|
||||
}
|
||||
}
|
||||
switch (CC) {
|
||||
default:
|
||||
llvm_unreachable("Unsupported CC for mangling");
|
||||
|
|
|
@ -105,8 +105,12 @@ static const CGFunctionInfo &arrangeFreeFunctionType(CodeGenTypes &CGT,
|
|||
/// Given the formal ext-info of a C++ instance method, adjust it
|
||||
/// according to the C++ ABI in effect.
|
||||
static void adjustCXXMethodInfo(CodeGenTypes &CGT,
|
||||
FunctionType::ExtInfo &extInfo) {
|
||||
// FIXME: thiscall on Microsoft
|
||||
FunctionType::ExtInfo &extInfo,
|
||||
bool isVariadic) {
|
||||
if (extInfo.getCC() == CC_Default) {
|
||||
CallingConv CC = CGT.getContext().getDefaultCXXMethodCallConv(isVariadic);
|
||||
extInfo = extInfo.withCallingConv(CC);
|
||||
}
|
||||
}
|
||||
|
||||
/// Arrange the argument and result information for a free function (i.e.
|
||||
|
@ -115,7 +119,7 @@ static const CGFunctionInfo &arrangeCXXMethodType(CodeGenTypes &CGT,
|
|||
SmallVectorImpl<CanQualType> &prefix,
|
||||
CanQual<FunctionProtoType> FTP) {
|
||||
FunctionType::ExtInfo extInfo = FTP->getExtInfo();
|
||||
adjustCXXMethodInfo(CGT, extInfo);
|
||||
adjustCXXMethodInfo(CGT, extInfo, FTP->isVariadic());
|
||||
return arrangeLLVMFunctionInfo(CGT, prefix, FTP, extInfo);
|
||||
}
|
||||
|
||||
|
@ -202,7 +206,7 @@ CodeGenTypes::arrangeCXXConstructorDeclaration(const CXXConstructorDecl *D,
|
|||
argTypes.push_back(FTP->getArgType(i));
|
||||
|
||||
FunctionType::ExtInfo extInfo = FTP->getExtInfo();
|
||||
adjustCXXMethodInfo(*this, extInfo);
|
||||
adjustCXXMethodInfo(*this, extInfo, FTP->isVariadic());
|
||||
return arrangeLLVMFunctionInfo(resultType, argTypes, extInfo, required);
|
||||
}
|
||||
|
||||
|
@ -220,9 +224,10 @@ CodeGenTypes::arrangeCXXDestructor(const CXXDestructorDecl *D,
|
|||
|
||||
CanQual<FunctionProtoType> FTP = GetFormalType(D);
|
||||
assert(FTP->getNumArgs() == 0 && "dtor with formal parameters");
|
||||
assert(FTP->isVariadic() == 0 && "dtor with formal parameters");
|
||||
|
||||
FunctionType::ExtInfo extInfo = FTP->getExtInfo();
|
||||
adjustCXXMethodInfo(*this, extInfo);
|
||||
adjustCXXMethodInfo(*this, extInfo, false);
|
||||
return arrangeLLVMFunctionInfo(resultType, argTypes, extInfo,
|
||||
RequiredArgs::All);
|
||||
}
|
||||
|
@ -354,7 +359,7 @@ CodeGenTypes::arrangeCXXMethodCall(const CallArgList &args,
|
|||
argTypes.push_back(Context.getCanonicalParamType(i->Ty));
|
||||
|
||||
FunctionType::ExtInfo info = FPT->getExtInfo();
|
||||
adjustCXXMethodInfo(*this, info);
|
||||
adjustCXXMethodInfo(*this, info, FPT->isVariadic());
|
||||
return arrangeLLVMFunctionInfo(GetReturnType(FPT->getResultType()),
|
||||
argTypes, info, required);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
|
||||
|
||||
class C {
|
||||
public:
|
||||
void simple_method() {}
|
||||
|
||||
void __cdecl cdecl_method() {}
|
||||
|
||||
void vararg_method(const char *fmt, ...) {}
|
||||
|
||||
static void static_method() {}
|
||||
|
||||
int a;
|
||||
};
|
||||
|
||||
void call_simple_method() {
|
||||
C instance;
|
||||
|
||||
instance.simple_method();
|
||||
// Make sure that the call uses the right calling convention:
|
||||
// CHECK: call x86_thiscallcc void @"\01?simple_method@C@@QAEXXZ"
|
||||
// CHECK: ret
|
||||
|
||||
// Make sure that the definition uses the right calling convention:
|
||||
// CHECK: define linkonce_odr x86_thiscallcc void @"\01?simple_method@C@@QAEXXZ"
|
||||
// CHECK: ret
|
||||
}
|
||||
|
||||
void call_cdecl_method() {
|
||||
C instance;
|
||||
instance.cdecl_method();
|
||||
// Make sure that the call uses the right calling convention:
|
||||
// CHECK: call void @"\01?cdecl_method@C@@QAAXXZ"
|
||||
// CHECK: ret
|
||||
|
||||
// Make sure that the definition uses the right calling convention:
|
||||
// CHECK: define linkonce_odr void @"\01?cdecl_method@C@@QAAXXZ"
|
||||
// CHECK: ret
|
||||
}
|
||||
|
||||
void call_vararg_method() {
|
||||
C instance;
|
||||
instance.vararg_method("Hello");
|
||||
// Make sure that the call uses the right calling convention:
|
||||
// CHECK: call void (%class.C*, i8*, ...)* @"\01?vararg_method@C@@QAAXPBDZZ"
|
||||
// CHECK: ret
|
||||
|
||||
// Make sure that the definition uses the right calling convention:
|
||||
// CHECK: define linkonce_odr void @"\01?vararg_method@C@@QAAXPBDZZ"
|
||||
}
|
||||
|
||||
void call_static_method() {
|
||||
C::static_method();
|
||||
// Make sure that the call uses the right calling convention:
|
||||
// CHECK: call void @"\01?static_method@C@@SAXXZ"
|
||||
// CHECK: ret
|
||||
|
||||
// Make sure that the definition uses the right calling convention:
|
||||
// CHECK: define linkonce_odr void @"\01?static_method@C@@SAXXZ"
|
||||
}
|
||||
|
||||
class Base {
|
||||
public:
|
||||
Base() {}
|
||||
~Base() {}
|
||||
};
|
||||
|
||||
class Child: public Base { };
|
||||
|
||||
void constructors() {
|
||||
Child c;
|
||||
// Make sure that the Base constructor call in the Child constructor uses
|
||||
// the right calling convention:
|
||||
// CHECK: define linkonce_odr x86_thiscallcc void @"\01??0Child@@QAE@XZ"
|
||||
// CHECK: call x86_thiscallcc void @"\01??0Base@@QAE@XZ"
|
||||
// CHECK: ret
|
||||
|
||||
// Make sure that the Base destructor call in the Child denstructor uses
|
||||
// the right calling convention:
|
||||
// CHECK: define linkonce_odr x86_thiscallcc void @"\01??1Child@@QAE@XZ"
|
||||
// CHECK: call x86_thiscallcc void @"\01??1Base@@QAE@XZ"
|
||||
// CHECK: ret
|
||||
|
||||
// Make sure that the Base destructor definition uses the right CC:
|
||||
// CHECK: define linkonce_odr x86_thiscallcc void @"\01??1Base@@QAE@XZ"
|
||||
|
||||
// Make sure that the Base constructor definition uses the right CC:
|
||||
// CHECK: define linkonce_odr x86_thiscallcc void @"\01??0Base@@QAE@XZ"
|
||||
}
|
|
@ -6,12 +6,12 @@ struct S {
|
|||
} s;
|
||||
|
||||
// CHECK: define internal void [[INIT_s:@.*global_var.*]] nounwind
|
||||
// CHECK: call void @"\01??0S@@QAE@XZ"
|
||||
// CHECK: call x86_thiscallcc void @"\01??0S@@QAE@XZ"
|
||||
// CHECK: call i32 @atexit(void ()* @"__dtor_\01?s@@3US@@A")
|
||||
// CHECK: ret void
|
||||
|
||||
// CHECK: define internal void @"__dtor_\01?s@@3US@@A"() nounwind {
|
||||
// CHECK: call void @"\01??1S@@QAE@XZ"
|
||||
// CHECK: call x86_thiscallcc void @"\01??1S@@QAE@XZ"
|
||||
// CHECK: ret void
|
||||
|
||||
// Force WeakODRLinkage by using templates
|
||||
|
@ -34,16 +34,16 @@ void force_usage() {
|
|||
}
|
||||
|
||||
// CHECK: define internal void [[INIT_foo:@.*global_var.*]] nounwind
|
||||
// CHECK: call void @"\01??0A@@QAE@XZ"
|
||||
// CHECK: call x86_thiscallcc void @"\01??0A@@QAE@XZ"
|
||||
// CHECK: call i32 @atexit(void ()* [[FOO_DTOR:@"__dtor_.*foo@.*]])
|
||||
// CHECK: ret void
|
||||
|
||||
// CHECK: define linkonce_odr void @"\01??0A@@QAE@XZ"
|
||||
// CHECK: define linkonce_odr x86_thiscallcc void @"\01??0A@@QAE@XZ"
|
||||
|
||||
// CHECK: define linkonce_odr void @"\01??1A@@QAE@XZ"
|
||||
// CHECK: define linkonce_odr x86_thiscallcc void @"\01??1A@@QAE@XZ"
|
||||
|
||||
// CHECK: define internal void [[FOO_DTOR]]
|
||||
// CHECK: call void @"\01??1A@@QAE@XZ"{{.*}}foo
|
||||
// CHECK: call x86_thiscallcc void @"\01??1A@@QAE@XZ"{{.*}}foo
|
||||
// CHECK: ret void
|
||||
|
||||
// CHECK: define internal void @_GLOBAL__I_a() nounwind {
|
||||
|
|
Загрузка…
Ссылка в новой задаче