Files
FEX-Emu--FEX/External/FEXCore/Source/Interface/IR/IREmitter.cpp
T
Ryan Houdek 1b720479c4 Adds a self contained IREmitter class
This class does IR emitting and some basic handling of IR specific
tasks.

This is going to be used to split the x86 OpDispatcher from the IR
emission so the IR emitter can be passed around without caring about x86
dependencies.
2020-05-08 19:03:22 -07:00

96 lines
2.8 KiB
C++

#include <FEXCore/IR/IREmitter.h>
namespace FEXCore::IR {
void IREmitter::ResetWorkingList() {
Data.Reset();
ListData.Reset();
CodeBlocks.clear();
CurrentWriteCursor = nullptr;
// This is necessary since we do "null" pointer checks
InvalidNode = reinterpret_cast<OrderedNode*>(ListData.Allocate(sizeof(OrderedNode)));
CurrentCodeBlock = nullptr;
}
void IREmitter::ReplaceAllUsesWithInclusive(OrderedNode *Node, OrderedNode *NewNode, IR::NodeWrapperIterator After, IR::NodeWrapperIterator End) {
uintptr_t ListBegin = ListData.Begin();
uintptr_t DataBegin = Data.Begin();
while (After != End) {
OrderedNodeWrapper *WrapperOp = After();
OrderedNode *RealNode = WrapperOp->GetNode(ListBegin);
FEXCore::IR::IROp_Header *IROp = RealNode->Op(DataBegin);
uint8_t NumArgs = IR::GetArgs(IROp->Op);
for (uint8_t i = 0; i < NumArgs; ++i) {
if (IROp->Args[i].ID() == Node->Wrapped(ListBegin).ID()) {
Node->RemoveUse();
NewNode->AddUse();
IROp->Args[i].NodeOffset = NewNode->Wrapped(ListBegin).NodeOffset;
}
}
++After;
}
}
void IREmitter::ReplaceNodeArgument(OrderedNode *Node, uint8_t Arg, OrderedNode *NewArg) {
uintptr_t ListBegin = ListData.Begin();
uintptr_t DataBegin = Data.Begin();
FEXCore::IR::IROp_Header *IROp = Node->Op(DataBegin);
OrderedNodeWrapper OldArgWrapper = IROp->Args[Arg];
OrderedNode *OldArg = OldArgWrapper.GetNode(ListBegin);
OldArg->RemoveUse();
NewArg->AddUse();
IROp->Args[Arg].NodeOffset = NewArg->Wrapped(ListBegin).NodeOffset;
}
void IREmitter::RemoveArgUses(OrderedNode *Node) {
uintptr_t ListBegin = ListData.Begin();
uintptr_t DataBegin = Data.Begin();
FEXCore::IR::IROp_Header *IROp = Node->Op(DataBegin);
uint8_t NumArgs = IR::GetArgs(IROp->Op);
for (uint8_t i = 0; i < NumArgs; ++i) {
auto ArgNode = IROp->Args[i].GetNode(ListBegin);
ArgNode->RemoveUse();
}
}
void IREmitter::Remove(OrderedNode *Node) {
RemoveArgUses(Node);
Node->Unlink(ListData.Begin());
}
IREmitter::IRPair<IROp_CodeBlock> IREmitter::CreateNewCodeBlock() {
auto OldCursor = GetWriteCursor();
SetWriteCursor(CodeBlocks.back());
auto CodeNode = CreateCodeNode();
auto NewNode = _Dummy();
SetCodeNodeBegin(CodeNode, NewNode);
auto EndBlock = _EndBlock(0);
SetCodeNodeLast(CodeNode, EndBlock);
if (CurrentCodeBlock) {
LinkCodeBlocks(CurrentCodeBlock, CodeNode);
}
SetWriteCursor(OldCursor);
return CodeNode;
}
void IREmitter::SetCurrentCodeBlock(OrderedNode *Node) {
CurrentCodeBlock = Node;
LogMan::Throw::A(Node->Op(Data.Begin())->Op == OP_CODEBLOCK, "Node wasn't codeblock. It was '%s'", std::string(IR::GetName(Node->Op(Data.Begin())->Op)).c_str());
SetWriteCursor(Node->Op(Data.Begin())->CW<IROp_CodeBlock>()->Begin.GetNode(ListData.Begin()));
}
}