Skip to content

Commit

Permalink
[EraVM][Runtime] Support system delegate call (#116)
Browse files Browse the repository at this point in the history
  • Loading branch information
akiramenai committed Apr 7, 2024
1 parent 1b38e61 commit 5cec8e9
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 26 deletions.
4 changes: 3 additions & 1 deletion llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10372,7 +10372,9 @@ TargetLowering::LowerCallTo(TargetLowering::CallLoweringInfo &CLI) const {
"LowerCall didn't return a valid chain!");
assert((!CLI.IsTailCall || InVals.empty()) &&
"LowerCall emitted a return value for a tail call!");
assert((CLI.IsTailCall || InVals.size() == CLI.Ins.size()) &&
// EraVM local begin
assert((CLI.IsTailCall || CLI.IsVarArg || InVals.size() == CLI.Ins.size()) &&
// EraVM local end
"LowerCall didn't emit the correct number of values!");

// For a tail call, the return value is merely live-out and there aren't
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/EraVM/EraVMISD.def
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
HANDLE_NODETYPE(RET)
HANDLE_NODETYPE(CALL)
HANDLE_NODETYPE(FARCALL)
HANDLE_NODETYPE(FARCALL_LONG)
HANDLE_NODETYPE(STATICCALL)
HANDLE_NODETYPE(DELEGATECALL)
HANDLE_NODETYPE(DELEGATECALL_LONG)
HANDLE_NODETYPE(MIMICCALL)
HANDLE_NODETYPE(INVOKE)
HANDLE_NODETYPE(BR_CC)
Expand Down
35 changes: 11 additions & 24 deletions llvm/lib/Target/EraVM/EraVMISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,37 +284,24 @@ SDValue EraVMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
bool IsVarArg = CLI.IsVarArg;

if (auto *GA = dyn_cast<GlobalAddressSDNode>(Callee.getNode())) {
auto farcall_pair = [&]() {
if (GA->getGlobal()->getName() == "__farcall_int") {
return std::make_pair<uint64_t, bool>(EraVMISD::FARCALL, true);
}
if (GA->getGlobal()->getName() == "__staticcall_int") {
return std::make_pair<uint64_t, bool>(EraVMISD::STATICCALL, true);
}
if (GA->getGlobal()->getName() == "__delegatecall_int") {
return std::make_pair<uint64_t, bool>(EraVMISD::DELEGATECALL, true);
}
if (GA->getGlobal()->getName() == "__mimiccall_int") {
return std::make_pair<uint64_t, bool>(EraVMISD::MIMICCALL, true);
}
return std::make_pair<uint64_t, bool>(0, false);
}();

auto farcall_opc = farcall_pair.first;
bool is_farcall = farcall_pair.second;
uint64_t farcall_opc =
StringSwitch<uint64_t>(GA->getGlobal()->getName())
.Case("__farcall_int", EraVMISD::FARCALL)
.Case("__farcall_int_l", EraVMISD::FARCALL)
.Case("__staticcall_int", EraVMISD::STATICCALL)
.Case("__delegatecall_int", EraVMISD::DELEGATECALL)
.Case("__delegatecall_int_l", EraVMISD::DELEGATECALL)
.Case("__mimiccall_int", EraVMISD::MIMICCALL)
.Default(0);

bool is_mimic = farcall_opc == EraVMISD::MIMICCALL;

if (is_farcall) {
if (farcall_opc) {
if (is_mimic)
Chain = DAG.getCopyToReg(Chain, DL, EraVM::R3, OutVals[2], SDValue());
SmallVector<SDValue, 8> Ops;
Ops.push_back(Chain);
Ops.push_back(OutVals[0]);
Ops.push_back(OutVals[1]);
if (is_mimic) {
Ops.push_back(OutVals[2]);
}
Ops.insert(Ops.end(), OutVals.begin(), OutVals.end());
Ops.push_back(CLI.UnwindBB);
SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
Chain = DAG.getNode(farcall_opc, DL, NodeTys, Ops);
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Target/EraVM/EraVMInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -1116,10 +1116,14 @@ let Defs = [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15],
isCall = 1, isTerminator = 1 in {
def FAR_CALL : ICall<8, CFNormal, (ins GR256:$abi, GR256:$address, jmptarget:$unwind),
"far_call\t$abi, $address, $unwind", [(EraVMfarcall GR256:$abi, GR256:$address, bb:$unwind)]>;
def FAR_CALLL : ICall<80, CFNormal, (ins GR256:$abi, GR256:$address, GR256:$op1, GR256:$op2, jmptarget:$unwind),
"far_call\t$abi, $address, $unwind", [(EraVMfarcall GR256:$abi, GR256:$address, GR256:$op1, GR256:$op2, bb:$unwind)]>;
def STATIC_CALL : ICall<10, CFNormal, (ins GR256:$abi, GR256:$address, jmptarget:$unwind),
"far_call.static\t$abi, $address, $unwind", [(EraVMstaticcall GR256:$abi, GR256:$address, bb:$unwind)]>;
def DELEGATE_CALL : ICall<11, CFDelegate, (ins GR256:$abi, GR256:$address, jmptarget:$unwind),
"far_call.delegate\t$abi, $address, $unwind", [(EraVMdelegatecall GR256:$abi, GR256:$address, bb:$unwind)]>;
def DELEGATE_CALLL : ICall<110, CFDelegate, (ins GR256:$abi, GR256:$address, GR256:$op1, GR256:$op2, jmptarget:$unwind),
"far_call.delegate\t$abi, $address, $unwind", [(EraVMdelegatecall GR256:$abi, GR256:$address, GR256:$op1, GR256:$op2, bb:$unwind)]>;
def MIMIC_CALL : ICall<12, CFMimic, (ins GR256:$abi, GR256:$address, GR256:$mimic, jmptarget:$unwind),
"far_call.mimic\t$abi, $address, $unwind", [(EraVMmimiccall GR256:$abi, GR256:$address, GR256:$mimic, bb:$unwind)]>;
}
Expand Down
23 changes: 22 additions & 1 deletion llvm/lib/Target/EraVM/eravm-runtime.ll
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,26 @@ define {i8 addrspace(3)*, i1}* @__systemcall(i256 %abi_params, i256 %address, i2
entry:
%in_res_result_ptr = getelementptr {i8 addrspace(3)*, i1}, {i8 addrspace(3)*, i1}* %in_res, i32 0, i32 0
%in_res_flag_ptr = getelementptr {i8 addrspace(3)*, i1}, {i8 addrspace(3)*, i1}* %in_res, i32 0, i32 1
%invoke_res = invoke i8 addrspace(3)* @__farcall_int(i256 %abi_params, i256 %address)
%invoke_res = invoke i8 addrspace(3)* @__farcall_int_l(i256 %abi_params, i256 %address, i256 %p0, i256 %p1)
to label %ok unwind label %err
ok:
store i8 addrspace(3)* %invoke_res, i8 addrspace(3)** %in_res_result_ptr
store i1 1, i1* %in_res_flag_ptr
ret {i8 addrspace(3)*, i1}* %in_res

err:
%res.2 = landingpad {i8 addrspace(3)*, i256} cleanup
%res = extractvalue {i8 addrspace(3)*, i256} %res.2, 0
store i8 addrspace(3)* %res, i8 addrspace(3)** %in_res_result_ptr
store i1 0, i1* %in_res_flag_ptr
ret {i8 addrspace(3)*, i1}* %in_res
}

define {i8 addrspace(3)*, i1}* @__systemdelegatecall(i256 %abi_params, i256 %address, i256 %p0, i256 %p1, {i8 addrspace(3)*, i1}* %in_res) personality i32 ()* @__personality {
entry:
%in_res_result_ptr = getelementptr {i8 addrspace(3)*, i1}, {i8 addrspace(3)*, i1}* %in_res, i32 0, i32 0
%in_res_flag_ptr = getelementptr {i8 addrspace(3)*, i1}, {i8 addrspace(3)*, i1}* %in_res, i32 0, i32 1
%invoke_res = invoke i8 addrspace(3)* @__delegatecall_int_l(i256 %abi_params, i256 %address, i256 %p0, i256 %p1)
to label %ok unwind label %err
ok:
store i8 addrspace(3)* %invoke_res, i8 addrspace(3)** %in_res_result_ptr
Expand Down Expand Up @@ -488,8 +507,10 @@ declare void @llvm.eravm.sstore(i256 %key, i256 %val)
declare i256 @llvm.eravm.sload(i256 %key)
declare i256 @llvm.eravm.iflt(i256, i256)
declare i8 addrspace(3)* @__farcall_int(i256, i256)
declare i8 addrspace(3)* @__farcall_int_l(i256, i256, i256, i256)
declare i8 addrspace(3)* @__staticcall_int(i256, i256)
declare i8 addrspace(3)* @__delegatecall_int(i256, i256)
declare i8 addrspace(3)* @__delegatecall_int_l(i256, i256, i256, i256)
declare i8 addrspace(3)* @__mimiccall_int(i256, i256, i256)
declare i32 @__personality()

Expand Down
8 changes: 8 additions & 0 deletions llvm/test/CodeGen/EraVM/intrinsic.ll
Original file line number Diff line number Diff line change
Expand Up @@ -199,11 +199,18 @@ define i256 @ifgtii() {
ret i256 %res
}

; CHECK-LABEL: invoke.farcall
define void @invoke.farcall({i256, i1}* %res) {
call {i256, i1}* @__farcall(i256 0, i256 0, {i256, i1}* %res)
ret void
}

; CHECK-LABEL: invoke.systemcall
define void @invoke.systemcall({i256, i1}* %res) {
call {i256, i1}* @__systemcall(i256 0, i256 1, i256 2, i256 3, {i256, i1}* %res)
ret void
}

declare i8* @llvm.stacksave()
declare void @llvm.stackrestore(i8*)

Expand All @@ -230,3 +237,4 @@ declare i256 @llvm.eravm.iflt(i256, i256)
declare i256 @llvm.eravm.ifgt(i256, i256)

declare {i256, i1}* @__farcall(i256, i256, {i256, i1}*)
declare {i256, i1}* @__systemcall(i256, i256, i256, i256, {i256, i1}*)

0 comments on commit 5cec8e9

Please sign in to comment.