Skip to content

Commit d964cc2

Browse files
committedMar 28, 2016
[lanai] Add Lanai backend to clang driver.
Changes to clang to add Lanai backend. Adds a new target, ABI and toolchain. General Lanai backend discussion on llvm-dev thread "[RFC] Lanai backend" (http://lists.llvm.org/pipermail/llvm-dev/2016-February/095118.html). Differential Revision: http://reviews.llvm.org/D17002 llvm-svn: 264655
1 parent 83c3bd3 commit d964cc2

12 files changed

+420
-0
lines changed
 

‎clang/lib/Basic/Targets.cpp

+108
Original file line numberDiff line numberDiff line change
@@ -5950,6 +5950,111 @@ const Builtin::Info HexagonTargetInfo::BuiltinInfo[] = {
59505950
#include "clang/Basic/BuiltinsHexagon.def"
59515951
};
59525952

5953+
class LanaiTargetInfo : public TargetInfo {
5954+
// Class for Lanai (32-bit).
5955+
// The CPU profiles supported by the Lanai backend
5956+
enum CPUKind {
5957+
CK_NONE,
5958+
CK_V11,
5959+
} CPU;
5960+
5961+
static const TargetInfo::GCCRegAlias GCCRegAliases[];
5962+
static const char *const GCCRegNames[];
5963+
5964+
public:
5965+
LanaiTargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) {
5966+
// Description string has to be kept in sync with backend.
5967+
resetDataLayout("E" // Big endian
5968+
"-m:e" // ELF name manging
5969+
"-p:32:32" // 32 bit pointers, 32 bit aligned
5970+
"-i64:64" // 64 bit integers, 64 bit aligned
5971+
"-a:0:32" // 32 bit alignment of objects of aggregate type
5972+
"-n32" // 32 bit native integer width
5973+
"-S64" // 64 bit natural stack alignment
5974+
);
5975+
5976+
// Setting RegParmMax equal to what mregparm was set to in the old
5977+
// toolchain
5978+
RegParmMax = 4;
5979+
5980+
// Set the default CPU to V11
5981+
CPU = CK_V11;
5982+
5983+
// Temporary approach to make everything at least word-aligned and allow for
5984+
// safely casting between pointers with different alignment requirements.
5985+
// TODO: Remove this when there are no more cast align warnings on the
5986+
// firmware.
5987+
MinGlobalAlign = 32;
5988+
}
5989+
5990+
void getTargetDefines(const LangOptions &Opts,
5991+
MacroBuilder &Builder) const override {
5992+
// Define __lanai__ when building for target lanai.
5993+
Builder.defineMacro("__lanai__");
5994+
5995+
// Set define for the CPU specified.
5996+
switch (CPU) {
5997+
case CK_V11:
5998+
Builder.defineMacro("__LANAI_V11__");
5999+
break;
6000+
case CK_NONE:
6001+
llvm_unreachable("Unhandled target CPU");
6002+
}
6003+
}
6004+
6005+
bool setCPU(const std::string &Name) override {
6006+
CPU = llvm::StringSwitch<CPUKind>(Name)
6007+
.Case("v11", CK_V11)
6008+
.Default(CK_NONE);
6009+
6010+
return CPU != CK_NONE;
6011+
}
6012+
6013+
bool hasFeature(StringRef Feature) const override {
6014+
return llvm::StringSwitch<bool>(Feature).Case("lanai", true).Default(false);
6015+
}
6016+
6017+
ArrayRef<const char *> getGCCRegNames() const override;
6018+
6019+
ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
6020+
6021+
BuiltinVaListKind getBuiltinVaListKind() const override {
6022+
return TargetInfo::VoidPtrBuiltinVaList;
6023+
}
6024+
6025+
ArrayRef<Builtin::Info> getTargetBuiltins() const override { return None; }
6026+
6027+
bool validateAsmConstraint(const char *&Name,
6028+
TargetInfo::ConstraintInfo &info) const override {
6029+
return false;
6030+
}
6031+
6032+
const char *getClobbers() const override { return ""; }
6033+
};
6034+
6035+
const char *const LanaiTargetInfo::GCCRegNames[] = {
6036+
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
6037+
"r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", "r21",
6038+
"r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"};
6039+
6040+
ArrayRef<const char *> LanaiTargetInfo::getGCCRegNames() const {
6041+
return llvm::makeArrayRef(GCCRegNames);
6042+
}
6043+
6044+
const TargetInfo::GCCRegAlias LanaiTargetInfo::GCCRegAliases[] = {
6045+
{{"pc"}, "r2"},
6046+
{{"sp"}, "r4"},
6047+
{{"fp"}, "r5"},
6048+
{{"rv"}, "r8"},
6049+
{{"rr1"}, "r10"},
6050+
{{"rr2"}, "r11"},
6051+
{{"rca"}, "r15"},
6052+
};
6053+
6054+
ArrayRef<TargetInfo::GCCRegAlias> LanaiTargetInfo::getGCCRegAliases() const {
6055+
return llvm::makeArrayRef(GCCRegAliases);
6056+
}
6057+
59536058
// Shared base class for SPARC v8 (32-bit) and SPARC v9 (64-bit).
59546059
class SparcTargetInfo : public TargetInfo {
59556060
static const TargetInfo::GCCRegAlias GCCRegAliases[];
@@ -7672,6 +7777,9 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple) {
76727777
case llvm::Triple::hexagon:
76737778
return new HexagonTargetInfo(Triple);
76747779

7780+
case llvm::Triple::lanai:
7781+
return new LanaiTargetInfo(Triple);
7782+
76757783
case llvm::Triple::aarch64:
76767784
if (Triple.isOSDarwin())
76777785
return new DarwinAArch64TargetInfo(Triple);

‎clang/lib/CodeGen/TargetInfo.cpp

+74
Original file line numberDiff line numberDiff line change
@@ -6582,6 +6582,78 @@ Address HexagonABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
65826582
/*AllowHigherAlign*/ true);
65836583
}
65846584

6585+
//===----------------------------------------------------------------------===//
6586+
// Lanai ABI Implementation
6587+
//===----------------------------------------------------------------------===//
6588+
6589+
class LanaiABIInfo : public DefaultABIInfo {
6590+
public:
6591+
LanaiABIInfo(CodeGen::CodeGenTypes &CGT) : DefaultABIInfo(CGT) {}
6592+
6593+
bool shouldUseInReg(QualType Ty, CCState &State) const;
6594+
6595+
void computeInfo(CGFunctionInfo &FI) const override {
6596+
CCState State(FI.getCallingConvention());
6597+
// Lanai uses 4 registers to pass arguments unless the function has the
6598+
// regparm attribute set.
6599+
if (FI.getHasRegParm()) {
6600+
State.FreeRegs = FI.getRegParm();
6601+
} else {
6602+
State.FreeRegs = 4;
6603+
}
6604+
6605+
if (!getCXXABI().classifyReturnType(FI))
6606+
FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
6607+
for (auto &I : FI.arguments())
6608+
I.info = classifyArgumentType(I.type, State);
6609+
}
6610+
6611+
ABIArgInfo classifyArgumentType(QualType RetTy, CCState &State) const;
6612+
};
6613+
6614+
bool LanaiABIInfo::shouldUseInReg(QualType Ty, CCState &State) const {
6615+
unsigned Size = getContext().getTypeSize(Ty);
6616+
unsigned SizeInRegs = llvm::alignTo(Size, 32U) / 32U;
6617+
6618+
if (SizeInRegs == 0)
6619+
return false;
6620+
6621+
if (SizeInRegs > State.FreeRegs) {
6622+
State.FreeRegs = 0;
6623+
return false;
6624+
}
6625+
6626+
State.FreeRegs -= SizeInRegs;
6627+
6628+
return true;
6629+
}
6630+
6631+
ABIArgInfo LanaiABIInfo::classifyArgumentType(QualType Ty,
6632+
CCState &State) const {
6633+
if (isAggregateTypeForABI(Ty))
6634+
return getNaturalAlignIndirect(Ty);
6635+
6636+
// Treat an enum type as its underlying type.
6637+
if (const auto *EnumTy = Ty->getAs<EnumType>())
6638+
Ty = EnumTy->getDecl()->getIntegerType();
6639+
6640+
if (shouldUseInReg(Ty, State))
6641+
return ABIArgInfo::getDirectInReg();
6642+
6643+
if (Ty->isPromotableIntegerType())
6644+
return ABIArgInfo::getExtend();
6645+
6646+
return ABIArgInfo::getDirect();
6647+
}
6648+
6649+
namespace {
6650+
class LanaiTargetCodeGenInfo : public TargetCodeGenInfo {
6651+
public:
6652+
LanaiTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
6653+
: TargetCodeGenInfo(new LanaiABIInfo(CGT)) {}
6654+
};
6655+
}
6656+
65856657
//===----------------------------------------------------------------------===//
65866658
// AMDGPU ABI Implementation
65876659
//===----------------------------------------------------------------------===//
@@ -7740,6 +7812,8 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
77407812
}
77417813
case llvm::Triple::hexagon:
77427814
return *(TheTargetCodeGenInfo = new HexagonTargetCodeGenInfo(Types));
7815+
case llvm::Triple::lanai:
7816+
return *(TheTargetCodeGenInfo = new LanaiTargetCodeGenInfo(Types));
77437817
case llvm::Triple::r600:
77447818
return *(TheTargetCodeGenInfo = new AMDGPUTargetCodeGenInfo(Types));
77457819
case llvm::Triple::amdgcn:

‎clang/lib/Driver/Driver.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -2459,6 +2459,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
24592459
case llvm::Triple::hexagon:
24602460
TC = new toolchains::HexagonToolChain(*this, Target, Args);
24612461
break;
2462+
case llvm::Triple::lanai:
2463+
TC = new toolchains::LanaiToolChain(*this, Target, Args);
2464+
break;
24622465
case llvm::Triple::xcore:
24632466
TC = new toolchains::XCoreToolChain(*this, Target, Args);
24642467
break;

‎clang/lib/Driver/ToolChains.h

+8
Original file line numberDiff line numberDiff line change
@@ -874,6 +874,14 @@ class LLVM_LIBRARY_VISIBILITY MipsLLVMToolChain : public Linux {
874874
std::string LibSuffix;
875875
};
876876

877+
class LLVM_LIBRARY_VISIBILITY LanaiToolChain : public Generic_ELF {
878+
public:
879+
LanaiToolChain(const Driver &D, const llvm::Triple &Triple,
880+
const llvm::opt::ArgList &Args)
881+
: Generic_ELF(D, Triple, Args) {}
882+
bool IsIntegratedAssemblerDefault() const override { return true; }
883+
};
884+
877885
class LLVM_LIBRARY_VISIBILITY HexagonToolChain : public Linux {
878886
protected:
879887
GCCVersion GCCLibAndIncVersion;

‎clang/lib/Driver/Tools.cpp

+37
Original file line numberDiff line numberDiff line change
@@ -1619,6 +1619,13 @@ static std::string getR600TargetGPU(const ArgList &Args) {
16191619
return "";
16201620
}
16211621

1622+
static std::string getLanaiTargetCPU(const ArgList &Args) {
1623+
if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
1624+
return A->getValue();
1625+
}
1626+
return "";
1627+
}
1628+
16221629
void Clang::AddSparcTargetArgs(const ArgList &Args,
16231630
ArgStringList &CmdArgs) const {
16241631
const Driver &D = getToolChain().getDriver();
@@ -1836,6 +1843,9 @@ static std::string getCPUName(const ArgList &Args, const llvm::Triple &T,
18361843
return "hexagon" +
18371844
toolchains::HexagonToolChain::GetTargetCPUVersion(Args).str();
18381845

1846+
case llvm::Triple::lanai:
1847+
return getLanaiTargetCPU(Args);
1848+
18391849
case llvm::Triple::systemz:
18401850
return getSystemZTargetCPU(Args);
18411851

@@ -2145,6 +2155,29 @@ void Clang::AddHexagonTargetArgs(const ArgList &Args,
21452155
CmdArgs.push_back("-machine-sink-split=0");
21462156
}
21472157

2158+
void Clang::AddLanaiTargetArgs(const ArgList &Args,
2159+
ArgStringList &CmdArgs) const {
2160+
if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
2161+
StringRef CPUName = A->getValue();
2162+
2163+
CmdArgs.push_back("-target-cpu");
2164+
CmdArgs.push_back(Args.MakeArgString(CPUName));
2165+
}
2166+
if (Arg *A = Args.getLastArg(options::OPT_mregparm_EQ)) {
2167+
StringRef Value = A->getValue();
2168+
// Only support mregparm=4 to support old usage. Report error for all other
2169+
// cases.
2170+
int Mregparm;
2171+
if (Value.getAsInteger(10, Mregparm)) {
2172+
if (Mregparm != 4) {
2173+
getToolChain().getDriver().Diag(
2174+
diag::err_drv_unsupported_option_argument)
2175+
<< A->getOption().getName() << Value;
2176+
}
2177+
}
2178+
}
2179+
}
2180+
21482181
void Clang::AddWebAssemblyTargetArgs(const ArgList &Args,
21492182
ArgStringList &CmdArgs) const {
21502183
// Default to "hidden" visibility.
@@ -4176,6 +4209,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
41764209
AddX86TargetArgs(Args, CmdArgs);
41774210
break;
41784211

4212+
case llvm::Triple::lanai:
4213+
AddLanaiTargetArgs(Args, CmdArgs);
4214+
break;
4215+
41794216
case llvm::Triple::hexagon:
41804217
AddHexagonTargetArgs(Args, CmdArgs);
41814218
break;

‎clang/lib/Driver/Tools.h

+2
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ class LLVM_LIBRARY_VISIBILITY Clang : public Tool {
8282
llvm::opt::ArgStringList &CmdArgs) const;
8383
void AddHexagonTargetArgs(const llvm::opt::ArgList &Args,
8484
llvm::opt::ArgStringList &CmdArgs) const;
85+
void AddLanaiTargetArgs(const llvm::opt::ArgList &Args,
86+
llvm::opt::ArgStringList &CmdArgs) const;
8587
void AddWebAssemblyTargetArgs(const llvm::opt::ArgList &Args,
8688
llvm::opt::ArgStringList &CmdArgs) const;
8789

‎clang/test/CodeGen/lanai-arguments.c

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// RUN: %clang_cc1 -triple lanai-unknown-unknown %s -emit-llvm -o - \
2+
// RUN: | FileCheck %s
3+
4+
// Basic argument/attribute tests for Lanai.
5+
6+
// CHECK: define void @f0(i32 inreg %i, i32 inreg %j, i64 inreg %k)
7+
void f0(int i, long j, long long k) {}
8+
9+
typedef struct {
10+
int aa;
11+
int bb;
12+
} s1;
13+
// CHECK: define void @f1(%struct.s1* byval align 4 %i)
14+
void f1(s1 i) {}
15+
16+
typedef struct {
17+
int cc;
18+
} s2;
19+
// CHECK: define void @f2(%struct.s2* noalias sret %agg.result)
20+
s2 f2() {
21+
s2 foo;
22+
return foo;
23+
}
24+
25+
typedef struct {
26+
int cc;
27+
int dd;
28+
} s3;
29+
// CHECK: define void @f3(%struct.s3* noalias sret %agg.result)
30+
s3 f3() {
31+
s3 foo;
32+
return foo;
33+
}
34+
35+
// CHECK: define void @f4(i64 inreg %i)
36+
void f4(long long i) {}
37+
38+
// CHECK: define void @f5(i8 inreg %a, i16 inreg %b)
39+
void f5(char a, short b) {}
40+
41+
// CHECK: define void @f6(i8 inreg %a, i16 inreg %b)
42+
void f6(unsigned char a, unsigned short b) {}
43+
44+
enum my_enum {
45+
ENUM1,
46+
ENUM2,
47+
ENUM3,
48+
};
49+
// Enums should be treated as the underlying i32.
50+
// CHECK: define void @f7(i32 inreg %a)
51+
void f7(enum my_enum a) {}
52+
53+
enum my_big_enum {
54+
ENUM4 = 0xFFFFFFFFFFFFFFFF,
55+
};
56+
// Big enums should be treated as the underlying i64.
57+
// CHECK: define void @f8(i64 inreg %a)
58+
void f8(enum my_big_enum a) {}
59+
60+
union simple_union {
61+
int a;
62+
char b;
63+
};
64+
// Unions should be passed as byval structs.
65+
// CHECK: define void @f9(%union.simple_union* byval align 4 %s)
66+
void f9(union simple_union s) {}
67+
68+
typedef struct {
69+
int b4 : 4;
70+
int b3 : 3;
71+
int b8 : 8;
72+
} bitfield1;
73+
// Bitfields should be passed as byval structs.
74+
// CHECK: define void @f10(%struct.bitfield1* byval align 4 %bf1)
75+
void f10(bitfield1 bf1) {}

0 commit comments

Comments
 (0)
Please sign in to comment.