Index: clang/lib/Basic/Targets.cpp =================================================================== --- clang/lib/Basic/Targets.cpp +++ clang/lib/Basic/Targets.cpp @@ -135,6 +135,11 @@ case llvm::Triple::lanai: return new LanaiTargetInfo(Triple, Opts); + case llvm::Triple::aarch64_32: + if (Triple.isOSDarwin()) + return new DarwinAArch64TargetInfo(Triple, Opts); + + return nullptr; case llvm::Triple::aarch64: if (Triple.isOSDarwin()) return new DarwinAArch64TargetInfo(Triple, Opts); Index: clang/lib/Basic/Targets/AArch64.h =================================================================== --- clang/lib/Basic/Targets/AArch64.h +++ clang/lib/Basic/Targets/AArch64.h @@ -89,6 +89,8 @@ } int getEHDataRegisterNumber(unsigned RegNo) const override; + + bool hasInt128Type() const override; }; class LLVM_LIBRARY_VISIBILITY AArch64leTargetInfo : public AArch64TargetInfo { Index: clang/lib/Basic/Targets/AArch64.cpp =================================================================== --- clang/lib/Basic/Targets/AArch64.cpp +++ clang/lib/Basic/Targets/AArch64.cpp @@ -51,7 +51,11 @@ HasLegalHalfType = true; HasFloat16 = true; - LongWidth = LongAlign = PointerWidth = PointerAlign = 64; + if (Triple.isArch64Bit()) + LongWidth = LongAlign = PointerWidth = PointerAlign = 64; + else + LongWidth = LongAlign = PointerWidth = PointerAlign = 32; + MaxVectorAlign = 128; MaxAtomicInlineWidth = 128; MaxAtomicPromoteWidth = 128; @@ -128,7 +132,7 @@ Builder.defineMacro("__ELF__"); // Target properties. - if (!getTriple().isOSWindows()) { + if (!getTriple().isOSWindows() && getTriple().isArch64Bit()) { Builder.defineMacro("_LP64"); Builder.defineMacro("__LP64__"); } @@ -447,14 +451,19 @@ return -1; } +bool AArch64TargetInfo::hasInt128Type() const { return true; } + AArch64leTargetInfo::AArch64leTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) : AArch64TargetInfo(Triple, Opts) {} void AArch64leTargetInfo::setDataLayout() { - if (getTriple().isOSBinFormatMachO()) - resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128"); - else + if (getTriple().isOSBinFormatMachO()) { + if(getTriple().isArch32Bit()) + resetDataLayout("e-m:o-p:32:32-i64:64-i128:128-n32:64-S128"); + else + resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128"); + } else resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"); } @@ -578,19 +587,34 @@ const TargetOptions &Opts) : DarwinTargetInfo(Triple, Opts) { Int64Type = SignedLongLong; + if (getTriple().isArch32Bit()) + IntMaxType = SignedLongLong; + + WCharType = SignedInt; UseSignedCharForObjCBool = false; LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64; LongDoubleFormat = &llvm::APFloat::IEEEdouble(); - TheCXXABI.set(TargetCXXABI::iOS64); + UseZeroLengthBitfieldAlignment = false; + + if (getTriple().isArch32Bit()) { + UseBitFieldTypeAlignment = false; + ZeroLengthBitfieldBoundary = 32; + UseZeroLengthBitfieldAlignment = true; + TheCXXABI.set(TargetCXXABI::WatchOS); + } else + TheCXXABI.set(TargetCXXABI::iOS64); } void DarwinAArch64TargetInfo::getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, MacroBuilder &Builder) const { Builder.defineMacro("__AARCH64_SIMD__"); - Builder.defineMacro("__ARM64_ARCH_8__"); + if (Triple.isArch32Bit()) + Builder.defineMacro("__ARM64_ARCH_8_32__"); + else + Builder.defineMacro("__ARM64_ARCH_8__"); Builder.defineMacro("__ARM_NEON__"); Builder.defineMacro("__LITTLE_ENDIAN__"); Builder.defineMacro("__REGISTER_PREFIX__", ""); Index: clang/lib/CodeGen/CGBuiltin.cpp =================================================================== --- clang/lib/CodeGen/CGBuiltin.cpp +++ clang/lib/CodeGen/CGBuiltin.cpp @@ -4183,6 +4183,7 @@ case llvm::Triple::thumbeb: return CGF->EmitARMBuiltinExpr(BuiltinID, E, Arch); case llvm::Triple::aarch64: + case llvm::Triple::aarch64_32: case llvm::Triple::aarch64_be: return CGF->EmitAArch64BuiltinExpr(BuiltinID, E, Arch); case llvm::Triple::x86: @@ -5612,7 +5613,8 @@ llvm::Type *PTy = llvm::PointerType::getUnqual(VTy->getVectorElementType()); // TODO: Currently in AArch32 mode the pointer operand comes first, whereas // in AArch64 it comes last. We may want to stick to one or another. - if (Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::aarch64_be) { + if (Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::aarch64_be || + Arch == llvm::Triple::aarch64_32) { llvm::Type *Tys[2] = { VTy, PTy }; std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end()); return EmitNeonCall(CGM.getIntrinsic(LLVMIntrinsic, Tys), Ops, ""); Index: clang/lib/CodeGen/TargetInfo.cpp =================================================================== --- clang/lib/CodeGen/TargetInfo.cpp +++ clang/lib/CodeGen/TargetInfo.cpp @@ -4938,7 +4938,7 @@ ABIKind getABIKind() const { return Kind; } bool isDarwinPCS() const { return Kind == DarwinPCS; } - ABIArgInfo classifyReturnType(QualType RetTy) const; + ABIArgInfo classifyReturnType(QualType RetTy, bool IsVariadic) const; ABIArgInfo classifyArgumentType(QualType RetTy) const; bool isHomogeneousAggregateBaseType(QualType Ty) const override; bool isHomogeneousAggregateSmallEnough(const Type *Ty, @@ -4948,7 +4948,8 @@ void computeInfo(CGFunctionInfo &FI) const override { if (!::classifyReturnType(getCXXABI(), FI, *this)) - FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); + FI.getReturnInfo() = + classifyReturnType(FI.getReturnType(), FI.isVariadic()); for (auto &it : FI.arguments()) it.info = classifyArgumentType(it.type); @@ -5131,23 +5132,24 @@ Alignment = getContext().getTypeUnadjustedAlign(Ty); Alignment = Alignment < 128 ? 64 : 128; } else { - Alignment = getContext().getTypeAlign(Ty); + Alignment = std::max(getContext().getTypeAlign(Ty), + (unsigned)getTarget().getPointerWidth(0)); } - Size = llvm::alignTo(Size, 64); // round up to multiple of 8 bytes + Size = llvm::alignTo(Size, Alignment); // We use a pair of i64 for 16-byte aggregate with 8-byte alignment. // For aggregates with 16-byte alignment, we use i128. - if (Alignment < 128 && Size == 128) { - llvm::Type *BaseTy = llvm::Type::getInt64Ty(getVMContext()); - return ABIArgInfo::getDirect(llvm::ArrayType::get(BaseTy, Size / 64)); - } - return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), Size)); + llvm::Type *BaseTy = llvm::Type::getIntNTy(getVMContext(), Alignment); + return ABIArgInfo::getDirect( + Size == Alignment ? BaseTy + : llvm::ArrayType::get(BaseTy, Size / Alignment)); } return getNaturalAlignIndirect(Ty, /*ByVal=*/false); } -ABIArgInfo AArch64ABIInfo::classifyReturnType(QualType RetTy) const { +ABIArgInfo AArch64ABIInfo::classifyReturnType(QualType RetTy, + bool IsVariadic) const { if (RetTy->isVoidType()) return ABIArgInfo::getIgnore(); @@ -5171,7 +5173,9 @@ const Type *Base = nullptr; uint64_t Members = 0; - if (isHomogeneousAggregate(RetTy, Base, Members)) + if (isHomogeneousAggregate(RetTy, Base, Members) && + !(getTarget().getTriple().getArch() == llvm::Triple::aarch64_32 && + IsVariadic)) // Homogeneous Floating-point Aggregates (HFAs) are returned directly. return ABIArgInfo::getDirect(); @@ -5206,6 +5210,14 @@ // NumElements should be power of 2. if (!llvm::isPowerOf2_32(NumElements)) return true; + + // arm64_32 has to be compatible with the ARM logic here, which allows huge + // vectors for some reason. + llvm::Triple Triple = getTarget().getTriple(); + if (Triple.getArch() == llvm::Triple::aarch64_32 && + Triple.isOSBinFormatMachO()) + return Size <= 32; + return Size != 64 && (Size != 128 || NumElements == 1); } return false; @@ -5497,7 +5509,8 @@ if (!isAggregateTypeForABI(Ty) && !isIllegalVectorType(Ty)) return EmitVAArgInstr(CGF, VAListAddr, Ty, ABIArgInfo::getDirect()); - CharUnits SlotSize = CharUnits::fromQuantity(8); + uint64_t PointerSize = getTarget().getPointerWidth(0) / 8; + CharUnits SlotSize = CharUnits::fromQuantity(PointerSize); // Empty records are ignored for parameter passing purposes. if (isEmptyRecord(getContext(), Ty, true)) { @@ -9361,6 +9374,7 @@ return SetCGInfo(new AVRTargetCodeGenInfo(Types)); case llvm::Triple::aarch64: + case llvm::Triple::aarch64_32: case llvm::Triple::aarch64_be: { AArch64ABIInfo::ABIKind Kind = AArch64ABIInfo::AAPCS; if (getTarget().getABI() == "darwinpcs") Index: clang/lib/Driver/ToolChain.cpp =================================================================== --- clang/lib/Driver/ToolChain.cpp +++ clang/lib/Driver/ToolChain.cpp @@ -565,6 +565,8 @@ Triple.setArchName("arm64"); return Triple.getTriple(); } + case llvm::Triple::aarch64_32: + return getTripleString(); case llvm::Triple::arm: case llvm::Triple::armeb: case llvm::Triple::thumb: Index: clang/lib/Driver/ToolChains/Clang.cpp =================================================================== --- clang/lib/Driver/ToolChains/Clang.cpp +++ clang/lib/Driver/ToolChains/Clang.cpp @@ -341,6 +341,7 @@ systemz::getSystemZTargetFeatures(Args, Features); break; case llvm::Triple::aarch64: + case llvm::Triple::aarch64_32: case llvm::Triple::aarch64_be: aarch64::getAArch64TargetFeatures(D, Triple, Args, Features); break; @@ -1333,6 +1334,7 @@ return true; case llvm::Triple::aarch64: + case llvm::Triple::aarch64_32: case llvm::Triple::aarch64_be: case llvm::Triple::arm: case llvm::Triple::armeb: @@ -1455,6 +1457,7 @@ break; case llvm::Triple::aarch64: + case llvm::Triple::aarch64_32: case llvm::Triple::aarch64_be: AddAArch64TargetArgs(Args, CmdArgs); CmdArgs.push_back("-fallow-half-arguments-and-returns"); @@ -3733,6 +3736,7 @@ RenderARMABI(Triple, Args, CmdArgs); break; case llvm::Triple::aarch64: + case llvm::Triple::aarch64_32: case llvm::Triple::aarch64_be: RenderAArch64ABI(Triple, Args, CmdArgs); break; @@ -5413,11 +5417,12 @@ // We only support -moutline in AArch64 right now. If we're not compiling // for AArch64, emit a warning and ignore the flag. Otherwise, add the // proper mllvm flags. - if (Triple.getArch() != llvm::Triple::aarch64) { + if (Triple.getArch() != llvm::Triple::aarch64 && + Triple.getArch() != llvm::Triple::aarch64_32) { D.Diag(diag::warn_drv_moutline_unsupported_opt) << Triple.getArchName(); } else { - CmdArgs.push_back("-mllvm"); - CmdArgs.push_back("-enable-machine-outliner"); + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back("-enable-machine-outliner"); } } else { // Disable all outlining behaviour. Index: clang/lib/Driver/ToolChains/CommonArgs.cpp =================================================================== --- clang/lib/Driver/ToolChains/CommonArgs.cpp +++ clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -254,6 +254,7 @@ return ""; case llvm::Triple::aarch64: + case llvm::Triple::aarch64_32: case llvm::Triple::aarch64_be: return aarch64::getAArch64TargetCPU(Args, T, A); Index: clang/lib/Driver/ToolChains/Darwin.cpp =================================================================== --- clang/lib/Driver/ToolChains/Darwin.cpp +++ clang/lib/Driver/ToolChains/Darwin.cpp @@ -56,7 +56,8 @@ .Cases("arm", "armv4t", "armv5", "armv6", "armv6m", llvm::Triple::arm) .Cases("armv7", "armv7em", "armv7k", "armv7m", llvm::Triple::arm) .Cases("armv7s", "xscale", llvm::Triple::arm) - .Case("arm64", llvm::Triple::aarch64) + .Case("arm64", llvm::Triple::aarch64) + .Case("arm64_32", llvm::Triple::aarch64_32) .Case("r600", llvm::Triple::r600) .Case("amdgcn", llvm::Triple::amdgcn) .Case("nvptx", llvm::Triple::nvptx) @@ -816,6 +817,9 @@ default: return getDefaultUniversalArchName(); + case llvm::Triple::aarch64_32: + return "arm64_32"; + case llvm::Triple::aarch64: return "arm64"; @@ -1597,7 +1601,7 @@ if (MachOArchName == "armv7" || MachOArchName == "armv7s" || MachOArchName == "arm64") OSTy = llvm::Triple::IOS; - else if (MachOArchName == "armv7k") + else if (MachOArchName == "armv7k" || MachOArchName == "arm64_32") OSTy = llvm::Triple::WatchOS; else if (MachOArchName != "armv6m" && MachOArchName != "armv7m" && MachOArchName != "armv7em") Index: clang/lib/Sema/SemaChecking.cpp =================================================================== --- clang/lib/Sema/SemaChecking.cpp +++ clang/lib/Sema/SemaChecking.cpp @@ -1514,6 +1514,7 @@ return ExprError(); break; case llvm::Triple::aarch64: + case llvm::Triple::aarch64_32: case llvm::Triple::aarch64_be: if (CheckAArch64BuiltinFunctionCall(BuiltinID, TheCall)) return ExprError(); @@ -1658,6 +1659,7 @@ llvm::Triple::ArchType Arch = Context.getTargetInfo().getTriple().getArch(); bool IsPolyUnsigned = Arch == llvm::Triple::aarch64 || + Arch == llvm::Triple::aarch64_32 || Arch == llvm::Triple::aarch64_be; bool IsInt64Long = Context.getTargetInfo().getInt64Type() == TargetInfo::SignedLong; @@ -5391,7 +5393,8 @@ static bool checkVAStartABI(Sema &S, unsigned BuiltinID, Expr *Fn) { const llvm::Triple &TT = S.Context.getTargetInfo().getTriple(); bool IsX64 = TT.getArch() == llvm::Triple::x86_64; - bool IsAArch64 = TT.getArch() == llvm::Triple::aarch64; + bool IsAArch64 = (TT.getArch() == llvm::Triple::aarch64 || + TT.getArch() == llvm::Triple::aarch64_32); bool IsWindows = TT.isOSWindows(); bool IsMSVAStart = BuiltinID == Builtin::BI__builtin_ms_va_start; if (IsX64 || IsAArch64) { Index: clang/lib/Sema/SemaType.cpp =================================================================== --- clang/lib/Sema/SemaType.cpp +++ clang/lib/Sema/SemaType.cpp @@ -7159,6 +7159,7 @@ // Signed poly is mathematically wrong, but has been baked into some ABIs by // now. bool IsPolyUnsigned = Triple.getArch() == llvm::Triple::aarch64 || + Triple.getArch() == llvm::Triple::aarch64_32 || Triple.getArch() == llvm::Triple::aarch64_be; if (VecKind == VectorType::NeonPolyVector) { if (IsPolyUnsigned) { @@ -7176,10 +7177,8 @@ // Non-polynomial vector types: the usual suspects are allowed, as well as // float64_t on AArch64. - bool Is64Bit = Triple.getArch() == llvm::Triple::aarch64 || - Triple.getArch() == llvm::Triple::aarch64_be; - - if (Is64Bit && BTy->getKind() == BuiltinType::Double) + if ((Triple.isArch64Bit() || Triple.getArch() == llvm::Triple::aarch64_32) && + BTy->getKind() == BuiltinType::Double) return true; return BTy->getKind() == BuiltinType::SChar || Index: clang/test/CodeGen/arm64_32-vaarg.c =================================================================== --- /dev/null +++ clang/test/CodeGen/arm64_32-vaarg.c @@ -0,0 +1,117 @@ +// RUN: %clang_cc1 -triple arm64_32-apple-ios7.0 -target-abi darwinpcs -emit-llvm -o - -O1 -ffreestanding %s | FileCheck %s + +#include + +typedef struct { + int a; +} OneInt; + +// No realignment should be needed here: slot size is 4 bytes. +int test_int(OneInt input, va_list *mylist) { +// CHECK-LABEL: define i32 @test_int(i32 %input +// CHECK: [[START:%.*]] = load i8*, i8** %mylist +// CHECK: [[NEXT:%.*]] = getelementptr inbounds i8, i8* [[START]], i32 4 +// CHECK: store i8* [[NEXT]], i8** %mylist + +// CHECK: [[ADDR_I32:%.*]] = bitcast i8* [[START]] to i32* +// CHECK: [[RES:%.*]] = load i32, i32* [[ADDR_I32]] +// CHECK: ret i32 [[RES]] + + return va_arg(*mylist, OneInt).a; +} + + +typedef struct { + long long a; +} OneLongLong; + +// Minimum slot size is 4 bytes, so address needs rounding up to multiple of 8. +long long test_longlong(OneLongLong input, va_list *mylist) { +// CHECK-LABEL: define i64 @test_longlong(i64 %input +// CHECK: [[STARTPTR:%.*]] = bitcast i8** %mylist to i32* +// CHECK: [[START:%.*]] = load i32, i32* [[STARTPTR]] + +// CHECK: [[ALIGN_TMP:%.*]] = add i32 [[START]], 7 +// CHECK: [[ALIGNED:%.*]] = and i32 [[ALIGN_TMP]], -8 +// CHECK: [[ALIGNED_ADDR:%.*]] = inttoptr i32 [[ALIGNED]] to i8* +// CHECK: [[NEXT:%.*]] = getelementptr inbounds i8, i8* [[ALIGNED_ADDR]], i32 8 +// CHECK: store i8* [[NEXT]], i8** %mylist + +// CHECK: [[ADDR_STRUCT:%.*]] = inttoptr i32 [[ALIGNED]] to %struct.OneLongLong* +// CHECK: [[ADDR_I64:%.*]] = getelementptr inbounds %struct.OneLongLong, %struct.OneLongLong* [[ADDR_STRUCT]], i32 0, i32 0 +// CHECK: [[RES:%.*]] = load i64, i64* [[ADDR_I64]] +// CHECK: ret i64 [[RES]] + + return va_arg(*mylist, OneLongLong).a; +} + + +typedef struct { + float arr[4]; +} HFA; + +// HFAs take priority over passing large structs indirectly. +float test_hfa(va_list *mylist) { +// CHECK-LABEL: define float @test_hfa +// CHECK: [[START:%.*]] = load i8*, i8** %mylist + +// CHECK: [[NEXT:%.*]] = getelementptr inbounds i8, i8* [[START]], i32 16 +// CHECK: store i8* [[NEXT]], i8** %mylist + +// CHECK: [[ADDR_FLOAT:%.*]] = bitcast i8* [[START]] to float* +// CHECK: [[RES:%.*]] = load float, float* [[ADDR_FLOAT]] +// CHECK: ret float [[RES]] + + return va_arg(*mylist, HFA).arr[0]; +} + +// armv7k does not return HFAs normally for variadic functions, so we must match +// that. +HFA test_hfa_return(int n, ...) { +// CHECK-LABEL: define [2 x i64] @test_hfa_return + HFA h = {0}; + return h; +} + +typedef struct { + long long a, b; + char c; +} BigStruct; + +// Structs bigger than 16 bytes are passed indirectly: a pointer is placed on +// the stack. +long long test_bigstruct(BigStruct input, va_list *mylist) { +// CHECK-LABEL: define i64 @test_bigstruct(%struct.BigStruct* +// CHECK: [[START:%.*]] = load i8*, i8** %mylist +// CHECK: [[NEXT:%.*]] = getelementptr inbounds i8, i8* [[START]], i32 4 +// CHECK: store i8* [[NEXT]], i8** %mylist + +// CHECK: [[INT_PTR:%.*]] = bitcast i8* [[START]] to %struct.BigStruct** +// CHECK: [[ADDR:%.*]] = load %struct.BigStruct*, %struct.BigStruct** [[INT_PTR]] +// CHECK: [[ADDR_I64:%.*]] = getelementptr inbounds %struct.BigStruct, %struct.BigStruct* [[ADDR]], i32 0, i32 0 +// CHECK: [[RES:%.*]] = load i64, i64* [[ADDR_I64]] +// CHECK: ret i64 [[RES]] + + return va_arg(*mylist, BigStruct).a; +} + +typedef struct { + short arr[3]; +} ThreeShorts; + +// Slot sizes are 4-bytes on arm64_32, so structs with less than 32-bit +// alignment must be passed via "[N x i32]" to be correctly allocated in the +// backend. +short test_threeshorts(ThreeShorts input, va_list *mylist) { +// CHECK-LABEL: define signext i16 @test_threeshorts([2 x i32] %input + +// CHECK: [[START:%.*]] = load i8*, i8** %mylist +// CHECK: [[NEXT:%.*]] = getelementptr inbounds i8, i8* [[START]], i32 8 +// CHECK: store i8* [[NEXT]], i8** %mylist + +// CHECK: [[ADDR_I32:%.*]] = bitcast i8* [[START]] to i16* +// CHECK: [[RES:%.*]] = load i16, i16* [[ADDR_I32]] +// CHECK: ret i16 [[RES]] + + return va_arg(*mylist, ThreeShorts).arr[0]; +} Index: clang/test/CodeGen/arm64_32.c =================================================================== --- /dev/null +++ clang/test/CodeGen/arm64_32.c @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -triple arm64_32-apple-ios7.0 -emit-llvm -o - %s | FileCheck %s + +struct Foo { + char a; + int b : 1; +}; + +int BitfieldOffset = sizeof(struct Foo); +// CHECK: @BitfieldOffset = global i32 2 + +int PointerSize = sizeof(void *); +// CHECK: @PointerSize = global i32 4 + +int PointerAlign = __alignof(void *); +// CHECK: @PointerAlign = global i32 4 + +int LongSize = sizeof(long); +// CHECK: @LongSize = global i32 4 + +int LongAlign = __alignof(long); +// CHECK: @LongAlign = global i32 4 + +// Not expected to change, but it's a difference between AAPCS and DarwinPCS +// that we need to be preserved for compatibility with ARMv7k. +long double LongDoubleVar = 0.0; +// CHECK: @LongDoubleVar = global double + +typedef float __attribute__((ext_vector_type(16))) v16f32; +v16f32 func(v16f32 in) { return in; } +// CHECK: define void @func(<16 x float>* noalias sret {{%.*}}, <16 x float> {{%.*}}) Index: clang/test/CodeGen/builtins-arm64.c =================================================================== --- clang/test/CodeGen/builtins-arm64.c +++ clang/test/CodeGen/builtins-arm64.c @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -triple arm64-unknown-linux -disable-O0-optnone -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-LINUX // RUN: %clang_cc1 -triple aarch64-windows -disable-O0-optnone -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-WIN +// RUN: %clang_cc1 -triple arm64_32-apple-ios -disable-O0-optnone -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s #include void f0(void *a, void *b) { @@ -7,10 +8,12 @@ // CHECK: call {{.*}} @__clear_cache } +#if __LP64__ void *tp (void) { return __builtin_thread_pointer (); -// CHECK: call {{.*}} @llvm.thread.pointer() +// CHECK-LINUX: call {{.*}} @llvm.thread.pointer() } +#endif // CHECK: call {{.*}} @llvm.bitreverse.i32(i32 %a) unsigned rbit(unsigned a) { Index: clang/test/CodeGen/target-data.c =================================================================== --- clang/test/CodeGen/target-data.c +++ clang/test/CodeGen/target-data.c @@ -163,6 +163,10 @@ // RUN: FileCheck %s -check-prefix=AARCH64 // AARCH64: target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" +// RUN: %clang_cc1 -triple arm64_32-apple-ios7.0 -o - -emit-llvm %s | \ +// RUN: FileCheck %s -check-prefix=AARCH64-ILP32 +// AARCH64-ILP32: target datalayout = "e-m:o-p:32:32-i64:64-i128:128-n32:64-S128" + // RUN: %clang_cc1 -triple thumb-unknown-gnueabi -o - -emit-llvm %s | \ // RUN: FileCheck %s -check-prefix=THUMB // THUMB: target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" Index: clang/test/CodeGenCXX/armv7k.cpp =================================================================== --- clang/test/CodeGenCXX/armv7k.cpp +++ clang/test/CodeGenCXX/armv7k.cpp @@ -1,6 +1,9 @@ // RUN: %clang_cc1 %s -triple=thumbv7k-apple-watchos -emit-llvm -o - -target-abi aapcs16 | FileCheck %s // RUN: %clang_cc1 %s -triple=thumbv7k-apple-watchos -emit-llvm -o - -target-abi aapcs16 | FileCheck -check-prefix=CHECK-GLOBALS %s +// RUN: %clang_cc1 %s -triple=arm64_32-apple-ios -emit-llvm -o - -target-abi darwinpcs | FileCheck %s +// RUN: %clang_cc1 %s -triple=arm64_32-apple-ios -emit-llvm -o - -target-abi darwinpcs | FileCheck -check-prefix=CHECK-GLOBALS %s + // __cxa_guard_acquire argument is 64-bit // rdar://11540122 struct A { Index: clang/test/Driver/aarch64-cpus.c =================================================================== --- clang/test/Driver/aarch64-cpus.c +++ clang/test/Driver/aarch64-cpus.c @@ -26,6 +26,9 @@ // ARM64-DARWIN: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "cyclone" // ARM64-DARWIN-SAME: "-target-feature" "+aes" +// RUN: %clang -target arm64-apple-darwin -arch arm64_32 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64_32-DARWIN %s +// ARM64_32-DARWIN: "-cc1"{{.*}} "-triple" "aarch64_32{{.*}}" "-target-cpu" "cyclone" + // RUN: %clang -target aarch64 -mcpu=cortex-a35 -### -c %s 2>&1 | FileCheck -check-prefix=CA35 %s // RUN: %clang -target aarch64 -mlittle-endian -mcpu=cortex-a35 -### -c %s 2>&1 | FileCheck -check-prefix=CA35 %s // RUN: %clang -target aarch64_be -mlittle-endian -mcpu=cortex-a35 -### -c %s 2>&1 | FileCheck -check-prefix=CA35 %s Index: clang/test/Driver/arm64_32-link.c =================================================================== --- /dev/null +++ clang/test/Driver/arm64_32-link.c @@ -0,0 +1,4 @@ +// RUN: %clang -target x86_64-apple-darwin -arch arm64_32 -miphoneos-version-min=8.0 %s -### 2>&1 | FileCheck %s + +// CHECK: clang{{.*}} "-triple" "aarch64_32-apple-ios8.0.0" +// CHECK: ld{{.*}} "-arch" "arm64_32" Index: clang/test/Preprocessor/aarch64-target-features.c =================================================================== --- clang/test/Preprocessor/aarch64-target-features.c +++ clang/test/Preprocessor/aarch64-target-features.c @@ -169,6 +169,9 @@ // RUN: %clang -target x86_64-apple-macosx -arch arm64 -### -c %s 2>&1 | FileCheck --check-prefix=CHECK-ARCH-ARM64 %s // CHECK-ARCH-ARM64: "-target-cpu" "cyclone" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+crypto" "-target-feature" "+zcm" "-target-feature" "+zcz" +// RUN: %clang -target x86_64-apple-macosx -arch arm64_32 -### -c %s 2>&1 | FileCheck --check-prefix=CHECK-ARCH-ARM64_32 %s +// CHECK-ARCH-ARM64_32: "-target-cpu" "cyclone" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+crypto" "-target-feature" "+zcm" "-target-feature" "+zcz" + // RUN: %clang -target aarch64 -march=armv8-a+fp+simd+crc+crypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MARCH-1 %s // RUN: %clang -target aarch64 -march=armv8-a+nofp+nosimd+nocrc+nocrypto+fp+simd+crc+crypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MARCH-1 %s // RUN: %clang -target aarch64 -march=armv8-a+nofp+nosimd+nocrc+nocrypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MARCH-2 %s Index: clang/test/Preprocessor/arm64_32.c =================================================================== --- /dev/null +++ clang/test/Preprocessor/arm64_32.c @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -E -dM -ffreestanding -triple=arm64_32-apple-ios < /dev/null | FileCheck %s --check-prefix=CHECK-32 +// RUN: %clang_cc1 -E -dM -ffreestanding -triple=arm64-apple-ios < /dev/null | FileCheck %s --check-prefix=CHECK-64 + +// CHECK-32: #define __ARM64_ARCH_8_32__ 1 +// CHECK-64: #define __ARM64_ARCH_8__ 1 Index: clang/test/Preprocessor/init-v7k-compat.c =================================================================== --- clang/test/Preprocessor/init-v7k-compat.c +++ clang/test/Preprocessor/init-v7k-compat.c @@ -1,3 +1,4 @@ +// RUN: %clang_cc1 -E -dM -ffreestanding -triple=arm64_32-apple-ios7.0 < /dev/null | FileCheck %s // RUN: %clang_cc1 -E -dM -ffreestanding -triple=thumbv7k-apple-watchos2.0 < /dev/null | FileCheck %s // Check that the chosen types for things like size_t, ptrdiff_t etc are as Index: clang/test/Preprocessor/stdint.c =================================================================== --- clang/test/Preprocessor/stdint.c +++ clang/test/Preprocessor/stdint.c @@ -105,6 +105,113 @@ // ARM:INTMAX_C_(0) 0LL // ARM:UINTMAX_C_(0) 0ULL // +// RUN: %clang_cc1 -E -ffreestanding -triple=arm64_32-apple-ios7.0 %s | FileCheck -check-prefix ARM64_32 %s +// +// ARM64_32:typedef long long int int64_t; +// ARM64_32:typedef long long unsigned int uint64_t; +// ARM64_32:typedef int64_t int_least64_t; +// ARM64_32:typedef uint64_t uint_least64_t; +// ARM64_32:typedef int64_t int_fast64_t; +// ARM64_32:typedef uint64_t uint_fast64_t; +// +// ARM64_32:typedef int int32_t; +// ARM64_32:typedef unsigned int uint32_t; +// ARM64_32:typedef int32_t int_least32_t; +// ARM64_32:typedef uint32_t uint_least32_t; +// ARM64_32:typedef int32_t int_fast32_t; +// ARM64_32:typedef uint32_t uint_fast32_t; +// +// ARM64_32:typedef short int16_t; +// ARM64_32:typedef unsigned short uint16_t; +// ARM64_32:typedef int16_t int_least16_t; +// ARM64_32:typedef uint16_t uint_least16_t; +// ARM64_32:typedef int16_t int_fast16_t; +// ARM64_32:typedef uint16_t uint_fast16_t; +// +// ARM64_32:typedef signed char int8_t; +// ARM64_32:typedef unsigned char uint8_t; +// ARM64_32:typedef int8_t int_least8_t; +// ARM64_32:typedef uint8_t uint_least8_t; +// ARM64_32:typedef int8_t int_fast8_t; +// ARM64_32:typedef uint8_t uint_fast8_t; +// +// ARM64_32:typedef long int intptr_t; +// ARM64_32:typedef long unsigned int uintptr_t; +// +// ARM64_32:typedef long long int intmax_t; +// ARM64_32:typedef long long unsigned int uintmax_t; +// +// ARM64_32:INT8_MAX_ 127 +// ARM64_32:INT8_MIN_ (-127 -1) +// ARM64_32:UINT8_MAX_ 255 +// ARM64_32:INT_LEAST8_MIN_ (-127 -1) +// ARM64_32:INT_LEAST8_MAX_ 127 +// ARM64_32:UINT_LEAST8_MAX_ 255 +// ARM64_32:INT_FAST8_MIN_ (-127 -1) +// ARM64_32:INT_FAST8_MAX_ 127 +// ARM64_32:UINT_FAST8_MAX_ 255 +// +// ARM64_32:INT16_MAX_ 32767 +// ARM64_32:INT16_MIN_ (-32767 -1) +// ARM64_32:UINT16_MAX_ 65535 +// ARM64_32:INT_LEAST16_MIN_ (-32767 -1) +// ARM64_32:INT_LEAST16_MAX_ 32767 +// ARM64_32:UINT_LEAST16_MAX_ 65535 +// ARM64_32:INT_FAST16_MIN_ (-32767 -1) +// ARM64_32:INT_FAST16_MAX_ 32767 +// ARM64_32:UINT_FAST16_MAX_ 65535 +// +// ARM64_32:INT32_MAX_ 2147483647 +// ARM64_32:INT32_MIN_ (-2147483647 -1) +// ARM64_32:UINT32_MAX_ 4294967295U +// ARM64_32:INT_LEAST32_MIN_ (-2147483647 -1) +// ARM64_32:INT_LEAST32_MAX_ 2147483647 +// ARM64_32:UINT_LEAST32_MAX_ 4294967295U +// ARM64_32:INT_FAST32_MIN_ (-2147483647 -1) +// ARM64_32:INT_FAST32_MAX_ 2147483647 +// ARM64_32:UINT_FAST32_MAX_ 4294967295U +// +// ARM64_32:INT64_MAX_ 9223372036854775807LL +// ARM64_32:INT64_MIN_ (-9223372036854775807LL -1) +// ARM64_32:UINT64_MAX_ 18446744073709551615ULL +// ARM64_32:INT_LEAST64_MIN_ (-9223372036854775807LL -1) +// ARM64_32:INT_LEAST64_MAX_ 9223372036854775807LL +// ARM64_32:UINT_LEAST64_MAX_ 18446744073709551615ULL +// ARM64_32:INT_FAST64_MIN_ (-9223372036854775807LL -1) +// ARM64_32:INT_FAST64_MAX_ 9223372036854775807LL +// ARM64_32:UINT_FAST64_MAX_ 18446744073709551615ULL +// +// ARM64_32:INTPTR_MIN_ (-2147483647L -1) +// ARM64_32:INTPTR_MAX_ 2147483647L +// ARM64_32:UINTPTR_MAX_ 4294967295UL +// ARM64_32:PTRDIFF_MIN_ (-2147483647L -1) +// ARM64_32:PTRDIFF_MAX_ 2147483647L +// ARM64_32:SIZE_MAX_ 4294967295UL +// +// ARM64_32:INTMAX_MIN_ (-9223372036854775807LL -1) +// ARM64_32:INTMAX_MAX_ 9223372036854775807LL +// ARM64_32:UINTMAX_MAX_ 18446744073709551615ULL +// +// ARM64_32:SIG_ATOMIC_MIN_ (-2147483647 -1) +// ARM64_32:SIG_ATOMIC_MAX_ 2147483647 +// ARM64_32:WINT_MIN_ (-2147483647 -1) +// ARM64_32:WINT_MAX_ 2147483647 +// +// ARM64_32:WCHAR_MAX_ 2147483647 +// ARM64_32:WCHAR_MIN_ (-2147483647 -1) +// +// ARM64_32:INT8_C_(0) 0 +// ARM64_32:UINT8_C_(0) 0U +// ARM64_32:INT16_C_(0) 0 +// ARM64_32:UINT16_C_(0) 0U +// ARM64_32:INT32_C_(0) 0 +// ARM64_32:UINT32_C_(0) 0U +// ARM64_32:INT64_C_(0) 0LL +// ARM64_32:UINT64_C_(0) 0ULL +// +// ARM64_32:INTMAX_C_(0) 0LL +// ARM64_32:UINTMAX_C_(0) 0ULL + // // RUN: %clang_cc1 -E -ffreestanding -triple=i386-none-none %s | FileCheck -check-prefix I386 %s // Index: clang/test/Sema/aarch64-neon-vector-types.c =================================================================== --- clang/test/Sema/aarch64-neon-vector-types.c +++ clang/test/Sema/aarch64-neon-vector-types.c @@ -3,6 +3,8 @@ // RUN: %clang_cc1 %s -triple arm64-none-linux-gnu -target-feature +neon -fsyntax-only -verify // RUN: %clang_cc1 %s -triple arm64-none-linux-gnu -target-feature +neon -DUSE_LONG -fsyntax-only -verify +// RUN: %clang_cc1 %s -triple arm64_32-apple-ios -target-feature +neon -fsyntax-only -verify + typedef float float32_t; typedef unsigned char poly8_t; typedef unsigned short poly16_t; Index: clang/test/Sema/types.c =================================================================== --- clang/test/Sema/types.c +++ clang/test/Sema/types.c @@ -2,6 +2,7 @@ // RUN: %clang_cc1 %s -fblocks -pedantic -verify -triple=mips64-linux-gnu // RUN: %clang_cc1 %s -fblocks -pedantic -verify -triple=x86_64-unknown-linux // RUN: %clang_cc1 %s -fblocks -pedantic -verify -triple=x86_64-unknown-linux-gnux32 +// RUN: %clang_cc1 %s -fblocks -pedantic -pedantic -verify -triple=arm64_32-apple-ios7.0 // rdar://6097662 typedef int (*T)[2];