зеркало из https://github.com/microsoft/clang-1.git
Add some ABI tweaks for i386-pc-win32 triple so that we return structs in an MSVC-compatible way. Patch by Joe Groff.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148992 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
0f12507d43
Коммит
55fc7e2b80
|
@ -389,8 +389,8 @@ ABIArgInfo DefaultABIInfo::classifyReturnType(QualType RetTy) const {
|
||||||
ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
|
ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// UseX86_MMXType - Return true if this is an MMX type that should use the special
|
/// UseX86_MMXType - Return true if this is an MMX type that should use the
|
||||||
/// x86_mmx type.
|
/// special x86_mmx type.
|
||||||
bool UseX86_MMXType(llvm::Type *IRType) {
|
bool UseX86_MMXType(llvm::Type *IRType) {
|
||||||
// If the type is an MMX type <2 x i32>, <4 x i16>, or <8 x i8>, use the
|
// If the type is an MMX type <2 x i32>, <4 x i16>, or <8 x i8>, use the
|
||||||
// special x86_mmx type.
|
// special x86_mmx type.
|
||||||
|
@ -418,6 +418,7 @@ class X86_32ABIInfo : public ABIInfo {
|
||||||
bool IsDarwinVectorABI;
|
bool IsDarwinVectorABI;
|
||||||
bool IsSmallStructInRegABI;
|
bool IsSmallStructInRegABI;
|
||||||
bool IsMMXDisabled;
|
bool IsMMXDisabled;
|
||||||
|
bool IsWin32FloatStructABI;
|
||||||
|
|
||||||
static bool isRegisterSize(unsigned Size) {
|
static bool isRegisterSize(unsigned Size) {
|
||||||
return (Size == 8 || Size == 16 || Size == 32 || Size == 64);
|
return (Size == 8 || Size == 16 || Size == 32 || Size == 64);
|
||||||
|
@ -447,15 +448,16 @@ public:
|
||||||
virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
|
virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
|
||||||
CodeGenFunction &CGF) const;
|
CodeGenFunction &CGF) const;
|
||||||
|
|
||||||
X86_32ABIInfo(CodeGen::CodeGenTypes &CGT, bool d, bool p, bool m)
|
X86_32ABIInfo(CodeGen::CodeGenTypes &CGT, bool d, bool p, bool m, bool w)
|
||||||
: ABIInfo(CGT), IsDarwinVectorABI(d), IsSmallStructInRegABI(p),
|
: ABIInfo(CGT), IsDarwinVectorABI(d), IsSmallStructInRegABI(p),
|
||||||
IsMMXDisabled(m) {}
|
IsMMXDisabled(m), IsWin32FloatStructABI(w) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class X86_32TargetCodeGenInfo : public TargetCodeGenInfo {
|
class X86_32TargetCodeGenInfo : public TargetCodeGenInfo {
|
||||||
public:
|
public:
|
||||||
X86_32TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, bool d, bool p, bool m)
|
X86_32TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT,
|
||||||
:TargetCodeGenInfo(new X86_32ABIInfo(CGT, d, p, m)) {}
|
bool d, bool p, bool m, bool w)
|
||||||
|
:TargetCodeGenInfo(new X86_32ABIInfo(CGT, d, p, m, w)) {}
|
||||||
|
|
||||||
void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
|
void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
|
||||||
CodeGen::CodeGenModule &CGM) const;
|
CodeGen::CodeGenModule &CGM) const;
|
||||||
|
@ -586,10 +588,12 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy) const {
|
||||||
|
|
||||||
// As a special-case, if the struct is a "single-element" struct, and
|
// As a special-case, if the struct is a "single-element" struct, and
|
||||||
// the field is of type "float" or "double", return it in a
|
// the field is of type "float" or "double", return it in a
|
||||||
// floating-point register. We apply a similar transformation for
|
// floating-point register. (MSVC does not apply this special case.)
|
||||||
// pointer types to improve the quality of the generated IR.
|
// We apply a similar transformation for pointer types to improve the
|
||||||
|
// quality of the generated IR.
|
||||||
if (const Type *SeltTy = isSingleElementStruct(RetTy, getContext()))
|
if (const Type *SeltTy = isSingleElementStruct(RetTy, getContext()))
|
||||||
if (SeltTy->isRealFloatingType() || SeltTy->hasPointerRepresentation())
|
if ((!IsWin32FloatStructABI && SeltTy->isRealFloatingType())
|
||||||
|
|| SeltTy->hasPointerRepresentation())
|
||||||
return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0)));
|
return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0)));
|
||||||
|
|
||||||
// FIXME: We should be able to narrow this integer in cases with dead
|
// FIXME: We should be able to narrow this integer in cases with dead
|
||||||
|
@ -2238,7 +2242,8 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty) const {
|
||||||
|
|
||||||
// FIXME: mingw-w64-gcc emits 128-bit struct as i128
|
// FIXME: mingw-w64-gcc emits 128-bit struct as i128
|
||||||
if (Size == 128 &&
|
if (Size == 128 &&
|
||||||
getContext().getTargetInfo().getTriple().getOS() == llvm::Triple::MinGW32)
|
getContext().getTargetInfo().getTriple().getOS()
|
||||||
|
== llvm::Triple::MinGW32)
|
||||||
return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(),
|
return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(),
|
||||||
Size));
|
Size));
|
||||||
|
|
||||||
|
@ -2373,7 +2378,8 @@ public:
|
||||||
ARMABIInfo(CodeGenTypes &CGT, ABIKind _Kind) : ABIInfo(CGT), Kind(_Kind) {}
|
ARMABIInfo(CodeGenTypes &CGT, ABIKind _Kind) : ABIInfo(CGT), Kind(_Kind) {}
|
||||||
|
|
||||||
bool isEABI() const {
|
bool isEABI() const {
|
||||||
StringRef Env = getContext().getTargetInfo().getTriple().getEnvironmentName();
|
StringRef Env =
|
||||||
|
getContext().getTargetInfo().getTriple().getEnvironmentName();
|
||||||
return (Env == "gnueabi" || Env == "eabi" || Env == "androideabi");
|
return (Env == "gnueabi" || Env == "eabi" || Env == "androideabi");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3591,7 +3597,8 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
|
||||||
|
|
||||||
if (Triple.isOSDarwin())
|
if (Triple.isOSDarwin())
|
||||||
return *(TheTargetCodeGenInfo =
|
return *(TheTargetCodeGenInfo =
|
||||||
new X86_32TargetCodeGenInfo(Types, true, true, DisableMMX));
|
new X86_32TargetCodeGenInfo(
|
||||||
|
Types, true, true, DisableMMX, false));
|
||||||
|
|
||||||
switch (Triple.getOS()) {
|
switch (Triple.getOS()) {
|
||||||
case llvm::Triple::Cygwin:
|
case llvm::Triple::Cygwin:
|
||||||
|
@ -3601,11 +3608,18 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
|
||||||
case llvm::Triple::FreeBSD:
|
case llvm::Triple::FreeBSD:
|
||||||
case llvm::Triple::OpenBSD:
|
case llvm::Triple::OpenBSD:
|
||||||
return *(TheTargetCodeGenInfo =
|
return *(TheTargetCodeGenInfo =
|
||||||
new X86_32TargetCodeGenInfo(Types, false, true, DisableMMX));
|
new X86_32TargetCodeGenInfo(
|
||||||
|
Types, false, true, DisableMMX, false));
|
||||||
|
|
||||||
|
case llvm::Triple::Win32:
|
||||||
|
return *(TheTargetCodeGenInfo =
|
||||||
|
new X86_32TargetCodeGenInfo(
|
||||||
|
Types, false, true, DisableMMX, true));
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return *(TheTargetCodeGenInfo =
|
return *(TheTargetCodeGenInfo =
|
||||||
new X86_32TargetCodeGenInfo(Types, false, false, DisableMMX));
|
new X86_32TargetCodeGenInfo(
|
||||||
|
Types, false, false, DisableMMX, false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
// RUN: %clang_cc1 -w -triple i386-pc-win32 -emit-llvm -o - %s | FileCheck %s
|
||||||
|
|
||||||
|
// CHECK: define i64 @f1_1()
|
||||||
|
// CHECK: define void @f1_2(i32 %a0.0, i32 %a0.1)
|
||||||
|
struct s1 {
|
||||||
|
int a;
|
||||||
|
int b;
|
||||||
|
};
|
||||||
|
struct s1 f1_1(void) { while (1) {} }
|
||||||
|
void f1_2(struct s1 a0) {}
|
||||||
|
|
||||||
|
// CHECK: define i32 @f2_1()
|
||||||
|
struct s2 {
|
||||||
|
short a;
|
||||||
|
short b;
|
||||||
|
};
|
||||||
|
struct s2 f2_1(void) { while (1) {} }
|
||||||
|
|
||||||
|
// CHECK: define i16 @f3_1()
|
||||||
|
struct s3 {
|
||||||
|
char a;
|
||||||
|
char b;
|
||||||
|
};
|
||||||
|
struct s3 f3_1(void) { while (1) {} }
|
||||||
|
|
||||||
|
// CHECK: define i8 @f4_1()
|
||||||
|
struct s4 {
|
||||||
|
char a:4;
|
||||||
|
char b:4;
|
||||||
|
};
|
||||||
|
struct s4 f4_1(void) { while (1) {} }
|
||||||
|
|
||||||
|
// CHECK: define i64 @f5_1()
|
||||||
|
// CHECK: define void @f5_2(double %a0.0)
|
||||||
|
struct s5 {
|
||||||
|
double a;
|
||||||
|
};
|
||||||
|
struct s5 f5_1(void) { while (1) {} }
|
||||||
|
void f5_2(struct s5 a0) {}
|
||||||
|
|
||||||
|
// CHECK: define i32 @f6_1()
|
||||||
|
// CHECK: define void @f6_2(float %a0.0)
|
||||||
|
struct s6 {
|
||||||
|
float a;
|
||||||
|
};
|
||||||
|
struct s6 f6_1(void) { while (1) {} }
|
||||||
|
void f6_2(struct s6 a0) {}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче