Skip to content

Commit

Permalink
Implement static syscalls
Browse files Browse the repository at this point in the history
  • Loading branch information
LucasSte committed Dec 17, 2024
1 parent 0e7ed1d commit 7dda748
Show file tree
Hide file tree
Showing 10 changed files with 91 additions and 22 deletions.
4 changes: 3 additions & 1 deletion llvm/lib/Target/SBF/Disassembler/SBFDisassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class SBFDisassembler : public MCDisassembler {
uint8_t getInstMode(uint64_t Inst) const { return (Inst >> 61) & 0x7; };
bool isMov32(uint64_t Inst) const { return (Inst >> 56) == 0xb4; }
bool isNewMem(uint64_t Inst) const;
bool isSyscallOrExit(uint64_t Inst) const { return (Inst >> 56) == 0x95; }
};

} // end anonymous namespace
Expand Down Expand Up @@ -202,7 +203,8 @@ DecodeStatus SBFDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
Result =
decodeInstruction(DecoderTableSBFALU32MEMv264,
Instr, Insn, Address, this, STI);
else if (isNewMem(Insn) && STI.hasFeature(SBF::FeatureNewMemEncoding))
else if ((isNewMem(Insn) && STI.hasFeature(SBF::FeatureNewMemEncoding)) ||
(isSyscallOrExit(Insn) && STI.hasFeature(SBF::FeatureStaticSyscalls)))
Result =
decodeInstruction(DecoderTableSBFv264,
Instr, Insn, Address, this, STI);
Expand Down
17 changes: 15 additions & 2 deletions llvm/lib/Target/SBF/SBFISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,7 @@ SDValue SBFTargetLowering::LowerFormalArguments(
}

const unsigned SBFTargetLowering::MaxArgs = 5;
const uint64_t SBFTargetLowering::MaxSyscall = 100;

SDValue SBFTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
SmallVectorImpl<SDValue> &InVals) const {
Expand Down Expand Up @@ -592,11 +593,21 @@ SDValue SBFTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
// If the callee is a GlobalAddress node (quite common, every direct call is)
// turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
// Likewise ExternalSymbol -> TargetExternalSymbol.
unsigned NodeCode = SBFISD::CALL;
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
Callee = DAG.getTargetGlobalAddress(G->getGlobal(), CLI.DL, PtrVT,
G->getOffset(), 0);
} else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee)) {
Callee = DAG.getTargetExternalSymbol(E->getSymbol(), PtrVT, 0);
} else if (ConstantSDNode * CNode = dyn_cast<ConstantSDNode>(Callee)) {
uint64_t Cte = CNode->getZExtValue();
uint64_t U32Max = static_cast<uint64_t>
(std::numeric_limits<uint32_t>::max());
if (Subtarget->getHasStaticSyscalls() && Cte >= U32Max - MaxSyscall) {
NodeCode = SBFISD::SYSCALL;
uint64_t SyscallCode = U32Max - Cte;
Callee = DAG.getConstant(SyscallCode, CLI.DL, MVT::i64);
}
}

// Returns a chain & a flag for retval copy to use.
Expand All @@ -610,14 +621,14 @@ SDValue SBFTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
for (auto &Reg : RegsToPass)
Ops.push_back(DAG.getRegister(Reg.first, Reg.second.getValueType()));

if (HasStackArgs) {
if (HasStackArgs && !Subtarget->getHasDynamicFrames()) {
Ops.push_back(DAG.getRegister(SBF::R5, MVT::i64));
}

if (InGlue.getNode())
Ops.push_back(InGlue);

Chain = DAG.getNode(SBFISD::CALL, CLI.DL, NodeTys, Ops);
Chain = DAG.getNode(NodeCode, CLI.DL, NodeTys, Ops);
InGlue = Chain.getValue(1);

DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.NoMerge);
Expand Down Expand Up @@ -919,6 +930,8 @@ const char *SBFTargetLowering::getTargetNodeName(unsigned Opcode) const {
return "SBFISD::Wrapper";
case SBFISD::MEMCPY:
return "SBFISD::MEMCPY";
case SBFISD::SYSCALL:
return "SBFISD::SYSCALL";
}
return nullptr;
}
Expand Down
6 changes: 5 additions & 1 deletion llvm/lib/Target/SBF/SBFISelLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ enum NodeType : unsigned {
SELECT_CC,
BR_CC,
Wrapper,
MEMCPY
MEMCPY,
SYSCALL,
};
}

Expand Down Expand Up @@ -90,6 +91,9 @@ class SBFTargetLowering : public TargetLowering {
// Maximum number of arguments to a call
static const unsigned MaxArgs;

// Maximum number of syscalls
static const uint64_t MaxSyscall;

// Lower a call into CALLSEQ_START - SBFISD:CALL - CALLSEQ_END chain
SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI,
SmallVectorImpl<SDValue> &InVals) const override;
Expand Down
27 changes: 14 additions & 13 deletions llvm/lib/Target/SBF/SBFInstrFormats.td
Original file line number Diff line number Diff line change
Expand Up @@ -72,19 +72,20 @@ class SBFJumpOp<bits<4> val> {
bits<4> Value = val;
}

def SBF_JA : SBFJumpOp<0x0>;
def SBF_JEQ : SBFJumpOp<0x1>;
def SBF_JGT : SBFJumpOp<0x2>;
def SBF_JGE : SBFJumpOp<0x3>;
def SBF_JNE : SBFJumpOp<0x5>;
def SBF_JSGT : SBFJumpOp<0x6>;
def SBF_JSGE : SBFJumpOp<0x7>;
def SBF_CALL : SBFJumpOp<0x8>;
def SBF_EXIT : SBFJumpOp<0x9>;
def SBF_JLT : SBFJumpOp<0xa>;
def SBF_JLE : SBFJumpOp<0xb>;
def SBF_JSLT : SBFJumpOp<0xc>;
def SBF_JSLE : SBFJumpOp<0xd>;
def SBF_JA : SBFJumpOp<0x0>;
def SBF_JEQ : SBFJumpOp<0x1>;
def SBF_JGT : SBFJumpOp<0x2>;
def SBF_JGE : SBFJumpOp<0x3>;
def SBF_JNE : SBFJumpOp<0x5>;
def SBF_JSGT : SBFJumpOp<0x6>;
def SBF_JSGE : SBFJumpOp<0x7>;
def SBF_CALL : SBFJumpOp<0x8>;
def SBF_EXIT : SBFJumpOp<0x9>;
def SBF_JLT : SBFJumpOp<0xa>;
def SBF_JLE : SBFJumpOp<0xb>;
def SBF_JSLT : SBFJumpOp<0xc>;
def SBF_JSLE : SBFJumpOp<0xd>;
def SBF_SYSCALL : SBFJumpOp<0x9>;

class SBFWidthModifer<bits<2> val> {
bits<2> Value = val;
Expand Down
18 changes: 18 additions & 0 deletions llvm/lib/Target/SBF/SBFInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,13 @@ def SDT_SBFMEMCPY : SDTypeProfile<0, 4, [SDTCisVT<0, i64>,
SDTCisVT<1, i64>,
SDTCisVT<2, i64>,
SDTCisVT<3, i64>]>;
def SDT_SBFSyscall : SDTypeProfile<0, 1, [SDTCisVT<0, i64>]>;

def SBFcall : SDNode<"SBFISD::CALL", SDT_SBFCall,
[SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
SDNPVariadic]>;
def SBFSyscall : SDNode<"SBFISD::SYSCALL", SDT_SBFSyscall,
[SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
def SBFretglue : SDNode<"SBFISD::RET_GLUE", SDTNone,
[SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
def SBFcallseq_start: SDNode<"ISD::CALLSEQ_START", SDT_SBFCallSeqStart,
Expand Down Expand Up @@ -801,6 +804,19 @@ class CALL<string OpcodeStr>
let SBFClass = SBF_JMP;
}

class SYSCALL<string OpcodeStr>
: TYPE_ALU_JMP<SBF_SYSCALL.Value, SBF_K.Value,
(outs),
(ins i64imm:$imm),
!strconcat(OpcodeStr, " $imm"),
[]> {
bits<32> imm;

let Inst{31-0} = imm;
let SBFClass = SBF_JMP;
}


class CALLX<string OpcodeStr>
: TYPE_ALU_JMP<SBF_CALL.Value, SBF_X.Value,
(outs),
Expand Down Expand Up @@ -838,6 +854,7 @@ let isCall=1, hasDelaySlot=0, Uses = [R10],
def JALX : CALLX<"callx">, Requires<[SBFNoCallxSrc]>;
let DecoderNamespace = "SBFv2" in {
def JALX_v2 : CALLX_SRC_REG<"callx">, Requires<[SBFCallxSrc]>;
def SYSCALL_v2 : SYSCALL<"syscall">, Requires<[SBFHasStaticSyscalls]>;
}
}

Expand Down Expand Up @@ -949,6 +966,7 @@ def : Pat<(SBFcall texternalsym:$dst), (JAL texternalsym:$dst)>;
def : Pat<(SBFcall imm:$dst), (JAL imm:$dst)>;
def : Pat<(SBFcall GPR:$dst), (JALX GPR:$dst)>, Requires<[SBFNoCallxSrc]>;
def : Pat<(SBFcall GPR:$dst), (JALX_v2 GPR:$dst)>, Requires<[SBFCallxSrc]>;
def : Pat<(SBFSyscall imm:$imm), (SYSCALL_v2 imm:$imm)>, Requires<[SBFHasStaticSyscalls]>;

// Loads
let Predicates = [SBFNoALU32, SBFOldMemEncoding] in {
Expand Down
25 changes: 25 additions & 0 deletions llvm/test/CodeGen/SBF/static_syscall.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
; RUN: llc -march=sbf < %s | FileCheck --check-prefix=CHECK-V1 %s
; RUN: llc -march=sbf -mattr=+static-syscalls -show-mc-encoding < %s | FileCheck --check-prefix=CHECK-V2 %s


; Function Attrs: nounwind
define dso_local i32 @test(i32 noundef %a, i32 noundef %b) {
entry:
; CHECK-LABEL: test

; CHECK-V1: call -2
; CHECK-V2: syscall 1 # encoding: [0x95,0x00,0x00,0x00,0x01,0x00,0x00,0x00]
%syscall_1 = tail call i32 inttoptr (i64 4294967294 to ptr)(i32 noundef %a, i32 noundef %b)

; CHECK-V1: call -12
; CHECK-V2: syscall 11 # encoding: [0x95,0x00,0x00,0x00,0x0b,0x00,0x00,0x00]
%syscall_2 = tail call i32 inttoptr (i64 4294967284 to ptr)(i32 noundef %a, i32 noundef %b)

; CHECK-V1: call -112
; CHECK-V2: call -112
%not_syscall = tail call i32 inttoptr (i64 4294967184 to ptr)(i32 noundef %a, i32 noundef %b)

%add_1 = add i32 %syscall_1, %syscall_2
%add_2 = add i32 %add_1, %not_syscall
ret i32 %add_1
}
6 changes: 6 additions & 0 deletions llvm/test/MC/Disassembler/SBF/sbf-jmp.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# RUN: llvm-mc --disassemble %s -triple=sbf-solana-solana \
# RUN: | FileCheck %s --check-prefix=CHECK-NEW
# RUN: llvm-mc --disassemble %s -triple=sbf-solana-solana -mattr=+static-syscalls \
# RUN: | FileCheck %s --check-prefix=CHECK-V2

# TODO: Test immediate field ranges.

Expand Down Expand Up @@ -109,5 +111,9 @@
# CHECK-NEW: exit
0x95,0x00,0x00,0x00,0x00,0x00,0x00,0x00

# CHECK-V2: syscall 5
0x95,0x00,0x00,0x00,0x05,0x00,0x00,0x00


# CHECK-NEW: return
0x9d,0x00,0x00,0x00,0x00,0x00,0x00,0x00
4 changes: 1 addition & 3 deletions llvm/test/MC/SBF/insn-unit.s
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,8 @@
// ======== BPF_JMP Class ========
ja Llabel0 // BPF_JA
call 1 // BPF_CALL
exit // BPF_EXIT
// CHECK: 05 00 1a 00 00 00 00 00 ja +0x1a
// CHECK: 05 00 19 00 00 00 00 00 ja +0x19
// CHECK: 85 00 00 00 01 00 00 00 call 0x1
// CHECK: 95 00 00 00 00 00 00 00 exit

jeq r0, r1, Llabel0 // BPF_JEQ | BPF_X
jne r3, r4, Llabel0 // BPF_JNE | BPF_X
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/MC/SBF/sbf-jmp.s
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,6 @@ call 8
# CHECK-ASM-OLD: encoding: [0x8d,0x00,0x00,0x00,0x04,0x00,0x00,0x00]
callx r4

# CHECK-OBJ-NEW: exit
# CHECK-ASM-NEW: encoding: [0x95,0x00,0x00,0x00,0x00,0x00,0x00,0x00]
# CHECK-OBJ-OLD: exit
# CHECK-ASM-OLD: encoding: [0x95,0x00,0x00,0x00,0x00,0x00,0x00,0x00]
exit
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# RUN: llvm-mc -triple=sbf-solana-solana --mcpu=sbfv2 -filetype=obj -o %t %s
# RUN: llvm-objdump -d -r %t | FileCheck --check-prefix=CHECK %s

syscall 9
return

// CHECK: 95 00 00 00 09 00 00 00 syscall 0x9
// CHECK: 9d 00 00 00 00 00 00 00 return

0 comments on commit 7dda748

Please sign in to comment.