Index: include/clang/Basic/TargetCXXABI.h =================================================================== --- include/clang/Basic/TargetCXXABI.h +++ include/clang/Basic/TargetCXXABI.h @@ -111,7 +111,11 @@ /// FIXME: should this be split into Win32 and Win64 variants? /// /// Only scattered and incomplete official documentation exists. - Microsoft + Microsoft, + + /// The PS4 ABI is basically GenericItaniumABI, as it was implemented + /// in LLVM 3.2. + PS4 }; private: @@ -143,6 +147,7 @@ case WatchOS: case GenericMIPS: case WebAssembly: + case PS4: return true; case Microsoft: @@ -162,6 +167,7 @@ case WatchOS: case GenericMIPS: case WebAssembly: + case PS4: return false; case Microsoft: @@ -195,6 +201,7 @@ case iOS64: case WatchOS: case Microsoft: + case PS4: return true; } llvm_unreachable("bad ABI kind"); @@ -277,6 +284,7 @@ case iOS: // old iOS compilers did not follow this rule case Microsoft: case GenericMIPS: + case PS4: return true; } llvm_unreachable("bad ABI kind"); @@ -323,6 +331,7 @@ case GenericARM: case iOS: case GenericMIPS: + case PS4: return UseTailPaddingUnlessPOD03; // iOS on ARM64 and WebAssembly use the C++11 POD rules. They do not honor Index: lib/AST/ASTContext.cpp =================================================================== --- lib/AST/ASTContext.cpp +++ lib/AST/ASTContext.cpp @@ -686,6 +686,7 @@ case TargetCXXABI::GenericAArch64: case TargetCXXABI::GenericMIPS: case TargetCXXABI::GenericItanium: + case TargetCXXABI::PS4: case TargetCXXABI::WebAssembly: return CreateItaniumCXXABI(*this); case TargetCXXABI::Microsoft: @@ -8573,6 +8574,7 @@ case TargetCXXABI::GenericMIPS: case TargetCXXABI::iOS: case TargetCXXABI::iOS64: + case TargetCXXABI::PS4: case TargetCXXABI::WebAssembly: case TargetCXXABI::WatchOS: return ItaniumMangleContext::create(*this, getDiagnostics()); Index: lib/AST/RecordLayoutBuilder.cpp =================================================================== --- lib/AST/RecordLayoutBuilder.cpp +++ lib/AST/RecordLayoutBuilder.cpp @@ -1595,12 +1595,15 @@ // #pragma pack, with any value, suppresses the insertion of padding. bool AllowPadding = MaxFieldAlignment.isZero(); + // PS4 remains compatible to pre r257462 behavior. + bool isPS4ABI = (Context.getTargetInfo().getCXXABI().getKind() == TargetCXXABI::PS4); + // Compute the real offset. if (FieldSize == 0 || (AllowPadding && (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize)) { FieldOffset = llvm::alignTo(FieldOffset, FieldAlign); - } else if (ExplicitFieldAlign) { + } else if (ExplicitFieldAlign && !isPS4ABI) { // TODO: figure it out what needs to be done on targets that don't honor // bit-field type alignment like ARM APCS ABI. FieldOffset = llvm::alignTo(FieldOffset, ExplicitFieldAlign); @@ -1612,7 +1615,7 @@ (UnpackedFieldOffset & (UnpackedFieldAlign-1)) + FieldSize > TypeSize)) UnpackedFieldOffset = llvm::alignTo(UnpackedFieldOffset, UnpackedFieldAlign); - else if (ExplicitFieldAlign) + else if (ExplicitFieldAlign && !isPS4ABI) UnpackedFieldOffset = llvm::alignTo(UnpackedFieldOffset, ExplicitFieldAlign); } Index: lib/Basic/Targets.cpp =================================================================== --- lib/Basic/Targets.cpp +++ lib/Basic/Targets.cpp @@ -602,6 +602,9 @@ PS4OSTargetInfo(const llvm::Triple &Triple) : OSTargetInfo(Triple) { this->WCharType = this->UnsignedShort; + // PS4 uses a variant of the C++11 ABI. + this->TheCXXABI.set(TargetCXXABI::PS4); + // On PS4, TLS variable cannot be aligned to more than 32 bytes (256 bits). this->MaxTLSAlign = 256; this->UserLabelPrefix = ""; Index: lib/CodeGen/CodeGenModule.cpp =================================================================== --- lib/CodeGen/CodeGenModule.cpp +++ lib/CodeGen/CodeGenModule.cpp @@ -69,6 +69,7 @@ case TargetCXXABI::WatchOS: case TargetCXXABI::GenericMIPS: case TargetCXXABI::GenericItanium: + case TargetCXXABI::PS4: case TargetCXXABI::WebAssembly: return CreateItaniumCXXABI(CGM); case TargetCXXABI::Microsoft: Index: lib/CodeGen/ItaniumCXXABI.cpp =================================================================== --- lib/CodeGen/ItaniumCXXABI.cpp +++ lib/CodeGen/ItaniumCXXABI.cpp @@ -480,6 +480,7 @@ return new WebAssemblyCXXABI(CGM); case TargetCXXABI::GenericItanium: + case TargetCXXABI::PS4: if (CGM.getContext().getTargetInfo().getTriple().getArch() == llvm::Triple::le32) { // For PNaCl, use ARM-style method pointers so that PNaCl code Index: test/Sema/bitfield-layout.c =================================================================== --- test/Sema/bitfield-layout.c +++ test/Sema/bitfield-layout.c @@ -2,6 +2,7 @@ // RUN: %clang_cc1 %s -fsyntax-only -verify -triple=arm-linux-gnueabihf // RUN: %clang_cc1 %s -fsyntax-only -verify -triple=aarch64-linux-gnu // RUN: %clang_cc1 %s -fsyntax-only -verify -triple=x86_64-pc-linux-gnu +// RUN: %clang_cc1 %s -fsyntax-only -verify -triple=x86_64-scei-ps4 // expected-no-diagnostics #include @@ -96,9 +97,15 @@ char c; }; +#if defined(__PS4__) +CHECK_SIZE(struct, g0, 16); +CHECK_ALIGN(struct, g0, 16); +CHECK_OFFSET(struct, g0, c, 2); +#else CHECK_SIZE(struct, g0, 32); CHECK_ALIGN(struct, g0, 16); CHECK_OFFSET(struct, g0, c, 17); +#endif // Bit-field with explicit align smaller than normal. struct g1 { @@ -109,7 +116,11 @@ CHECK_SIZE(struct, g1, 4); CHECK_ALIGN(struct, g1, 4); +#if defined(__PS4__) +CHECK_OFFSET(struct, g1, c, 2); +#else CHECK_OFFSET(struct, g1, c, 3); +#endif // Same as above but without explicit align. struct g2 { @@ -130,9 +141,14 @@ char c; }; -CHECK_SIZE(struct, g3, 32); CHECK_ALIGN(struct, g3, 16); +#if defined(__PS4__) +CHECK_SIZE(struct, g3, 16); +CHECK_OFFSET(struct, g3, c, 2); +#else +CHECK_SIZE(struct, g3, 32); CHECK_OFFSET(struct, g3, c, 17); +#endif struct __attribute__((packed)) g4 { char a; @@ -142,7 +158,11 @@ CHECK_SIZE(struct, g4, 4); CHECK_ALIGN(struct, g4, 2); +#if defined(__PS4__) +CHECK_OFFSET(struct, g4, c, 2); +#else CHECK_OFFSET(struct, g4, c, 3); +#endif struct g5 { char : 1; @@ -162,28 +182,44 @@ char : 1; __attribute__((aligned(1))) int n : 25; }; +#if defined(__PS4__) +CHECK_SIZE(struct, g7, 4); +#else CHECK_SIZE(struct, g7, 8); +#endif CHECK_ALIGN(struct, g7, 4); struct __attribute__((packed)) g8 { char : 1; __attribute__((aligned(1))) int n : 25; }; +#if defined(__PS4__) +CHECK_SIZE(struct, g8, 4); +#else CHECK_SIZE(struct, g8, 5); +#endif CHECK_ALIGN(struct, g8, 1); struct g9 { __attribute__((aligned(1))) char a : 2, b : 2, c : 2, d : 2, e : 2; int i; }; +#if defined(__PS4__) +CHECK_SIZE(struct, g9, 8); +#else CHECK_SIZE(struct, g9, 12); +#endif CHECK_ALIGN(struct, g9, 4); struct __attribute__((packed)) g10 { __attribute__((aligned(1))) char a : 2, b : 2, c : 2, d : 2, e : 2; int i; }; +#if defined(__PS4__) +CHECK_SIZE(struct, g10, 6); +#else CHECK_SIZE(struct, g10, 9); +#endif CHECK_ALIGN(struct, g10, 1); struct g11 {