Added block linking

Each time an instruction finishes it jumps to the next one instead of going back to the switch block
This commit is contained in:
Dani Messerman 2015-04-30 23:28:12 +03:00
parent 3864675b6d
commit d7367172e8
5 changed files with 42 additions and 20 deletions

View File

@ -25,11 +25,18 @@ void InstructionBlock::GenerateEntryBlock()
void InstructionBlock::GenerateCode() void InstructionBlock::GenerateCode()
{ {
Module()->IrBuilder()->SetInsertPoint(entry_basic_block); auto ir_builder = Module()->IrBuilder();
ir_builder->SetInsertPoint(entry_basic_block);
instruction->GenerateCode(this); instruction->GenerateCode(this);
exit_basic_block = Module()->IrBuilder()->GetInsertBlock(); auto basic_block = ir_builder->GetInsertBlock();
// If the basic block is terminated there has been a jump
// If not, jump to the next instruction
if (!basic_block->getTerminator())
{
Module()->WritePCConst(Address() + 4);
}
} }
llvm::Value *InstructionBlock::Read(Register reg) llvm::Value *InstructionBlock::Read(Register reg)

View File

@ -47,7 +47,6 @@ public:
ModuleGen *Module() { return module; } ModuleGen *Module() { return module; }
llvm::BasicBlock *GetEntryBasicBlock() { return entry_basic_block; } llvm::BasicBlock *GetEntryBasicBlock() { return entry_basic_block; }
llvm::BasicBlock *GetExitBasicBlock() { return exit_basic_block; }
private: private:
// Textual representation of the address // Textual representation of the address
// Used to generate names // Used to generate names
@ -58,7 +57,4 @@ private:
// The block at the entry to instruction // The block at the entry to instruction
llvm::BasicBlock *entry_basic_block; llvm::BasicBlock *entry_basic_block;
// The block at the exit from the instruction
llvm::BasicBlock *exit_basic_block;
}; };

View File

@ -1,6 +1,7 @@
#include "DataProcessing.h" #include "DataProcessing.h"
#include "Disassembler.h" #include "Disassembler.h"
#include "InstructionBlock.h" #include "InstructionBlock.h"
#include "ModuleGen.h"
static RegisterInstruction<DataProcessing> register_instruction; static RegisterInstruction<DataProcessing> register_instruction;
@ -32,4 +33,9 @@ void DataProcessing::GenerateCode(InstructionBlock* instruction_block)
auto value = instruction_block->Read(rm); auto value = instruction_block->Read(rm);
instruction_block->Write(rd, value); instruction_block->Write(rd, value);
if (rd == Register::PC)
{
instruction_block->Module()->ReadPC();
}
} }

View File

@ -35,12 +35,32 @@ void ModuleGen::Run()
GenerateGetBlockAddressFunction(); GenerateGetBlockAddressFunction();
GenerateInstructionsCode(); GenerateInstructionsCode();
GenerateInstructionsTermination();
AddInstructionsToRunFunction(); AddInstructionsToRunFunction();
GenerateBlockAddressArray(); GenerateBlockAddressArray();
} }
void ModuleGen::ReadPC()
{
ir_builder->CreateBr(run_function_re_entry);
}
void ModuleGen::WritePCConst(u32 pc)
{
auto i = instruction_blocks_by_pc.find(pc);
if (i != instruction_blocks_by_pc.end())
{
// Found instruction, jump to it
ir_builder->CreateBr(i->second->GetEntryBasicBlock());
}
else
{
// Didn't find instruction, write PC and exit
machine->WriteRegiser(Register::PC, ir_builder->getInt32(pc));
ir_builder->CreateRetVoid();
}
}
void ModuleGen::GenerateGlobals() void ModuleGen::GenerateGlobals()
{ {
machine->GenerateGlobals(); machine->GenerateGlobals();
@ -200,17 +220,6 @@ void ModuleGen::GenerateInstructionsCode()
} }
} }
void ModuleGen::GenerateInstructionsTermination()
{
// Return to the switch
for (auto &block : instruction_blocks)
{
ir_builder->SetInsertPoint(block->GetExitBasicBlock());
Machine()->WriteRegiser(Register::PC, ir_builder->getInt32(block->Address() + 4));
ir_builder->CreateBr(run_function_re_entry);
}
}
void ModuleGen::AddInstructionsToRunFunction() void ModuleGen::AddInstructionsToRunFunction()
{ {
std::stack<BasicBlock *> basic_blocks_stack; std::stack<BasicBlock *> basic_blocks_stack;
@ -223,6 +232,7 @@ void ModuleGen::AddInstructionsToRunFunction()
{ {
auto basic_block = basic_blocks_stack.top(); auto basic_block = basic_blocks_stack.top();
basic_blocks_stack.pop(); basic_blocks_stack.pop();
if (basic_block->getParent()) continue; // Already added to run
basic_block->insertInto(run_function); basic_block->insertInto(run_function);
auto terminator = basic_block->getTerminator(); auto terminator = basic_block->getTerminator();
for (auto i = 0; i < terminator->getNumSuccessors(); ++i) for (auto i = 0; i < terminator->getNumSuccessors(); ++i)

View File

@ -20,6 +20,11 @@ public:
void Run(); void Run();
// Generate code to read pc and run all following instructions, used in cases of indirect branch
void ReadPC();
// Generate code to write to pc and run all following instructions, used in cases of direct branch
void WritePCConst(u32 pc);
llvm::IRBuilder<> *IrBuilder() { return ir_builder.get(); } llvm::IRBuilder<> *IrBuilder() { return ir_builder.get(); }
llvm::Module *Module() { return module; } llvm::Module *Module() { return module; }
MachineState *Machine() { return machine.get(); } MachineState *Machine() { return machine.get(); }
@ -37,8 +42,6 @@ private:
void GenerateInstructionsEntry(); void GenerateInstructionsEntry();
// Generates the code of each instruction // Generates the code of each instruction
void GenerateInstructionsCode(); void GenerateInstructionsCode();
// Terminates each block
void GenerateInstructionsTermination();
// Adds all the basic blocks of an instruction to the run function // Adds all the basic blocks of an instruction to the run function
void AddInstructionsToRunFunction(); void AddInstructionsToRunFunction();