summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/Basic/Targets.cpp108
-rw-r--r--clang/lib/CodeGen/TargetInfo.cpp74
-rw-r--r--clang/lib/Driver/Driver.cpp3
-rw-r--r--clang/lib/Driver/ToolChains.h8
-rw-r--r--clang/lib/Driver/Tools.cpp37
-rw-r--r--clang/lib/Driver/Tools.h2
-rw-r--r--clang/test/CodeGen/lanai-arguments.c75
-rw-r--r--clang/test/CodeGen/lanai-regparm.c18
-rw-r--r--clang/test/CodeGen/target-data.c4
-rw-r--r--clang/test/Driver/lanai-toolchain.c2
-rw-r--r--clang/test/Driver/lanai-unknown-unknown.cpp86
-rw-r--r--clang/test/Preprocessor/init.c3
12 files changed, 420 insertions, 0 deletions
diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp
index d55a1c7c4fc..95c9a6e56ee 100644
--- a/clang/lib/Basic/Targets.cpp
+++ b/clang/lib/Basic/Targets.cpp
@@ -5950,6 +5950,111 @@ const Builtin::Info HexagonTargetInfo::BuiltinInfo[] = {
#include "clang/Basic/BuiltinsHexagon.def"
};
+class LanaiTargetInfo : public TargetInfo {
+ // Class for Lanai (32-bit).
+ // The CPU profiles supported by the Lanai backend
+ enum CPUKind {
+ CK_NONE,
+ CK_V11,
+ } CPU;
+
+ static const TargetInfo::GCCRegAlias GCCRegAliases[];
+ static const char *const GCCRegNames[];
+
+public:
+ LanaiTargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) {
+ // Description string has to be kept in sync with backend.
+ resetDataLayout("E" // Big endian
+ "-m:e" // ELF name manging
+ "-p:32:32" // 32 bit pointers, 32 bit aligned
+ "-i64:64" // 64 bit integers, 64 bit aligned
+ "-a:0:32" // 32 bit alignment of objects of aggregate type
+ "-n32" // 32 bit native integer width
+ "-S64" // 64 bit natural stack alignment
+ );
+
+ // Setting RegParmMax equal to what mregparm was set to in the old
+ // toolchain
+ RegParmMax = 4;
+
+ // Set the default CPU to V11
+ CPU = CK_V11;
+
+ // Temporary approach to make everything at least word-aligned and allow for
+ // safely casting between pointers with different alignment requirements.
+ // TODO: Remove this when there are no more cast align warnings on the
+ // firmware.
+ MinGlobalAlign = 32;
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ // Define __lanai__ when building for target lanai.
+ Builder.defineMacro("__lanai__");
+
+ // Set define for the CPU specified.
+ switch (CPU) {
+ case CK_V11:
+ Builder.defineMacro("__LANAI_V11__");
+ break;
+ case CK_NONE:
+ llvm_unreachable("Unhandled target CPU");
+ }
+ }
+
+ bool setCPU(const std::string &Name) override {
+ CPU = llvm::StringSwitch<CPUKind>(Name)
+ .Case("v11", CK_V11)
+ .Default(CK_NONE);
+
+ return CPU != CK_NONE;
+ }
+
+ bool hasFeature(StringRef Feature) const override {
+ return llvm::StringSwitch<bool>(Feature).Case("lanai", true).Default(false);
+ }
+
+ ArrayRef<const char *> getGCCRegNames() const override;
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::VoidPtrBuiltinVaList;
+ }
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override { return None; }
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &info) const override {
+ return false;
+ }
+
+ const char *getClobbers() const override { return ""; }
+};
+
+const char *const LanaiTargetInfo::GCCRegNames[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
+ "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", "r21",
+ "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"};
+
+ArrayRef<const char *> LanaiTargetInfo::getGCCRegNames() const {
+ return llvm::makeArrayRef(GCCRegNames);
+}
+
+const TargetInfo::GCCRegAlias LanaiTargetInfo::GCCRegAliases[] = {
+ {{"pc"}, "r2"},
+ {{"sp"}, "r4"},
+ {{"fp"}, "r5"},
+ {{"rv"}, "r8"},
+ {{"rr1"}, "r10"},
+ {{"rr2"}, "r11"},
+ {{"rca"}, "r15"},
+};
+
+ArrayRef<TargetInfo::GCCRegAlias> LanaiTargetInfo::getGCCRegAliases() const {
+ return llvm::makeArrayRef(GCCRegAliases);
+}
+
// Shared base class for SPARC v8 (32-bit) and SPARC v9 (64-bit).
class SparcTargetInfo : public TargetInfo {
static const TargetInfo::GCCRegAlias GCCRegAliases[];
@@ -7672,6 +7777,9 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple) {
case llvm::Triple::hexagon:
return new HexagonTargetInfo(Triple);
+ case llvm::Triple::lanai:
+ return new LanaiTargetInfo(Triple);
+
case llvm::Triple::aarch64:
if (Triple.isOSDarwin())
return new DarwinAArch64TargetInfo(Triple);
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp
index 8f300103e63..8c457fcd097 100644
--- a/clang/lib/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CodeGen/TargetInfo.cpp
@@ -6583,6 +6583,78 @@ Address HexagonABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
}
//===----------------------------------------------------------------------===//
+// Lanai ABI Implementation
+//===----------------------------------------------------------------------===//
+
+class LanaiABIInfo : public DefaultABIInfo {
+public:
+ LanaiABIInfo(CodeGen::CodeGenTypes &CGT) : DefaultABIInfo(CGT) {}
+
+ bool shouldUseInReg(QualType Ty, CCState &State) const;
+
+ void computeInfo(CGFunctionInfo &FI) const override {
+ CCState State(FI.getCallingConvention());
+ // Lanai uses 4 registers to pass arguments unless the function has the
+ // regparm attribute set.
+ if (FI.getHasRegParm()) {
+ State.FreeRegs = FI.getRegParm();
+ } else {
+ State.FreeRegs = 4;
+ }
+
+ if (!getCXXABI().classifyReturnType(FI))
+ FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+ for (auto &I : FI.arguments())
+ I.info = classifyArgumentType(I.type, State);
+ }
+
+ ABIArgInfo classifyArgumentType(QualType RetTy, CCState &State) const;
+};
+
+bool LanaiABIInfo::shouldUseInReg(QualType Ty, CCState &State) const {
+ unsigned Size = getContext().getTypeSize(Ty);
+ unsigned SizeInRegs = llvm::alignTo(Size, 32U) / 32U;
+
+ if (SizeInRegs == 0)
+ return false;
+
+ if (SizeInRegs > State.FreeRegs) {
+ State.FreeRegs = 0;
+ return false;
+ }
+
+ State.FreeRegs -= SizeInRegs;
+
+ return true;
+}
+
+ABIArgInfo LanaiABIInfo::classifyArgumentType(QualType Ty,
+ CCState &State) const {
+ if (isAggregateTypeForABI(Ty))
+ return getNaturalAlignIndirect(Ty);
+
+ // Treat an enum type as its underlying type.
+ if (const auto *EnumTy = Ty->getAs<EnumType>())
+ Ty = EnumTy->getDecl()->getIntegerType();
+
+ if (shouldUseInReg(Ty, State))
+ return ABIArgInfo::getDirectInReg();
+
+ if (Ty->isPromotableIntegerType())
+ return ABIArgInfo::getExtend();
+
+ return ABIArgInfo::getDirect();
+}
+
+namespace {
+class LanaiTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+ LanaiTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
+ : TargetCodeGenInfo(new LanaiABIInfo(CGT)) {}
+};
+}
+
+//===----------------------------------------------------------------------===//
// AMDGPU ABI Implementation
//===----------------------------------------------------------------------===//
@@ -7740,6 +7812,8 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
}
case llvm::Triple::hexagon:
return *(TheTargetCodeGenInfo = new HexagonTargetCodeGenInfo(Types));
+ case llvm::Triple::lanai:
+ return *(TheTargetCodeGenInfo = new LanaiTargetCodeGenInfo(Types));
case llvm::Triple::r600:
return *(TheTargetCodeGenInfo = new AMDGPUTargetCodeGenInfo(Types));
case llvm::Triple::amdgcn:
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 75dcfc96cd8..e434e68c7b9 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -2459,6 +2459,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
case llvm::Triple::hexagon:
TC = new toolchains::HexagonToolChain(*this, Target, Args);
break;
+ case llvm::Triple::lanai:
+ TC = new toolchains::LanaiToolChain(*this, Target, Args);
+ break;
case llvm::Triple::xcore:
TC = new toolchains::XCoreToolChain(*this, Target, Args);
break;
diff --git a/clang/lib/Driver/ToolChains.h b/clang/lib/Driver/ToolChains.h
index 458fd03feda..49283a9c201 100644
--- a/clang/lib/Driver/ToolChains.h
+++ b/clang/lib/Driver/ToolChains.h
@@ -874,6 +874,14 @@ private:
std::string LibSuffix;
};
+class LLVM_LIBRARY_VISIBILITY LanaiToolChain : public Generic_ELF {
+public:
+ LanaiToolChain(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args)
+ : Generic_ELF(D, Triple, Args) {}
+ bool IsIntegratedAssemblerDefault() const override { return true; }
+};
+
class LLVM_LIBRARY_VISIBILITY HexagonToolChain : public Linux {
protected:
GCCVersion GCCLibAndIncVersion;
diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp
index e725e5af488..118e1afb214 100644
--- a/clang/lib/Driver/Tools.cpp
+++ b/clang/lib/Driver/Tools.cpp
@@ -1619,6 +1619,13 @@ static std::string getR600TargetGPU(const ArgList &Args) {
return "";
}
+static std::string getLanaiTargetCPU(const ArgList &Args) {
+ if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
+ return A->getValue();
+ }
+ return "";
+}
+
void Clang::AddSparcTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
const Driver &D = getToolChain().getDriver();
@@ -1836,6 +1843,9 @@ static std::string getCPUName(const ArgList &Args, const llvm::Triple &T,
return "hexagon" +
toolchains::HexagonToolChain::GetTargetCPUVersion(Args).str();
+ case llvm::Triple::lanai:
+ return getLanaiTargetCPU(Args);
+
case llvm::Triple::systemz:
return getSystemZTargetCPU(Args);
@@ -2145,6 +2155,29 @@ void Clang::AddHexagonTargetArgs(const ArgList &Args,
CmdArgs.push_back("-machine-sink-split=0");
}
+void Clang::AddLanaiTargetArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
+ StringRef CPUName = A->getValue();
+
+ CmdArgs.push_back("-target-cpu");
+ CmdArgs.push_back(Args.MakeArgString(CPUName));
+ }
+ if (Arg *A = Args.getLastArg(options::OPT_mregparm_EQ)) {
+ StringRef Value = A->getValue();
+ // Only support mregparm=4 to support old usage. Report error for all other
+ // cases.
+ int Mregparm;
+ if (Value.getAsInteger(10, Mregparm)) {
+ if (Mregparm != 4) {
+ getToolChain().getDriver().Diag(
+ diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << Value;
+ }
+ }
+ }
+}
+
void Clang::AddWebAssemblyTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
// Default to "hidden" visibility.
@@ -4176,6 +4209,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
AddX86TargetArgs(Args, CmdArgs);
break;
+ case llvm::Triple::lanai:
+ AddLanaiTargetArgs(Args, CmdArgs);
+ break;
+
case llvm::Triple::hexagon:
AddHexagonTargetArgs(Args, CmdArgs);
break;
diff --git a/clang/lib/Driver/Tools.h b/clang/lib/Driver/Tools.h
index 6884cd42f3b..c9d5c2238d6 100644
--- a/clang/lib/Driver/Tools.h
+++ b/clang/lib/Driver/Tools.h
@@ -82,6 +82,8 @@ private:
llvm::opt::ArgStringList &CmdArgs) const;
void AddHexagonTargetArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
+ void AddLanaiTargetArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
void AddWebAssemblyTargetArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
diff --git a/clang/test/CodeGen/lanai-arguments.c b/clang/test/CodeGen/lanai-arguments.c
new file mode 100644
index 00000000000..43a6c3280c7
--- /dev/null
+++ b/clang/test/CodeGen/lanai-arguments.c
@@ -0,0 +1,75 @@
+// RUN: %clang_cc1 -triple lanai-unknown-unknown %s -emit-llvm -o - \
+// RUN: | FileCheck %s
+
+// Basic argument/attribute tests for Lanai.
+
+// CHECK: define void @f0(i32 inreg %i, i32 inreg %j, i64 inreg %k)
+void f0(int i, long j, long long k) {}
+
+typedef struct {
+ int aa;
+ int bb;
+} s1;
+// CHECK: define void @f1(%struct.s1* byval align 4 %i)
+void f1(s1 i) {}
+
+typedef struct {
+ int cc;
+} s2;
+// CHECK: define void @f2(%struct.s2* noalias sret %agg.result)
+s2 f2() {
+ s2 foo;
+ return foo;
+}
+
+typedef struct {
+ int cc;
+ int dd;
+} s3;
+// CHECK: define void @f3(%struct.s3* noalias sret %agg.result)
+s3 f3() {
+ s3 foo;
+ return foo;
+}
+
+// CHECK: define void @f4(i64 inreg %i)
+void f4(long long i) {}
+
+// CHECK: define void @f5(i8 inreg %a, i16 inreg %b)
+void f5(char a, short b) {}
+
+// CHECK: define void @f6(i8 inreg %a, i16 inreg %b)
+void f6(unsigned char a, unsigned short b) {}
+
+enum my_enum {
+ ENUM1,
+ ENUM2,
+ ENUM3,
+};
+// Enums should be treated as the underlying i32.
+// CHECK: define void @f7(i32 inreg %a)
+void f7(enum my_enum a) {}
+
+enum my_big_enum {
+ ENUM4 = 0xFFFFFFFFFFFFFFFF,
+};
+// Big enums should be treated as the underlying i64.
+// CHECK: define void @f8(i64 inreg %a)
+void f8(enum my_big_enum a) {}
+
+union simple_union {
+ int a;
+ char b;
+};
+// Unions should be passed as byval structs.
+// CHECK: define void @f9(%union.simple_union* byval align 4 %s)
+void f9(union simple_union s) {}
+
+typedef struct {
+ int b4 : 4;
+ int b3 : 3;
+ int b8 : 8;
+} bitfield1;
+// Bitfields should be passed as byval structs.
+// CHECK: define void @f10(%struct.bitfield1* byval align 4 %bf1)
+void f10(bitfield1 bf1) {}
diff --git a/clang/test/CodeGen/lanai-regparm.c b/clang/test/CodeGen/lanai-regparm.c
new file mode 100644
index 00000000000..c315f43bca7
--- /dev/null
+++ b/clang/test/CodeGen/lanai-regparm.c
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -triple lanai-unknown-unknown -mregparm 4 %s -emit-llvm -o - | FileCheck %s
+
+void f1(int a, int b, int c, int d,
+ int e, int f, int g, int h);
+
+void f2(int a, int b) __attribute((regparm(0)));
+
+void f0() {
+// CHECK: call void @f1(i32 inreg 1, i32 inreg 2, i32 inreg 3, i32 inreg 4,
+// CHECK: i32 5, i32 6, i32 7, i32 8)
+ f1(1, 2, 3, 4, 5, 6, 7, 8);
+// CHECK: call void @f2(i32 1, i32 2)
+ f2(1, 2);
+}
+
+// CHECK: declare void @f1(i32 inreg, i32 inreg, i32 inreg, i32 inreg,
+// CHECK: i32, i32, i32, i32)
+// CHECK: declare void @f2(i32, i32)
diff --git a/clang/test/CodeGen/target-data.c b/clang/test/CodeGen/target-data.c
index a2c02be9491..760cb633d5b 100644
--- a/clang/test/CodeGen/target-data.c
+++ b/clang/test/CodeGen/target-data.c
@@ -86,6 +86,10 @@
// RUN: FileCheck %s -check-prefix=WEBASSEMBLY64
// WEBASSEMBLY64: target datalayout = "e-m:e-p:64:64-i64:64-n32:64-S128"
+// RUN: %clang_cc1 -triple lanai-unknown-unknown -o - -emit-llvm %s | \
+// RUN: FileCheck %s -check-prefix=LANAI
+// LANAI: target datalayout = "E-m:e-p:32:32-i64:64-a:0:32-n32-S64"
+
// RUN: %clang_cc1 -triple powerpc-unknown -o - -emit-llvm %s | \
// RUN: FileCheck %s -check-prefix=PPC
// PPC: target datalayout = "E-m:e-p:32:32-i64:64-n32"
diff --git a/clang/test/Driver/lanai-toolchain.c b/clang/test/Driver/lanai-toolchain.c
new file mode 100644
index 00000000000..55236665a24
--- /dev/null
+++ b/clang/test/Driver/lanai-toolchain.c
@@ -0,0 +1,2 @@
+// RUN: %clang -target lanai-unknown-unknown -v 2> %t
+// RUN: grep 'Target: lanai-unknown-unknown' %t
diff --git a/clang/test/Driver/lanai-unknown-unknown.cpp b/clang/test/Driver/lanai-unknown-unknown.cpp
new file mode 100644
index 00000000000..5ce0adf9f3a
--- /dev/null
+++ b/clang/test/Driver/lanai-unknown-unknown.cpp
@@ -0,0 +1,86 @@
+// RUN: %clang -target lanai-unknown-unknown -### %s -emit-llvm-only -c 2>&1 \
+// RUN: | FileCheck %s -check-prefix=ECHO
+// RUN: %clang -target lanai-unknown-unknown %s -emit-llvm -S -o - \
+// RUN: | FileCheck %s
+
+// ECHO: {{.*}} "-cc1" {{.*}}lanai-unknown-unknown.c
+
+typedef __builtin_va_list va_list;
+typedef __SIZE_TYPE__ size_t;
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+
+extern "C" {
+
+// CHECK: @align_c = global i32 1
+int align_c = __alignof(char);
+
+// CHECK: @align_s = global i32 2
+int align_s = __alignof(short);
+
+// CHECK: @align_i = global i32 4
+int align_i = __alignof(int);
+
+// CHECK: @align_l = global i32 4
+int align_l = __alignof(long);
+
+// CHECK: @align_ll = global i32 8
+int align_ll = __alignof(long long);
+
+// CHECK: @align_p = global i32 4
+int align_p = __alignof(void*);
+
+// CHECK: @align_vl = global i32 4
+int align_vl = __alignof(va_list);
+
+// Check types
+
+// CHECK: signext i8 @check_char()
+char check_char() { return 0; }
+
+// CHECK: signext i16 @check_short()
+short check_short() { return 0; }
+
+// CHECK: i32 @check_int()
+int check_int() { return 0; }
+
+// CHECK: i32 @check_long()
+long check_long() { return 0; }
+
+// CHECK: i64 @check_longlong()
+long long check_longlong() { return 0; }
+
+// CHECK: zeroext i8 @check_uchar()
+unsigned char check_uchar() { return 0; }
+
+// CHECK: zeroext i16 @check_ushort()
+unsigned short check_ushort() { return 0; }
+
+// CHECK: i32 @check_uint()
+unsigned int check_uint() { return 0; }
+
+// CHECK: i32 @check_ulong()
+unsigned long check_ulong() { return 0; }
+
+// CHECK: i64 @check_ulonglong()
+unsigned long long check_ulonglong() { return 0; }
+
+// CHECK: i32 @check_size_t()
+size_t check_size_t() { return 0; }
+
+}
+
+template<int> void Switch();
+template<> void Switch<4>();
+template<> void Switch<8>();
+template<> void Switch<16>();
+
+void check_pointer_size() {
+ // CHECK: SwitchILi4
+ Switch<sizeof(void*)>();
+
+ // CHECK: SwitchILi8
+ Switch<sizeof(long long)>();
+
+ // CHECK: SwitchILi4
+ Switch<sizeof(va_list)>();
+}
diff --git a/clang/test/Preprocessor/init.c b/clang/test/Preprocessor/init.c
index 7ec4521665b..dbd4de605e5 100644
--- a/clang/test/Preprocessor/init.c
+++ b/clang/test/Preprocessor/init.c
@@ -8414,6 +8414,9 @@
// RUN: %clang_cc1 -triple arm-linux-androideabi -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix ANDROID %s
// ANDROID:#define __ANDROID__ 1
//
+// RUN: %clang_cc1 -triple lanai-unknown-unknown -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix LANAI %s
+// LANAI: #define __lanai__ 1
+//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-unknown-freebsd < /dev/null | FileCheck -match-full-lines -check-prefix PPC64-FREEBSD %s
// PPC64-FREEBSD-NOT: #define __LONG_DOUBLE_128__ 1
//
OpenPOWER on IntegriCloud