mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-24 13:51:05 +00:00
Added TBAA
This commit is contained in:
parent
d7367172e8
commit
8331f6b3cc
@ -5,6 +5,7 @@ set(SRCS
|
|||||||
Disassembler.cpp
|
Disassembler.cpp
|
||||||
InstructionBlock.cpp
|
InstructionBlock.cpp
|
||||||
MachineState.cpp
|
MachineState.cpp
|
||||||
|
TBAA.cpp
|
||||||
|
|
||||||
Instructions/Instruction.cpp
|
Instructions/Instruction.cpp
|
||||||
Instructions/DataProcessing.cpp
|
Instructions/DataProcessing.cpp
|
||||||
@ -15,6 +16,7 @@ set(HEADERS
|
|||||||
Disassembler.h
|
Disassembler.h
|
||||||
InstructionBlock.h
|
InstructionBlock.h
|
||||||
MachineState.h
|
MachineState.h
|
||||||
|
TBAA.h
|
||||||
|
|
||||||
Instructions/Types.h
|
Instructions/Types.h
|
||||||
Instructions/Instruction.h
|
Instructions/Instruction.h
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A register in a broad sense: R0-R15, and flags
|
* A register in a broad sense: R0-R15, and flags
|
||||||
*/
|
*/
|
||||||
@ -5,9 +7,12 @@ enum class Register
|
|||||||
{
|
{
|
||||||
R0, R1, R2, R3, R4, R5, R6, R7,
|
R0, R1, R2, R3, R4, R5, R6, R7,
|
||||||
R8, R9, R10, R11, R12, SP, LR, PC,
|
R8, R9, R10, R11, R12, SP, LR, PC,
|
||||||
N, Z, C, V
|
N, Z, C, V,
|
||||||
|
Count
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const size_t RegisterCount = static_cast<size_t>(Register::Count);
|
||||||
|
|
||||||
enum class Condition
|
enum class Condition
|
||||||
{
|
{
|
||||||
EQ, NE, CS, CC, MI, PL, VS, VC, HI, LS, GE, LT, GT, LE, AL, Invalid
|
EQ, NE, CS, CC, MI, PL, VS, VC, HI, LS, GE, LT, GT, LE, AL, Invalid
|
||||||
|
@ -26,13 +26,15 @@ void MachineState::GenerateGlobals()
|
|||||||
|
|
||||||
Value* MachineState::ReadRegiser(Register reg)
|
Value* MachineState::ReadRegiser(Register reg)
|
||||||
{
|
{
|
||||||
auto load = module->IrBuilder()->CreateLoad(GetRegisterPtr(reg));
|
auto load = module->IrBuilder()->CreateAlignedLoad(GetRegisterPtr(reg), 4);
|
||||||
|
module->GetTBAA()->TagRegister(load, reg);
|
||||||
return load;
|
return load;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value* MachineState::WriteRegiser(Register reg, Value *value)
|
Value* MachineState::WriteRegiser(Register reg, Value *value)
|
||||||
{
|
{
|
||||||
auto store = module->IrBuilder()->CreateAlignedStore(value, GetRegisterPtr(reg), 4);
|
auto store = module->IrBuilder()->CreateAlignedStore(value, GetRegisterPtr(reg), 4);
|
||||||
|
module->GetTBAA()->TagRegister(store, reg);
|
||||||
return store;
|
return store;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,5 +53,6 @@ Value *MachineState::GetRegisterPtr(Register reg)
|
|||||||
index = static_cast<unsigned>(reg)-static_cast<unsigned>(Register::N);
|
index = static_cast<unsigned>(reg)-static_cast<unsigned>(Register::N);
|
||||||
}
|
}
|
||||||
auto base = module->IrBuilder()->CreateAlignedLoad(global, 4);
|
auto base = module->IrBuilder()->CreateAlignedLoad(global, 4);
|
||||||
|
module->GetTBAA()->TagConst(base);
|
||||||
return module->IrBuilder()->CreateConstInBoundsGEP1_32(base, index);
|
return module->IrBuilder()->CreateConstInBoundsGEP1_32(base, index);
|
||||||
}
|
}
|
@ -17,6 +17,7 @@ ModuleGen::ModuleGen(llvm::Module* module)
|
|||||||
{
|
{
|
||||||
ir_builder = make_unique<IRBuilder<>>(getGlobalContext());
|
ir_builder = make_unique<IRBuilder<>>(getGlobalContext());
|
||||||
machine = make_unique<MachineState>(this);
|
machine = make_unique<MachineState>(this);
|
||||||
|
tbaa = make_unique<TBAA>();
|
||||||
}
|
}
|
||||||
|
|
||||||
ModuleGen::~ModuleGen()
|
ModuleGen::~ModuleGen()
|
||||||
@ -25,6 +26,7 @@ ModuleGen::~ModuleGen()
|
|||||||
|
|
||||||
void ModuleGen::Run()
|
void ModuleGen::Run()
|
||||||
{
|
{
|
||||||
|
tbaa->GenerateTags();
|
||||||
GenerateGlobals();
|
GenerateGlobals();
|
||||||
|
|
||||||
DecodeInstructions();
|
DecodeInstructions();
|
||||||
@ -133,6 +135,7 @@ void ModuleGen::GenerateGetBlockAddressFunction()
|
|||||||
ir_builder->SetInsertPoint(index_in_bounds_basic_block);
|
ir_builder->SetInsertPoint(index_in_bounds_basic_block);
|
||||||
Value *gep_values[] = { ir_builder->getInt32(0), index };
|
Value *gep_values[] = { ir_builder->getInt32(0), index };
|
||||||
auto block_address = ir_builder->CreateLoad(ir_builder->CreateInBoundsGEP(block_address_array, gep_values));
|
auto block_address = ir_builder->CreateLoad(ir_builder->CreateInBoundsGEP(block_address_array, gep_values));
|
||||||
|
tbaa->TagConst(block_address);
|
||||||
ir_builder->CreateRet(block_address);
|
ir_builder->CreateRet(block_address);
|
||||||
|
|
||||||
ir_builder->SetInsertPoint(index_out_of_bounds_basic_block);
|
ir_builder->SetInsertPoint(index_out_of_bounds_basic_block);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include <llvm/IR/IRBuilder.h>
|
#include <llvm/IR/IRBuilder.h>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <common/common_types.h>
|
#include <common/common_types.h>
|
||||||
|
#include "TBAA.h"
|
||||||
|
|
||||||
enum class Register;
|
enum class Register;
|
||||||
|
|
||||||
@ -28,6 +29,7 @@ public:
|
|||||||
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(); }
|
||||||
|
TBAA *GetTBAA() { return tbaa.get(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Generates the declarations of all the globals of the module
|
// Generates the declarations of all the globals of the module
|
||||||
@ -46,6 +48,7 @@ private:
|
|||||||
void AddInstructionsToRunFunction();
|
void AddInstructionsToRunFunction();
|
||||||
|
|
||||||
std::unique_ptr<MachineState> machine;
|
std::unique_ptr<MachineState> machine;
|
||||||
|
std::unique_ptr<TBAA> tbaa;
|
||||||
|
|
||||||
std::unique_ptr<llvm::IRBuilder<>> ir_builder;
|
std::unique_ptr<llvm::IRBuilder<>> ir_builder;
|
||||||
llvm::Module *module;
|
llvm::Module *module;
|
||||||
|
33
src/binary_translation/TBAA.cpp
Normal file
33
src/binary_translation/TBAA.cpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#include "TBAA.h"
|
||||||
|
#include <llvm/IR/MDBuilder.h>
|
||||||
|
#include <llvm/IR/LLVMContext.h>
|
||||||
|
#include <llvm/IR/Metadata.h>
|
||||||
|
#include <sstream>
|
||||||
|
#include <llvm/IR/Instruction.h>
|
||||||
|
|
||||||
|
using namespace llvm;
|
||||||
|
|
||||||
|
void TBAA::GenerateTags()
|
||||||
|
{
|
||||||
|
MDBuilder md_builder(getGlobalContext());
|
||||||
|
|
||||||
|
auto tbaa_root = md_builder.createTBAARoot("Root");
|
||||||
|
|
||||||
|
for (auto i = 0; i < RegisterCount; ++i)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "Register_" << i;
|
||||||
|
register_nodes[i] = md_builder.createTBAAScalarTypeNode(ss.str(), tbaa_root);
|
||||||
|
}
|
||||||
|
const_node = md_builder.createTBAAScalarTypeNode("Readonly", tbaa_root);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TBAA::TagRegister(Instruction* instruction, Register reg)
|
||||||
|
{
|
||||||
|
instruction->setMetadata(LLVMContext::MD_tbaa, register_nodes[(int)reg]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TBAA::TagConst(Instruction* instruction)
|
||||||
|
{
|
||||||
|
instruction->setMetadata(LLVMContext::MD_tbaa, const_node);
|
||||||
|
}
|
28
src/binary_translation/TBAA.h
Normal file
28
src/binary_translation/TBAA.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#include "Instructions/Types.h"
|
||||||
|
|
||||||
|
namespace llvm
|
||||||
|
{
|
||||||
|
class Instruction;
|
||||||
|
class MDNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Manages TBAA.
|
||||||
|
A TBAA type is generated for each register and global.
|
||||||
|
It is a bit of an abuse of TBAA but because nothing aliases it is a good way
|
||||||
|
to notify LLVM of it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class TBAA
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void GenerateTags();
|
||||||
|
|
||||||
|
void TagRegister(llvm::Instruction *instruction, Register reg);
|
||||||
|
void TagConst(llvm::Instruction *instruction);
|
||||||
|
private:
|
||||||
|
llvm::MDNode *register_nodes[RegisterCount];
|
||||||
|
// Tag for everything that is never written.
|
||||||
|
// Since it is never written, one tag works
|
||||||
|
llvm::MDNode *const_node;
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user