mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-24 14:11:05 +00:00
Added some shifts
This commit is contained in:
parent
66f70e7321
commit
22fbe294be
168
src/binary_translation/ARMFuncs.cpp
Normal file
168
src/binary_translation/ARMFuncs.cpp
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
#include "ARMFuncs.h"
|
||||||
|
#include "InstructionBlock.h"
|
||||||
|
|
||||||
|
ARMFuncs::ShiftTN ARMFuncs::DecodeImmShift(InstructionBlock* instruction, u32 type, u32 imm5)
|
||||||
|
{
|
||||||
|
auto ir_builder = instruction->IrBuilder();
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case 0: return{ SRType::LSL, ir_builder->getInt32(imm5) };
|
||||||
|
case 1: return{ SRType::LSR, ir_builder->getInt32(imm5 ? imm5 : 32) };
|
||||||
|
case 2: return{ SRType::ASR, ir_builder->getInt32(imm5 ? imm5 : 32) };
|
||||||
|
case 3:
|
||||||
|
if (imm5)
|
||||||
|
return{ SRType::ROR, ir_builder->getInt32(imm5) };
|
||||||
|
else
|
||||||
|
return{ SRType::RRX, ir_builder->getInt32(1) };
|
||||||
|
default: assert(false, "Invalid shift type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ARMFuncs::SRType ARMFuncs::DecodeRegShift(u32 type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case 0: return SRType::LSL;
|
||||||
|
case 1: return SRType::LSR;
|
||||||
|
case 2: return SRType::ASR;
|
||||||
|
case 3: return SRType::ROR;
|
||||||
|
default: assert(false, "Invalid shift type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Value* ARMFuncs::Shift(InstructionBlock* instruction, llvm::Value* value, SRType type, llvm::Value* amount, llvm::Value* carry_in)
|
||||||
|
{
|
||||||
|
return Shift_C(instruction, value, type, amount, carry_in).result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ARMFuncs::ResultCarry ARMFuncs::Shift_C(InstructionBlock* instruction, llvm::Value* value, SRType type, llvm::Value* amount, llvm::Value* carry_in)
|
||||||
|
{
|
||||||
|
auto ir_builder = instruction->IrBuilder();
|
||||||
|
|
||||||
|
// amount_zero_basic_block will not recieve any code, it used only for the phi
|
||||||
|
auto amount_zero_basic_block = instruction->CreateBasicBlock("ShiftCAmount0");
|
||||||
|
auto amount_not_zero_basic_block = instruction->CreateBasicBlock("ShiftCAmountNot0");
|
||||||
|
auto phi_basic_block = instruction->CreateBasicBlock("ShiftCPhi");
|
||||||
|
|
||||||
|
ir_builder->CreateCondBr(ir_builder->CreateICmpEQ(amount, ir_builder->getInt32(0)), amount_zero_basic_block, amount_not_zero_basic_block);
|
||||||
|
|
||||||
|
ir_builder->SetInsertPoint(amount_zero_basic_block);
|
||||||
|
ir_builder->CreateBr(phi_basic_block);
|
||||||
|
|
||||||
|
ir_builder->SetInsertPoint(amount_not_zero_basic_block);
|
||||||
|
ResultCarry result_amount_not_zero = {};
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case SRType::LSL: result_amount_not_zero = LSL_C(instruction, value, amount); break;
|
||||||
|
case SRType::LSR: result_amount_not_zero = LSR_C(instruction, value, amount); break;
|
||||||
|
case SRType::ASR: result_amount_not_zero = ASR_C(instruction, value, amount); break;
|
||||||
|
case SRType::ROR: result_amount_not_zero = ROR_C(instruction, value, amount); break;
|
||||||
|
case SRType::RRX: result_amount_not_zero = RRX_C(instruction, value, carry_in); break;
|
||||||
|
default: assert(false, "Invalid shift type");
|
||||||
|
}
|
||||||
|
auto pred = ir_builder->GetInsertBlock(); // The basic block might have changed and needs to be current for the phi
|
||||||
|
ir_builder->CreateBr(phi_basic_block);
|
||||||
|
|
||||||
|
ir_builder->SetInsertPoint(phi_basic_block);
|
||||||
|
auto result_phi = ir_builder->CreatePHI(ir_builder->getInt32Ty(), 2);
|
||||||
|
auto carry_phi = ir_builder->CreatePHI(ir_builder->getInt1Ty(), 2);
|
||||||
|
|
||||||
|
result_phi->addIncoming(value, amount_zero_basic_block);
|
||||||
|
result_phi->addIncoming(result_amount_not_zero.result, pred);
|
||||||
|
carry_phi->addIncoming(carry_in, amount_zero_basic_block);
|
||||||
|
carry_phi->addIncoming(result_amount_not_zero.carry, pred);
|
||||||
|
|
||||||
|
return{ result_phi, carry_phi };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates code for LSL, LSR that checks for 0 shift
|
||||||
|
llvm::Value* ShiftZeroCheck(
|
||||||
|
InstructionBlock *instruction, llvm::Value* x, llvm::Value* shift,
|
||||||
|
std::function<ARMFuncs::ResultCarry(InstructionBlock *, llvm::Value*, llvm::Value*)> non_zero_function)
|
||||||
|
{
|
||||||
|
auto ir_builder = instruction->IrBuilder();
|
||||||
|
|
||||||
|
// amount_zero_basic_block will not recieve any code, it used only for the phi
|
||||||
|
auto amount_zero_basic_block = instruction->CreateBasicBlock("ShiftZeroCheckAmount0");
|
||||||
|
auto amount_not_zero_basic_block = instruction->CreateBasicBlock("ShiftZeroCheckAmountNot0");
|
||||||
|
auto phi_basic_block = instruction->CreateBasicBlock("ShiftZeroCheckPhi");
|
||||||
|
|
||||||
|
ir_builder->CreateCondBr(ir_builder->CreateICmpEQ(shift, ir_builder->getInt32(0)), amount_zero_basic_block, amount_not_zero_basic_block);
|
||||||
|
|
||||||
|
ir_builder->SetInsertPoint(amount_zero_basic_block);
|
||||||
|
ir_builder->CreateBr(phi_basic_block);
|
||||||
|
|
||||||
|
ir_builder->SetInsertPoint(amount_not_zero_basic_block);
|
||||||
|
auto result_amount_not_zero = non_zero_function(instruction, x, shift);
|
||||||
|
auto pred = ir_builder->GetInsertBlock(); // The basic block might have changed and needs to be current for the phi
|
||||||
|
ir_builder->CreateBr(phi_basic_block);
|
||||||
|
|
||||||
|
ir_builder->SetInsertPoint(phi_basic_block);
|
||||||
|
auto phi = ir_builder->CreatePHI(ir_builder->getInt32Ty(), 2);
|
||||||
|
|
||||||
|
phi->addIncoming(x, amount_zero_basic_block);
|
||||||
|
phi->addIncoming(result_amount_not_zero.result, pred);
|
||||||
|
|
||||||
|
return phi;
|
||||||
|
}
|
||||||
|
|
||||||
|
ARMFuncs::ResultCarry ARMFuncs::LSL_C(InstructionBlock* instruction, llvm::Value* x, llvm::Value* shift)
|
||||||
|
{
|
||||||
|
auto ir_builder = instruction->IrBuilder();
|
||||||
|
auto N = ir_builder->getInt32(32);
|
||||||
|
|
||||||
|
auto result = ir_builder->CreateShl(x, shift);
|
||||||
|
auto carry = ir_builder->CreateTrunc(ir_builder->CreateLShr(x, ir_builder->CreateSub(N, shift, "", true, true)), ir_builder->getInt1Ty());
|
||||||
|
return{ result, carry };
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Value* ARMFuncs::LSL(InstructionBlock* instruction, llvm::Value* x, llvm::Value* shift)
|
||||||
|
{
|
||||||
|
return ShiftZeroCheck(instruction, x, shift, &ARMFuncs::LSL_C);
|
||||||
|
}
|
||||||
|
|
||||||
|
ARMFuncs::ResultCarry ARMFuncs::LSR_C(InstructionBlock* instruction, llvm::Value* x, llvm::Value* shift)
|
||||||
|
{
|
||||||
|
auto ir_builder = instruction->IrBuilder();
|
||||||
|
auto one = ir_builder->getInt32(1);
|
||||||
|
|
||||||
|
auto result = ir_builder->CreateLShr(x, shift);
|
||||||
|
auto carry = ir_builder->CreateTrunc(ir_builder->CreateLShr(x, ir_builder->CreateSub(shift, one, "", true, true)), ir_builder->getInt1Ty());
|
||||||
|
return{ result, carry };
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Value* ARMFuncs::LSR(InstructionBlock* instruction, llvm::Value* x, llvm::Value* shift)
|
||||||
|
{
|
||||||
|
return ShiftZeroCheck(instruction, x, shift, &ARMFuncs::LSR_C);
|
||||||
|
}
|
||||||
|
|
||||||
|
ARMFuncs::ResultCarry ARMFuncs::ASR_C(InstructionBlock* instruction, llvm::Value* x, llvm::Value* shift)
|
||||||
|
{
|
||||||
|
auto ir_builder = instruction->IrBuilder();
|
||||||
|
auto one = ir_builder->getInt32(1);
|
||||||
|
|
||||||
|
auto result = ir_builder->CreateAShr(x, shift);
|
||||||
|
auto carry = ir_builder->CreateTrunc(ir_builder->CreateLShr(x, ir_builder->CreateSub(shift, one, "", true, true)), ir_builder->getInt1Ty());
|
||||||
|
return{ result, carry };
|
||||||
|
}
|
||||||
|
|
||||||
|
ARMFuncs::ResultCarry ARMFuncs::ROR_C(InstructionBlock* instruction, llvm::Value* x, llvm::Value* shift)
|
||||||
|
{
|
||||||
|
auto ir_builder = instruction->IrBuilder();
|
||||||
|
auto N = ir_builder->getInt32(32);
|
||||||
|
auto m = ir_builder->CreateURem(shift, N);
|
||||||
|
|
||||||
|
auto result = ir_builder->CreateOr(LSR(instruction, x, m), LSL(instruction, x, ir_builder->CreateSub(N, m)));
|
||||||
|
auto carry = ir_builder->CreateTrunc(ir_builder->CreateLShr(result, ir_builder->getInt32(31)), ir_builder->getInt1Ty());
|
||||||
|
return{ result, carry };
|
||||||
|
}
|
||||||
|
|
||||||
|
ARMFuncs::ResultCarry ARMFuncs::RRX_C(InstructionBlock* instruction, llvm::Value* x, llvm::Value* carry_in)
|
||||||
|
{
|
||||||
|
auto ir_builder = instruction->IrBuilder();
|
||||||
|
|
||||||
|
auto result = ir_builder->CreateLShr(x, 1);
|
||||||
|
result = ir_builder->CreateOr(result, ir_builder->CreateShl(ir_builder->CreateZExt(carry_in, ir_builder->getInt32Ty()), 31));
|
||||||
|
auto carry = ir_builder->CreateTrunc(x, ir_builder->getInt1Ty());
|
||||||
|
return{ result, carry };
|
||||||
|
}
|
42
src/binary_translation/ARMFuncs.h
Normal file
42
src/binary_translation/ARMFuncs.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#include <common/common_types.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Functions from the manual,
|
||||||
|
* A8.4.3 Pseudocode details of instruction-specified shifts and rotates
|
||||||
|
* A2.2.1 Integer arithmetic
|
||||||
|
*/
|
||||||
|
|
||||||
|
class InstructionBlock;
|
||||||
|
|
||||||
|
namespace llvm
|
||||||
|
{
|
||||||
|
class Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ARMFuncs
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class SRType { LSL, LSR, ASR, RRX, ROR };
|
||||||
|
struct ShiftTN
|
||||||
|
{
|
||||||
|
SRType type;
|
||||||
|
llvm::Value *amount;
|
||||||
|
};
|
||||||
|
struct ResultCarry
|
||||||
|
{
|
||||||
|
llvm::Value *result, *carry;
|
||||||
|
};
|
||||||
|
|
||||||
|
static ShiftTN DecodeImmShift(InstructionBlock *instruction, u32 type, u32 imm5);
|
||||||
|
static SRType DecodeRegShift(u32 type);
|
||||||
|
|
||||||
|
static llvm::Value *Shift(InstructionBlock *instruction, llvm::Value *value, SRType type, llvm::Value *amount, llvm::Value *carry_in);
|
||||||
|
static ResultCarry Shift_C(InstructionBlock *instruction, llvm::Value *value, SRType type, llvm::Value *amount, llvm::Value *carry_in);
|
||||||
|
static ResultCarry LSL_C(InstructionBlock *instruction, llvm::Value *x, llvm::Value *shift);
|
||||||
|
static llvm::Value *LSL(InstructionBlock *instruction, llvm::Value *x, llvm::Value *shift);
|
||||||
|
static ResultCarry LSR_C(InstructionBlock *instruction, llvm::Value *x, llvm::Value *shift);
|
||||||
|
static llvm::Value *LSR(InstructionBlock *instruction, llvm::Value *x, llvm::Value *shift);
|
||||||
|
static ResultCarry ASR_C(InstructionBlock *instruction, llvm::Value *x, llvm::Value *shift);
|
||||||
|
static ResultCarry ROR_C(InstructionBlock *instruction, llvm::Value *x, llvm::Value *shift);
|
||||||
|
static ResultCarry RRX_C(InstructionBlock *instruction, llvm::Value *x, llvm::Value *carry_in);
|
||||||
|
};
|
@ -6,6 +6,7 @@ set(SRCS
|
|||||||
InstructionBlock.cpp
|
InstructionBlock.cpp
|
||||||
MachineState.cpp
|
MachineState.cpp
|
||||||
TBAA.cpp
|
TBAA.cpp
|
||||||
|
ARMFuncs.cpp
|
||||||
|
|
||||||
Instructions/Instruction.cpp
|
Instructions/Instruction.cpp
|
||||||
Instructions/DataProcessing.cpp
|
Instructions/DataProcessing.cpp
|
||||||
@ -19,6 +20,7 @@ set(HEADERS
|
|||||||
MachineState.h
|
MachineState.h
|
||||||
TBAA.h
|
TBAA.h
|
||||||
BinarySearch.h
|
BinarySearch.h
|
||||||
|
ARMFuncs.h
|
||||||
|
|
||||||
Instructions/Types.h
|
Instructions/Types.h
|
||||||
Instructions/Instruction.h
|
Instructions/Instruction.h
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <common/common_types.h>
|
#include <common/common_types.h>
|
||||||
|
#include <llvm/IR/IRBuilder.h>
|
||||||
|
#include "ModuleGen.h"
|
||||||
|
|
||||||
namespace llvm
|
namespace llvm
|
||||||
{
|
{
|
||||||
@ -8,7 +10,6 @@ namespace llvm
|
|||||||
class BasicBlock;
|
class BasicBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ModuleGen;
|
|
||||||
class Instruction;
|
class Instruction;
|
||||||
|
|
||||||
enum class Register;
|
enum class Register;
|
||||||
@ -51,6 +52,7 @@ public:
|
|||||||
|
|
||||||
u32 Address();
|
u32 Address();
|
||||||
ModuleGen *Module() { return module; }
|
ModuleGen *Module() { return module; }
|
||||||
|
llvm::IRBuilder<> *IrBuilder() { return module->IrBuilder(); }
|
||||||
|
|
||||||
llvm::BasicBlock *GetEntryBasicBlock() { return entry_basic_block; }
|
llvm::BasicBlock *GetEntryBasicBlock() { return entry_basic_block; }
|
||||||
private:
|
private:
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include "Disassembler.h"
|
#include "Disassembler.h"
|
||||||
#include "InstructionBlock.h"
|
#include "InstructionBlock.h"
|
||||||
#include "ModuleGen.h"
|
#include "ModuleGen.h"
|
||||||
|
#include "ARMFuncs.h"
|
||||||
|
|
||||||
static RegisterInstruction<DataProcessing> register_instruction;
|
static RegisterInstruction<DataProcessing> register_instruction;
|
||||||
|
|
||||||
@ -9,12 +10,11 @@ bool DataProcessing::Decode()
|
|||||||
{
|
{
|
||||||
// Mov and shifts must have zeroes at some operands of different data processing instructions
|
// Mov and shifts must have zeroes at some operands of different data processing instructions
|
||||||
if (ReadFields({ CondDef(), FieldDef<3>(0), FieldDef<4>((u32)ShortOpType::MoveAndShifts), FieldDef<1>(&s), FieldDef<4>(0),
|
if (ReadFields({ CondDef(), FieldDef<3>(0), FieldDef<4>((u32)ShortOpType::MoveAndShifts), FieldDef<1>(&s), FieldDef<4>(0),
|
||||||
FieldDef<4>(&rd), FieldDef<5>(&imm5), FieldDef<3>(0), FieldDef<4>(&rm) }))
|
FieldDef<4>(&rd), FieldDef<5>(&imm5), FieldDef<2>(&op2), FieldDef<1>(0), FieldDef<4>(&rm) }))
|
||||||
{
|
{
|
||||||
form = Form::Register;
|
form = Form::Register;
|
||||||
if (imm5 != 0) return false; // Shifts
|
if (rm == Register::PC) return false;
|
||||||
if (s != 0) return false; // Set flags
|
if (rd == Register::PC && s) return false; // SEE SUBS PC, LR and related instructions;
|
||||||
if (rm == Register::PC) return false; // Jump
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (ReadFields({ CondDef(), FieldDef<3>(1), FieldDef<4>(&short_op), FieldDef<1>(&s), FieldDef<4>(&rn),
|
if (ReadFields({ CondDef(), FieldDef<3>(1), FieldDef<4>(&short_op), FieldDef<1>(&s), FieldDef<4>(&rn),
|
||||||
@ -29,10 +29,51 @@ bool DataProcessing::Decode()
|
|||||||
|
|
||||||
void DataProcessing::GenerateInstructionCode(InstructionBlock* instruction_block)
|
void DataProcessing::GenerateInstructionCode(InstructionBlock* instruction_block)
|
||||||
{
|
{
|
||||||
// Currently supports only mov reg, reg
|
auto ir_builder = instruction_block->IrBuilder();
|
||||||
|
|
||||||
auto value = instruction_block->Read(rm);
|
auto original_carry = instruction_block->Read(Register::C);
|
||||||
instruction_block->Write(rd, value);
|
ARMFuncs::ResultCarry result = { instruction_block->Read(rm), original_carry };
|
||||||
|
|
||||||
|
switch (op2)
|
||||||
|
{
|
||||||
|
case Op2Type::MoveAndLSL:
|
||||||
|
if (imm5 != 0)
|
||||||
|
{
|
||||||
|
result = ARMFuncs::Shift_C(instruction_block, result.result, ARMFuncs::SRType::LSL,
|
||||||
|
ARMFuncs::DecodeImmShift(instruction_block, 0, imm5).amount, result.carry);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Op2Type::LSR:
|
||||||
|
result = ARMFuncs::Shift_C(instruction_block, result.result, ARMFuncs::SRType::LSR,
|
||||||
|
ARMFuncs::DecodeImmShift(instruction_block, 1, imm5).amount, result.carry);
|
||||||
|
break;
|
||||||
|
case Op2Type::ASR:
|
||||||
|
result = ARMFuncs::Shift_C(instruction_block, result.result, ARMFuncs::SRType::ASR,
|
||||||
|
ARMFuncs::DecodeImmShift(instruction_block, 2, imm5).amount, result.carry);
|
||||||
|
break;
|
||||||
|
case Op2Type::RRXAndROR:
|
||||||
|
if (imm5 == 0)
|
||||||
|
{
|
||||||
|
result = ARMFuncs::Shift_C(instruction_block, result.result, ARMFuncs::SRType::RRX,
|
||||||
|
ir_builder->getInt32(1), result.carry);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = ARMFuncs::Shift_C(instruction_block, result.result, ARMFuncs::SRType::ROR,
|
||||||
|
ARMFuncs::DecodeImmShift(instruction_block, 3, imm5).amount, result.carry);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
instruction_block->Write(rd, result.result);
|
||||||
|
|
||||||
|
if (s)
|
||||||
|
{
|
||||||
|
instruction_block->Write(Register::N, ir_builder->CreateTrunc(ir_builder->CreateLShr(result.result, 31), ir_builder->getInt1Ty()));
|
||||||
|
instruction_block->Write(Register::Z, ir_builder->CreateICmpEQ(result.result, ir_builder->getInt32(0)));
|
||||||
|
if (result.carry != original_carry)
|
||||||
|
instruction_block->Write(Register::C, result.carry);
|
||||||
|
}
|
||||||
|
|
||||||
if (rd == Register::PC)
|
if (rd == Register::PC)
|
||||||
{
|
{
|
||||||
|
@ -18,6 +18,10 @@ public:
|
|||||||
// Compare, Test, Misc
|
// Compare, Test, Misc
|
||||||
BitwiseOr = 12, MoveAndShifts, BitwiseBitClear, BitwiseNot
|
BitwiseOr = 12, MoveAndShifts, BitwiseBitClear, BitwiseNot
|
||||||
};
|
};
|
||||||
|
enum class Op2Type
|
||||||
|
{
|
||||||
|
MoveAndLSL, LSR, ASR, RRXAndROR
|
||||||
|
};
|
||||||
enum class Form
|
enum class Form
|
||||||
{
|
{
|
||||||
Register, RegisterShiftedRegister, Immediate
|
Register, RegisterShiftedRegister, Immediate
|
||||||
@ -35,4 +39,5 @@ private:
|
|||||||
Register rm;
|
Register rm;
|
||||||
u32 imm12;
|
u32 imm12;
|
||||||
u32 imm5;
|
u32 imm5;
|
||||||
|
Op2Type op2;
|
||||||
};
|
};
|
@ -5,6 +5,7 @@
|
|||||||
#include <llvm/IR/Constants.h>
|
#include <llvm/IR/Constants.h>
|
||||||
#include <llvm/IR/LLVMContext.h>
|
#include <llvm/IR/LLVMContext.h>
|
||||||
#include <llvm/IR/GlobalVariable.h>
|
#include <llvm/IR/GlobalVariable.h>
|
||||||
|
#include "TBAA.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ class ModuleGen;
|
|||||||
namespace llvm
|
namespace llvm
|
||||||
{
|
{
|
||||||
class Value;
|
class Value;
|
||||||
|
class Instruction;
|
||||||
class GlobalVariable;
|
class GlobalVariable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include <llvm/IR/GlobalVariable.h>
|
#include <llvm/IR/GlobalVariable.h>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include "MachineState.h"
|
#include "MachineState.h"
|
||||||
|
#include "TBAA.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
#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;
|
||||||
|
|
||||||
class InstructionBlock;
|
class InstructionBlock;
|
||||||
class MachineState;
|
class MachineState;
|
||||||
|
class TBAA;
|
||||||
|
|
||||||
namespace llvm
|
namespace llvm
|
||||||
{
|
{
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#pragma once
|
||||||
#include "Instructions/Types.h"
|
#include "Instructions/Types.h"
|
||||||
|
|
||||||
namespace llvm
|
namespace llvm
|
||||||
|
Loading…
Reference in New Issue
Block a user