diff --git a/llvm/lib/Target/EVM/CMakeLists.txt b/llvm/lib/Target/EVM/CMakeLists.txt index e2c1e7852fa6..ceed4bf575e0 100644 --- a/llvm/lib/Target/EVM/CMakeLists.txt +++ b/llvm/lib/Target/EVM/CMakeLists.txt @@ -36,7 +36,6 @@ add_llvm_target(EVMCodeGen EVMStackify.cpp EVMSubtarget.cpp EVMTargetMachine.cpp - EVMTargetObjectFile.cpp EVMTargetTransformInfo.cpp LINK_COMPONENTS diff --git a/llvm/lib/Target/EVM/EVMAsmPrinter.cpp b/llvm/lib/Target/EVM/EVMAsmPrinter.cpp index 168dcf273ed7..22b3d476d072 100644 --- a/llvm/lib/Target/EVM/EVMAsmPrinter.cpp +++ b/llvm/lib/Target/EVM/EVMAsmPrinter.cpp @@ -39,12 +39,36 @@ class EVMAsmPrinter : public AsmPrinter { StringRef getPassName() const override { return "EVM Assembly "; } + void SetupMachineFunction(MachineFunction &MF) override; + void emitInstruction(const MachineInstr *MI) override; void emitFunctionEntryLabel() override; + + /// Return true if the basic block has exactly one predecessor and the control + /// transfer mechanism between the predecessor and this block is a + /// fall-through. + bool isBlockOnlyReachableByFallthrough( + const MachineBasicBlock *MBB) const override; }; } // end of anonymous namespace +void EVMAsmPrinter::SetupMachineFunction(MachineFunction &MF) { + // Unbundle bundles. + for (MachineBasicBlock &MBB : MF) { + MachineBasicBlock::instr_iterator I = MBB.instr_begin(), + E = MBB.instr_end(); + for (; I != E; ++I) { + if (I->isBundledWithPred()) { + assert(I->isConditionalBranch() || I->isUnconditionalBranch()); + I->unbundleFromPred(); + } + } + } + + AsmPrinter::SetupMachineFunction(MF); +} + void EVMAsmPrinter::emitFunctionEntryLabel() { AsmPrinter::emitFunctionEntryLabel(); @@ -70,12 +94,17 @@ void EVMAsmPrinter::emitFunctionEntryLabel() { void EVMAsmPrinter::emitInstruction(const MachineInstr *MI) { EVMMCInstLower MCInstLowering(OutContext, *this, VRegMapping, MF->getRegInfo()); - MCInst TmpInst; MCInstLowering.Lower(MI, TmpInst); EmitToStreamer(*OutStreamer, TmpInst); } +bool EVMAsmPrinter::isBlockOnlyReachableByFallthrough( + const MachineBasicBlock *MBB) const { + // For simplicity, always emit BB labels. + return false; +} + extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeEVMAsmPrinter() { const RegisterAsmPrinter X(getTheEVMTarget()); } diff --git a/llvm/lib/Target/EVM/EVMISelLowering.cpp b/llvm/lib/Target/EVM/EVMISelLowering.cpp index f4f65d50ed28..6c8738d2d52f 100644 --- a/llvm/lib/Target/EVM/EVMISelLowering.cpp +++ b/llvm/lib/Target/EVM/EVMISelLowering.cpp @@ -387,7 +387,7 @@ SDValue EVMTargetLowering::LowerFormalArguments( fail(DL, DAG, "VarArg is not supported yet"); MachineFunction &MF = DAG.getMachineFunction(); - auto *MFI = MF.getInfo(); + auto *MFI = MF.getInfo(); // Set up the incoming ARGUMENTS value, which serves to represent the liveness // of the incoming values before they're represented by virtual registers. diff --git a/llvm/lib/Target/EVM/EVMInstrInfo.cpp b/llvm/lib/Target/EVM/EVMInstrInfo.cpp index 69b98ae7152f..caa9e68cb011 100644 --- a/llvm/lib/Target/EVM/EVMInstrInfo.cpp +++ b/llvm/lib/Target/EVM/EVMInstrInfo.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "EVMInstrInfo.h" +#include "EVMMachineFunctionInfo.h" #include "MCTargetDesc/EVMMCTargetDesc.h" using namespace llvm; @@ -65,6 +66,12 @@ bool EVMInstrInfo::analyzeBranch(MachineBasicBlock &MBB, FBB = nullptr; Cond.clear(); + const auto *MFI = MBB.getParent()->getInfo(); + if (MFI->getIsStackified()) { + LLVM_DEBUG(dbgs() << "Can't analyze terminators in stackified code"); + return true; + } + // Iterate backwards and analyze all terminators. MachineBasicBlock::reverse_iterator I = MBB.rbegin(), E = MBB.rend(); while (I != E) { diff --git a/llvm/lib/Target/EVM/EVMInstrInfo.td b/llvm/lib/Target/EVM/EVMInstrInfo.td index 0ece41690a4b..8700834e45d8 100644 --- a/llvm/lib/Target/EVM/EVMInstrInfo.td +++ b/llvm/lib/Target/EVM/EVMInstrInfo.td @@ -794,7 +794,7 @@ foreach I = {1-16} in { defm PUSH0 : I<(outs), (ins), [], "PUSH0", "", 0x5F, 2>; -def PUSH8_LABEL : NI<(outs), (ins jmptarget:$dst), [], false, "", 0, 0> { +def PUSH_LABEL : NI<(outs), (ins jmptarget:$dst), [], false, "", 0, 0> { let isCodeGenOnly = 1; } @@ -1122,7 +1122,7 @@ def PUSH32_S : NI<(outs), (ins i256imm:$imm), [], true, "PUSH32 $imm", } // Pseudo instructions for linkage -let isCodeGenOnly = 1 in -defm DATA - : I<(outs GPR:$dst), (ins jmptarget:$reloc), [], "", - "", 0, 0>; +let isCodeGenOnly = 1, BaseName = "DATA" in { + def DATA : NI<(outs GPR:$dst), (ins jmptarget:$reloc), [], false, "", 0, 0>; + def DATA_S : NI<(outs), (ins jmptarget:$reloc), [], true, "", 0, 0>; +} diff --git a/llvm/lib/Target/EVM/EVMMCInstLower.cpp b/llvm/lib/Target/EVM/EVMMCInstLower.cpp index ceea05b7f723..297385478bb7 100644 --- a/llvm/lib/Target/EVM/EVMMCInstLower.cpp +++ b/llvm/lib/Target/EVM/EVMMCInstLower.cpp @@ -27,33 +27,23 @@ using namespace llvm; extern cl::opt EVMKeepRegisters; -static void removeRegisterOperands(const MachineInstr *MI, MCInst &OutMI) { - // Remove all uses of stackified registers to bring the instruction format - // into its final stack form used throughout MC, and transition opcodes to - // their _S variant. +// Stackify instruction that were not stackified before. +// Only two instructions need to be stackified here: PUSH_LABEL and DATA_S, +static void stackifyInstruction(const MachineInstr *MI, MCInst &OutMI) { if (MI->isDebugInstr() || MI->isLabel() || MI->isInlineAsm()) return; - // Transform 'register' instruction to 'stack' one. - unsigned RegOpcode = OutMI.getOpcode(); - if (RegOpcode == EVM::PUSH8_LABEL) { - // Replace PUSH8_LABEL with PUSH8_S opcode. - OutMI.setOpcode(EVM::PUSH8_S); - } else { - unsigned StackOpcode = EVM::getStackOpcode(RegOpcode); - OutMI.setOpcode(StackOpcode); - } + // Check there are no register operands. + assert(std::all_of(OutMI.begin(), OutMI.end(), + [](const MCOperand &MO) { return !MO.isReg(); })); - // Remove register operands. - for (auto I = OutMI.getNumOperands(); I; --I) { - auto &MO = OutMI.getOperand(I - 1); - if (MO.isReg()) { - OutMI.erase(&MO); - } - } - - if (RegOpcode == EVM::DATA) + // Set up final opcodes for the following codegen-only instructions. + unsigned Opcode = OutMI.getOpcode(); + if (Opcode == EVM::PUSH_LABEL || Opcode == EVM::DATA_S) OutMI.setOpcode(EVM::PUSH4_S); + + // Check that all the instructions are in the 'stack' form. + assert(EVM::getRegisterOpcode(OutMI.getOpcode())); } MCSymbol * @@ -136,7 +126,7 @@ void EVMMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) { case MachineOperand::MO_MCSymbol: { MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VariantKind::VK_None; unsigned Opc = MI->getOpcode(); - if (Opc == EVM::DATA) + if (Opc == EVM::DATA_S) Kind = MCSymbolRefExpr::VariantKind::VK_EVM_DATA; MCOp = MCOperand::createExpr( @@ -156,7 +146,7 @@ void EVMMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) { OutMI.addOperand(MCOp); } if (!EVMKeepRegisters) - removeRegisterOperands(MI, OutMI); + stackifyInstruction(MI, OutMI); else if (Desc.variadicOpsAreDefs()) OutMI.insert(OutMI.begin(), MCOperand::createImm(MI->getNumExplicitDefs())); } diff --git a/llvm/lib/Target/EVM/EVMMachineFunctionInfo.cpp b/llvm/lib/Target/EVM/EVMMachineFunctionInfo.cpp index 63574319e396..50db06c257f9 100644 --- a/llvm/lib/Target/EVM/EVMMachineFunctionInfo.cpp +++ b/llvm/lib/Target/EVM/EVMMachineFunctionInfo.cpp @@ -13,11 +13,26 @@ #include "EVMMachineFunctionInfo.h" using namespace llvm; -EVMFunctionInfo::~EVMFunctionInfo() = default; // anchor. +EVMMachineFunctionInfo::~EVMMachineFunctionInfo() = default; -MachineFunctionInfo * -EVMFunctionInfo::clone(BumpPtrAllocator &Allocator, MachineFunction &DestMF, - const DenseMap - &Src2DstMBB) const { - return DestMF.cloneInfo(*this); +MachineFunctionInfo *EVMMachineFunctionInfo::clone( + BumpPtrAllocator &Allocator, MachineFunction &DestMF, + const DenseMap &Src2DstMBB) + const { + return DestMF.cloneInfo(*this); +} + +yaml::EVMMachineFunctionInfo::~EVMMachineFunctionInfo() = default; + +yaml::EVMMachineFunctionInfo::EVMMachineFunctionInfo( + const llvm::EVMMachineFunctionInfo &MFI) + : IsStackified(MFI.getIsStackified()) {} + +void yaml::EVMMachineFunctionInfo::mappingImpl(yaml::IO &YamlIO) { + MappingTraits::mapping(YamlIO, *this); +} + +void EVMMachineFunctionInfo::initializeBaseYamlFields( + const yaml::EVMMachineFunctionInfo &YamlMFI) { + IsStackified = YamlMFI.IsStackified; } diff --git a/llvm/lib/Target/EVM/EVMMachineFunctionInfo.h b/llvm/lib/Target/EVM/EVMMachineFunctionInfo.h index b39709960358..0d49c32cebe8 100644 --- a/llvm/lib/Target/EVM/EVMMachineFunctionInfo.h +++ b/llvm/lib/Target/EVM/EVMMachineFunctionInfo.h @@ -16,13 +16,33 @@ #include "MCTargetDesc/EVMMCTargetDesc.h" #include "llvm/CodeGen/MIRYamlMapping.h" #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/MC/MCSymbolWasm.h" namespace llvm { +class EVMMachineFunctionInfo; + +namespace yaml { + +struct EVMMachineFunctionInfo final : public yaml::MachineFunctionInfo { + bool IsStackified = false; + + EVMMachineFunctionInfo() = default; + explicit EVMMachineFunctionInfo(const llvm::EVMMachineFunctionInfo &MFI); + ~EVMMachineFunctionInfo() override; + + void mappingImpl(yaml::IO &YamlIO) override; +}; + +template <> struct MappingTraits { + static void mapping(IO &YamlIO, EVMMachineFunctionInfo &MFI) { + YamlIO.mapOptional("isStackified", MFI.IsStackified, false); + } +}; +} // end namespace yaml + /// This class is derived from MachineFunctionInfo and contains private /// EVM-specific information for each MachineFunction. -class EVMFunctionInfo final : public MachineFunctionInfo { +class EVMMachineFunctionInfo final : public MachineFunctionInfo { /// A mapping from CodeGen vreg index to a boolean value indicating whether /// the given register is considered to be "stackified", meaning it has been /// determined or made to meet the stack requirements: @@ -34,16 +54,21 @@ class EVMFunctionInfo final : public MachineFunctionInfo { /// Number of parameters. Their type doesn't matter as it always is i256. unsigned NumberOfParameters = 0; + /// If the MF's instructions are in 'stack' form. + bool IsStackified = false; + public: - explicit EVMFunctionInfo(MachineFunction &MF) {} - EVMFunctionInfo(const Function &F, const TargetSubtargetInfo *STI) {} - ~EVMFunctionInfo() override; + explicit EVMMachineFunctionInfo(MachineFunction &MF) {} + EVMMachineFunctionInfo(const Function &F, const TargetSubtargetInfo *STI) {} + ~EVMMachineFunctionInfo() override; MachineFunctionInfo * clone(BumpPtrAllocator &Allocator, MachineFunction &DestMF, const DenseMap &Src2DstMBB) const override; + void initializeBaseYamlFields(const yaml::EVMMachineFunctionInfo &YamlMFI); + void stackifyVReg(MachineRegisterInfo &MRI, unsigned VReg) { assert(MRI.getUniqueVRegDef(VReg)); auto I = Register::virtReg2Index(VReg); @@ -72,7 +97,12 @@ class EVMFunctionInfo final : public MachineFunctionInfo { unsigned getNumParams() const { return NumberOfParameters; } + + void setIsStackified(bool Val = true) { IsStackified = Val; } + + bool getIsStackified() const { return IsStackified; } }; + } // end namespace llvm #endif // LLVM_LIB_TARGET_EVM_EVMMACHINEFUNCTIONINFO_H diff --git a/llvm/lib/Target/EVM/EVMRegColoring.cpp b/llvm/lib/Target/EVM/EVMRegColoring.cpp index f2f5fe51c6a0..d18461b3a97a 100644 --- a/llvm/lib/Target/EVM/EVMRegColoring.cpp +++ b/llvm/lib/Target/EVM/EVMRegColoring.cpp @@ -80,7 +80,7 @@ bool EVMRegColoring::runOnMachineFunction(MachineFunction &MF) { LiveIntervals *Liveness = &getAnalysis(); const MachineBlockFrequencyInfo *MBFI = &getAnalysis(); - EVMFunctionInfo &MFI = *MF.getInfo(); + EVMMachineFunctionInfo &MFI = *MF.getInfo(); // Gather all register intervals into a list and sort them. unsigned NumVRegs = MRI->getNumVirtRegs(); diff --git a/llvm/lib/Target/EVM/EVMSingleUseExpression.cpp b/llvm/lib/Target/EVM/EVMSingleUseExpression.cpp index f383fa7e4ca2..8337dc7875d1 100644 --- a/llvm/lib/Target/EVM/EVMSingleUseExpression.cpp +++ b/llvm/lib/Target/EVM/EVMSingleUseExpression.cpp @@ -268,7 +268,8 @@ static bool shouldRematerialize(const MachineInstr &Def, // TODO: Compute memory dependencies in a way that uses AliasAnalysis to be // more precise. static bool isSafeToMove(const MachineOperand *Def, const MachineOperand *Use, - const MachineInstr *Insert, const EVMFunctionInfo &MFI, + const MachineInstr *Insert, + const EVMMachineFunctionInfo &MFI, const MachineRegisterInfo &MRI) { const MachineInstr *DefI = Def->getParent(); const MachineInstr *UseI = Use->getParent(); @@ -390,7 +391,7 @@ static void shrinkToUses(LiveInterval &LI, LiveIntervals &LIS) { static MachineInstr *moveForSingleUse(unsigned Reg, MachineOperand &Op, MachineInstr *Def, MachineBasicBlock &MBB, MachineInstr *Insert, LiveIntervals &LIS, - EVMFunctionInfo &MFI, + EVMMachineFunctionInfo &MFI, MachineRegisterInfo &MRI) { LLVM_DEBUG(dbgs() << "Move for single use: "; Def->dump()); @@ -430,8 +431,8 @@ static MachineInstr *moveForSingleUse(unsigned Reg, MachineOperand &Op, static MachineInstr *rematerializeCheapDef( unsigned Reg, MachineOperand &Op, MachineInstr &Def, MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator Insert, LiveIntervals &LIS, - EVMFunctionInfo &MFI, MachineRegisterInfo &MRI, const EVMInstrInfo *TII, - const EVMRegisterInfo *TRI) { + EVMMachineFunctionInfo &MFI, MachineRegisterInfo &MRI, + const EVMInstrInfo *TII, const EVMRegisterInfo *TRI) { LLVM_DEBUG(dbgs() << "Rematerializing cheap def: "; Def.dump()); LLVM_DEBUG(dbgs() << " - for use in "; Op.getParent()->dump()); @@ -593,7 +594,7 @@ bool EVMSingleUseExpression::runOnMachineFunction(MachineFunction &MF) { bool Changed = false; MachineRegisterInfo &MRI = MF.getRegInfo(); - EVMFunctionInfo &MFI = *MF.getInfo(); + EVMMachineFunctionInfo &MFI = *MF.getInfo(); const auto *TII = MF.getSubtarget().getInstrInfo(); const auto *TRI = MF.getSubtarget().getRegisterInfo(); auto &MDT = getAnalysis(); diff --git a/llvm/lib/Target/EVM/EVMStackify.cpp b/llvm/lib/Target/EVM/EVMStackify.cpp index 5c674f4f10c4..d5c32e402c83 100644 --- a/llvm/lib/Target/EVM/EVMStackify.cpp +++ b/llvm/lib/Target/EVM/EVMStackify.cpp @@ -320,6 +320,8 @@ class StackModel { void peelPhysStack(StackType Type, unsigned NumItems, MachineBasicBlock *BB, MIIter Pos); + void stackifyInstruction(MachineInstr *MI); + static unsigned getDUPOpcode(unsigned Depth); static unsigned getSWAPOpcode(unsigned Depth); @@ -724,10 +726,10 @@ void StackModel::handleLStackAtJump(MachineBasicBlock *MBB, MachineInstr *MI, // EVM::NoRegister. clearPhysStackAtInst(StackType::L, MI, Reg); - // Insert "PUSH8_LABEL %bb" instruction that should be be replaced with + // Insert "PUSH_LABEL %bb" instruction that should be be replaced with // the actual PUSH* one in the MC layer to contain actual jump target // offset. - BuildMI(*MI->getParent(), MI, DebugLoc(), TII->get(EVM::PUSH8_LABEL)) + BuildMI(*MI->getParent(), MI, DebugLoc(), TII->get(EVM::PUSH_LABEL)) .addMBB(MBB); // Add JUMPDEST at the beginning of the target MBB. @@ -759,7 +761,7 @@ void StackModel::handleReturn(MachineInstr *MI) { ReturnRegs.push_back(MO.getReg()); } - auto *MFI = MF->getInfo(); + auto *MFI = MF->getInfo(); if (MFI->getNumParams() >= ReturnRegs.size()) { // Move the return registers to the stack location where // arguments were resided. @@ -874,13 +876,12 @@ void StackModel::handleCall(MachineInstr *MI) { It->setPostInstrSymbol(*MF, RetSym); // Create push of the return address. - BuildMI(MBB, It, MI->getDebugLoc(), TII->get(EVM::PUSH8_LABEL)) - .addSym(RetSym); + BuildMI(MBB, It, MI->getDebugLoc(), TII->get(EVM::PUSH_LABEL)).addSym(RetSym); // Create push of the callee's address. const MachineOperand *CalleeOp = MI->explicit_uses().begin(); assert(CalleeOp->isGlobal()); - BuildMI(MBB, It, MI->getDebugLoc(), TII->get(EVM::PUSH8_LABEL)) + BuildMI(MBB, It, MI->getDebugLoc(), TII->get(EVM::PUSH_LABEL)) .addGlobalAddress(CalleeOp->getGlobal()); } @@ -987,6 +988,29 @@ void StackModel::preProcess() { BuildMI(MBB, MBB.begin(), DebugLoc(), TII->get(EVM::JUMPDEST)); } +// Remove all registers operands of the \p MI and repaces the opcode with +// the stack variant variant. +void StackModel::stackifyInstruction(MachineInstr *MI) { + if (MI->isDebugInstr() || MI->isLabel() || MI->isInlineAsm()) + return; + + unsigned RegOpcode = MI->getOpcode(); + if (RegOpcode == EVM::PUSH_LABEL) + return; + + // Remove register operands. + for (unsigned I = MI->getNumOperands(); I > 0; --I) { + auto &MO = MI->getOperand(I - 1); + if (MO.isReg()) { + MI->removeOperand(I - 1); + } + } + + // Transform 'register' instruction to the 'stack' one. + unsigned StackOpcode = EVM::getStackOpcode(RegOpcode); + MI->setDesc(TII->get(StackOpcode)); +} + void StackModel::postProcess() { for (MachineBasicBlock &MBB : *MF) { for (MachineInstr &MI : MBB) { @@ -1013,6 +1037,42 @@ void StackModel::postProcess() { for (auto *MI : ToErase) MI->eraseFromParent(); + + for (MachineBasicBlock &MBB : *MF) + for (MachineInstr &MI : MBB) + stackifyInstruction(&MI); + + auto *MFI = MF->getInfo(); + MFI->setIsStackified(); + + // In a stackified code register liveness has no meaning. + MachineRegisterInfo &MRI = MF->getRegInfo(); + MRI.invalidateLiveness(); + + // In EVM architecture jump target is set up using one of PUSH* instructions + // that come right before the jump instruction. + // For example: + + // PUSH_LABEL %bb.10 + // JUMPI_S + // PUSH_LABEL %bb.9 + // JUMP_S + // + // The problem here is that such MIR is not valid. There should not be + // non-terminator (PUSH) instructions between terminator (JUMP) ones. + // To overcome this issue, we bundle adjacent instructions + // together and unbundle them in the AsmPrinter. + for (MachineBasicBlock &MBB : *MF) { + MachineBasicBlock::instr_iterator I = MBB.instr_begin(), + E = MBB.instr_end(); + for (; I != E; ++I) { + if (I->isBranch()) { + auto P = std::next(I); + if (P != E && P->getOpcode() == EVM::PUSH_LABEL) + I->bundleWithPred(); + } + } + } } void StackModel::dumpState() const { @@ -1129,9 +1189,6 @@ class EVMStackify final : public MachineFunctionPass { AU.addRequired(); AU.addRequired(); AU.addPreserved(); - AU.addPreserved(); - AU.addPreserved(); - AU.addPreservedID(LiveVariablesID); AU.addPreserved(); MachineFunctionPass::getAnalysisUsage(AU); } diff --git a/llvm/lib/Target/EVM/EVMTargetMachine.cpp b/llvm/lib/Target/EVM/EVMTargetMachine.cpp index 29154cd8c30b..eaf0892de5ff 100644 --- a/llvm/lib/Target/EVM/EVMTargetMachine.cpp +++ b/llvm/lib/Target/EVM/EVMTargetMachine.cpp @@ -17,6 +17,8 @@ #include "EVMTargetObjectFile.h" #include "EVMTargetTransformInfo.h" #include "TargetInfo/EVMTargetInfo.h" +#include "llvm/CodeGen/MIRParser/MIParser.h" +#include "llvm/CodeGen/MIRYamlMapping.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/TargetPassConfig.h" #include "llvm/InitializePasses.h" @@ -84,7 +86,26 @@ EVMTargetMachine::getTargetTransformInfo(const Function &F) const { MachineFunctionInfo *EVMTargetMachine::createMachineFunctionInfo( BumpPtrAllocator &Allocator, const Function &F, const TargetSubtargetInfo *STI) const { - return EVMFunctionInfo::create(Allocator, F, STI); + return EVMMachineFunctionInfo::create(Allocator, F, + STI); +} + +yaml::MachineFunctionInfo *EVMTargetMachine::createDefaultFuncInfoYAML() const { + return new yaml::EVMMachineFunctionInfo(); +} + +yaml::MachineFunctionInfo * +EVMTargetMachine::convertFuncInfoToYAML(const MachineFunction &MF) const { + const auto *MFI = MF.getInfo(); + return new yaml::EVMMachineFunctionInfo(*MFI); +} + +bool EVMTargetMachine::parseMachineFunctionInfo( + const yaml::MachineFunctionInfo &MFI, PerFunctionMIParsingState &PFS, + SMDiagnostic &Error, SMRange &SourceRange) const { + const auto &YamlMFI = static_cast(MFI); + PFS.MF.getInfo()->initializeBaseYamlFields(YamlMFI); + return false; } void EVMTargetMachine::registerPassBuilderCallbacks(PassBuilder &PB) { diff --git a/llvm/lib/Target/EVM/EVMTargetMachine.h b/llvm/lib/Target/EVM/EVMTargetMachine.h index 10309fc56005..3bb1b542b48e 100644 --- a/llvm/lib/Target/EVM/EVMTargetMachine.h +++ b/llvm/lib/Target/EVM/EVMTargetMachine.h @@ -43,6 +43,14 @@ class EVMTargetMachine final : public LLVMTargetMachine { createMachineFunctionInfo(BumpPtrAllocator &Allocator, const Function &F, const TargetSubtargetInfo *STI) const override; + yaml::MachineFunctionInfo *createDefaultFuncInfoYAML() const override; + yaml::MachineFunctionInfo * + convertFuncInfoToYAML(const MachineFunction &MF) const override; + bool parseMachineFunctionInfo(const yaml::MachineFunctionInfo &, + PerFunctionMIParsingState &PFS, + SMDiagnostic &Error, + SMRange &SourceRange) const override; + TargetLoweringObjectFile *getObjFileLowering() const override { return TLOF.get(); } diff --git a/llvm/lib/Target/EVM/EVMTargetObjectFile.cpp b/llvm/lib/Target/EVM/EVMTargetObjectFile.cpp deleted file mode 100644 index 1da524fbe949..000000000000 --- a/llvm/lib/Target/EVM/EVMTargetObjectFile.cpp +++ /dev/null @@ -1,20 +0,0 @@ -//===------------- EVMTargetObjectFile.cpp - EVM Object Info --------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the functions of the EVM-specific subclass -// of TargetLoweringObjectFile. -// -//===----------------------------------------------------------------------===// - -#include "EVMTargetObjectFile.h" - -using namespace llvm; - -// Code sections need to be aligned on 1, otherwise linker will add padding -// between .text sections of the object files being linked. -unsigned EVMELFTargetObjectFile::getTextSectionAlignment() const { return 1; } diff --git a/llvm/lib/Target/EVM/EVMTargetObjectFile.h b/llvm/lib/Target/EVM/EVMTargetObjectFile.h index 7de553b2480e..1afa2bb7fb41 100644 --- a/llvm/lib/Target/EVM/EVMTargetObjectFile.h +++ b/llvm/lib/Target/EVM/EVMTargetObjectFile.h @@ -22,7 +22,9 @@ class EVMELFTargetObjectFile final : public TargetLoweringObjectFileELF { public: EVMELFTargetObjectFile() = default; - unsigned getTextSectionAlignment() const override; + // Code sections need to be aligned on 1, otherwise linker will add padding + // between .text sections of the object files being linked. + unsigned getTextSectionAlignment() const override { return 1; } }; } // end namespace llvm diff --git a/llvm/lib/Target/EVM/MCTargetDesc/EVMAsmBackend.cpp b/llvm/lib/Target/EVM/MCTargetDesc/EVMAsmBackend.cpp index e2d4cbfd10af..b8af5de6aab8 100644 --- a/llvm/lib/Target/EVM/MCTargetDesc/EVMAsmBackend.cpp +++ b/llvm/lib/Target/EVM/MCTargetDesc/EVMAsmBackend.cpp @@ -23,6 +23,9 @@ #include "llvm/MC/MCValue.h" #include "llvm/MC/TargetRegistry.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" + +#include using namespace llvm; @@ -100,10 +103,6 @@ const MCFixupKindInfo &EVMAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { // in EVMFixupKinds.h. // // Name Offset (bits) Size (bits) Flags - {"fixup_SecRel_i64", 0, 8 * 8, MCFixupKindInfo::FKF_IsTarget}, - {"fixup_SecRel_i56", 0, 8 * 7, MCFixupKindInfo::FKF_IsTarget}, - {"fixup_SecRel_i48", 0, 8 * 6, MCFixupKindInfo::FKF_IsTarget}, - {"fixup_SecRel_i40", 0, 8 * 5, MCFixupKindInfo::FKF_IsTarget}, {"fixup_SecRel_i32", 0, 8 * 4, MCFixupKindInfo::FKF_IsTarget}, {"fixup_SecRel_i24", 0, 8 * 3, MCFixupKindInfo::FKF_IsTarget}, {"fixup_SecRel_i16", 0, 8 * 2, MCFixupKindInfo::FKF_IsTarget}, @@ -136,6 +135,9 @@ bool EVMAsmBackend::evaluateTargetFixup(const MCAssembler &Asm, return false; Value = Target.getConstant(); + if (Value > std::numeric_limits::max()) + report_fatal_error("Fixup value exceeds the displacement 2^32"); + if (const MCSymbolRefExpr *A = Target.getSymA()) { const MCSymbol &Sym = A->getSymbol(); assert(Sym.isDefined()); @@ -180,18 +182,6 @@ void EVMAsmBackend::relaxInstruction(MCInst &Inst, switch (Inst.getOpcode()) { default: llvm_unreachable("Unexpected instruction for relaxation"); - case EVM::PUSH8_S: - Inst.setOpcode(EVM::PUSH7_S); - break; - case EVM::PUSH7_S: - Inst.setOpcode(EVM::PUSH6_S); - break; - case EVM::PUSH6_S: - Inst.setOpcode(EVM::PUSH5_S); - break; - case EVM::PUSH5_S: - Inst.setOpcode(EVM::PUSH4_S); - break; case EVM::PUSH4_S: Inst.setOpcode(EVM::PUSH3_S); break; @@ -229,14 +219,6 @@ bool EVMAsmBackend::fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, switch (FixUpKind) { default: llvm_unreachable("Unexpected target fixup kind"); - case EVM::fixup_SecRel_i64: - return OffsetByteWidth < 8; - case EVM::fixup_SecRel_i56: - return OffsetByteWidth < 7; - case EVM::fixup_SecRel_i48: - return OffsetByteWidth < 6; - case EVM::fixup_SecRel_i40: - return OffsetByteWidth < 5; case EVM::fixup_SecRel_i32: return OffsetByteWidth < 4; case EVM::fixup_SecRel_i24: @@ -251,10 +233,6 @@ bool EVMAsmBackend::mayNeedRelaxation(const MCInst &Inst, switch (Inst.getOpcode()) { default: return false; - case EVM::PUSH8_S: - case EVM::PUSH7_S: - case EVM::PUSH6_S: - case EVM::PUSH5_S: case EVM::PUSH4_S: case EVM::PUSH3_S: case EVM::PUSH2_S: diff --git a/llvm/lib/Target/EVM/MCTargetDesc/EVMFixupKinds.h b/llvm/lib/Target/EVM/MCTargetDesc/EVMFixupKinds.h index 8d63558bd5ef..ed5ea473e603 100644 --- a/llvm/lib/Target/EVM/MCTargetDesc/EVMFixupKinds.h +++ b/llvm/lib/Target/EVM/MCTargetDesc/EVMFixupKinds.h @@ -14,11 +14,7 @@ namespace llvm { namespace EVM { enum Fixups { - fixup_SecRel_i64 = FirstTargetFixupKind, // 64-bit unsigned - fixup_SecRel_i56, // 56-bit unsigned - fixup_SecRel_i48, // 48-bit unsigned - fixup_SecRel_i40, // 40-bit unsigned - fixup_SecRel_i32, // 32-bit unsigned + fixup_SecRel_i32 = FirstTargetFixupKind, // 32-bit unsigned fixup_SecRel_i24, // 24-bit unsigned fixup_SecRel_i16, // 16-bit unsigned fixup_SecRel_i8, // 8-bit unsigned diff --git a/llvm/lib/Target/EVM/MCTargetDesc/EVMMCCodeEmitter.cpp b/llvm/lib/Target/EVM/MCTargetDesc/EVMMCCodeEmitter.cpp index 0e952d2ed20e..9363d06e4d2f 100644 --- a/llvm/lib/Target/EVM/MCTargetDesc/EVMMCCodeEmitter.cpp +++ b/llvm/lib/Target/EVM/MCTargetDesc/EVMMCCodeEmitter.cpp @@ -54,14 +54,6 @@ EVM::Fixups getFixupForOpc(unsigned Opcode, MCSymbolRefExpr::VariantKind Kind) { switch (Opcode) { default: llvm_unreachable("Unexpected MI for the SymbolRef MO"); - case EVM::PUSH8_S: - return EVM::fixup_SecRel_i64; - case EVM::PUSH7_S: - return EVM::fixup_SecRel_i56; - case EVM::PUSH6_S: - return EVM::fixup_SecRel_i48; - case EVM::PUSH5_S: - return EVM::fixup_SecRel_i40; case EVM::PUSH4_S: switch (Kind) { default: diff --git a/llvm/test/CodeGen/EVM/fallthrough.mir b/llvm/test/CodeGen/EVM/fallthrough.mir new file mode 100644 index 000000000000..b5efb4f62911 --- /dev/null +++ b/llvm/test/CodeGen/EVM/fallthrough.mir @@ -0,0 +1,45 @@ +# RUN: llc -x mir --start-after=evm-stackify < %s | FileCheck %s + + +--- | + + target datalayout = "E-p:256:256-i256:256:256-S256-a:256:256" + target triple = "evm" + define void @test_fallthrough() { ret void } + +... +--- +# CHECK: PUSH4 @.BB0_1 +# CHECK-NEXT: JUMPI +# CHECK-NEXT: PUSH4 @.BB0_2 +# CHECK-NEXT: JUMP +# CHECK-NEXT: .BB0_1: + +name: test_fallthrough +tracksRegLiveness: false +machineFunctionInfo: + isStackified: true +body: | + bb.0: + JUMPDEST_S + PUSH_LABEL %bb.10 { + JUMPI_S + } + PUSH_LABEL %bb.13 { + JUMP_S + } + + bb.10: + liveins: $value_stack + JUMPDEST_S + PUSH0_S + PUSH0_S + REVERT_S + + bb.13: + liveins: $value_stack + JUMPDEST_S + PUSH0_S + PUSH0_S + REVERT_S +... diff --git a/llvm/test/CodeGen/Generic/undef-phi.ll b/llvm/test/CodeGen/Generic/undef-phi.ll index 89d73901436d..0e221fe612ab 100644 --- a/llvm/test/CodeGen/Generic/undef-phi.ll +++ b/llvm/test/CodeGen/Generic/undef-phi.ll @@ -1,5 +1,4 @@ ; RUN: llc < %s -verify-machineinstrs -verify-coalescing -; UNSUPPORTED: target=evm{{.*}} ; ; This function has a PHI with one undefined input. Verify that PHIElimination ; inserts an IMPLICIT_DEF instruction in the predecessor so all paths to the use