Skip to content

Commit c503eca

Browse files
committed
[clang] Add driver support for riscv64-mti toolchains
Default to not using integrated as and adjust assembler output to be compatible with v0.97 gas. Rudimentary big-endian support. co-authored by Dragan Mladjenovic <[email protected]>
1 parent 4aa168a commit c503eca

File tree

14 files changed

+236
-83
lines changed

14 files changed

+236
-83
lines changed

clang/lib/Driver/ToolChains/Arch/RISCV.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -336,12 +336,14 @@ std::string riscv::getRISCVArch(const llvm::opt::ArgList &Args,
336336
// - On `riscv{XLEN}-unknown-elf` we default to `rv{XLEN}imac`
337337
// - On all other OSs we use `rv{XLEN}imafdc` (equivalent to `rv{XLEN}gc`)
338338
if (Triple.isRISCV32()) {
339-
if (Triple.getOS() == llvm::Triple::UnknownOS)
339+
if (Triple.getOS() == llvm::Triple::UnknownOS &&
340+
Triple.getVendor() != llvm::Triple::MipsTechnologies)
340341
return "rv32imac";
341342
else
342343
return "rv32imafdc";
343344
} else {
344-
if (Triple.getOS() == llvm::Triple::UnknownOS)
345+
if (Triple.getOS() == llvm::Triple::UnknownOS &&
346+
Triple.getVendor() != llvm::Triple::MipsTechnologies)
345347
return "rv64imac";
346348
else if (Triple.isAndroid())
347349
return "rv64imafdcv_zba_zbb_zbs";

clang/lib/Driver/ToolChains/Gnu.cpp

Lines changed: 113 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -252,9 +252,17 @@ static const char *getLDMOption(const llvm::Triple &T, const ArgList &Args) {
252252
case llvm::Triple::ppc64le:
253253
return "elf64lppc";
254254
case llvm::Triple::riscv32:
255-
return "elf32lriscv";
256-
case llvm::Triple::riscv64:
257-
return "elf64lriscv";
255+
case llvm::Triple::riscv64: {
256+
bool IsBigEndian = false;
257+
if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
258+
options::OPT_mbig_endian))
259+
IsBigEndian = A->getOption().matches(options::OPT_mbig_endian);
260+
261+
if (T.getArch() == llvm::Triple::riscv32)
262+
return IsBigEndian ? "elf32briscv" : "elf32lriscv";
263+
else
264+
return IsBigEndian ? "elf64briscv" : "elf64lriscv";
265+
}
258266
case llvm::Triple::sparc:
259267
case llvm::Triple::sparcel:
260268
return "elf32_sparc";
@@ -402,6 +410,14 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
402410
CmdArgs.push_back(Arch == llvm::Triple::aarch64_be ? "-EB" : "-EL");
403411
}
404412

413+
if (Triple.isRISCV() &&
414+
Triple.getVendor() == llvm::Triple::MipsTechnologies) {
415+
bool IsBigEndian = false;
416+
if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
417+
options::OPT_mbig_endian))
418+
IsBigEndian = A->getOption().matches(options::OPT_mbig_endian);
419+
CmdArgs.push_back(IsBigEndian ? "-EB" : "-EL");
420+
}
405421
// Most Android ARM64 targets should enable the linker fix for erratum
406422
// 843419. Only non-Cortex-A53 devices are allowed to skip this flag.
407423
if (Arch == llvm::Triple::aarch64 && (isAndroid || isOHOSFamily)) {
@@ -765,7 +781,8 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
765781
}
766782
case llvm::Triple::riscv32:
767783
case llvm::Triple::riscv64: {
768-
StringRef ABIName = riscv::getRISCVABI(Args, getToolChain().getTriple());
784+
const llvm::Triple &Triple = getToolChain().getTriple();
785+
StringRef ABIName = riscv::getRISCVABI(Args, Triple);
769786
CmdArgs.push_back("-mabi");
770787
CmdArgs.push_back(ABIName.data());
771788
std::string MArchName =
@@ -774,6 +791,14 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
774791
CmdArgs.push_back(Args.MakeArgString(MArchName));
775792
if (!Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, true))
776793
Args.addOptOutFlag(CmdArgs, options::OPT_mrelax, options::OPT_mno_relax);
794+
795+
if (Triple.getVendor() == llvm::Triple::MipsTechnologies) {
796+
bool IsBigEndian = false;
797+
if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
798+
options::OPT_mbig_endian))
799+
IsBigEndian = A->getOption().matches(options::OPT_mbig_endian);
800+
CmdArgs.push_back(IsBigEndian ? "-EB" : "-EL");
801+
}
777802
break;
778803
}
779804
case llvm::Triple::sparc:
@@ -1873,9 +1898,18 @@ static void findRISCVBareMetalMultilibs(const Driver &D,
18731898
.flag(Twine("-march=", Element.march).str())
18741899
.flag(Twine("-mabi=", Element.mabi).str()));
18751900
}
1901+
SmallVector<MultilibBuilder, 2> Endian;
1902+
if (TargetTriple.getVendor() == llvm::Triple::MipsTechnologies) {
1903+
Endian.push_back(
1904+
MultilibBuilder("/riscv").flag("-EL").flag("-EB", /*Disallow=*/true));
1905+
Endian.push_back(
1906+
MultilibBuilder("/riscveb").flag("-EB").flag("-EL", /*Disallow=*/true));
1907+
}
18761908
MultilibSet RISCVMultilibs =
18771909
MultilibSetBuilder()
18781910
.Either(Ms)
1911+
.Either(Endian)
1912+
.Either(ArrayRef<MultilibBuilder>(Ms))
18791913
.makeMultilibSet()
18801914
.FilterOut(NonExistent)
18811915
.setFilePathsCallback([](const Multilib &M) {
@@ -1899,6 +1933,19 @@ static void findRISCVBareMetalMultilibs(const Driver &D,
18991933
}
19001934
}
19011935

1936+
bool IsBigEndian = false;
1937+
if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
1938+
options::OPT_mbig_endian))
1939+
IsBigEndian = A->getOption().matches(options::OPT_mbig_endian);
1940+
1941+
if (IsBigEndian) {
1942+
D.Diag(diag::err_drv_unsupported_opt_for_target)
1943+
<< "-EB" << TargetTriple.str();
1944+
}
1945+
1946+
addMultilibFlag(IsBigEndian, "-EB", Flags);
1947+
addMultilibFlag(!IsBigEndian, "-EL", Flags);
1948+
19021949
if (selectRISCVMultilib(D, RISCVMultilibs, MArch, Flags,
19031950
Result.SelectedMultilibs))
19041951
Result.Multilibs = RISCVMultilibs;
@@ -1923,15 +1970,34 @@ static void findRISCVMultilibs(const Driver &D,
19231970
MultilibBuilder("lib64/lp64f").flag("-m64").flag("-mabi=lp64f");
19241971
MultilibBuilder Lp64d =
19251972
MultilibBuilder("lib64/lp64d").flag("-m64").flag("-mabi=lp64d");
1973+
1974+
SmallVector<MultilibBuilder, 2> Endian;
1975+
if (TargetTriple.getVendor() == llvm::Triple::MipsTechnologies) {
1976+
Endian.push_back(
1977+
MultilibBuilder("/riscv").flag("-EL").flag("-EB", /*Disallow=*/true));
1978+
Endian.push_back(
1979+
MultilibBuilder("/riscveb").flag("-EB").flag("-EL", /*Disallow=*/true));
1980+
}
1981+
19261982
MultilibSet RISCVMultilibs =
19271983
MultilibSetBuilder()
1984+
.Either(Endian)
19281985
.Either({Ilp32, Ilp32f, Ilp32d, Lp64, Lp64f, Lp64d})
19291986
.makeMultilibSet()
19301987
.FilterOut(NonExistent);
19311988

19321989
Multilib::flags_list Flags;
19331990
bool IsRV64 = TargetTriple.getArch() == llvm::Triple::riscv64;
19341991
StringRef ABIName = tools::riscv::getRISCVABI(Args, TargetTriple);
1992+
bool IsBigEndian = false;
1993+
if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
1994+
options::OPT_mbig_endian))
1995+
IsBigEndian = A->getOption().matches(options::OPT_mbig_endian);
1996+
1997+
if (IsBigEndian) {
1998+
D.Diag(diag::err_drv_unsupported_opt_for_target)
1999+
<< "-EB" << TargetTriple.str();
2000+
}
19352001

19362002
addMultilibFlag(!IsRV64, "-m32", Flags);
19372003
addMultilibFlag(IsRV64, "-m64", Flags);
@@ -1941,6 +2007,8 @@ static void findRISCVMultilibs(const Driver &D,
19412007
addMultilibFlag(ABIName == "lp64", "-mabi=lp64", Flags);
19422008
addMultilibFlag(ABIName == "lp64f", "-mabi=lp64f", Flags);
19432009
addMultilibFlag(ABIName == "lp64d", "-mabi=lp64d", Flags);
2010+
addMultilibFlag(IsBigEndian, "-EB", Flags);
2011+
addMultilibFlag(!IsBigEndian, "-EL", Flags);
19442012

19452013
if (RISCVMultilibs.select(D, Flags, Result.SelectedMultilibs))
19462014
Result.Multilibs = RISCVMultilibs;
@@ -2565,8 +2633,8 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
25652633
static const char *const RISCV32Triples[] = {"riscv32-unknown-linux-gnu",
25662634
"riscv32-unknown-elf"};
25672635
static const char *const RISCV64LibDirs[] = {"/lib64", "/lib"};
2568-
static const char *const RISCV64Triples[] = {"riscv64-unknown-linux-gnu",
2569-
"riscv64-unknown-elf"};
2636+
static const char *const RISCV64Triples[] = {
2637+
"riscv64-unknown-linux-gnu", "riscv64-unknown-elf", "riscv64-mti-elf"};
25702638

25712639
static const char *const SPARCv8LibDirs[] = {"/lib32", "/lib"};
25722640
static const char *const SPARCv8Triples[] = {"sparc-linux-gnu",
@@ -3137,6 +3205,45 @@ bool Generic_GCC::IsIntegratedAssemblerDefault() const {
31373205
case llvm::Triple::nvptx64:
31383206
case llvm::Triple::xcore:
31393207
return false;
3208+
case llvm::Triple::aarch64:
3209+
case llvm::Triple::aarch64_be:
3210+
case llvm::Triple::amdgcn:
3211+
case llvm::Triple::arm:
3212+
case llvm::Triple::armeb:
3213+
case llvm::Triple::avr:
3214+
case llvm::Triple::bpfel:
3215+
case llvm::Triple::bpfeb:
3216+
case llvm::Triple::csky:
3217+
case llvm::Triple::hexagon:
3218+
case llvm::Triple::lanai:
3219+
case llvm::Triple::loongarch32:
3220+
case llvm::Triple::loongarch64:
3221+
case llvm::Triple::m68k:
3222+
case llvm::Triple::mips:
3223+
case llvm::Triple::mipsel:
3224+
case llvm::Triple::mips64:
3225+
case llvm::Triple::mips64el:
3226+
case llvm::Triple::msp430:
3227+
case llvm::Triple::ppc:
3228+
case llvm::Triple::ppcle:
3229+
case llvm::Triple::ppc64:
3230+
case llvm::Triple::ppc64le:
3231+
case llvm::Triple::r600:
3232+
case llvm::Triple::sparc:
3233+
case llvm::Triple::sparcel:
3234+
case llvm::Triple::sparcv9:
3235+
case llvm::Triple::systemz:
3236+
case llvm::Triple::thumb:
3237+
case llvm::Triple::thumbeb:
3238+
case llvm::Triple::ve:
3239+
case llvm::Triple::x86:
3240+
case llvm::Triple::x86_64:
3241+
return true;
3242+
case llvm::Triple::riscv32:
3243+
case llvm::Triple::riscv64:
3244+
if (getTriple().getVendor() != llvm::Triple::MipsTechnologies)
3245+
return true;
3246+
return false;
31403247
default:
31413248
return true;
31423249
}

clang/lib/Driver/ToolChains/Linux.cpp

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -274,11 +274,14 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
274274
const bool IsHexagon = Arch == llvm::Triple::hexagon;
275275
const bool IsRISCV = Triple.isRISCV();
276276
const bool IsCSKY = Triple.isCSKY();
277+
const bool IsMipsSysRoot =
278+
IsMips ||
279+
(IsRISCV && Triple.getVendor() == llvm::Triple::MipsTechnologies);
277280

278281
if (IsCSKY && !SelectedMultilibs.empty())
279282
SysRoot = SysRoot + SelectedMultilibs.back().osSuffix();
280283

281-
if ((IsMips || IsCSKY) && !SysRoot.empty())
284+
if ((IsMipsSysRoot || IsCSKY) && !SysRoot.empty())
282285
ExtraOpts.push_back("--sysroot=" + SysRoot);
283286

284287
// Do not use 'gnu' hash style for Mips targets because .gnu.hash
@@ -412,7 +415,12 @@ std::string Linux::computeSysRoot() const {
412415
return std::string();
413416
}
414417

415-
if (!GCCInstallation.isValid() || !getTriple().isMIPS())
418+
const bool IsMipsSysRoot =
419+
getTriple().isMIPS() ||
420+
(getTriple().isRISCV() &&
421+
getTriple().getVendor() == llvm::Triple::MipsTechnologies);
422+
423+
if (!GCCInstallation.isValid() || !IsMipsSysRoot)
416424
return std::string();
417425

418426
// Standalone MIPS toolchains use different names for sysroot folder
@@ -422,8 +430,19 @@ std::string Linux::computeSysRoot() const {
422430
const StringRef InstallDir = GCCInstallation.getInstallPath();
423431
const StringRef TripleStr = GCCInstallation.getTriple().str();
424432
const Multilib &Multilib = GCCInstallation.getMultilib();
433+
std::string Path;
434+
if (getTriple().isRISCV()) {
435+
Path =
436+
(InstallDir + "/../../../../sysroot" + Multilib.osSuffix() + "/../..")
437+
.str();
438+
439+
if (getVFS().exists(Path))
440+
return Path;
441+
442+
return std::string();
443+
}
425444

426-
std::string Path =
445+
Path =
427446
(InstallDir + "/../../../../" + TripleStr + "/libc" + Multilib.osSuffix())
428447
.str();
429448

clang/lib/Driver/ToolChains/RISCVToolchain.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ Tool *RISCVToolChain::buildLinker() const {
7777
}
7878

7979
ToolChain::RuntimeLibType RISCVToolChain::GetDefaultRuntimeLibType() const {
80-
return GCCInstallation.isValid() ?
81-
ToolChain::RLT_Libgcc : ToolChain::RLT_CompilerRT;
80+
return GCCInstallation.isValid() ? ToolChain::RLT_Libgcc
81+
: ToolChain::RLT_CompilerRT;
8282
}
8383

8484
ToolChain::UnwindLibType
@@ -173,6 +173,14 @@ void RISCV::Linker::ConstructJob(Compilation &C, const JobAction &JA,
173173
}
174174
CmdArgs.push_back("-X");
175175

176+
if (ToolChain.getTriple().getVendor() == llvm::Triple::MipsTechnologies) {
177+
bool IsBigEndian = false;
178+
if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
179+
options::OPT_mbig_endian))
180+
IsBigEndian = A->getOption().matches(options::OPT_mbig_endian);
181+
CmdArgs.push_back(IsBigEndian ? "-EB" : "-EL");
182+
}
183+
176184
std::string Linker = getToolChain().GetLinkerPath();
177185

178186
bool WantCRTs =
@@ -229,4 +237,10 @@ void RISCV::Linker::ConstructJob(Compilation &C, const JobAction &JA,
229237
JA, *this, ResponseFileSupport::AtFileCurCP(), Args.MakeArgString(Linker),
230238
CmdArgs, Inputs, Output));
231239
}
240+
241+
bool RISCVToolChain::IsIntegratedAssemblerDefault() const {
242+
if (getTriple().getVendor() != llvm::Triple::MipsTechnologies)
243+
return true;
244+
return false;
245+
}
232246
// RISCV tools end.

clang/lib/Driver/ToolChains/RISCVToolchain.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class LLVM_LIBRARY_VISIBILITY RISCVToolChain : public Generic_ELF {
2222
const llvm::opt::ArgList &Args);
2323

2424
static bool hasGCCToolchain(const Driver &D, const llvm::opt::ArgList &Args);
25+
bool IsIntegratedAssemblerDefault() const override;
2526
void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
2627
llvm::opt::ArgStringList &CC1Args,
2728
Action::OffloadKind) const override;

llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,11 @@ const MCExpr *RISCVMCAsmInfo::getExprForFDESymbol(const MCSymbol *Sym,
4545
assert(Encoding & dwarf::DW_EH_PE_sdata4 && "Unexpected encoding");
4646
return RISCVMCExpr::create(ME, RISCVMCExpr::VK_RISCV_32_PCREL, Ctx);
4747
}
48+
49+
void RISCVMCAsmInfo::setUseIntegratedAssembler(bool Value) {
50+
UseIntegratedAssembler = Value;
51+
if (!UseIntegratedAssembler) {
52+
// gas doesn't handle non-constant <u>leb128
53+
HasLEB128Directives = false;
54+
}
55+
}

llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ class RISCVMCAsmInfo : public MCAsmInfoELF {
2626

2727
const MCExpr *getExprForFDESymbol(const MCSymbol *Sym, unsigned Encoding,
2828
MCStreamer &Streamer) const override;
29+
/// Set whether assembly (inline or otherwise) should be parsed.
30+
void setUseIntegratedAssembler(bool Value) override;
2931
};
3032

3133
} // namespace llvm

llvm/lib/Target/RISCV/RISCVInstrInfoZb.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ def UNZIP_RV32 : Unary_r<0b000010001111, 0b101, "unzip">,
427427
// Pseudo Instructions
428428
//===----------------------------------------------------------------------===//
429429

430-
let Predicates = [HasStdExtZba, IsRV64] in {
430+
let Predicates = [HasStdExtZba, IsRV64], EmitPriority = 0 in {
431431
def : InstAlias<"zext.w $rd, $rs", (ADD_UW GPR:$rd, GPR:$rs, X0)>;
432432
} // Predicates = [HasStdExtZba, IsRV64]
433433

llvm/test/CodeGen/RISCV/div-by-constant.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ define i32 @udiv_constant_add(i32 %a) nounwind {
6262
;
6363
; RV64IMZB-LABEL: udiv_constant_add:
6464
; RV64IMZB: # %bb.0:
65-
; RV64IMZB-NEXT: zext.w a1, a0
65+
; RV64IMZB-NEXT: add.uw a1, a0, zero
6666
; RV64IMZB-NEXT: lui a2, 149797
6767
; RV64IMZB-NEXT: addiw a2, a2, -1755
6868
; RV64IMZB-NEXT: mul a1, a1, a2

0 commit comments

Comments
 (0)