Skip to content

Commit

Permalink
[EVM] Remove FunctionInfo struct (#742)
Browse files Browse the repository at this point in the history
Signed-off-by: Vladimir Radosavljevic <vr@matterlabs.dev>
  • Loading branch information
vladimirradosavljevic authored Nov 27, 2024
1 parent 5a7e27f commit 51a6cbc
Show file tree
Hide file tree
Showing 9 changed files with 86 additions and 95 deletions.
18 changes: 4 additions & 14 deletions llvm/lib/Target/EVM/EVMControlFlowGraph.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ inline bool canBeFreelyGenerated(StackSlot const &Slot) {
/// Control flow graph consisting of 'CFG::BasicBlock`s' connected by control
/// flow.
struct CFG {
explicit CFG() {}
explicit CFG(const MachineFunction &MF) : MF(MF) {}
CFG(CFG const &) = delete;
CFG(CFG &&) = delete;
CFG &operator=(CFG const &) = delete;
Expand Down Expand Up @@ -204,7 +204,6 @@ struct CFG {
std::variant<FunctionCall, BuiltinCall, Assignment> Operation;
};

struct FunctionInfo;
/// A basic control flow block containing 'Operation`s' acting on the stack.
/// Maintains a list of entry blocks and a typed exit.
struct BasicBlock {
Expand All @@ -230,7 +229,6 @@ struct CFG {

struct FunctionReturn {
Stack RetValues;
CFG::FunctionInfo *Info = nullptr;
};

struct Terminated {};
Expand All @@ -254,21 +252,13 @@ struct CFG {
Exit = InvalidExit{};
};

struct FunctionInfo {
MachineFunction *MF = nullptr;
BasicBlock *Entry = nullptr;
std::vector<StackSlot> Parameters;
std::vector<BasicBlock *> Exits;
bool CanContinue = true;
};

FunctionInfo FuncInfo;

/// Container for blocks for explicit ownership.
std::list<BasicBlock> Blocks;
DenseMap<const MachineBasicBlock *, BasicBlock *> MachineBBToBB;
std::vector<StackSlot> Parameters;
const MachineFunction &MF;

BasicBlock &getBlock(const MachineBasicBlock *MBB) {
BasicBlock &getBlock(const MachineBasicBlock *MBB) const {
auto It = MachineBBToBB.find(MBB);
assert(It != MachineBBToBB.end());
return *It->second;
Expand Down
35 changes: 12 additions & 23 deletions llvm/lib/Target/EVM/EVMControlFlowGraphBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,12 @@ using namespace llvm;

/// Marks each block that needs to maintain a clean stack. That is each block
/// that has an outgoing path to a function return.
static void markNeedsCleanStack(CFG &Cfg) {
for (CFG::BasicBlock *Exit : Cfg.FuncInfo.Exits)
static void markNeedsCleanStack(std::vector<CFG::BasicBlock *> &Exits) {
for (CFG::BasicBlock *Exit : Exits)
EVMUtils::BreadthFirstSearch<CFG::BasicBlock *>{{Exit}}.run(
[&](CFG::BasicBlock *Block, auto AddChild) {
Block->NeedsCleanStack = true;
// TODO: it seems this is not needed, as the return block has
// no childs.
// Traverse over predecessors to mark them as well.
for (CFG::BasicBlock *Entry : Block->Entries)
AddChild(Entry);
});
Expand All @@ -45,8 +44,7 @@ static void markNeedsCleanStack(CFG &Cfg) {
/// Marks each cut-vertex in the CFG, i.e. each block that begins a disconnected
/// sub-graph of the CFG. Entering such a block means that control flow will
/// never return to a previously visited block.
static void markStartsOfSubGraphs(CFG &Cfg) {
CFG::BasicBlock *Entry = Cfg.FuncInfo.Entry;
static void markStartsOfSubGraphs(CFG::BasicBlock *Entry) {
/**
* Detect bridges following Algorithm 1 in
* https://arxiv.org/pdf/2108.07346.pdf and mark the bridge targets as starts
Expand Down Expand Up @@ -112,27 +110,19 @@ static void markStartsOfSubGraphs(CFG &Cfg) {
std::unique_ptr<CFG> ControlFlowGraphBuilder::build(MachineFunction &MF,
const LiveIntervals &LIS,
MachineLoopInfo *MLI) {
auto Result = std::make_unique<CFG>();
auto Result = std::make_unique<CFG>(MF);
ControlFlowGraphBuilder Builder(*Result, LIS, MLI);

for (MachineBasicBlock &MBB : MF)
Result->createBlock(&MBB);

Result->FuncInfo.MF = &MF;
Result->FuncInfo.Entry = &Result->getBlock(&MF.front());
const Function &F = MF.getFunction();
if (F.hasFnAttribute(Attribute::NoReturn))
Result->FuncInfo.CanContinue = false;

// Handle function parameters
auto *MFI = MF.getInfo<EVMMachineFunctionInfo>();
Result->FuncInfo.Parameters =
std::vector<StackSlot>(MFI->getNumParams(), JunkSlot{});
Result->Parameters = std::vector<StackSlot>(MFI->getNumParams(), JunkSlot{});
for (const MachineInstr &MI : MF.front()) {
if (MI.getOpcode() == EVM::ARGUMENT) {
int64_t ArgIdx = MI.getOperand(1).getImm();
Result->FuncInfo.Parameters[ArgIdx] =
VariableSlot{MI.getOperand(0).getReg()};
Result->Parameters[ArgIdx] = VariableSlot{MI.getOperand(0).getReg()};
}
}

Expand All @@ -142,12 +132,12 @@ std::unique_ptr<CFG> ControlFlowGraphBuilder::build(MachineFunction &MF,
for (MachineBasicBlock &MBB : MF)
Builder.handleBasicBlockSuccessors(MBB);

markStartsOfSubGraphs(*Result);
markNeedsCleanStack(*Result);
markStartsOfSubGraphs(&Result->getBlock(&MF.front()));
markNeedsCleanStack(Builder.Exits);

LLVM_DEBUG({
dbgs() << "************* CFG *************\n";
ControlFlowGraphPrinter P(dbgs());
ControlFlowGraphPrinter P(dbgs(), MF);
P(*Result);
});

Expand Down Expand Up @@ -328,16 +318,15 @@ void ControlFlowGraphBuilder::handleFunctionCall(const MachineInstr &MI) {
}

void ControlFlowGraphBuilder::handleReturn(const MachineInstr &MI) {
Cfg.FuncInfo.Exits.emplace_back(CurrentBlock);
Exits.emplace_back(CurrentBlock);
Stack Input;
collectInstrOperands(MI, &Input, nullptr);
// We need to reverse input operands to restore original ordering,
// as it is in the instruction.
// Calling convention: return values are passed in stack such that the
// last one specified in the RET instruction is passed on the stack TOP.
std::reverse(Input.begin(), Input.end());
CurrentBlock->Exit =
CFG::BasicBlock::FunctionReturn{std::move(Input), &Cfg.FuncInfo};
CurrentBlock->Exit = CFG::BasicBlock::FunctionReturn{std::move(Input)};
}

static std::pair<MachineInstr *, MachineInstr *>
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/EVM/EVMControlFlowGraphBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class ControlFlowGraphBuilder {
const LiveIntervals &LIS;
MachineLoopInfo *MLI = nullptr;
CFG::BasicBlock *CurrentBlock = nullptr;
std::vector<CFG::BasicBlock *> Exits;
};

} // namespace llvm
Expand Down
26 changes: 13 additions & 13 deletions llvm/lib/Target/EVM/EVMOptimizedCodeTransform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@ EVMOptimizedCodeTransform::EVMOptimizedCodeTransform(EVMAssembly &Assembly,
CFG const &Cfg,
StackLayout const &Layout,
MachineFunction &MF)
: Assembly(Assembly), Layout(Layout), FuncInfo(&Cfg.FuncInfo), MF(MF) {}
: Assembly(Assembly), Layout(Layout), MF(MF),
EntryBB(Cfg.getBlock(&MF.front())), Parameters(Cfg.Parameters) {}

bool EVMOptimizedCodeTransform::AreLayoutsCompatible(Stack const &SourceStack,
Stack const &TargetStack) {
Expand Down Expand Up @@ -185,7 +186,7 @@ void EVMOptimizedCodeTransform::createStackLayout(Stack TargetStack) {
" slots in " + stackToString(CurrentStack))
.str();

report_fatal_error(FuncInfo->MF->getName() + Twine(": ") + Msg);
report_fatal_error(MF.getName() + Twine(": ") + Msg);
}
},
// Push or dup callback.
Expand Down Expand Up @@ -310,7 +311,7 @@ void EVMOptimizedCodeTransform::createOperationEntryLayout(

void EVMOptimizedCodeTransform::operator()(const CFG::BasicBlock &Block) {
// Current location for the entry BB was set up in operator()().
if (&Block != FuncInfo->Entry)
if (&Block != &EntryBB)
Assembly.setCurrentLocation(Block.MBB);

// Assert that this is the first visit of the block and mark as generated.
Expand All @@ -322,7 +323,7 @@ void EVMOptimizedCodeTransform::operator()(const CFG::BasicBlock &Block) {
// Assert that the stack is valid for entering the block. The entry layout
// of the function entry block should is fully determined by the first
// instruction, so we can ignore 'BlockInfo.entryLayout'.
if (&Block != FuncInfo->Entry) {
if (&Block != &EntryBB) {
assert(AreLayoutsCompatible(CurrentStack, BlockInfo.entryLayout));
// Might set some slots to junk, if not required by the block.
CurrentStack = BlockInfo.entryLayout;
Expand Down Expand Up @@ -431,14 +432,13 @@ void EVMOptimizedCodeTransform::operator()(const CFG::BasicBlock &Block) {
(*this)(*CondJump.NonZero);
},
[&](CFG::BasicBlock::FunctionReturn const &FuncReturn) {
assert(FuncInfo->CanContinue);
assert(!MF.getFunction().hasFnAttribute(Attribute::NoReturn));

// Construct the function return layout, which is fully determined
// by the function signature.
Stack ExitStack = FuncReturn.RetValues;

ExitStack.emplace_back(
FunctionReturnLabelSlot{FuncReturn.Info->MF});
ExitStack.emplace_back(FunctionReturnLabelSlot{&MF});

// Create the function return layout and jump.
createStackLayout(ExitStack);
Expand Down Expand Up @@ -471,24 +471,24 @@ void EVMOptimizedCodeTransform::operator()(const CFG::BasicBlock &Block) {

void EVMOptimizedCodeTransform::operator()() {
assert(CurrentStack.empty() && Assembly.getStackHeight() == 0);
Assembly.setCurrentLocation(FuncInfo->Entry->MBB);
Assembly.setCurrentLocation(EntryBB.MBB);

assert(!BlockLabels.count(FuncInfo->Entry));
assert(!BlockLabels.count(&EntryBB));

// Create function entry layout in CurrentStack.
if (FuncInfo->CanContinue)
CurrentStack.emplace_back(FunctionReturnLabelSlot{FuncInfo->MF});
if (!MF.getFunction().hasFnAttribute(Attribute::NoReturn))
CurrentStack.emplace_back(FunctionReturnLabelSlot{&MF});

// Calling convention: input arguments are passed in stack such that the
// first one specified in the function declaration is passed on the stack TOP.
for (auto const &Param : reverse(FuncInfo->Parameters))
for (auto const &Param : reverse(Parameters))
CurrentStack.emplace_back(Param);

Assembly.setStackHeight(static_cast<int>(CurrentStack.size()));
Assembly.appendLabel();

// Visit the function entry block.
(*this)(*FuncInfo->Entry);
(*this)(EntryBB);

Assembly.finalize();
}
5 changes: 3 additions & 2 deletions llvm/lib/Target/EVM/EVMOptimizedCodeTransform.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,9 @@ class EVMOptimizedCodeTransform {

EVMAssembly &Assembly;
StackLayout const &Layout;
CFG::FunctionInfo const *FuncInfo = nullptr;
MachineFunction &MF;
const MachineFunction &MF;
const CFG::BasicBlock &EntryBB;
const std::vector<StackSlot> &Parameters;

Stack CurrentStack;
DenseMap<const MachineInstr *, MCSymbol *> CallToReturnMCSymbol;
Expand Down
35 changes: 20 additions & 15 deletions llvm/lib/Target/EVM/EVMStackDebug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,19 +83,22 @@ std::string llvm::stackSlotToString(const StackSlot &Slot) {

#ifndef NDEBUG
void ControlFlowGraphPrinter::operator()(const CFG &Cfg) {
(*this)(Cfg.FuncInfo);
(*this)();
for (const auto &Block : Cfg.Blocks)
printBlock(Block);
}

void ControlFlowGraphPrinter::operator()(CFG::FunctionInfo const &Info) {
OS << "Function: " << Info.MF->getName() << '\n';
OS << "Entry block: " << getBlockId(*Info.Entry) << ";\n";
void ControlFlowGraphPrinter::operator()() {
OS << "Function: " << MF.getName() << '\n';
OS << "Entry block: " << getBlockId(MF.front()) << ";\n";
}

std::string ControlFlowGraphPrinter::getBlockId(CFG::BasicBlock const &Block) {
return std::to_string(Block.MBB->getNumber()) + "." +
std::string(Block.MBB->getName());
return getBlockId(*Block.MBB);
}

std::string ControlFlowGraphPrinter::getBlockId(const MachineBasicBlock &MBB) {
return std::to_string(MBB.getNumber()) + "." + std::string(MBB.getName());
}

void ControlFlowGraphPrinter::printBlock(CFG::BasicBlock const &Block) {
Expand Down Expand Up @@ -159,8 +162,8 @@ void ControlFlowGraphPrinter::printBlock(CFG::BasicBlock const &Block) {
},
[&](const CFG::BasicBlock::FunctionReturn &Return) {
OS << "Block" << getBlockId(Block)
<< "Exit [label=\"FunctionReturn["
<< Return.Info->MF->getName() << "]\"];\n";
<< "Exit [label=\"FunctionReturn[" << MF.getName()
<< "]\"];\n";
OS << "Return values: " << stackToString(Return.RetValues);
},
[&](const CFG::BasicBlock::Terminated &) {
Expand Down Expand Up @@ -191,9 +194,10 @@ void StackLayoutPrinter::operator()(CFG::BasicBlock const &Block,
}
}

void StackLayoutPrinter::operator()(CFG::FunctionInfo const &Info) {
OS << "Function: " << Info.MF->getName() << "(";
for (const StackSlot &ParamSlot : Info.Parameters) {
void StackLayoutPrinter::operator()(CFG::BasicBlock const &EntryBB,
const std::vector<StackSlot> &Parameters) {
OS << "Function: " << MF.getName() << "(";
for (const StackSlot &ParamSlot : Parameters) {
if (const auto *Slot = std::get_if<VariableSlot>(&ParamSlot))
OS << printReg(Slot->VirtualReg, nullptr, 0, nullptr) << ' ';
else if (std::holds_alternative<JunkSlot>(ParamSlot))
Expand All @@ -202,8 +206,9 @@ void StackLayoutPrinter::operator()(CFG::FunctionInfo const &Info) {
llvm_unreachable("Unexpected stack slot");
}
OS << ");\n";
OS << "FunctionEntry " << " -> Block" << getBlockId(*Info.Entry) << ";\n";
(*this)(*Info.Entry, false);
OS << "FunctionEntry "
<< " -> Block" << getBlockId(EntryBB) << ";\n";
(*this)(EntryBB, false);
}

void StackLayoutPrinter::printBlock(CFG::BasicBlock const &Block) {
Expand Down Expand Up @@ -283,8 +288,8 @@ void StackLayoutPrinter::printBlock(CFG::BasicBlock const &Block) {
},
[&](CFG::BasicBlock::FunctionReturn const &Return) {
OS << "Block" << getBlockId(Block)
<< "Exit [label=\"FunctionReturn["
<< Return.Info->MF->getName() << "]\"];\n";
<< "Exit [label=\"FunctionReturn[" << MF.getName()
<< "]\"];\n";
},
[&](CFG::BasicBlock::Terminated const &) {
OS << "Block" << getBlockId(Block)
Expand Down
16 changes: 11 additions & 5 deletions llvm/lib/Target/EVM/EVMStackDebug.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,31 +33,37 @@ std::string stackToString(Stack const &S);
#ifndef NDEBUG
class ControlFlowGraphPrinter {
public:
ControlFlowGraphPrinter(raw_ostream &OS) : OS(OS) {}
ControlFlowGraphPrinter(raw_ostream &OS, const MachineFunction &MF)
: OS(OS), MF(MF) {}
void operator()(const CFG &Cfg);

private:
void operator()(const CFG::FunctionInfo &Info);
void operator()();
std::string getBlockId(const CFG::BasicBlock &Block);
std::string getBlockId(const MachineBasicBlock &MBB);
void printBlock(const CFG::BasicBlock &Block);

raw_ostream &OS;
const MachineFunction &MF;
};

class StackLayoutPrinter {
public:
StackLayoutPrinter(raw_ostream &OS, const StackLayout &StackLayout)
: OS(OS), Layout(StackLayout) {}
StackLayoutPrinter(raw_ostream &OS, const StackLayout &StackLayout,
const MachineFunction &MF)
: OS(OS), Layout(StackLayout), MF(MF) {}

void operator()(CFG::BasicBlock const &Block, bool IsMainEntry = true);
void operator()(CFG::FunctionInfo const &Info);
void operator()(CFG::BasicBlock const &EntryBB,
const std::vector<StackSlot> &Parameters);

private:
void printBlock(CFG::BasicBlock const &Block);
std::string getBlockId(CFG::BasicBlock const &Block);

raw_ostream &OS;
const StackLayout &Layout;
const MachineFunction &MF;
std::map<CFG::BasicBlock const *, size_t> BlockIds;
size_t BlockCount = 0;
std::list<CFG::BasicBlock const *> BlocksToPrint;
Expand Down
Loading

0 comments on commit 51a6cbc

Please sign in to comment.