[VENTUS][RISCV] Add vararg support

Because ventus riscv is designed specially for OpenCL language, we originally add or remove some language features mainly for serving OpenCL, but we now need to add customized `printf` function which is expected to be written in C, so we need also to add support for C language features in current ventus

Signed-off-by: zhoujingya <jing.zhou@terapines.com>
This commit is contained in:
zhoujingya 2023-04-13 14:04:14 +08:00
parent 0642d65513
commit 8ba248d102
7 changed files with 91 additions and 11 deletions

View File

@ -19,7 +19,9 @@ Download all the repositories firstly
### 2: Build all the programs
Assume you have already installed essential build tools such as cmake, clang, ninja etc.
> You can refer to [official website](https://llvm.org/docs/GettingStarted.html) for llvm building guidance, if you see package missing information, just install the missing packages.
Assume you have already installed essential build tools such as cmake, clang, ninja, ccache etc.
Run `./build-ventus.sh` to automatically build all the programs, but we need to run firstly
* `export POCL_DIR=<path-to-pocl-dir>`, default folder path will be set to be **`<llvm-ventus-parentFolder>`/pocl**

View File

@ -44,6 +44,28 @@ const LangASMap RISCVTargetInfo::VentusAddrSpaceMap = {
Generic, // hlsl_groupshared
};
void RISCVTargetInfo::adjust(DiagnosticsEngine &Diags, LangOptions &Opts) {
TargetInfo::adjust(Diags, Opts);
llvm::Triple Triple = getTriple();
bool isRV32 = Triple.isRISCV32();
// Only OpenCL language needs special address mapping
if(Opts.OpenCL) {
UseAddrSpaceMapMangling = true;
AddrSpaceMap = &VentusAddrSpaceMap;
if(isRV32)
resetDataLayout("e-m:e-p:32:32-i64:64-n32-S128-A5-G1");
else
resetDataLayout("e-m:e-p:64:64-i64:64-i128:128-n32:64-S128-A5-G1");
}
// Not OpenCL language, we no not need special data layout
// just follow the official way
else {
if(isRV32)
resetDataLayout("e-m:e-p:32:32-i64:64-n32-S128");
else
resetDataLayout("e-m:e-p:64:64-i64:64-i128:128-n32:64-S128");
}
}
ArrayRef<const char *> RISCVTargetInfo::getGCCRegNames() const {
static const char *const GCCRegNames[] = {

View File

@ -53,8 +53,7 @@ public:
HasRISCVVTypes = true;
MCountName = "_mcount";
HasFloat16 = true;
UseAddrSpaceMapMangling = true;
AddrSpaceMap = &VentusAddrSpaceMap;
}
bool setCPU(const std::string &Name) override {
@ -64,6 +63,8 @@ public:
return true;
}
void adjust(DiagnosticsEngine &Diags, LangOptions &Opts) override;
StringRef getABI() const override { return ABI; }
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override;
@ -191,7 +192,6 @@ public:
//HasFloat16 = true;
//resetDataLayout("e-m:e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256"
// "-v256:256-v512:512-v1024:1024-n32:64-S128-A5-G1");
resetDataLayout("e-m:e-p:32:32-i64:64-n32-S128-A5-G1");
}
bool setABI(const std::string &Name) override {
@ -215,7 +215,6 @@ public:
: RISCVTargetInfo(Triple, Opts) {
LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
IntMaxType = Int64Type = SignedLong;
resetDataLayout("e-m:e-p:64:64-i64:64-i128:128-n32:64-S128-A5-G1");
}
bool setABI(const std::string &Name) override {

View File

@ -11341,9 +11341,27 @@ void VentusRISCVABIInfo::computeInfo(CGFunctionInfo &FI) const {
}
}
// OpenCL do not support varargs when try to define customized functions
// but here we need to add support for C language IR code generation
Address VentusRISCVABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
QualType Ty) const {
llvm_unreachable("TODO: Support varargs in ventus!");
CharUnits SlotSize = CharUnits::fromQuantity(XLen / 8);
// Empty records are ignored for parameter passing purposes.
if (isEmptyRecord(getContext(), Ty, true)) {
Address Addr = Address(CGF.Builder.CreateLoad(VAListAddr),
getVAListElementType(CGF), SlotSize);
Addr = CGF.Builder.CreateElementBitCast(Addr, CGF.ConvertTypeForMem(Ty));
return Addr;
}
auto TInfo = getContext().getTypeInfoInChars(Ty);
// Arguments bigger than 2*Xlen bytes are passed indirectly.
bool IsIndirect = TInfo.Width > 2 * SlotSize;
return emitVoidPtrVAArg(CGF, VAListAddr, Ty, IsIndirect, TInfo,
SlotSize, /*AllowHigherAlign=*/true);
}
ABIArgInfo VentusRISCVABIInfo::classifyReturnType(QualType RetTy) const {

View File

@ -0,0 +1,27 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
// RUN: %clang_cc1 -triple riscv32 -S -emit-llvm -mllvm -riscv-common-data-layout \
// RUN: %s -o - | FileCheck --check-prefix=CHECK-RV32 %s
// CHECK-RV32-LABEL: @test_vararg(
// CHECK-RV32-NEXT: entry:
// CHECK-RV32-NEXT: [[FMT_ADDR:%.*]] = alloca ptr, align 4
// CHECK-RV32-NEXT: [[VA:%.*]] = alloca ptr, align 4
// CHECK-RV32-NEXT: [[RETVAL1:%.*]] = alloca i32, align 4
// CHECK-RV32-NEXT: store ptr [[FMT:%.*]], ptr [[FMT_ADDR]], align 4
// CHECK-RV32-NEXT: call void @llvm.va_start(ptr [[VA]])
// CHECK-RV32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4
// CHECK-RV32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4
// CHECK-RV32-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4
// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARGP_CUR]], align 4
// CHECK-RV32-NEXT: store i32 [[TMP0]], ptr [[RETVAL1]], align 4
// CHECK-RV32-NEXT: call void @llvm.va_end(ptr [[VA]])
// CHECK-RV32-NEXT: [[TMP1:%.*]] = load i32, ptr [[RETVAL1]], align 4
// CHECK-RV32-NEXT: ret i32 [[TMP1]]
//
int test_vararg(char *fmt,...) {
__builtin_va_list va;
__builtin_va_start(va, fmt);
int retval = __builtin_va_arg(va, int);
__builtin_va_end(va);
return retval;
}

View File

@ -115,7 +115,8 @@ void RISCVAsmPrinter::emitInstruction(const MachineInstr *MI) {
return;
}
if (RISCVII::IsVecImm12MemInstr(MI->getDesc().TSFlags)) {
if (MI->getOperand(2).getReg() == RISCV::X0) {
if (MI->getOperand(2).isReg() && MI->getOperand(2).getReg() == RISCV::X0) {
OutStreamer->emitInstruction(MCInstBuilder(MI->getOpcode())
.addReg(MI->getOperand(0).getReg())
.addReg(MI->getOperand(1).getReg())

View File

@ -54,6 +54,11 @@ static cl::opt<bool>
cl::desc("Enable the machine combiner pass"),
cl::init(true), cl::Hidden);
static cl::opt<bool> EnableCommonDataLayout(
"riscv-common-data-layout",
cl::desc("Enable the common data layout for other language(not OpenCL)"),
cl::init(false), cl::Hidden);
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget() {
RegisterTargetMachine<RISCVTargetMachine> X(getTheRISCV32Target());
RegisterTargetMachine<RISCVTargetMachine> Y(getTheRISCV64Target());
@ -71,8 +76,14 @@ static StringRef computeDataLayout(const Triple &TT, StringRef CPU) {
// if (CPU == "ventus-gpgpu")
// return "e-m:e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256"
// "-v256:256-v512:512-v1024:1024-n32:64-S128-A5-G1";
if (TT.isArch64Bit())
bool IsRV32 = TT.isRISCV32();
if (EnableCommonDataLayout) {
if(IsRV32)
return "e-m:e-p:32:32-i64:64-n32-S128";
else
return "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128";
}
if(!IsRV32)
return "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128-A5-G1";
assert(TT.isArch32Bit() && "only RV32 and RV64 are currently supported");
return "e-m:e-p:32:32-i64:64-n32-S128-A5-G1";
@ -94,7 +105,6 @@ RISCVTargetMachine::RISCVTargetMachine(const Target &T, const Triple &TT,
getEffectiveCodeModel(CM, CodeModel::Small), OL),
TLOF(std::make_unique<RISCVELFTargetObjectFile>()) {
initAsmInfo();
// RISC-V supports the MachineOutliner.
setMachineOutliner(true);
setSupportsDefaultOutlining(true);
@ -129,7 +139,8 @@ RISCVTargetMachine::getSubtargetImpl(const Function &F) const {
}
ABIName = ModuleTargetABI->getString();
}
I = std::make_unique<RISCVSubtarget>(TargetTriple, CPU, TuneCPU, FS, ABIName, *this);
I = std::make_unique<RISCVSubtarget>(TargetTriple, CPU, TuneCPU, FS,
ABIName, *this);
}
return I.get();
}