Skip to content

Commit

Permalink
Check CI
Browse files Browse the repository at this point in the history
Signed-off-by: Mikhail Sherstennikov <[email protected]>
  • Loading branch information
shermike committed Mar 15, 2024
1 parent 2422e4d commit d93fb1b
Show file tree
Hide file tree
Showing 28 changed files with 971 additions and 305 deletions.
7 changes: 5 additions & 2 deletions clang/include/clang/Basic/BuiltinsEVM.def
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ BUILTIN(__builtin_evm_gas, "LLLLi", "nc")
//- **Return:** *None*
//- **Codegen details:**
// - LOG1 opcode: `0xa1`
BUILTIN(__builtin_evm_log1, "vcC*LLLLiLLLLi", "nc")
BUILTIN(__builtin_evm_log1, "vvC*LLLLiLLLLi", "nc")

// @brief Log2
//
Expand Down Expand Up @@ -469,7 +469,7 @@ BUILTIN(__builtin_evm_staticcall, "LLLLiLLLLiLLLLiLLLLiLLLLiLLLLiLLLLi", "nc")
//- **Return:** *Ends execution*
//- **Codegen details**
// - REVERT opcode: `0xfd`
BUILTIN(__builtin_evm_revert, "vLLLLiLLLLi", "nc")
BUILTIN(__builtin_evm_revert, "vvC*LLLLi", "nc")

// @brief SelfDestruct
//
Expand Down Expand Up @@ -513,5 +513,8 @@ BUILTIN(__builtin_evm_printf, "vcC*.", "nc")
// the frame buffer, which will be passed to SHA3 instruction.
BUILTIN(__builtin_evm_sha3_vargs, "LLLLi.", "nc")

// Load config parameter.
BUILTIN(__builtin_evm_cload, "LLLLiLLLLi", "nc")

#undef BUILTIN
#undef TARGET_BUILTIN
3 changes: 2 additions & 1 deletion llvm/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ autoconf/autom4te.cache
# Visual Studio built-in CMake configuration
/CMakeSettings.json
# CLion project configuration
/.idea
.idea
# Qt Creator project configuration
/CMakeLists.txt.user

Expand All @@ -43,6 +43,7 @@ projects/*
!projects/*.*
!projects/evm-sdk
!projects/evm-tests
!projects/evm-tools
!projects/Makefile
runtimes/*
!runtimes/*.*
Expand Down
5 changes: 4 additions & 1 deletion llvm/include/llvm/IR/IntrinsicsEVM.td
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ let TargetPrefix = "evm" in { // All intrinsics start with "llvm.evm."
[IntrWriteMem, IntrHasSideEffects]>;

def int_evm_revert : ClangBuiltin<"__builtin_evm_revert">,
Intrinsic<[], [llvm_i256_ty, llvm_i256_ty], [IntrWriteMem, IntrHasSideEffects, IntrNoReturn]>;
Intrinsic<[], [llvm_ptr_ty, llvm_i256_ty], [IntrWriteMem, IntrHasSideEffects, IntrNoReturn]>;

def int_evm_return : ClangBuiltin<"__builtin_evm_return">,
Intrinsic<[], [llvm_i256_ty, llvm_i256_ty], [IntrWriteMem, IntrHasSideEffects, IntrNoReturn]>;
Expand All @@ -169,4 +169,7 @@ let TargetPrefix = "evm" in { // All intrinsics start with "llvm.evm."
Intrinsic<[llvm_i256_ty], [llvm_i256_ty, llvm_i256_ty, llvm_i256_ty], [IntrNoMem]>;

def int_evm_printf : Intrinsic<[], [llvm_ptr_ty, llvm_vararg_ty], []>;

def int_evm_cload : ClangBuiltin<"__builtin_evm_cload">,
Intrinsic<[llvm_i256_ty], [llvm_i256_ty], [IntrNoMem, IntrHasSideEffects]>;
}
13 changes: 9 additions & 4 deletions llvm/lib/Target/EVM/EVMAsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,11 +203,16 @@ void EVMAsmPrinter::emitConstantPool() {
Signature->Params.push_back(valTypeFromMVT(RegisterVT));
}

ComputeValueVTs(TLI, DL, F.getFunctionType()->getReturnType(), EResults);
for (EVT VT : EResults) {
auto RegisterVT = TLI.getRegisterType(F.getContext(), VT);
Signature->Returns.push_back(valTypeFromMVT(RegisterVT));
if (F.getFunctionType()->getReturnType()->isPointerTy()) {
Signature->Returns.push_back(ValType::PTR);
} else {
ComputeValueVTs(TLI, DL, F.getFunctionType()->getReturnType(), EResults);
for (EVT VT : EResults) {
auto RegisterVT = TLI.getRegisterType(F.getContext(), VT);
Signature->Returns.push_back(valTypeFromMVT(RegisterVT));
}
}

Streamer->emitFunctionType(Sym);
}

Expand Down
62 changes: 43 additions & 19 deletions llvm/lib/Target/EVM/EVMConvertRegToStack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,13 +146,14 @@ static unsigned getSlotMemOpcode(bool IsStore) {
}

int EVMConvertRegToStack::convertCall(MachineInstr &MI, MachineBasicBlock &MBB) const {
int StackOpcode = -1;

auto& MF = *MBB.getParent();
EVMMachineFunctionInfo *MFI = MF.getInfo<EVMMachineFunctionInfo>();

unsigned FrameSize = MFI->getFrameSizeInBytes();
assert(FrameSize % MFI->getStackSlotSizeInBytes() == 0);
if (MFI->hasDynamicAlloc()) {
FrameSize += MFI->getStackSlotSizeInBytes();
}

auto* InsertBefore = &MI;
auto MakeInst = [&]<class... Imms>(unsigned Opcode, Imms... imms) {
Expand All @@ -167,22 +168,45 @@ int EVMConvertRegToStack::convertCall(MachineInstr &MI, MachineBasicBlock &MBB)
using namespace EVM;
auto LoadOpc = getSlotMemOpcode(false);
auto StoreOpc = getSlotMemOpcode(true);
auto SlotSize = MFI->getStackSlotSizeInBytes();

// Update FP for the callee frame
if (MFI->hasDynamicAlloc()) {
// Function has dynamic stack allocation, so we need to read frame size
// from the special slot in the frame.
auto Offset = MF.getFrameInfo().getObjectOffset(MFI->getDynSizeIndex());
MakeInst(PUSH32, FpAddress) // fpaddr
.addComment(MF, "Call start");
MakeInst(MLOAD); // fp
MakeInst(DUP1); // fp, fp
MakeInst(PUSH32, Offset); // fp, fp, dyn_size_offset
MakeInst(ADD); // fp, new_fp_slot
MakeInst(MLOAD); // fp, new_fp
MakeInst(PUSH32, SlotSize); // fp, new_fp, slot_size
MakeInst(ADD); // fp, new_fp + slot_size
MakeInst(SWAP1); // new_fp, fp
MakeInst(DUP2); // new_fp, fp, new_fp
MakeInst(PUSH32, SlotSize); // new_fp, fp, new_fp, slot_size
MakeInst(SWAP1); // new_fp, fp, slot_size, new_fp
MakeInst(SUB); // new_fp, fp, new_fp - slot_size
MakeInst(StoreOpc); // new_fp
} else {
// Save current FP in the slot after current frame
MakeInst(PUSH32, FpAddress) // fpaddr
.addComment(MF, "Call start");
MakeInst(MLOAD); // fp
MakeInst(DUP1); // fp, fp
MakeInst(PUSH32, FrameSize); // fp, fp, frame_size
MakeInst(ADD); // fp, fp + frame_size
MakeInst(StoreOpc); // -

MakeInst(PUSH32, FpAddress); // fpaddr
MakeInst(MLOAD); // fp
MakeInst(PUSH32, FrameSize + SlotSize);
// fp, frame_size
MakeInst(ADD); // new_fp
}

// Save current FP in the slot after current frame
MakeInst(PUSH32, FpAddress).addComment(MF, "Call start");
// fpaddr
MakeInst(MLOAD); // fp
MakeInst(DUP1); // fp, fp
MakeInst(PUSH32, FrameSize); // fp, fp, frame_size
MakeInst(ADD); // fp, fp + frame_size
MakeInst(StoreOpc); // -

// Update FP to the callee frame
MakeInst(PUSH32, FpAddress); // fpaddr
MakeInst(MLOAD); // fp
MakeInst(PUSH32, FrameSize + MFI->getStackSlotSizeInBytes());
// fp, frame_size
MakeInst(ADD); // new_fp
MakeInst(DUP1); // new_fp, new_fp
MakeInst(PUSH32, FpAddress); // new_fp, new_fp, fpaddr
MakeInst(MSTORE); // new_fp
Expand All @@ -192,6 +216,7 @@ int EVMConvertRegToStack::convertCall(MachineInstr &MI, MachineBasicBlock &MBB)
MakeInst(PUSH32, SpAddress); // new_fp, spaddr
MakeInst(MSTORE); // -

int StackOpcode;
if (MF.getSubtarget<EVMSubtarget>().hasSubroutine()) {
// With subroutine support we do not push return address on to stack
StackOpcode = EVM::JUMPSUB;
Expand Down Expand Up @@ -219,8 +244,7 @@ int EVMConvertRegToStack::convertCall(MachineInstr &MI, MachineBasicBlock &MBB)
MakeInst(JUMPDEST).addComment(MF, "Call continuation");
MakeInst(PUSH32, FpAddress); // fpaddr
MakeInst(MLOAD); // fp
MakeInst(PUSH32, MFI->getStackSlotSizeInBytes());
// fp, slot_size
MakeInst(PUSH32, SlotSize); // fp, slot_size
MakeInst(SWAP1); // slot_size, fp
MakeInst(SUB); // fp - slot_size
MakeInst(LoadOpc); // caller_fp
Expand Down
54 changes: 20 additions & 34 deletions llvm/lib/Target/EVM/EVMFinalization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,6 @@ bool EVMFinalization::runOnMachineFunction(MachineFunction &MF) {
BuildMI(MBB, begin, begin->getDebugLoc(), TII->get(EVM::BEGINSUB));
}


// use iterator since we need to remove pseudo instructions
for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
I != E;) {
Expand All @@ -161,39 +160,26 @@ bool EVMFinalization::runOnMachineFunction(MachineFunction &MF) {
}
}


// Emit final code to separate file. It is better than disassembling of the result binary, since it contains basic
// blocks and some additional information.
// TODO(EVM): this is kept in the repository solely for debug purposes. Once the EVM matures, we need to rework it.
if (1) {
unsigned Pc = 89;
std::error_code EC;
raw_fd_ostream OS("code.ir", EC);
OS << "Function: " << MF.getName() << '\n';
for (MachineBasicBlock &MBB : MF) {
OS << "\nbb." << MBB.getNumber()<< '.' << MBB.getName() << ":\n";
OS << "; predecessors: ";
if (!MBB.pred_empty()) {
ListSeparator LS;
for (auto *Pred : MBB.predecessors())
OS << LS << printMBBReference(*Pred);
OS << '\n';
}
if (!MBB.succ_empty()) {
OS.indent(2) << "successors: ";
ListSeparator LS;
for (auto I = MBB.succ_begin(), E = MBB.succ_end(); I != E; ++I) {
OS << LS << printMBBReference(**I);
}
OS << '\n';
}
for (auto &MI : MBB) {
OS << " " << Pc << " " << MI;
Pc += 1;
// TSFlags contains immediate size
Pc += MI.getDesc().TSFlags;
}
}
auto& MFI = *MF.getInfo<EVMMachineFunctionInfo>();
if (MFI.hasDynamicAlloc()) {
auto I = ++(MF.begin()->instr_begin()); //->getNextNode();
auto &MBB = *MF.begin();
auto Offset = MF.getFrameInfo().getObjectOffset(MFI.getDynSizeIndex());
unsigned FpAddress = MF.getSubtarget<EVMSubtarget>().getFramePointer();

auto TII = MF.getSubtarget<EVMSubtarget>().getInstrInfo();
BuildMI(MBB, *I, DebugLoc(), TII->get(EVM::PUSH4))
.addImm(FpAddress);
BuildMI(MBB, *I, DebugLoc(), TII->get(EVM::MLOAD)); // fp
BuildMI(MBB, *I, DebugLoc(), TII->get(EVM::DUP1)); // fp, fp
BuildMI(MBB, *I, DebugLoc(), TII->get(EVM::PUSH4))
.addImm(MFI.getFrameSizeInBytes()); // fp, fp, frame_size
BuildMI(MBB, *I, DebugLoc(), TII->get(EVM::ADD)); // fp, new_fp = fp + frame_size
BuildMI(MBB, *I, DebugLoc(), TII->get(EVM::SWAP1)); // new_fp, fp
BuildMI(MBB, *I, DebugLoc(), TII->get(EVM::PUSH4))
.addImm(Offset); // new_fp, fp, dyn_size_offset
BuildMI(MBB, *I, DebugLoc(), TII->get(EVM::ADD)); // new_fp, dyn_size_slot
BuildMI(MBB, *I, DebugLoc(), TII->get(EVM::MSTORE));
}

return Changed;
Expand Down
42 changes: 36 additions & 6 deletions llvm/lib/Target/EVM/EVMISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,7 @@ EVMTargetLowering::EVMTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::FrameIndex, VT, Custom);
setOperationAction(ISD::TargetFrameIndex, VT, Custom);

// FIXME: DYNAMIC_STACKALLOC
setOperationAction(ISD::DYNAMIC_STACKALLOC, VT, Expand);
setOperationAction(ISD::DYNAMIC_STACKALLOC, VT, Custom);
}
setOperationAction(ISD::BR_CC, MVT::i256, Custom);
setOperationAction(ISD::BR_JT, MVT::Other, Expand);
Expand Down Expand Up @@ -382,6 +381,8 @@ SDValue EVMTargetLowering::LowerOperation(SDValue Op,
// arithmetic instructions.
return DAG.getNode(ISD::TRUNCATE, SDLoc(Op), Op.getValueType(), Res);
}
case ISD::DYNAMIC_STACKALLOC:
return LowerDYNAMIC_STACKALLOC(Op, DAG);
case ISD::CTLZ:
case ISD::CTTZ:
case ISD::CTLZ_ZERO_UNDEF:
Expand Down Expand Up @@ -433,6 +434,32 @@ SDValue EVMTargetLowering::LowerCtxz(SDValue Op, SelectionDAG &DAG) const {
return ResNode;
}

SDValue EVMTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const {
SDLoc DL(Op);
SDValue Chain = Op.getOperand(0);
SDValue Size = Op.getOperand(1);

MachineFunction &MF = DAG.getMachineFunction();
auto& MFI = *MF.getInfo<EVMMachineFunctionInfo>();

if (!MFI.hasDynamicAlloc()) {
auto Ty = IntegerType::get(MF.getFunction().getContext(), 32);
auto Align = MF.getDataLayout().getPrefTypeAlign(Ty);
auto Index = MF.getFrameInfo().CreateStackObject(32, Align, false);
MFI.setDynSizeIndex(Index);
}

auto FI = DAG.getTargetFrameIndex(MFI.getDynSizeIndex(), {MVT::i256});
auto LD = DAG.getLoad(MVT::i256, DL, Chain, FI, MachinePointerInfo());
if (Size.getValueSizeInBits() < 256) {
Size = DAG.getNode(ISD::ZERO_EXTEND, DL, {MVT::i256}, Size);
}
auto NewDynSize = DAG.getNode(ISD::ADD, DL, MVT::i256, {LD, Size});
Chain = DAG.getStore(Chain, DL, NewDynSize, FI, MachinePointerInfo());

return DAG.getMergeValues({LD, Chain}, DL);
}

SDValue EVMTargetLowering::LowerCopyToReg(SDValue Op,
SelectionDAG &DAG) const {
SDValue Src = Op.getOperand(2);
Expand All @@ -457,11 +484,14 @@ void EVMTargetLowering::ReplaceNodeResults(SDNode *N,
SelectionDAG &DAG) const {
SDLoc DL(N);

assert(N->getNumValues() == 1);

auto Result = LowerOperation(SDValue(N, 0), DAG);

Results.push_back(Result);
if (Result.getOpcode() == ISD::MERGE_VALUES) {
for (unsigned i = 0; i < Result.getNumOperands(); i++) {
Results.push_back(Result.getOperand(i));
}
} else {
Results.push_back(Result);
}
}

MachineBasicBlock *
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/EVM/EVMISelLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ class EVMTargetLowering : public TargetLowering {
SDValue LowerBasicBlock(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerCopyToReg(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerCtxz(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const;

// This method returns the name of a target specific DAG node.
const char *getTargetNodeName(unsigned Opcode) const override;
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/Target/EVM/EVMInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,10 @@ defm SLOAD : Inst_1_1<"SLOAD",
defm SSTORE : Inst_2_0<"SSTORE",
[(int_evm_sstore GPR:$src1, GPR:$src2)],
0x55, 200000>;

defm CLOAD : Inst_1_1<"CLOAD",
[(set GPR:$dst, (int_evm_cload GPR:$src))],
0xc4, 200>;
}

let isBranch = 1, isTerminator = 1, isIndirectBranch = 1 in {
Expand Down Expand Up @@ -699,6 +703,8 @@ def : Pat<(i256 (int_evm_sload GPR:$addr)),
(i256 (SLOAD_r GPR:$addr))>;
def : Pat<(int_evm_sstore GPR:$offset, GPR:$value),
(SSTORE_r GPR:$offset, GPR:$value)>;
def : Pat<(i256 (int_evm_cload GPR:$addr)),
(i256 (CLOAD_r GPR:$addr))>;

def : Pat<(int_evm_mload GPR:$addr), (MLOAD_r GPR:$addr)>;
def : Pat<(int_evm_mstore GPR:$offset, GPR:$value),
Expand Down
14 changes: 13 additions & 1 deletion llvm/lib/Target/EVM/EVMMachineFunctionInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,18 @@ class EVMMachineFunctionInfo : public MachineFunctionInfo {
return SpillsCount * getStackSlotSizeInBytes() + LocalsSize;
}

bool hasDynamicAlloc() const {
return DynSizeIndex != -1;
}

void setDynSizeIndex(int I) {
DynSizeIndex = I;
}

int getDynSizeIndex() const {
return DynSizeIndex;
}

static unsigned getStackSlotSizeInBytes() {
return 8;
}
Expand All @@ -50,7 +62,7 @@ class EVMMachineFunctionInfo : public MachineFunctionInfo {
MachineFunction &MF;
unsigned NumStackArgs{0};
unsigned SpillsCount{0};

int DynSizeIndex{-1};
};

} // end namespace llvm
Expand Down
Loading

0 comments on commit d93fb1b

Please sign in to comment.