mirror of https://github.com/microsoft/clang.git
Add default calling convention support for regcall.
Added support for regcall as default calling convention. Also added code to exclude main when applying default calling conventions. Patch-By: eandrews Differential Revision: https://reviews.llvm.org/D39210 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317268 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
603490dae3
commit
05b45eab31
|
@ -77,7 +77,8 @@ public:
|
|||
DCC_CDecl,
|
||||
DCC_FastCall,
|
||||
DCC_StdCall,
|
||||
DCC_VectorCall
|
||||
DCC_VectorCall,
|
||||
DCC_RegCall
|
||||
};
|
||||
|
||||
enum AddrSpaceMapMangling { ASMM_Target, ASMM_On, ASMM_Off };
|
||||
|
|
|
@ -704,7 +704,7 @@ def fnative_half_arguments_and_returns : Flag<["-"], "fnative-half-arguments-and
|
|||
def fallow_half_arguments_and_returns : Flag<["-"], "fallow-half-arguments-and-returns">,
|
||||
HelpText<"Allow function arguments and returns of type half">;
|
||||
def fdefault_calling_conv_EQ : Joined<["-"], "fdefault-calling-conv=">,
|
||||
HelpText<"Set default MS calling convention">, Values<"cdecl,fastcall,stdcall,vectorcall">;
|
||||
HelpText<"Set default calling convention">, Values<"cdecl,fastcall,stdcall,vectorcall,regcall">;
|
||||
def finclude_default_header : Flag<["-"], "finclude-default-header">,
|
||||
HelpText<"Include the default header file for OpenCL">;
|
||||
def fpreserve_vec3_type : Flag<["-"], "fpreserve-vec3-type">,
|
||||
|
|
|
@ -302,6 +302,8 @@ def _SLASH_Gz : CLFlag<"Gz">,
|
|||
HelpText<"Set __stdcall as a default calling convention">;
|
||||
def _SLASH_Gv : CLFlag<"Gv">,
|
||||
HelpText<"Set __vectorcall as a default calling convention">;
|
||||
def _SLASH_Gregcall : CLFlag<"Gregcall">,
|
||||
HelpText<"Set __regcall as a default calling convention">;
|
||||
|
||||
// Ignored:
|
||||
|
||||
|
|
|
@ -9281,6 +9281,11 @@ CallingConv ASTContext::getDefaultCallingConvention(bool IsVariadic,
|
|||
if (!IsVariadic)
|
||||
return CC_X86VectorCall;
|
||||
break;
|
||||
case LangOptions::DCC_RegCall:
|
||||
// __regcall cannot be applied to variadic functions.
|
||||
if (!IsVariadic)
|
||||
return CC_X86RegCall;
|
||||
break;
|
||||
}
|
||||
return Target->getDefaultCallingConv(TargetInfo::CCMT_Unknown);
|
||||
}
|
||||
|
|
|
@ -4972,7 +4972,8 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
|
|||
// Parse the default calling convention options.
|
||||
if (Arg *CCArg =
|
||||
Args.getLastArg(options::OPT__SLASH_Gd, options::OPT__SLASH_Gr,
|
||||
options::OPT__SLASH_Gz, options::OPT__SLASH_Gv)) {
|
||||
options::OPT__SLASH_Gz, options::OPT__SLASH_Gv,
|
||||
options::OPT__SLASH_Gregcall)) {
|
||||
unsigned DCCOptId = CCArg->getOption().getID();
|
||||
const char *DCCFlag = nullptr;
|
||||
bool ArchSupported = true;
|
||||
|
@ -4993,6 +4994,10 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
|
|||
ArchSupported = Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64;
|
||||
DCCFlag = "-fdefault-calling-conv=vectorcall";
|
||||
break;
|
||||
case options::OPT__SLASH_Gregcall:
|
||||
ArchSupported = Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64;
|
||||
DCCFlag = "-fdefault-calling-conv=regcall";
|
||||
break;
|
||||
}
|
||||
|
||||
// MSVC doesn't warn if /Gr or /Gz is used on x64, so we don't either.
|
||||
|
|
|
@ -2310,12 +2310,12 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
|
|||
// Check for MS default calling conventions being specified.
|
||||
if (Arg *A = Args.getLastArg(OPT_fdefault_calling_conv_EQ)) {
|
||||
LangOptions::DefaultCallingConvention DefaultCC =
|
||||
llvm::StringSwitch<LangOptions::DefaultCallingConvention>(
|
||||
A->getValue())
|
||||
llvm::StringSwitch<LangOptions::DefaultCallingConvention>(A->getValue())
|
||||
.Case("cdecl", LangOptions::DCC_CDecl)
|
||||
.Case("fastcall", LangOptions::DCC_FastCall)
|
||||
.Case("stdcall", LangOptions::DCC_StdCall)
|
||||
.Case("vectorcall", LangOptions::DCC_VectorCall)
|
||||
.Case("regcall", LangOptions::DCC_RegCall)
|
||||
.Default(LangOptions::DCC_None);
|
||||
if (DefaultCC == LangOptions::DCC_None)
|
||||
Diags.Report(diag::err_drv_invalid_value)
|
||||
|
@ -2326,7 +2326,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
|
|||
bool emitError = (DefaultCC == LangOptions::DCC_FastCall ||
|
||||
DefaultCC == LangOptions::DCC_StdCall) &&
|
||||
Arch != llvm::Triple::x86;
|
||||
emitError |= DefaultCC == LangOptions::DCC_VectorCall &&
|
||||
emitError |= (DefaultCC == LangOptions::DCC_VectorCall ||
|
||||
DefaultCC == LangOptions::DCC_RegCall) &&
|
||||
!(Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64);
|
||||
if (emitError)
|
||||
Diags.Report(diag::err_drv_argument_not_allowed_with)
|
||||
|
|
|
@ -9673,6 +9673,13 @@ void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) {
|
|||
assert(T->isFunctionType() && "function decl is not of function type");
|
||||
const FunctionType* FT = T->castAs<FunctionType>();
|
||||
|
||||
// Set default calling convention for main()
|
||||
if (FT->getCallConv() != CC_C) {
|
||||
FT = Context.adjustFunctionType(FT, FT->getExtInfo().withCallingConv(CC_C));
|
||||
FD->setType(QualType(FT, 0));
|
||||
T = Context.getCanonicalType(FD->getType());
|
||||
}
|
||||
|
||||
if (getLangOpts().GNUMode && !getLangOpts().CPlusPlus) {
|
||||
// In C with GNU extensions we allow main() to have non-integer return
|
||||
// type, but we should warn about the extension, and we disable the
|
||||
|
|
|
@ -3,18 +3,21 @@
|
|||
// RUN: %clang_cc1 -triple i486-unknown-linux-gnu -fdefault-calling-conv=stdcall -emit-llvm -o - %s | FileCheck %s --check-prefix=STDCALL --check-prefix=ALL
|
||||
// RUN: %clang_cc1 -triple i486-unknown-linux-gnu -mrtd -emit-llvm -o - %s | FileCheck %s --check-prefix=STDCALL --check-prefix=ALL
|
||||
// RUN: %clang_cc1 -triple i986-unknown-linux-gnu -fdefault-calling-conv=vectorcall -emit-llvm -o - %s | FileCheck %s --check-prefix=VECTORCALL --check-prefix=ALL
|
||||
// RUN: %clang_cc1 -triple i986-unknown-linux-gnu -fdefault-calling-conv=regcall -emit-llvm -o - %s | FileCheck %s --check-prefix=REGCALL --check-prefix=ALL
|
||||
|
||||
// CDECL: define void @_Z5test1v
|
||||
// FASTCALL: define x86_fastcallcc void @_Z5test1v
|
||||
// STDCALL: define x86_stdcallcc void @_Z5test1v
|
||||
// VECTORCALL: define x86_vectorcallcc void @_Z5test1v
|
||||
// REGCALL: define x86_regcallcc void @_Z17__regcall3__test1v
|
||||
void test1() {}
|
||||
|
||||
// fastcall, stdcall, and vectorcall all do not support variadic functions.
|
||||
// fastcall, stdcall, vectorcall and regcall do not support variadic functions.
|
||||
// CDECL: define void @_Z12testVariadicz
|
||||
// FASTCALL: define void @_Z12testVariadicz
|
||||
// STDCALL: define void @_Z12testVariadicz
|
||||
// VECTORCALL: define void @_Z12testVariadicz
|
||||
// REGCALL: define void @_Z12testVariadicz
|
||||
void testVariadic(...){}
|
||||
|
||||
// ALL: define void @_Z5test2v
|
||||
|
@ -29,6 +32,9 @@ void __attribute__((stdcall)) test4() {}
|
|||
// ALL: define x86_vectorcallcc void @_Z5test5v
|
||||
void __attribute__((vectorcall)) test5() {}
|
||||
|
||||
// ALL: define x86_regcallcc void @_Z17__regcall3__test6v
|
||||
void __attribute__((regcall)) test6() {}
|
||||
|
||||
// ALL: define linkonce_odr void @_ZN1A11test_memberEv
|
||||
class A {
|
||||
public:
|
||||
|
@ -39,3 +45,8 @@ void test() {
|
|||
A a;
|
||||
a.test_member();
|
||||
}
|
||||
|
||||
// ALL: define i32 @main
|
||||
int main() {
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,9 @@
|
|||
// RUN: %clang_cl --target=i686-windows-msvc /Gv -### -- %s 2>&1 | FileCheck --check-prefix=VECTORCALL %s
|
||||
// VECTORCALL: -fdefault-calling-conv=vectorcall
|
||||
|
||||
// RUN: %clang_cl --target=i686-windows-msvc /Gregcall -### -- %s 2>&1 | FileCheck --check-prefix=REGCALL %s
|
||||
// REGCALL: -fdefault-calling-conv=regcall
|
||||
|
||||
// Last one should win:
|
||||
|
||||
// RUN: %clang_cl --target=i686-windows-msvc /Gd /Gv -### -- %s 2>&1 | FileCheck --check-prefix=LASTWINS_VECTOR %s
|
||||
|
|
Loading…
Reference in New Issue