forked from OSchip/llvm-project
AArch64: add arm64_32 support to Clang.
This commit is contained in:
parent
77cc246412
commit
44e5879f0f
|
@ -122,6 +122,11 @@ TargetInfo *AllocateTarget(const llvm::Triple &Triple,
|
|||
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);
|
||||
|
|
|
@ -51,7 +51,11 @@ AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple,
|
|||
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;
|
||||
|
@ -160,7 +164,7 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
|
|||
Builder.defineMacro("__ELF__");
|
||||
|
||||
// Target properties.
|
||||
if (!getTriple().isOSWindows()) {
|
||||
if (!getTriple().isOSWindows() && getTriple().isArch64Bit()) {
|
||||
Builder.defineMacro("_LP64");
|
||||
Builder.defineMacro("__LP64__");
|
||||
}
|
||||
|
@ -506,14 +510,19 @@ int AArch64TargetInfo::getEHDataRegisterNumber(unsigned RegNo) const {
|
|||
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");
|
||||
}
|
||||
|
||||
|
@ -631,19 +640,34 @@ DarwinAArch64TargetInfo::DarwinAArch64TargetInfo(const llvm::Triple &Triple,
|
|||
const TargetOptions &Opts)
|
||||
: DarwinTargetInfo<AArch64leTargetInfo>(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__", "");
|
||||
|
|
|
@ -97,6 +97,8 @@ public:
|
|||
}
|
||||
|
||||
int getEHDataRegisterNumber(unsigned RegNo) const override;
|
||||
|
||||
bool hasInt128Type() const override;
|
||||
};
|
||||
|
||||
class LLVM_LIBRARY_VISIBILITY AArch64leTargetInfo : public AArch64TargetInfo {
|
||||
|
|
|
@ -4238,6 +4238,7 @@ static Value *EmitTargetArchBuiltinExpr(CodeGenFunction *CGF,
|
|||
case llvm::Triple::thumbeb:
|
||||
return CGF->EmitARMBuiltinExpr(BuiltinID, E, ReturnValue, Arch);
|
||||
case llvm::Triple::aarch64:
|
||||
case llvm::Triple::aarch64_32:
|
||||
case llvm::Triple::aarch64_be:
|
||||
return CGF->EmitAArch64BuiltinExpr(BuiltinID, E, Arch);
|
||||
case llvm::Triple::bpfeb:
|
||||
|
@ -5670,7 +5671,8 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
|
|||
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, "");
|
||||
|
|
|
@ -4991,7 +4991,7 @@ private:
|
|||
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,
|
||||
|
@ -5001,7 +5001,8 @@ private:
|
|||
|
||||
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);
|
||||
|
@ -5184,23 +5185,24 @@ ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty) const {
|
|||
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();
|
||||
|
||||
|
@ -5224,7 +5226,9 @@ ABIArgInfo AArch64ABIInfo::classifyReturnType(QualType RetTy) const {
|
|||
|
||||
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();
|
||||
|
||||
|
@ -5259,6 +5263,14 @@ bool AArch64ABIInfo::isIllegalVectorType(QualType Ty) const {
|
|||
// 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;
|
||||
|
@ -5550,7 +5562,8 @@ Address AArch64ABIInfo::EmitDarwinVAArg(Address VAListAddr, QualType Ty,
|
|||
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)) {
|
||||
|
@ -9773,6 +9786,7 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
|
|||
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")
|
||||
|
|
|
@ -637,6 +637,8 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,
|
|||
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:
|
||||
|
|
|
@ -342,6 +342,7 @@ static void getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple,
|
|||
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;
|
||||
|
@ -1351,6 +1352,7 @@ static bool isSignedCharDefault(const llvm::Triple &Triple) {
|
|||
return true;
|
||||
|
||||
case llvm::Triple::aarch64:
|
||||
case llvm::Triple::aarch64_32:
|
||||
case llvm::Triple::aarch64_be:
|
||||
case llvm::Triple::arm:
|
||||
case llvm::Triple::armeb:
|
||||
|
@ -1473,6 +1475,7 @@ void Clang::RenderTargetOptions(const llvm::Triple &EffectiveTriple,
|
|||
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");
|
||||
|
@ -4032,6 +4035,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
RenderARMABI(Triple, Args, CmdArgs);
|
||||
break;
|
||||
case llvm::Triple::aarch64:
|
||||
case llvm::Triple::aarch64_32:
|
||||
case llvm::Triple::aarch64_be:
|
||||
RenderAArch64ABI(Triple, Args, CmdArgs);
|
||||
break;
|
||||
|
@ -5789,11 +5793,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
// 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.
|
||||
|
|
|
@ -253,6 +253,7 @@ std::string tools::getCPUName(const ArgList &Args, const llvm::Triple &T,
|
|||
return "";
|
||||
|
||||
case llvm::Triple::aarch64:
|
||||
case llvm::Triple::aarch64_32:
|
||||
case llvm::Triple::aarch64_be:
|
||||
return aarch64::getAArch64TargetCPU(Args, T, A);
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@ llvm::Triple::ArchType darwin::getArchTypeForMachOArchName(StringRef Str) {
|
|||
.Cases("armv7", "armv7em", "armv7k", "armv7m", llvm::Triple::arm)
|
||||
.Cases("armv7s", "xscale", llvm::Triple::arm)
|
||||
.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)
|
||||
|
@ -832,6 +833,9 @@ StringRef MachO::getMachOArchName(const ArgList &Args) const {
|
|||
default:
|
||||
return getDefaultUniversalArchName();
|
||||
|
||||
case llvm::Triple::aarch64_32:
|
||||
return "arm64_32";
|
||||
|
||||
case llvm::Triple::aarch64:
|
||||
return "arm64";
|
||||
|
||||
|
@ -1640,7 +1644,7 @@ inferDeploymentTargetFromArch(DerivedArgList &Args, const Darwin &Toolchain,
|
|||
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")
|
||||
|
|
|
@ -1536,6 +1536,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
|
|||
return ExprError();
|
||||
break;
|
||||
case llvm::Triple::aarch64:
|
||||
case llvm::Triple::aarch64_32:
|
||||
case llvm::Triple::aarch64_be:
|
||||
if (CheckAArch64BuiltinFunctionCall(BuiltinID, TheCall))
|
||||
return ExprError();
|
||||
|
@ -1685,6 +1686,7 @@ bool Sema::CheckNeonBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
|
|||
|
||||
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;
|
||||
|
@ -5516,7 +5518,8 @@ ExprResult Sema::CheckOSLogFormatStringArg(Expr *Arg) {
|
|||
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) {
|
||||
|
|
|
@ -7215,6 +7215,7 @@ static bool isPermittedNeonBaseType(QualType &Ty,
|
|||
// 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) {
|
||||
|
@ -7232,10 +7233,8 @@ static bool isPermittedNeonBaseType(QualType &Ty,
|
|||
|
||||
// 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 ||
|
||||
|
|
|
@ -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 <stdarg.h>
|
||||
|
||||
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];
|
||||
}
|
|
@ -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> {{%.*}})
|
|
@ -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-ios13 -disable-O0-optnone -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s
|
||||
#include <stdint.h>
|
||||
|
||||
void f0(void *a, void *b) {
|
||||
|
@ -9,7 +10,7 @@ void f0(void *a, void *b) {
|
|||
|
||||
void *tp (void) {
|
||||
return __builtin_thread_pointer ();
|
||||
// CHECK: call {{.*}} @llvm.thread.pointer()
|
||||
// CHECK-LINUX: call {{.*}} @llvm.thread.pointer()
|
||||
}
|
||||
|
||||
// CHECK: call {{.*}} @llvm.bitreverse.i32(i32 %a)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
|
@ -167,6 +167,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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
//
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
|
|
Loading…
Reference in New Issue