Index: include/llvm/ADT/Triple.h =================================================================== --- include/llvm/ADT/Triple.h +++ include/llvm/ADT/Triple.h @@ -192,7 +192,14 @@ AMDOpenCL, CoreCLR, OpenCL, - LastEnvironmentType = OpenCL + AndroidABI32, + AndroidABI64, + ABI32, + ABIN32, + ABI64, + GNUABI32, + GNUABIN32, + LastEnvironmentType = GNUABIN32 }; enum ObjectFormatType { UnknownObjectFormat, @@ -478,7 +485,8 @@ bool isGNUEnvironment() const { EnvironmentType Env = getEnvironment(); - return Env == Triple::GNU || Env == Triple::GNUABI64 || + return Env == Triple::GNU || Env == Triple::GNUABI32 || + Env == Triple::GNUABIN32 || Env == Triple::GNUABI64 || Env == Triple::GNUEABI || Env == Triple::GNUEABIHF || Env == Triple::GNUX32; } @@ -576,7 +584,11 @@ } /// Tests whether the target is Android - bool isAndroid() const { return getEnvironment() == Triple::Android; } + bool isAndroid() const { + EnvironmentType Env = getEnvironment(); + return Env == Triple::Android || Env == Triple::AndroidABI32 || + Env == Triple::AndroidABI64; + } /// Tests whether the environment is musl-libc bool isMusl() const { @@ -675,6 +687,22 @@ /// architecture if no such variant can be found. llvm::Triple getLittleEndianArchVariant() const; + /// Form a triple with variant of the current architecture and the specified + /// ABI. + /// + /// Generally speaking the target specifies the ABI in the triple if the ABI + /// has a large effect on the output (e.g. ELFCLASS32/ELFCLASS64, REL/RELA, + /// different sets of relocs) and/or is not link-compatible with other ABI's. + /// If the ABI is fairly small in effect (e.g. calling convention) then and/or + /// is link-compatible with other ABI's then MCTargetOptions is preferable. + /// + /// \param ABI The ABI name to use. If it is an empty string then the triple's + /// default is used. + /// \returns A new triple with the requested ABI or an unknown architecture + /// if no such variant can be found. Also, an ABI name that is + /// consistent with the triple. + std::pair getABIVariant(StringRef ABI) const; + /// Get the (LLVM) name of the minimum ARM CPU for the arch we are targeting. /// /// \param Arch the architecture name (e.g., "armv7s"). If it is an empty Index: lib/Support/Triple.cpp =================================================================== --- lib/Support/Triple.cpp +++ lib/Support/Triple.cpp @@ -200,7 +200,12 @@ const char *Triple::getEnvironmentTypeName(EnvironmentType Kind) { switch (Kind) { case UnknownEnvironment: return "unknown"; + case ABI32: return "abi32"; + case ABIN32: return "abin32"; + case ABI64: return "abi64"; case GNU: return "gnu"; + case GNUABI32: return "gnuabi32"; + case GNUABIN32: return "gnuabin32"; case GNUABI64: return "gnuabi64"; case GNUEABIHF: return "gnueabihf"; case GNUEABI: return "gnueabi"; @@ -209,6 +214,8 @@ case EABI: return "eabi"; case EABIHF: return "eabihf"; case Android: return "android"; + case AndroidABI32: return "androidabi32"; + case AndroidABI64: return "androidabi64"; case Musl: return "musl"; case MuslEABI: return "musleabi"; case MuslEABIHF: return "musleabihf"; @@ -468,14 +475,21 @@ static Triple::EnvironmentType parseEnvironment(StringRef EnvironmentName) { return StringSwitch(EnvironmentName) + .StartsWith("abi32", Triple::ABI32) + .StartsWith("abin32", Triple::ABIN32) + .StartsWith("abi64", Triple::ABI64) .StartsWith("eabihf", Triple::EABIHF) .StartsWith("eabi", Triple::EABI) + .StartsWith("gnuabi32", Triple::GNUABI32) + .StartsWith("gnuabin32", Triple::GNUABIN32) .StartsWith("gnuabi64", Triple::GNUABI64) .StartsWith("gnueabihf", Triple::GNUEABIHF) .StartsWith("gnueabi", Triple::GNUEABI) .StartsWith("gnux32", Triple::GNUX32) .StartsWith("code16", Triple::CODE16) .StartsWith("gnu", Triple::GNU) + .StartsWith("androidabi32", Triple::AndroidABI32) + .StartsWith("androidabi64", Triple::AndroidABI64) .StartsWith("android", Triple::Android) .StartsWith("musleabihf", Triple::MuslEABIHF) .StartsWith("musleabi", Triple::MuslEABI) @@ -1428,6 +1442,98 @@ } } +std::pair Triple::getABIVariant(StringRef ABI) const { + Triple T(*this); + switch (getArch()) { + default: + if (ABI == "") + return std::make_pair(T, ABI); + T.setArch(Triple::UnknownArch); + return std::make_pair(T, ABI); + + case Triple::arm: + case Triple::armeb: + case Triple::aarch64: + case Triple::aarch64_be: + case Triple::thumb: + case Triple::thumbeb: + if (ABI == "" || ABI == "aapcs16" || ABI == "darwinpcs" || + ABI.startswith("apcs") || ABI.startswith("aapcs")) + return std::make_pair(T, ABI); + T.setArch(Triple::UnknownArch); + return std::make_pair(T, ABI); + + case Triple::ppc64: + case Triple::ppc64le: + if (ABI == "" || ABI.startswith("elfv1") || ABI.startswith("elfv2")) + return std::make_pair(T, ABI); + T.setArch(Triple::UnknownArch); + return std::make_pair(T, ABI); + + case Triple::mips: + case Triple::mipsel: + case Triple::mips64: + case Triple::mips64el: { + EnvironmentType NewEnv; + + if (ABI == "") + ABI = (getArch() == Triple::mips || getArch() == Triple::mipsel) ? "o32" : "n64"; + + switch (T.getEnvironment()) { + default: + T.setArch(Triple::UnknownArch); + return std::make_pair(T, ABI); + + case Triple::Android: + case Triple::AndroidABI64: + NewEnv = StringSwitch(ABI) + .Case("o32", Triple::AndroidABI32) + .Case("n64", Triple::AndroidABI64) + .Default(Triple::UnknownEnvironment); + break; + case Triple::UnknownEnvironment: + case Triple::ABI32: + case Triple::ABIN32: + case Triple::ABI64: + NewEnv = StringSwitch(ABI) + .Case("o32", Triple::ABI32) + .Case("n32", Triple::ABIN32) + .Case("n64", Triple::ABI64) + .Default(Triple::UnknownEnvironment); + break; + + case Triple::GNU: + case Triple::GNUABI32: + case Triple::GNUABIN32: + case Triple::GNUABI64: + NewEnv = StringSwitch(ABI) + .Case("o32", Triple::GNUABI32) + .Case("n32", Triple::GNUABIN32) + .Case("n64", Triple::GNUABI64) + .Default(Triple::UnknownEnvironment); + break; + } + + if (NewEnv == Triple::UnknownEnvironment) { + T.setArch(Triple::UnknownArch); + return std::make_pair(T, ABI); + } + + // We have to keep the Arch and Environment in sync at the moment due to + // a false correlation between mips/mipsel and O32 and mips64/mips64el and + // N64 that is required by the MIPS backend. + if (ABI == "o32") + T = T.get32BitArchVariant(); + else if (ABI == "n32" || ABI == "n64") + T = T.get64BitArchVariant(); + + if (NewEnv != T.getEnvironment()) + T.setEnvironment(NewEnv); + return std::make_pair(T, ""); + } + } +} + StringRef Triple::getARMCPUForArch(StringRef MArch) const { if (MArch.empty()) MArch = getArchName(); Index: lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp +++ lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp @@ -57,6 +57,17 @@ return MipsABIInfo::N64(); else if (!Options.getABIName().empty()) llvm_unreachable("Unknown ABI option for MIPS"); + else if (TT.getEnvironment() == Triple::ABI32 || + TT.getEnvironment() == Triple::AndroidABI32 || + TT.getEnvironment() == Triple::GNUABI32) + return MipsABIInfo::O32(); + else if (TT.getEnvironment() == Triple::ABIN32 || + TT.getEnvironment() == Triple::GNUABIN32) + return MipsABIInfo::N32(); + else if (TT.getEnvironment() == Triple::ABI64 || + TT.getEnvironment() == Triple::AndroidABI64 || + TT.getEnvironment() == Triple::GNUABI64) + return MipsABIInfo::N64(); if (TT.getArch() == Triple::mips64 || TT.getArch() == Triple::mips64el) return MipsABIInfo::N64(); Index: test/CodeGen/Mips/compactbranches/no-beqzc-bnezc.ll =================================================================== --- test/CodeGen/Mips/compactbranches/no-beqzc-bnezc.ll +++ test/CodeGen/Mips/compactbranches/no-beqzc-bnezc.ll @@ -103,7 +103,7 @@ define i32 @f6(i32 %a) { ; CHECK-LABEL: f6: -; CHECK: beqzc ${{[0-9]+}}, $BB +; CHECK: beqzc ${{[0-9]+}}, %cmp = icmp eq i32 %a, 0 br i1 %cmp, label %if.then, label %if.end @@ -117,7 +117,7 @@ define i32 @f7(i32 %a) { ; CHECK-LABEL: f7: -; CHECK: bnezc ${{[0-9]+}}, $BB +; CHECK: bnezc ${{[0-9]+}}, %cmp = icmp eq i32 0, %a br i1 %cmp, label %if.then, label %if.end Index: test/CodeGen/Mips/ehframe-indirect.ll =================================================================== --- test/CodeGen/Mips/ehframe-indirect.ll +++ test/CodeGen/Mips/ehframe-indirect.ll @@ -4,8 +4,6 @@ ; RUN: FileCheck -check-prefixes=ALL,LINUX,LINUX-O32,O32 %s ; RUN: llc -mtriple=mips64el-linux-gnu -mabi=n32 < %s -asm-verbose -relocation-model=pic | \ ; RUN: FileCheck -check-prefixes=ALL,LINUX,LINUX-N32,N32 %s -; RUN: llc -mtriple=mips64el-linux-android -mabi=n32 < %s -asm-verbose -relocation-model=pic | \ -; RUN: FileCheck -check-prefixes=ALL,LINUX,LINUX-N32,N32 %s ; RUN: llc -mtriple=mips64el-linux-gnu < %s -asm-verbose -relocation-model=pic | \ ; RUN: FileCheck -check-prefixes=ALL,LINUX,LINUX-N64,N64 %s ; RUN: llc -mtriple=mips64el-linux-android < %s -asm-verbose -relocation-model=pic | \ Index: test/CodeGen/Mips/fp16-promote.ll =================================================================== --- test/CodeGen/Mips/fp16-promote.ll +++ test/CodeGen/Mips/fp16-promote.ll @@ -1,4 +1,4 @@ -; RUN: llc -asm-verbose=false -mtriple=mipsel-linux-gnueabi -relocation-model=pic < %s | FileCheck %s -check-prefix=CHECK-LIBCALL +; RUN: llc -asm-verbose=false -mtriple=mipsel-linux-gnu -relocation-model=pic < %s | FileCheck %s -check-prefix=CHECK-LIBCALL ; CHECK-LIBCALL-LABEL: test_fadd: ; CHECK-LIBCALL: %call16(__gnu_h2f_ieee) Index: test/CodeGen/Mips/tailcall/tail-call-arguments-clobber.ll =================================================================== --- test/CodeGen/Mips/tailcall/tail-call-arguments-clobber.ll +++ test/CodeGen/Mips/tailcall/tail-call-arguments-clobber.ll @@ -1,8 +1,8 @@ ; RUN: llc -march=mips -mcpu=mips32 -O0 -relocation-model=pic -mips-tail-calls=1 < %s | FileCheck \ ; RUN: %s -check-prefix=MIPS32 -; RUN: llc -march=mips64 -mcpu=mips64 -O0 -relocation-model=pic -mabi=n64 \ +; RUN: llc -march=mips64 -mcpu=mips64 -O0 -relocation-model=pic -target-abi n64 \ ; RUN: -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=MIPS64 -; RUN: llc -march=mips64 -mcpu=mips64 -O0 -relocation-model=pic -mabi=n32 \ +; RUN: llc -march=mips64 -mcpu=mips64 -O0 -relocation-model=pic -target-abi n32 \ ; RUN: -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=MIPS64 Index: test/MC/Mips/cpsetup.s =================================================================== --- test/MC/Mips/cpsetup.s +++ test/MC/Mips/cpsetup.s @@ -1,21 +1,21 @@ # RUN: llvm-mc -triple mips-unknown-linux -mabi=o32 -filetype=obj -o - %s | \ # RUN: llvm-objdump -d -r - | FileCheck -check-prefixes=ALL,O32 %s -# RUN: llvm-mc -triple mips-unknown-unknown -mabi=o32 %s | \ +# RUN: llvm-mc -triple mips-unknown-linux -mabi=o32 %s | \ # RUN: FileCheck -check-prefixes=ALL,ASM,ASM-O32 %s # RUN: llvm-mc -triple mips64-unknown-linux -mabi=n32 -filetype=obj -o - %s | \ # RUN: llvm-objdump -d -r - | \ # RUN: FileCheck -check-prefixes=ALL,NXX,N32 %s -# RUN: llvm-mc -triple mips64-unknown-unknown -mabi=n32 %s | \ +# RUN: llvm-mc -triple mips64-unknown-linux -mabi=n32 %s | \ # RUN: FileCheck -check-prefixes=ALL,ASM,ASM-N32 %s # RUN: llvm-mc -triple mips64-unknown-linux %s -filetype=obj -o - | \ # RUN: llvm-objdump -d -r - | \ # RUN: FileCheck -check-prefixes=ALL,NXX,N64 %s -# RUN: llvm-mc -triple mips64-unknown-unknown %s | \ +# RUN: llvm-mc -triple mips64-unknown-linux %s | \ # RUN: FileCheck -check-prefixes=ALL,ASM,ASM-N64 %s .text Index: test/MC/Mips/elf_reginfo.s =================================================================== --- test/MC/Mips/elf_reginfo.s +++ test/MC/Mips/elf_reginfo.s @@ -1,5 +1,5 @@ # These *MUST* match the output of gas compiled with the same triple and -# corresponding options (-mabi=64 -> -mattr=+n64 for example). +# corresponding options. # RUN: llvm-mc -filetype=obj -triple=mips64el-linux -mabi=n64 %s -o - \ # RUN: | llvm-readobj -s | FileCheck --check-prefix=CHECK_64 %s Index: test/MC/Mips/expansion-jal-sym-pic.s =================================================================== --- test/MC/Mips/expansion-jal-sym-pic.s +++ test/MC/Mips/expansion-jal-sym-pic.s @@ -161,8 +161,8 @@ # O32: addiu $25, $25, %lo($tmp0) # encoding: [0x27,0x39,A,A] # O32: # fixup A - offset: 0, value: %lo($tmp0), kind: fixup_Mips_LO16 -# N32: lw $25, %got_disp($tmp0)($gp) # encoding: [0x8f,0x99,A,A] -# N32: # fixup A - offset: 0, value: %got_disp($tmp0), kind: fixup_Mips_GOT_DISP +# N32: lw $25, %got_disp(.Ltmp0)($gp) # encoding: [0x8f,0x99,A,A] +# N32: # fixup A - offset: 0, value: %got_disp(.Ltmp0), kind: fixup_Mips_GOT_DISP # N64: ld $25, %got_disp(.Ltmp0)($gp) # encoding: [0xdf,0x99,A,A] # N64: # fixup A - offset: 0, value: %got_disp(.Ltmp0), kind: fixup_Mips_GOT_DISP Index: test/MC/Mips/mips64-register-names-o32.s =================================================================== --- test/MC/Mips/mips64-register-names-o32.s +++ test/MC/Mips/mips64-register-names-o32.s @@ -2,40 +2,40 @@ # RUN: -mabi=o32 | FileCheck %s # Check that the register names are mapped to their correct numbers for o32 -# Second byte of daddiu with $zero at rt contains the number of the source +# Second byte of addiu with $zero at rt contains the number of the source # register. .set noat -daddiu $zero, $zero, 0 # CHECK: encoding: [0x64,0x00,0x00,0x00] -daddiu $at, $zero, 0 # CHECK: encoding: [0x64,0x01,0x00,0x00] -daddiu $v0, $zero, 0 # CHECK: encoding: [0x64,0x02,0x00,0x00] -daddiu $v1, $zero, 0 # CHECK: encoding: [0x64,0x03,0x00,0x00] -daddiu $a0, $zero, 0 # CHECK: encoding: [0x64,0x04,0x00,0x00] -daddiu $a1, $zero, 0 # CHECK: encoding: [0x64,0x05,0x00,0x00] -daddiu $a2, $zero, 0 # CHECK: encoding: [0x64,0x06,0x00,0x00] -daddiu $a3, $zero, 0 # CHECK: encoding: [0x64,0x07,0x00,0x00] -daddiu $t0, $zero, 0 # CHECK: encoding: [0x64,0x08,0x00,0x00] -daddiu $t1, $zero, 0 # CHECK: encoding: [0x64,0x09,0x00,0x00] -daddiu $t2, $zero, 0 # CHECK: encoding: [0x64,0x0a,0x00,0x00] -daddiu $t3, $zero, 0 # CHECK: encoding: [0x64,0x0b,0x00,0x00] -daddiu $t4, $zero, 0 # CHECK: encoding: [0x64,0x0c,0x00,0x00] -daddiu $t5, $zero, 0 # CHECK: encoding: [0x64,0x0d,0x00,0x00] -daddiu $t6, $zero, 0 # CHECK: encoding: [0x64,0x0e,0x00,0x00] -daddiu $t7, $zero, 0 # CHECK: encoding: [0x64,0x0f,0x00,0x00] -daddiu $s0, $zero, 0 # CHECK: encoding: [0x64,0x10,0x00,0x00] -daddiu $s1, $zero, 0 # CHECK: encoding: [0x64,0x11,0x00,0x00] -daddiu $s2, $zero, 0 # CHECK: encoding: [0x64,0x12,0x00,0x00] -daddiu $s3, $zero, 0 # CHECK: encoding: [0x64,0x13,0x00,0x00] -daddiu $s4, $zero, 0 # CHECK: encoding: [0x64,0x14,0x00,0x00] -daddiu $s5, $zero, 0 # CHECK: encoding: [0x64,0x15,0x00,0x00] -daddiu $s6, $zero, 0 # CHECK: encoding: [0x64,0x16,0x00,0x00] -daddiu $s7, $zero, 0 # CHECK: encoding: [0x64,0x17,0x00,0x00] -daddiu $t8, $zero, 0 # CHECK: encoding: [0x64,0x18,0x00,0x00] -daddiu $t9, $zero, 0 # CHECK: encoding: [0x64,0x19,0x00,0x00] -daddiu $k0, $zero, 0 # CHECK: encoding: [0x64,0x1a,0x00,0x00] -daddiu $k1, $zero, 0 # CHECK: encoding: [0x64,0x1b,0x00,0x00] -daddiu $gp, $zero, 0 # CHECK: encoding: [0x64,0x1c,0x00,0x00] -daddiu $sp, $zero, 0 # CHECK: encoding: [0x64,0x1d,0x00,0x00] -daddiu $fp, $zero, 0 # CHECK: encoding: [0x64,0x1e,0x00,0x00] -daddiu $s8, $zero, 0 # CHECK: encoding: [0x64,0x1e,0x00,0x00] -daddiu $ra, $zero, 0 # CHECK: encoding: [0x64,0x1f,0x00,0x00] +addiu $zero, $zero, 0 # CHECK: encoding: [0x24,0x00,0x00,0x00] +addiu $at, $zero, 0 # CHECK: encoding: [0x24,0x01,0x00,0x00] +addiu $v0, $zero, 0 # CHECK: encoding: [0x24,0x02,0x00,0x00] +addiu $v1, $zero, 0 # CHECK: encoding: [0x24,0x03,0x00,0x00] +addiu $a0, $zero, 0 # CHECK: encoding: [0x24,0x04,0x00,0x00] +addiu $a1, $zero, 0 # CHECK: encoding: [0x24,0x05,0x00,0x00] +addiu $a2, $zero, 0 # CHECK: encoding: [0x24,0x06,0x00,0x00] +addiu $a3, $zero, 0 # CHECK: encoding: [0x24,0x07,0x00,0x00] +addiu $t0, $zero, 0 # CHECK: encoding: [0x24,0x08,0x00,0x00] +addiu $t1, $zero, 0 # CHECK: encoding: [0x24,0x09,0x00,0x00] +addiu $t2, $zero, 0 # CHECK: encoding: [0x24,0x0a,0x00,0x00] +addiu $t3, $zero, 0 # CHECK: encoding: [0x24,0x0b,0x00,0x00] +addiu $t4, $zero, 0 # CHECK: encoding: [0x24,0x0c,0x00,0x00] +addiu $t5, $zero, 0 # CHECK: encoding: [0x24,0x0d,0x00,0x00] +addiu $t6, $zero, 0 # CHECK: encoding: [0x24,0x0e,0x00,0x00] +addiu $t7, $zero, 0 # CHECK: encoding: [0x24,0x0f,0x00,0x00] +addiu $s0, $zero, 0 # CHECK: encoding: [0x24,0x10,0x00,0x00] +addiu $s1, $zero, 0 # CHECK: encoding: [0x24,0x11,0x00,0x00] +addiu $s2, $zero, 0 # CHECK: encoding: [0x24,0x12,0x00,0x00] +addiu $s3, $zero, 0 # CHECK: encoding: [0x24,0x13,0x00,0x00] +addiu $s4, $zero, 0 # CHECK: encoding: [0x24,0x14,0x00,0x00] +addiu $s5, $zero, 0 # CHECK: encoding: [0x24,0x15,0x00,0x00] +addiu $s6, $zero, 0 # CHECK: encoding: [0x24,0x16,0x00,0x00] +addiu $s7, $zero, 0 # CHECK: encoding: [0x24,0x17,0x00,0x00] +addiu $t8, $zero, 0 # CHECK: encoding: [0x24,0x18,0x00,0x00] +addiu $t9, $zero, 0 # CHECK: encoding: [0x24,0x19,0x00,0x00] +addiu $k0, $zero, 0 # CHECK: encoding: [0x24,0x1a,0x00,0x00] +addiu $k1, $zero, 0 # CHECK: encoding: [0x24,0x1b,0x00,0x00] +addiu $gp, $zero, 0 # CHECK: encoding: [0x24,0x1c,0x00,0x00] +addiu $sp, $zero, 0 # CHECK: encoding: [0x24,0x1d,0x00,0x00] +addiu $fp, $zero, 0 # CHECK: encoding: [0x24,0x1e,0x00,0x00] +addiu $s8, $zero, 0 # CHECK: encoding: [0x24,0x1e,0x00,0x00] +addiu $ra, $zero, 0 # CHECK: encoding: [0x24,0x1f,0x00,0x00] Index: tools/llc/llc.cpp =================================================================== --- tools/llc/llc.cpp +++ tools/llc/llc.cpp @@ -400,7 +400,15 @@ Options.MCOptions.MCUseDwarfDirectory = EnableDwarfDirectory; Options.MCOptions.AsmVerbose = AsmVerbose; Options.MCOptions.PreserveAsmComments = PreserveComments; - Options.MCOptions.ABIName = MABI; + + // Adjust the triple if we can. Otherwise put the ABI name in + // MCTargetOptions::ABIName. + std::tie(TheTriple, Options.MCOptions.ABIName) = + TheTriple.getABIVariant(MABI); + if (TheTriple.getArch() == Triple::UnknownArch) { + errs() << argv[0] << ": error: invalid -mabi value.\n"; + return 1; + } std::unique_ptr Target( TheTarget->createTargetMachine(TheTriple.getTriple(), CPUStr, FeaturesStr, Index: tools/llvm-mc/llvm-mc.cpp =================================================================== --- tools/llvm-mc/llvm-mc.cpp +++ tools/llvm-mc/llvm-mc.cpp @@ -475,8 +475,16 @@ if (!TheTarget) return 1; + // Adjust the triple if we can. Otherwise put the ABI name in + // MCTargetOptions::ABIName. MCTargetOptions MCOptions = InitMCTargetOptionsFromFlags(); - MCOptions.ABIName = MABI; + Triple TT; + std::tie(TT, MCOptions.ABIName) = Triple(TripleName).getABIVariant(MABI); + if (TT.getArch() == Triple::UnknownArch) { + errs() << ProgName << ": error: invalid -mabi value\n"; + return 1; + } + TripleName = TT.str(); // Now that GetTarget() has (potentially) replaced TripleName, it's safe to // construct the Triple object. Index: unittests/ADT/TripleTest.cpp =================================================================== --- unittests/ADT/TripleTest.cpp +++ unittests/ADT/TripleTest.cpp @@ -254,6 +254,42 @@ EXPECT_EQ(Triple::AMDHSA, T.getOS()); EXPECT_EQ(Triple::OpenCL, T.getEnvironment()); + T = Triple("mips-mti-linux-gnu"); + EXPECT_EQ(Triple::mips, T.getArch()); + EXPECT_EQ(Triple::MipsTechnologies, T.getVendor()); + EXPECT_EQ(Triple::Linux, T.getOS()); + EXPECT_EQ(Triple::GNU, T.getEnvironment()); + + T = Triple("mipsel-img-linux-gnu"); + EXPECT_EQ(Triple::mipsel, T.getArch()); + EXPECT_EQ(Triple::ImaginationTechnologies, T.getVendor()); + EXPECT_EQ(Triple::Linux, T.getOS()); + EXPECT_EQ(Triple::GNU, T.getEnvironment()); + + T = Triple("mips64-mti-linux-gnu"); + EXPECT_EQ(Triple::mips64, T.getArch()); + EXPECT_EQ(Triple::MipsTechnologies, T.getVendor()); + EXPECT_EQ(Triple::Linux, T.getOS()); + EXPECT_EQ(Triple::GNU, T.getEnvironment()); + + T = Triple("mips64el-img-linux-gnu"); + EXPECT_EQ(Triple::mips64el, T.getArch()); + EXPECT_EQ(Triple::ImaginationTechnologies, T.getVendor()); + EXPECT_EQ(Triple::Linux, T.getOS()); + EXPECT_EQ(Triple::GNU, T.getEnvironment()); + + T = Triple("mips64el-img-linux-gnuabin32"); + EXPECT_EQ(Triple::mips64el, T.getArch()); + EXPECT_EQ(Triple::ImaginationTechnologies, T.getVendor()); + EXPECT_EQ(Triple::Linux, T.getOS()); + EXPECT_EQ(Triple::GNUABIN32, T.getEnvironment()); + + T = Triple("mips64el-unknown-linux-gnuabi64"); + EXPECT_EQ(Triple::mips64el, T.getArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::Linux, T.getOS()); + EXPECT_EQ(Triple::GNUABI64, T.getEnvironment()); + T = Triple("huh"); EXPECT_EQ(Triple::UnknownArch, T.getArch()); } @@ -729,6 +765,155 @@ EXPECT_EQ(Triple::UnknownArch, T.getLittleEndianArchVariant().getArch()); } +TEST(TripleTest, ABIVariants) { + Triple T, MutatedT; + StringRef MutatedABI; + EXPECT_EQ(Triple::UnknownArch, T.getABIVariant("").first.getArch()); + EXPECT_EQ(Triple::UnknownArch, T.getABIVariant("32").first.getArch()); + + T.setArch(Triple::UnknownArch); + EXPECT_EQ(Triple::UnknownArch, T.getABIVariant("").first.getArch()); + EXPECT_EQ(Triple::UnknownArch, T.getABIVariant("32").first.getArch()); + + // Try a triple that doesn't mutate the triple in getABIVariant(). + // This should leave the triple and abi unchanged. + T = Triple("x86_64-pc-linux-gnu"); + std::tie(MutatedT, MutatedABI) = T.getABIVariant(""); + EXPECT_EQ(T, MutatedT); + EXPECT_EQ("", MutatedABI); + + // Try an unsupported ABI name. This should change the arch component of the + // triple to UnknownArch. Other parts of the result are undefined. + std::tie(MutatedT, MutatedABI) = T.getABIVariant("32"); + EXPECT_EQ(Triple::UnknownArch, MutatedT.getArch()); + + for (const auto &TripleStr : + {"mips-linux-gnu", "mipsel-linux-gnu", "mips-mti-linux-gnu", + "mipsel-img-linux-gnu", "mips64-linux-gnu", "mips64el-linux-gnu", + "mips64-mti-linux-gnu", "mips64el-img-linux-gnu"}) { + T = Triple(Triple::normalize(TripleStr)); + std::pair Default = T.getABIVariant(""); + std::pair O32 = T.getABIVariant("o32"); + std::pair N32 = T.getABIVariant("n32"); + std::pair N64 = T.getABIVariant("n64"); + + EXPECT_EQ(T.getArch(), Default.first.getArch()); + EXPECT_EQ(T.get32BitArchVariant().getArch(), O32.first.getArch()); + EXPECT_EQ(T.get64BitArchVariant().getArch(), N32.first.getArch()); + EXPECT_EQ(T.get64BitArchVariant().getArch(), N64.first.getArch()); + + EXPECT_EQ(T.getVendor(), Default.first.getVendor()); + EXPECT_EQ(T.getVendor(), O32.first.getVendor()); + EXPECT_EQ(T.getVendor(), N32.first.getVendor()); + EXPECT_EQ(T.getVendor(), N64.first.getVendor()); + + EXPECT_EQ(T.getOS(), Default.first.getOS()); + EXPECT_EQ(T.getOS(), O32.first.getOS()); + EXPECT_EQ(T.getOS(), N32.first.getOS()); + EXPECT_EQ(T.getOS(), N64.first.getOS()); + + EXPECT_EQ((T.getArch() == Triple::mips64 || T.getArch() == Triple::mips64el) + ? Triple::GNUABI64 + : Triple::GNUABI32, + Default.first.getEnvironment()); + EXPECT_EQ(Triple::GNUABI32, O32.first.getEnvironment()); + EXPECT_EQ(Triple::GNUABIN32, N32.first.getEnvironment()); + EXPECT_EQ(Triple::GNUABI64, N64.first.getEnvironment()); + + EXPECT_EQ("", Default.second); + EXPECT_EQ("", O32.second); + EXPECT_EQ("", N32.second); + EXPECT_EQ("", N64.second); + + // Try an unsupported ABI name. This should change the arch component of the + // triple to UnknownArch. Other values are undefined. + std::pair Foo = T.getABIVariant("foo"); + EXPECT_EQ(Triple::UnknownArch, Foo.first.getArch()); + } + + for (const auto &TripleStr : + {"mipsel-linux-android", "mips64el-linux-android"}) { + T = Triple(Triple::normalize(TripleStr)); + std::pair Default = T.getABIVariant(""); + std::pair O32 = T.getABIVariant("o32"); + std::pair N32 = T.getABIVariant("n32"); + std::pair N64 = T.getABIVariant("n64"); + + EXPECT_EQ(T.getArch(), Default.first.getArch()); + EXPECT_EQ(T.get32BitArchVariant().getArch(), O32.first.getArch()); + EXPECT_EQ(T.get64BitArchVariant().getArch(), N64.first.getArch()); + + EXPECT_EQ(T.getVendor(), Default.first.getVendor()); + EXPECT_EQ(T.getVendor(), O32.first.getVendor()); + EXPECT_EQ(T.getVendor(), N64.first.getVendor()); + + EXPECT_EQ(T.getOS(), Default.first.getOS()); + EXPECT_EQ(T.getOS(), O32.first.getOS()); + EXPECT_EQ(T.getOS(), N64.first.getOS()); + + EXPECT_EQ((T.getArch() == Triple::mips64 || T.getArch() == Triple::mips64el) + ? Triple::AndroidABI64 + : Triple::AndroidABI32, + Default.first.getEnvironment()); + EXPECT_EQ(Triple::AndroidABI32, O32.first.getEnvironment()); + EXPECT_EQ(Triple::AndroidABI64, N64.first.getEnvironment()); + + EXPECT_EQ("", Default.second); + EXPECT_EQ("", O32.second); + EXPECT_EQ("", N64.second); + + // Try an unsupported ABI name. This should change the arch component of the + // triple to UnknownArch. Other values are undefined. + std::pair Foo = T.getABIVariant("foo"); + EXPECT_EQ(Triple::UnknownArch, Foo.first.getArch()); + + // N32 is known to LLVM but unsupported for Android. + EXPECT_EQ(Triple::UnknownArch, N32.first.getArch()); + } + + for (const auto &TripleStr : + {"mips-linux", "mipsel-linux", "mips-mti-linux", "mipsel-img-linux", + "mips-unknown-freebsd", "mips64-linux", "mips64el-linux", + "mips64-mti-linux", "mips64el-img-linux", "mips64-unknown-freebsd"}) { + T = Triple(Triple::normalize(TripleStr)); + std::pair Default = T.getABIVariant(""); + std::pair O32 = T.getABIVariant("o32"); + std::pair N32 = T.getABIVariant("n32"); + std::pair N64 = T.getABIVariant("n64"); + std::pair Foo = T.getABIVariant("foo"); + + EXPECT_EQ(T.getArch(), Default.first.getArch()); + EXPECT_EQ(T.get32BitArchVariant().getArch(), O32.first.getArch()); + EXPECT_EQ(T.get64BitArchVariant().getArch(), N32.first.getArch()); + EXPECT_EQ(T.get64BitArchVariant().getArch(), N64.first.getArch()); + EXPECT_EQ(Triple::UnknownArch, Foo.first.getArch()); + + EXPECT_EQ(T.getVendor(), Default.first.getVendor()); + EXPECT_EQ(T.getVendor(), O32.first.getVendor()); + EXPECT_EQ(T.getVendor(), N32.first.getVendor()); + EXPECT_EQ(T.getVendor(), N64.first.getVendor()); + + EXPECT_EQ(T.getOS(), Default.first.getOS()); + EXPECT_EQ(T.getOS(), O32.first.getOS()); + EXPECT_EQ(T.getOS(), N32.first.getOS()); + EXPECT_EQ(T.getOS(), N64.first.getOS()); + + EXPECT_EQ((T.getArch() == Triple::mips64 || T.getArch() == Triple::mips64el) + ? Triple::ABI64 + : Triple::ABI32, + Default.first.getEnvironment()); + EXPECT_EQ(Triple::ABI32, O32.first.getEnvironment()); + EXPECT_EQ(Triple::ABIN32, N32.first.getEnvironment()); + EXPECT_EQ(Triple::ABI64, N64.first.getEnvironment()); + + EXPECT_EQ("", Default.second); + EXPECT_EQ("", O32.second); + EXPECT_EQ("", N32.second); + EXPECT_EQ("", N64.second); + EXPECT_EQ("foo", Foo.second); + } +} + TEST(TripleTest, getOSVersion) { Triple T; unsigned Major, Minor, Micro;