From 7dda7488d031be0462545fb603cdfbee9ca08d02 Mon Sep 17 00:00:00 2001 From: Lucas Date: Tue, 17 Dec 2024 18:11:57 -0300 Subject: [PATCH 1/3] Implement static syscalls --- .../SBF/Disassembler/SBFDisassembler.cpp | 4 ++- llvm/lib/Target/SBF/SBFISelLowering.cpp | 17 ++++++++++-- llvm/lib/Target/SBF/SBFISelLowering.h | 6 ++++- llvm/lib/Target/SBF/SBFInstrFormats.td | 27 ++++++++++--------- llvm/lib/Target/SBF/SBFInstrInfo.td | 18 +++++++++++++ llvm/test/CodeGen/SBF/static_syscall.ll | 25 +++++++++++++++++ llvm/test/MC/Disassembler/SBF/sbf-jmp.txt | 6 +++++ llvm/test/MC/SBF/insn-unit.s | 4 +-- llvm/test/MC/SBF/sbf-jmp.s | 4 +-- .../{sbf-return.s => sbf-return-syscall.s} | 2 ++ 10 files changed, 91 insertions(+), 22 deletions(-) create mode 100644 llvm/test/CodeGen/SBF/static_syscall.ll rename llvm/test/MC/SBF/{sbf-return.s => sbf-return-syscall.s} (77%) diff --git a/llvm/lib/Target/SBF/Disassembler/SBFDisassembler.cpp b/llvm/lib/Target/SBF/Disassembler/SBFDisassembler.cpp index f9489bc85df3eb..327b6a9b8588a8 100644 --- a/llvm/lib/Target/SBF/Disassembler/SBFDisassembler.cpp +++ b/llvm/lib/Target/SBF/Disassembler/SBFDisassembler.cpp @@ -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 @@ -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); diff --git a/llvm/lib/Target/SBF/SBFISelLowering.cpp b/llvm/lib/Target/SBF/SBFISelLowering.cpp index 94b4c3f2bbcc6a..c7e429211a5718 100644 --- a/llvm/lib/Target/SBF/SBFISelLowering.cpp +++ b/llvm/lib/Target/SBF/SBFISelLowering.cpp @@ -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 &InVals) const { @@ -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(Callee)) { Callee = DAG.getTargetGlobalAddress(G->getGlobal(), CLI.DL, PtrVT, G->getOffset(), 0); } else if (ExternalSymbolSDNode *E = dyn_cast(Callee)) { Callee = DAG.getTargetExternalSymbol(E->getSymbol(), PtrVT, 0); + } else if (ConstantSDNode * CNode = dyn_cast(Callee)) { + uint64_t Cte = CNode->getZExtValue(); + uint64_t U32Max = static_cast + (std::numeric_limits::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. @@ -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); @@ -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; } diff --git a/llvm/lib/Target/SBF/SBFISelLowering.h b/llvm/lib/Target/SBF/SBFISelLowering.h index ef4449bada44b0..baec9caa72f8aa 100644 --- a/llvm/lib/Target/SBF/SBFISelLowering.h +++ b/llvm/lib/Target/SBF/SBFISelLowering.h @@ -28,7 +28,8 @@ enum NodeType : unsigned { SELECT_CC, BR_CC, Wrapper, - MEMCPY + MEMCPY, + SYSCALL, }; } @@ -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 &InVals) const override; diff --git a/llvm/lib/Target/SBF/SBFInstrFormats.td b/llvm/lib/Target/SBF/SBFInstrFormats.td index ae49010b6772fb..8821ed39b33759 100644 --- a/llvm/lib/Target/SBF/SBFInstrFormats.td +++ b/llvm/lib/Target/SBF/SBFInstrFormats.td @@ -72,19 +72,20 @@ class SBFJumpOp 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 val> { bits<2> Value = val; diff --git a/llvm/lib/Target/SBF/SBFInstrInfo.td b/llvm/lib/Target/SBF/SBFInstrInfo.td index b9e667070d9b55..94e17a961a24bf 100644 --- a/llvm/lib/Target/SBF/SBFInstrInfo.td +++ b/llvm/lib/Target/SBF/SBFInstrInfo.td @@ -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, @@ -801,6 +804,19 @@ class CALL let SBFClass = SBF_JMP; } +class SYSCALL + : TYPE_ALU_JMP { + bits<32> imm; + + let Inst{31-0} = imm; + let SBFClass = SBF_JMP; +} + + class CALLX : TYPE_ALU_JMP, Requires<[SBFNoCallxSrc]>; let DecoderNamespace = "SBFv2" in { def JALX_v2 : CALLX_SRC_REG<"callx">, Requires<[SBFCallxSrc]>; + def SYSCALL_v2 : SYSCALL<"syscall">, Requires<[SBFHasStaticSyscalls]>; } } @@ -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 { diff --git a/llvm/test/CodeGen/SBF/static_syscall.ll b/llvm/test/CodeGen/SBF/static_syscall.ll new file mode 100644 index 00000000000000..af1601ba590214 --- /dev/null +++ b/llvm/test/CodeGen/SBF/static_syscall.ll @@ -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 +} diff --git a/llvm/test/MC/Disassembler/SBF/sbf-jmp.txt b/llvm/test/MC/Disassembler/SBF/sbf-jmp.txt index 278ed8d3774da3..a51c1230ea4308 100644 --- a/llvm/test/MC/Disassembler/SBF/sbf-jmp.txt +++ b/llvm/test/MC/Disassembler/SBF/sbf-jmp.txt @@ -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. @@ -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 diff --git a/llvm/test/MC/SBF/insn-unit.s b/llvm/test/MC/SBF/insn-unit.s index ed24fdcf0b5220..54e51b437b1952 100644 --- a/llvm/test/MC/SBF/insn-unit.s +++ b/llvm/test/MC/SBF/insn-unit.s @@ -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 diff --git a/llvm/test/MC/SBF/sbf-jmp.s b/llvm/test/MC/SBF/sbf-jmp.s index ac1dbdde2b9294..308e40eeeceb40 100644 --- a/llvm/test/MC/SBF/sbf-jmp.s +++ b/llvm/test/MC/SBF/sbf-jmp.s @@ -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 diff --git a/llvm/test/MC/SBF/sbf-return.s b/llvm/test/MC/SBF/sbf-return-syscall.s similarity index 77% rename from llvm/test/MC/SBF/sbf-return.s rename to llvm/test/MC/SBF/sbf-return-syscall.s index 11e333f76983ef..9f3b9ca00004aa 100644 --- a/llvm/test/MC/SBF/sbf-return.s +++ b/llvm/test/MC/SBF/sbf-return-syscall.s @@ -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 \ No newline at end of file From 92e78eb28630d0a2b5cc62d3fb4968b48c058e60 Mon Sep 17 00:00:00 2001 From: Lucas Date: Wed, 18 Dec 2024 11:19:28 -0300 Subject: [PATCH 2/3] Rename syscall and return --- llvm/lib/Target/SBF/SBFInstrInfo.td | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Target/SBF/SBFInstrInfo.td b/llvm/lib/Target/SBF/SBFInstrInfo.td index 94e17a961a24bf..728ee17a53f678 100644 --- a/llvm/lib/Target/SBF/SBFInstrInfo.td +++ b/llvm/lib/Target/SBF/SBFInstrInfo.td @@ -854,7 +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]>; + def SYSCALL_v3 : SYSCALL<"syscall">, Requires<[SBFHasStaticSyscalls]>; } } @@ -900,7 +900,7 @@ class RETURN let isReturn = 1, isTerminator = 1, hasDelaySlot=0, isBarrier = 1, isNotDuplicable = 1, Predicates = [SBFHasStaticSyscalls] in { - def RETURN : RETURN<"return">; + def RETURN_v3 : RETURN<"return">; } // ADJCALLSTACKDOWN/UP pseudo insns @@ -966,7 +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]>; +def : Pat<(SBFSyscall imm:$imm), (SYSCALL_v3 imm:$imm)>, Requires<[SBFHasStaticSyscalls]>; // Loads let Predicates = [SBFNoALU32, SBFOldMemEncoding] in { From e79f5453b9f3ae1b18640851172661e2395fc0f7 Mon Sep 17 00:00:00 2001 From: Lucas Date: Wed, 18 Dec 2024 16:20:24 -0300 Subject: [PATCH 3/3] Remove external call from v3 and use pointer value directly --- llvm/lib/Target/SBF/SBFISelLowering.cpp | 14 ++----- llvm/lib/Target/SBF/SBFISelLowering.h | 3 -- llvm/lib/Target/SBF/SBFInstrInfo.td | 2 +- llvm/test/CodeGen/SBF/call_internal.ll | 15 ++++--- llvm/test/CodeGen/SBF/static_syscall.ll | 24 +++++------ llvm/test/CodeGen/SBF/static_syscall_2.ll | 50 +++++++++++++++++++++++ 6 files changed, 76 insertions(+), 32 deletions(-) create mode 100644 llvm/test/CodeGen/SBF/static_syscall_2.ll diff --git a/llvm/lib/Target/SBF/SBFISelLowering.cpp b/llvm/lib/Target/SBF/SBFISelLowering.cpp index c7e429211a5718..fd160e6032b8fa 100644 --- a/llvm/lib/Target/SBF/SBFISelLowering.cpp +++ b/llvm/lib/Target/SBF/SBFISelLowering.cpp @@ -446,7 +446,6 @@ SDValue SBFTargetLowering::LowerFormalArguments( } const unsigned SBFTargetLowering::MaxArgs = 5; -const uint64_t SBFTargetLowering::MaxSyscall = 100; SDValue SBFTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, SmallVectorImpl &InVals) const { @@ -599,15 +598,10 @@ SDValue SBFTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, G->getOffset(), 0); } else if (ExternalSymbolSDNode *E = dyn_cast(Callee)) { Callee = DAG.getTargetExternalSymbol(E->getSymbol(), PtrVT, 0); - } else if (ConstantSDNode * CNode = dyn_cast(Callee)) { - uint64_t Cte = CNode->getZExtValue(); - uint64_t U32Max = static_cast - (std::numeric_limits::max()); - if (Subtarget->getHasStaticSyscalls() && Cte >= U32Max - MaxSyscall) { - NodeCode = SBFISD::SYSCALL; - uint64_t SyscallCode = U32Max - Cte; - Callee = DAG.getConstant(SyscallCode, CLI.DL, MVT::i64); - } + } else if (isa(Callee) && Subtarget->getHasStaticSyscalls()) { + // When static syscalls are enabled and we have a constant operand for call, + // we emit a syscall. + NodeCode = SBFISD::SYSCALL; } // Returns a chain & a flag for retval copy to use. diff --git a/llvm/lib/Target/SBF/SBFISelLowering.h b/llvm/lib/Target/SBF/SBFISelLowering.h index baec9caa72f8aa..561af2a0aa569d 100644 --- a/llvm/lib/Target/SBF/SBFISelLowering.h +++ b/llvm/lib/Target/SBF/SBFISelLowering.h @@ -91,9 +91,6 @@ 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 &InVals) const override; diff --git a/llvm/lib/Target/SBF/SBFInstrInfo.td b/llvm/lib/Target/SBF/SBFInstrInfo.td index 728ee17a53f678..734fe58e13498f 100644 --- a/llvm/lib/Target/SBF/SBFInstrInfo.td +++ b/llvm/lib/Target/SBF/SBFInstrInfo.td @@ -963,7 +963,7 @@ def : Pat<(i64 (and (i64 GPR:$src), 0xffffFFFF)), // Calls def : Pat<(SBFcall tglobaladdr:$dst), (JAL tglobaladdr:$dst)>; def : Pat<(SBFcall texternalsym:$dst), (JAL texternalsym:$dst)>; -def : Pat<(SBFcall imm:$dst), (JAL imm:$dst)>; +def : Pat<(SBFcall imm:$dst), (JAL imm:$dst)>, Requires<[SBFNoStaticSyscalls]>; 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_v3 imm:$imm)>, Requires<[SBFHasStaticSyscalls]>; diff --git a/llvm/test/CodeGen/SBF/call_internal.ll b/llvm/test/CodeGen/SBF/call_internal.ll index 8d92c6dc3063af..8b181c5c07e776 100644 --- a/llvm/test/CodeGen/SBF/call_internal.ll +++ b/llvm/test/CodeGen/SBF/call_internal.ll @@ -1,8 +1,8 @@ -; RUN: llc < %s -march=sbf --show-mc-encoding | FileCheck --check-prefix=CHECK-ASM %s -; RUN: llc -march=sbf --filetype=obj -o - %s | llvm-objdump -d - | FileCheck --check-prefix=CHECK-OBJ %s -; RUN: llc < %s -march=sbf -mcpu=sbfv2 --show-mc-encoding | FileCheck --check-prefix=CHECK-ASM %s +; RUN: llc < %s -march=sbf --show-mc-encoding | FileCheck --check-prefixes=CHECK-ASM,CHECK-ASM-V0 %s +; RUN: llc -march=sbf --filetype=obj -o - %s | llvm-objdump -d - | FileCheck --check-prefixes=CHECK-OBJ,CHECK-OBJ-V0 %s +; RUN: llc < %s -march=sbf -mcpu=sbfv2 --show-mc-encoding | FileCheck --check-prefixes=CHECK-ASM,CHECK-ASM-V3 %s ; RUN: llc -march=sbf -mcpu=sbfv2 --filetype=obj -o - %s | llvm-objdump -d - -; | FileCheck --check-prefix=CHECK-OBJ %s +; | FileCheck --check-prefixes=CHECK-OBJ,CHECK-OBJ-V3 %s @.str = private unnamed_addr constant [5 x i8] c"foo\0A\00", align 1 @@ -16,8 +16,11 @@ entry: ; Function Attrs: nounwind define dso_local i64 @entrypoint(ptr noundef %input) local_unnamed_addr #1 { entry: -; CHECK-ASM: call 1811268606 # encoding: [0x85,0x00,0x00,0x00,0xfe,0xc3,0xf5,0x6b] -; CHECK-OBJ: 85 00 00 00 fe c3 f5 6b call 0x6bf5c3fe +; CHECK-ASM-V0: call 1811268606 # encoding: [0x85,0x00,0x00,0x00,0xfe,0xc3,0xf5,0x6b] +; CHECK-ASM-V3: syscall 1811268606 # encoding: [0x95,0x00,0x00,0x00,0xfe,0xc3,0xf5,0x6b] + +; CHECK-OBJ-V0: 85 00 00 00 fe c3 f5 6b call 0x6bf5c3fe +; CHECK-OBJ-V3: 95 00 00 00 fe c3 f5 6b syscall 0x6bf5c3fe tail call void inttoptr (i64 1811268606 to ptr)(ptr noundef nonnull @.str, i64 noundef 4) #3 %add.ptr = getelementptr inbounds i8, ptr %input, i64 4 diff --git a/llvm/test/CodeGen/SBF/static_syscall.ll b/llvm/test/CodeGen/SBF/static_syscall.ll index af1601ba590214..fe5a66660e96a4 100644 --- a/llvm/test/CodeGen/SBF/static_syscall.ll +++ b/llvm/test/CodeGen/SBF/static_syscall.ll @@ -1,5 +1,5 @@ -; 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 +; RUN: llc -march=sbf < %s | FileCheck --check-prefix=CHECK-V0 %s +; RUN: llc -march=sbf -mattr=+static-syscalls -show-mc-encoding < %s | FileCheck --check-prefix=CHECK-V3 %s ; Function Attrs: nounwind @@ -7,19 +7,19 @@ 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-V0: call 2 +; CHECK-V3 syscall 2 # encoding: [0x95,0x00,0x00,0x00,0x01,0x00,0x00,0x00] + %syscall_1 = tail call i32 inttoptr (i64 2 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-V0: call 11 +; CHECK-V3: syscall 11 # encoding: [0x95,0x00,0x00,0x00,0x0b,0x00,0x00,0x00] + %syscall_2 = tail call i32 inttoptr (i64 11 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) +; CHECK-V0: call 112 +; CHECK-V3: syscall 112 + %syscall_3 = tail call i32 inttoptr (i64 112 to ptr)(i32 noundef %a, i32 noundef %b) %add_1 = add i32 %syscall_1, %syscall_2 - %add_2 = add i32 %add_1, %not_syscall + %add_2 = add i32 %add_1, %syscall_3 ret i32 %add_1 } diff --git a/llvm/test/CodeGen/SBF/static_syscall_2.ll b/llvm/test/CodeGen/SBF/static_syscall_2.ll new file mode 100644 index 00000000000000..6c7ac56b5a873f --- /dev/null +++ b/llvm/test/CodeGen/SBF/static_syscall_2.ll @@ -0,0 +1,50 @@ +; RUN: llc -march=sbf -mattr=+static-syscalls < %s | FileCheck --check-prefix=CHECK %s + +; Syscall declaration in C: +; +; int c_declaration(int a, int b) { +; int (*const syscall)(int a, int b) = (void*)50; +; return syscall(a, b); +; } +; The following is the unoptimized output from clang: + +define dso_local i32 @c_declaration(i32 noundef %a, i32 noundef %b) #0 { +entry: + %a.addr = alloca i32, align 4 + %b.addr = alloca i32, align 4 + %syscall = alloca ptr, align 8 + store i32 %a, ptr %a.addr, align 4 + store i32 %b, ptr %b.addr, align 4 + store ptr inttoptr (i64 50 to ptr), ptr %syscall, align 8 + %0 = load i32, ptr %a.addr, align 4 + %1 = load i32, ptr %b.addr, align 4 + +; Ensure the syscall instruction is emitted +; CHECK: syscall 50 + + %call = call i32 inttoptr (i64 50 to ptr)(i32 noundef %0, i32 noundef %1) + ret i32 %call +} + +; Syscall declaration in Rust: +; +; #[no_mangle] +; pub unsafe fn rust_declaration(b: u64) -> u32 { +; let syscall : extern "C" fn(b: u64) -> u32 = core::mem::transmute(60u64); +; return syscall(b); +; } +; The following is the unoptimized output from rustc: + +define i32 @rust_declaration(i64 %b) unnamed_addr { +start: + %syscall.dbg.spill = alloca [8 x i8], align 8 + %b.dbg.spill = alloca [8 x i8], align 8 + store i64 %b, ptr %b.dbg.spill, align 8 + store ptr getelementptr (i8, ptr null, i64 60), ptr %syscall.dbg.spill, align 8 + +; Ensure the syscall instruction is emitted +; CHECK: syscall 60 + + %_0 = call i32 getelementptr (i8, ptr null, i64 60)(i64 %b) + ret i32 %_0 +} \ No newline at end of file