bool-ifying xe::cpu
This commit is contained in:
parent
a38b05db24
commit
ade5388728
|
@ -17,7 +17,7 @@ Assembler::Assembler(Backend* backend) : backend_(backend) {}
|
|||
|
||||
Assembler::~Assembler() { Reset(); }
|
||||
|
||||
int Assembler::Initialize() { return 0; }
|
||||
bool Assembler::Initialize() { return true; }
|
||||
|
||||
void Assembler::Reset() {}
|
||||
|
||||
|
|
|
@ -34,14 +34,14 @@ class Assembler {
|
|||
Assembler(Backend* backend);
|
||||
virtual ~Assembler();
|
||||
|
||||
virtual int Initialize();
|
||||
virtual bool Initialize();
|
||||
|
||||
virtual void Reset();
|
||||
|
||||
virtual int Assemble(FunctionInfo* symbol_info, hir::HIRBuilder* builder,
|
||||
uint32_t debug_info_flags,
|
||||
std::unique_ptr<DebugInfo> debug_info,
|
||||
uint32_t trace_flags, Function** out_function) = 0;
|
||||
virtual bool Assemble(FunctionInfo* symbol_info, hir::HIRBuilder* builder,
|
||||
uint32_t debug_info_flags,
|
||||
std::unique_ptr<DebugInfo> debug_info,
|
||||
uint32_t trace_flags, Function** out_function) = 0;
|
||||
|
||||
protected:
|
||||
Backend* backend_;
|
||||
|
|
|
@ -19,7 +19,7 @@ Backend::Backend(Processor* processor) : processor_(processor) {
|
|||
|
||||
Backend::~Backend() = default;
|
||||
|
||||
int Backend::Initialize() { return 0; }
|
||||
bool Backend::Initialize() { return true; }
|
||||
|
||||
void* Backend::AllocThreadData() { return nullptr; }
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ class Backend {
|
|||
Processor* processor() const { return processor_; }
|
||||
const MachineInfo* machine_info() const { return &machine_info_; }
|
||||
|
||||
virtual int Initialize();
|
||||
virtual bool Initialize();
|
||||
|
||||
virtual void* AllocThreadData();
|
||||
virtual void FreeThreadData(void* thread_data);
|
||||
|
|
|
@ -41,16 +41,15 @@ X64Assembler::~X64Assembler() {
|
|||
allocator_.reset();
|
||||
}
|
||||
|
||||
int X64Assembler::Initialize() {
|
||||
int result = Assembler::Initialize();
|
||||
if (result) {
|
||||
return result;
|
||||
bool X64Assembler::Initialize() {
|
||||
if (!Assembler::Initialize()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
allocator_.reset(new XbyakAllocator());
|
||||
emitter_.reset(new X64Emitter(x64_backend_, allocator_.get()));
|
||||
|
||||
return result;
|
||||
return true;
|
||||
}
|
||||
|
||||
void X64Assembler::Reset() {
|
||||
|
@ -58,10 +57,10 @@ void X64Assembler::Reset() {
|
|||
Assembler::Reset();
|
||||
}
|
||||
|
||||
int X64Assembler::Assemble(FunctionInfo* symbol_info, HIRBuilder* builder,
|
||||
uint32_t debug_info_flags,
|
||||
std::unique_ptr<DebugInfo> debug_info,
|
||||
uint32_t trace_flags, Function** out_function) {
|
||||
bool X64Assembler::Assemble(FunctionInfo* symbol_info, HIRBuilder* builder,
|
||||
uint32_t debug_info_flags,
|
||||
std::unique_ptr<DebugInfo> debug_info,
|
||||
uint32_t trace_flags, Function** out_function) {
|
||||
SCOPE_profile_cpu_f("cpu");
|
||||
|
||||
// Reset when we leave.
|
||||
|
@ -70,10 +69,9 @@ int X64Assembler::Assemble(FunctionInfo* symbol_info, HIRBuilder* builder,
|
|||
// Lower HIR -> x64.
|
||||
void* machine_code = 0;
|
||||
size_t code_size = 0;
|
||||
int result = emitter_->Emit(builder, debug_info_flags, debug_info.get(),
|
||||
trace_flags, machine_code, code_size);
|
||||
if (result) {
|
||||
return result;
|
||||
if (!emitter_->Emit(builder, debug_info_flags, debug_info.get(), trace_flags,
|
||||
machine_code, code_size)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Stash generated machine code.
|
||||
|
@ -91,7 +89,7 @@ int X64Assembler::Assemble(FunctionInfo* symbol_info, HIRBuilder* builder,
|
|||
*out_function = fn;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void X64Assembler::DumpMachineCode(DebugInfo* debug_info, void* machine_code,
|
||||
|
|
|
@ -29,13 +29,14 @@ class X64Assembler : public Assembler {
|
|||
X64Assembler(X64Backend* backend);
|
||||
~X64Assembler() override;
|
||||
|
||||
int Initialize() override;
|
||||
bool Initialize() override;
|
||||
|
||||
void Reset() override;
|
||||
|
||||
int Assemble(FunctionInfo* symbol_info, hir::HIRBuilder* builder,
|
||||
uint32_t debug_info_flags, std::unique_ptr<DebugInfo> debug_info,
|
||||
uint32_t trace_flags, Function** out_function) override;
|
||||
bool Assemble(FunctionInfo* symbol_info, hir::HIRBuilder* builder,
|
||||
uint32_t debug_info_flags,
|
||||
std::unique_ptr<DebugInfo> debug_info, uint32_t trace_flags,
|
||||
Function** out_function) override;
|
||||
|
||||
private:
|
||||
void DumpMachineCode(DebugInfo* debug_info, void* machine_code,
|
||||
|
|
|
@ -24,10 +24,9 @@ X64Backend::X64Backend(Processor* processor)
|
|||
|
||||
X64Backend::~X64Backend() { delete code_cache_; }
|
||||
|
||||
int X64Backend::Initialize() {
|
||||
int result = Backend::Initialize();
|
||||
if (result) {
|
||||
return result;
|
||||
bool X64Backend::Initialize() {
|
||||
if (!Backend::Initialize()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RegisterSequences();
|
||||
|
@ -42,9 +41,8 @@ int X64Backend::Initialize() {
|
|||
};
|
||||
|
||||
code_cache_ = new X64CodeCache();
|
||||
result = code_cache_->Initialize();
|
||||
if (result) {
|
||||
return result;
|
||||
if (!code_cache_->Initialize()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Generate thunks used to transition between jitted code and host code.
|
||||
|
@ -53,7 +51,7 @@ int X64Backend::Initialize() {
|
|||
host_to_guest_thunk_ = thunk_emitter->EmitHostToGuestThunk();
|
||||
guest_to_host_thunk_ = thunk_emitter->EmitGuestToHostThunk();
|
||||
|
||||
return result;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<Assembler> X64Backend::CreateAssembler() {
|
||||
|
|
|
@ -33,7 +33,7 @@ class X64Backend : public Backend {
|
|||
HostToGuestThunk host_to_guest_thunk() const { return host_to_guest_thunk_; }
|
||||
GuestToHostThunk guest_to_host_thunk() const { return guest_to_host_thunk_; }
|
||||
|
||||
int Initialize() override;
|
||||
bool Initialize() override;
|
||||
|
||||
std::unique_ptr<Assembler> CreateAssembler() override;
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ class X64CodeCache {
|
|||
X64CodeCache(size_t chunk_size = DEFAULT_CHUNK_SIZE);
|
||||
virtual ~X64CodeCache();
|
||||
|
||||
int Initialize();
|
||||
bool Initialize();
|
||||
|
||||
// TODO(benvanik): ELF serialization/etc
|
||||
// TODO(benvanik): keep track of code blocks
|
||||
|
|
|
@ -57,7 +57,7 @@ X64CodeCache::~X64CodeCache() {
|
|||
head_chunk_ = NULL;
|
||||
}
|
||||
|
||||
int X64CodeCache::Initialize() { return 0; }
|
||||
bool X64CodeCache::Initialize() { return true; }
|
||||
|
||||
void* X64CodeCache::PlaceCode(void* machine_code, size_t code_size,
|
||||
size_t stack_size) {
|
||||
|
|
|
@ -70,13 +70,11 @@ X64Emitter::X64Emitter(X64Backend* backend, XbyakAllocator* allocator)
|
|||
trace_flags_(0),
|
||||
cpu_() {}
|
||||
|
||||
X64Emitter::~X64Emitter() {}
|
||||
X64Emitter::~X64Emitter() = default;
|
||||
|
||||
int X64Emitter::Initialize() { return 0; }
|
||||
|
||||
int X64Emitter::Emit(HIRBuilder* builder, uint32_t debug_info_flags,
|
||||
DebugInfo* debug_info, uint32_t trace_flags,
|
||||
void*& out_code_address, size_t& out_code_size) {
|
||||
bool X64Emitter::Emit(HIRBuilder* builder, uint32_t debug_info_flags,
|
||||
DebugInfo* debug_info, uint32_t trace_flags,
|
||||
void*& out_code_address, size_t& out_code_size) {
|
||||
SCOPE_profile_cpu_f("cpu");
|
||||
|
||||
// Reset.
|
||||
|
@ -88,9 +86,8 @@ int X64Emitter::Emit(HIRBuilder* builder, uint32_t debug_info_flags,
|
|||
|
||||
// Fill the generator with code.
|
||||
size_t stack_size = 0;
|
||||
int result = Emit(builder, stack_size);
|
||||
if (result) {
|
||||
return result;
|
||||
if (!Emit(builder, stack_size)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy the final code to the cache and relocate it.
|
||||
|
@ -103,7 +100,7 @@ int X64Emitter::Emit(HIRBuilder* builder, uint32_t debug_info_flags,
|
|||
source_map_count_, (SourceMapEntry*)source_map_arena_.CloneContents());
|
||||
}
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void* X64Emitter::Emplace(size_t stack_size) {
|
||||
|
@ -120,7 +117,7 @@ void* X64Emitter::Emplace(size_t stack_size) {
|
|||
return new_address;
|
||||
}
|
||||
|
||||
int X64Emitter::Emit(HIRBuilder* builder, size_t& out_stack_size) {
|
||||
bool X64Emitter::Emit(HIRBuilder* builder, size_t& out_stack_size) {
|
||||
// Calculate stack size. We need to align things to their natural sizes.
|
||||
// This could be much better (sort by type/etc).
|
||||
auto locals = builder->locals();
|
||||
|
@ -204,7 +201,7 @@ int X64Emitter::Emit(HIRBuilder* builder, size_t& out_stack_size) {
|
|||
nop();
|
||||
#endif // XE_DEBUG
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void X64Emitter::MarkSourceOffset(const Instr* i) {
|
||||
|
|
|
@ -105,11 +105,9 @@ class X64Emitter : public Xbyak::CodeGenerator {
|
|||
X64Backend* backend() const { return backend_; }
|
||||
const Xbyak::util::Cpu* cpu() const { return &cpu_; }
|
||||
|
||||
int Initialize();
|
||||
|
||||
int Emit(hir::HIRBuilder* builder, uint32_t debug_info_flags,
|
||||
DebugInfo* debug_info, uint32_t trace_flags, void*& out_code_address,
|
||||
size_t& out_code_size);
|
||||
bool Emit(hir::HIRBuilder* builder, uint32_t debug_info_flags,
|
||||
DebugInfo* debug_info, uint32_t trace_flags,
|
||||
void*& out_code_address, size_t& out_code_size);
|
||||
|
||||
public:
|
||||
// Reserved: rsp
|
||||
|
@ -182,7 +180,7 @@ class X64Emitter : public Xbyak::CodeGenerator {
|
|||
|
||||
protected:
|
||||
void* Emplace(size_t stack_size);
|
||||
int Emit(hir::HIRBuilder* builder, size_t& out_stack_size);
|
||||
bool Emit(hir::HIRBuilder* builder, size_t& out_stack_size);
|
||||
void EmitGetCurrentThreadId();
|
||||
void EmitTraceUserCallReturn();
|
||||
|
||||
|
|
|
@ -30,19 +30,21 @@ void X64Function::Setup(void* machine_code, size_t code_size) {
|
|||
code_size_ = code_size;
|
||||
}
|
||||
|
||||
int X64Function::AddBreakpointImpl(debug::Breakpoint* breakpoint) { return 0; }
|
||||
|
||||
int X64Function::RemoveBreakpointImpl(debug::Breakpoint* breakpoint) {
|
||||
return 0;
|
||||
bool X64Function::AddBreakpointImpl(debug::Breakpoint* breakpoint) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int X64Function::CallImpl(ThreadState* thread_state, uint32_t return_address) {
|
||||
bool X64Function::RemoveBreakpointImpl(debug::Breakpoint* breakpoint) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool X64Function::CallImpl(ThreadState* thread_state, uint32_t return_address) {
|
||||
auto backend =
|
||||
reinterpret_cast<X64Backend*>(thread_state->processor()->backend());
|
||||
auto thunk = backend->host_to_guest_thunk();
|
||||
thunk(machine_code_, thread_state->context(),
|
||||
reinterpret_cast<void*>(uintptr_t(return_address)));
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace x64
|
||||
|
|
|
@ -30,9 +30,9 @@ class X64Function : public Function {
|
|||
void Setup(void* machine_code, size_t code_size);
|
||||
|
||||
protected:
|
||||
virtual int AddBreakpointImpl(debug::Breakpoint* breakpoint);
|
||||
virtual int RemoveBreakpointImpl(debug::Breakpoint* breakpoint);
|
||||
virtual int CallImpl(ThreadState* thread_state, uint32_t return_address);
|
||||
virtual bool AddBreakpointImpl(debug::Breakpoint* breakpoint);
|
||||
virtual bool RemoveBreakpointImpl(debug::Breakpoint* breakpoint);
|
||||
virtual bool CallImpl(ThreadState* thread_state, uint32_t return_address);
|
||||
|
||||
private:
|
||||
void* machine_code_;
|
||||
|
|
|
@ -27,18 +27,18 @@ void Compiler::AddPass(std::unique_ptr<CompilerPass> pass) {
|
|||
|
||||
void Compiler::Reset() {}
|
||||
|
||||
int Compiler::Compile(xe::cpu::hir::HIRBuilder* builder) {
|
||||
bool Compiler::Compile(xe::cpu::hir::HIRBuilder* builder) {
|
||||
// TODO(benvanik): sophisticated stuff. Run passes in parallel, run until they
|
||||
// stop changing things, etc.
|
||||
for (size_t i = 0; i < passes_.size(); ++i) {
|
||||
auto& pass = passes_[i];
|
||||
scratch_arena_.Reset();
|
||||
if (pass->Run(builder)) {
|
||||
return 1;
|
||||
if (!pass->Run(builder)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
|
|
|
@ -40,7 +40,7 @@ class Compiler {
|
|||
|
||||
void Reset();
|
||||
|
||||
int Compile(hir::HIRBuilder* builder);
|
||||
bool Compile(hir::HIRBuilder* builder);
|
||||
|
||||
private:
|
||||
Processor* processor_;
|
||||
|
|
|
@ -19,10 +19,10 @@ CompilerPass::CompilerPass() : processor_(nullptr), compiler_(nullptr) {}
|
|||
|
||||
CompilerPass::~CompilerPass() = default;
|
||||
|
||||
int CompilerPass::Initialize(Compiler* compiler) {
|
||||
bool CompilerPass::Initialize(Compiler* compiler) {
|
||||
processor_ = compiler->processor();
|
||||
compiler_ = compiler;
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
Arena* CompilerPass::scratch_arena() const {
|
||||
|
|
|
@ -30,9 +30,9 @@ class CompilerPass {
|
|||
CompilerPass();
|
||||
virtual ~CompilerPass();
|
||||
|
||||
virtual int Initialize(Compiler* compiler);
|
||||
virtual bool Initialize(Compiler* compiler);
|
||||
|
||||
virtual int Run(hir::HIRBuilder* builder) = 0;
|
||||
virtual bool Run(hir::HIRBuilder* builder) = 0;
|
||||
|
||||
protected:
|
||||
Arena* scratch_arena() const;
|
||||
|
|
|
@ -30,7 +30,7 @@ ConstantPropagationPass::ConstantPropagationPass() : CompilerPass() {}
|
|||
|
||||
ConstantPropagationPass::~ConstantPropagationPass() {}
|
||||
|
||||
int ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||
bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||
// Once ContextPromotion has run there will likely be a whole slew of
|
||||
// constants that can be pushed through the function.
|
||||
// Example:
|
||||
|
@ -98,7 +98,7 @@ int ConstantPropagationPass::Run(HIRBuilder* builder) {
|
|||
case OPCODE_CALL_INDIRECT:
|
||||
if (i->src1.value->IsConstant()) {
|
||||
FunctionInfo* symbol_info;
|
||||
if (processor_->LookupFunctionInfo(
|
||||
if (!processor_->LookupFunctionInfo(
|
||||
(uint32_t)i->src1.value->constant.i32, &symbol_info)) {
|
||||
break;
|
||||
}
|
||||
|
@ -468,7 +468,7 @@ int ConstantPropagationPass::Run(HIRBuilder* builder) {
|
|||
block = block->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ConstantPropagationPass::PropagateCarry(Value* v, bool did_carry) {
|
||||
|
|
|
@ -22,7 +22,7 @@ class ConstantPropagationPass : public CompilerPass {
|
|||
ConstantPropagationPass();
|
||||
~ConstantPropagationPass() override;
|
||||
|
||||
int Run(hir::HIRBuilder* builder) override;
|
||||
bool Run(hir::HIRBuilder* builder) override;
|
||||
|
||||
private:
|
||||
void PropagateCarry(hir::Value* v, bool did_carry);
|
||||
|
|
|
@ -36,9 +36,9 @@ ContextPromotionPass::ContextPromotionPass() : CompilerPass() {}
|
|||
|
||||
ContextPromotionPass::~ContextPromotionPass() {}
|
||||
|
||||
int ContextPromotionPass::Initialize(Compiler* compiler) {
|
||||
if (CompilerPass::Initialize(compiler)) {
|
||||
return 1;
|
||||
bool ContextPromotionPass::Initialize(Compiler* compiler) {
|
||||
if (!CompilerPass::Initialize(compiler)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// This is a terrible implementation.
|
||||
|
@ -46,10 +46,10 @@ int ContextPromotionPass::Initialize(Compiler* compiler) {
|
|||
context_values_.resize(context_info->size());
|
||||
context_validity_.resize(static_cast<uint32_t>(context_info->size()));
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
int ContextPromotionPass::Run(HIRBuilder* builder) {
|
||||
bool ContextPromotionPass::Run(HIRBuilder* builder) {
|
||||
// Like mem2reg, but because context memory is unaliasable it's easier to
|
||||
// check and convert LoadContext/StoreContext into value operations.
|
||||
// Example of load->value promotion:
|
||||
|
@ -82,7 +82,7 @@ int ContextPromotionPass::Run(HIRBuilder* builder) {
|
|||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ContextPromotionPass::PromoteBlock(Block* block) {
|
||||
|
|
|
@ -34,9 +34,9 @@ class ContextPromotionPass : public CompilerPass {
|
|||
ContextPromotionPass();
|
||||
virtual ~ContextPromotionPass() override;
|
||||
|
||||
int Initialize(Compiler* compiler) override;
|
||||
bool Initialize(Compiler* compiler) override;
|
||||
|
||||
int Run(hir::HIRBuilder* builder) override;
|
||||
bool Run(hir::HIRBuilder* builder) override;
|
||||
|
||||
private:
|
||||
void PromoteBlock(hir::Block* block);
|
||||
|
|
|
@ -29,7 +29,7 @@ ControlFlowAnalysisPass::ControlFlowAnalysisPass() : CompilerPass() {}
|
|||
|
||||
ControlFlowAnalysisPass::~ControlFlowAnalysisPass() {}
|
||||
|
||||
int ControlFlowAnalysisPass::Run(HIRBuilder* builder) {
|
||||
bool ControlFlowAnalysisPass::Run(HIRBuilder* builder) {
|
||||
// Reset edges for all blocks. Needed to be re-runnable.
|
||||
// Note that this wastes a bunch of arena memory, so we shouldn't
|
||||
// re-run too often.
|
||||
|
@ -71,7 +71,7 @@ int ControlFlowAnalysisPass::Run(HIRBuilder* builder) {
|
|||
block = block->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace passes
|
||||
|
|
|
@ -22,7 +22,7 @@ class ControlFlowAnalysisPass : public CompilerPass {
|
|||
ControlFlowAnalysisPass();
|
||||
~ControlFlowAnalysisPass() override;
|
||||
|
||||
int Run(hir::HIRBuilder* builder) override;
|
||||
bool Run(hir::HIRBuilder* builder) override;
|
||||
|
||||
private:
|
||||
};
|
||||
|
|
|
@ -30,7 +30,7 @@ ControlFlowSimplificationPass::ControlFlowSimplificationPass()
|
|||
|
||||
ControlFlowSimplificationPass::~ControlFlowSimplificationPass() {}
|
||||
|
||||
int ControlFlowSimplificationPass::Run(HIRBuilder* builder) {
|
||||
bool ControlFlowSimplificationPass::Run(HIRBuilder* builder) {
|
||||
// Walk backwards and merge blocks if possible.
|
||||
bool merged_any = false;
|
||||
auto block = builder->last_block();
|
||||
|
@ -52,7 +52,7 @@ int ControlFlowSimplificationPass::Run(HIRBuilder* builder) {
|
|||
block = prev_block;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace passes
|
||||
|
|
|
@ -22,7 +22,7 @@ class ControlFlowSimplificationPass : public CompilerPass {
|
|||
ControlFlowSimplificationPass();
|
||||
~ControlFlowSimplificationPass() override;
|
||||
|
||||
int Run(hir::HIRBuilder* builder) override;
|
||||
bool Run(hir::HIRBuilder* builder) override;
|
||||
|
||||
private:
|
||||
};
|
||||
|
|
|
@ -42,14 +42,14 @@ DataFlowAnalysisPass::DataFlowAnalysisPass() : CompilerPass() {}
|
|||
|
||||
DataFlowAnalysisPass::~DataFlowAnalysisPass() {}
|
||||
|
||||
int DataFlowAnalysisPass::Run(HIRBuilder* builder) {
|
||||
bool DataFlowAnalysisPass::Run(HIRBuilder* builder) {
|
||||
// Linearize blocks so that we can detect cycles and propagate dependencies.
|
||||
uint32_t block_count = LinearizeBlocks(builder);
|
||||
|
||||
// Analyze value flow and add locals as needed.
|
||||
AnalyzeFlow(builder, block_count);
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t DataFlowAnalysisPass::LinearizeBlocks(HIRBuilder* builder) {
|
||||
|
|
|
@ -22,7 +22,7 @@ class DataFlowAnalysisPass : public CompilerPass {
|
|||
DataFlowAnalysisPass();
|
||||
~DataFlowAnalysisPass() override;
|
||||
|
||||
int Run(hir::HIRBuilder* builder) override;
|
||||
bool Run(hir::HIRBuilder* builder) override;
|
||||
|
||||
private:
|
||||
uint32_t LinearizeBlocks(hir::HIRBuilder* builder);
|
||||
|
|
|
@ -27,7 +27,7 @@ DeadCodeEliminationPass::DeadCodeEliminationPass() : CompilerPass() {}
|
|||
|
||||
DeadCodeEliminationPass::~DeadCodeEliminationPass() {}
|
||||
|
||||
int DeadCodeEliminationPass::Run(HIRBuilder* builder) {
|
||||
bool DeadCodeEliminationPass::Run(HIRBuilder* builder) {
|
||||
// ContextPromotion/DSE will likely leave around a lot of dead statements.
|
||||
// Code generated for comparison/testing produces many unused statements and
|
||||
// with proper use analysis it should be possible to remove most of them:
|
||||
|
@ -143,7 +143,7 @@ int DeadCodeEliminationPass::Run(HIRBuilder* builder) {
|
|||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void DeadCodeEliminationPass::MakeNopRecursive(Instr* i) {
|
||||
|
|
|
@ -22,7 +22,7 @@ class DeadCodeEliminationPass : public CompilerPass {
|
|||
DeadCodeEliminationPass();
|
||||
~DeadCodeEliminationPass() override;
|
||||
|
||||
int Run(hir::HIRBuilder* builder) override;
|
||||
bool Run(hir::HIRBuilder* builder) override;
|
||||
|
||||
private:
|
||||
void MakeNopRecursive(hir::Instr* i);
|
||||
|
|
|
@ -28,7 +28,7 @@ FinalizationPass::FinalizationPass() : CompilerPass() {}
|
|||
|
||||
FinalizationPass::~FinalizationPass() {}
|
||||
|
||||
int FinalizationPass::Run(HIRBuilder* builder) {
|
||||
bool FinalizationPass::Run(HIRBuilder* builder) {
|
||||
// Process the HIR and prepare it for lowering.
|
||||
// After this is done the HIR should be ready for emitting.
|
||||
|
||||
|
@ -65,7 +65,7 @@ int FinalizationPass::Run(HIRBuilder* builder) {
|
|||
block = block->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace passes
|
||||
|
|
|
@ -22,7 +22,7 @@ class FinalizationPass : public CompilerPass {
|
|||
FinalizationPass();
|
||||
~FinalizationPass() override;
|
||||
|
||||
int Run(hir::HIRBuilder* builder) override;
|
||||
bool Run(hir::HIRBuilder* builder) override;
|
||||
|
||||
private:
|
||||
};
|
||||
|
|
|
@ -69,7 +69,7 @@ RegisterAllocationPass::~RegisterAllocationPass() {
|
|||
}
|
||||
}
|
||||
|
||||
int RegisterAllocationPass::Run(HIRBuilder* builder) {
|
||||
bool RegisterAllocationPass::Run(HIRBuilder* builder) {
|
||||
// Simple per-block allocator that operates on SSA form.
|
||||
// Registers do not move across blocks, though this could be
|
||||
// optimized with some intra-block analysis (dominators/etc).
|
||||
|
@ -151,7 +151,7 @@ int RegisterAllocationPass::Run(HIRBuilder* builder) {
|
|||
// Unable to spill anything - this shouldn't happen.
|
||||
XELOGE("Unable to spill any registers");
|
||||
assert_always();
|
||||
return 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Demand allocation.
|
||||
|
@ -159,7 +159,7 @@ int RegisterAllocationPass::Run(HIRBuilder* builder) {
|
|||
// Boned.
|
||||
XELOGE("Register allocation failed");
|
||||
assert_always();
|
||||
return 1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -169,7 +169,7 @@ int RegisterAllocationPass::Run(HIRBuilder* builder) {
|
|||
block = block->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void RegisterAllocationPass::DumpUsage(const char* name) {
|
||||
|
|
|
@ -27,7 +27,7 @@ class RegisterAllocationPass : public CompilerPass {
|
|||
RegisterAllocationPass(const backend::MachineInfo* machine_info);
|
||||
~RegisterAllocationPass() override;
|
||||
|
||||
int Run(hir::HIRBuilder* builder) override;
|
||||
bool Run(hir::HIRBuilder* builder) override;
|
||||
|
||||
private:
|
||||
// TODO(benvanik): rewrite all this set shit -- too much indirection, the
|
||||
|
|
|
@ -27,10 +27,10 @@ SimplificationPass::SimplificationPass() : CompilerPass() {}
|
|||
|
||||
SimplificationPass::~SimplificationPass() {}
|
||||
|
||||
int SimplificationPass::Run(HIRBuilder* builder) {
|
||||
bool SimplificationPass::Run(HIRBuilder* builder) {
|
||||
EliminateConversions(builder);
|
||||
SimplifyAssignments(builder);
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void SimplificationPass::EliminateConversions(HIRBuilder* builder) {
|
||||
|
|
|
@ -22,7 +22,7 @@ class SimplificationPass : public CompilerPass {
|
|||
SimplificationPass();
|
||||
~SimplificationPass() override;
|
||||
|
||||
int Run(hir::HIRBuilder* builder) override;
|
||||
bool Run(hir::HIRBuilder* builder) override;
|
||||
|
||||
private:
|
||||
void EliminateConversions(hir::HIRBuilder* builder);
|
||||
|
|
|
@ -33,7 +33,7 @@ ValidationPass::ValidationPass() : CompilerPass() {}
|
|||
|
||||
ValidationPass::~ValidationPass() {}
|
||||
|
||||
int ValidationPass::Run(HIRBuilder* builder) {
|
||||
bool ValidationPass::Run(HIRBuilder* builder) {
|
||||
#if 0
|
||||
StringBuffer str;
|
||||
builder->Dump(&str);
|
||||
|
@ -48,15 +48,15 @@ int ValidationPass::Run(HIRBuilder* builder) {
|
|||
while (label) {
|
||||
assert_true(label->block == block);
|
||||
if (label->block != block) {
|
||||
return 1;
|
||||
return false;
|
||||
}
|
||||
label = label->next;
|
||||
}
|
||||
|
||||
auto instr = block->instr_head;
|
||||
while (instr) {
|
||||
if (ValidateInstruction(block, instr)) {
|
||||
return 1;
|
||||
if (!ValidateInstruction(block, instr)) {
|
||||
return false;
|
||||
}
|
||||
instr = instr->next;
|
||||
}
|
||||
|
@ -64,13 +64,13 @@ int ValidationPass::Run(HIRBuilder* builder) {
|
|||
block = block->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
int ValidationPass::ValidateInstruction(Block* block, Instr* instr) {
|
||||
bool ValidationPass::ValidateInstruction(Block* block, Instr* instr) {
|
||||
assert_true(instr->block == block);
|
||||
if (instr->block != block) {
|
||||
return 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (instr->dest) {
|
||||
|
@ -84,33 +84,33 @@ int ValidationPass::ValidateInstruction(Block* block, Instr* instr) {
|
|||
|
||||
uint32_t signature = instr->opcode->signature;
|
||||
if (GET_OPCODE_SIG_TYPE_SRC1(signature) == OPCODE_SIG_TYPE_V) {
|
||||
if (ValidateValue(block, instr, instr->src1.value)) {
|
||||
return 1;
|
||||
if (!ValidateValue(block, instr, instr->src1.value)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (GET_OPCODE_SIG_TYPE_SRC2(signature) == OPCODE_SIG_TYPE_V) {
|
||||
if (ValidateValue(block, instr, instr->src2.value)) {
|
||||
return 1;
|
||||
if (!ValidateValue(block, instr, instr->src2.value)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (GET_OPCODE_SIG_TYPE_SRC3(signature) == OPCODE_SIG_TYPE_V) {
|
||||
if (ValidateValue(block, instr, instr->src3.value)) {
|
||||
return 1;
|
||||
if (!ValidateValue(block, instr, instr->src3.value)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
int ValidationPass::ValidateValue(Block* block, Instr* instr, Value* value) {
|
||||
bool ValidationPass::ValidateValue(Block* block, Instr* instr, Value* value) {
|
||||
// if (value->def) {
|
||||
// auto def = value->def;
|
||||
// assert_true(def->block == block);
|
||||
// if (def->block != block) {
|
||||
// return 1;
|
||||
// return false;
|
||||
// }
|
||||
//}
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace passes
|
||||
|
|
|
@ -22,11 +22,11 @@ class ValidationPass : public CompilerPass {
|
|||
ValidationPass();
|
||||
~ValidationPass() override;
|
||||
|
||||
int Run(hir::HIRBuilder* builder) override;
|
||||
bool Run(hir::HIRBuilder* builder) override;
|
||||
|
||||
private:
|
||||
int ValidateInstruction(hir::Block* block, hir::Instr* instr);
|
||||
int ValidateValue(hir::Block* block, hir::Instr* instr, hir::Value* value);
|
||||
bool ValidateInstruction(hir::Block* block, hir::Instr* instr);
|
||||
bool ValidateValue(hir::Block* block, hir::Instr* instr, hir::Value* value);
|
||||
};
|
||||
|
||||
} // namespace passes
|
||||
|
|
|
@ -58,7 +58,7 @@ void ValueReductionPass::ComputeLastUse(Value* value) {
|
|||
value->last_use = last_use ? last_use->instr : nullptr;
|
||||
}
|
||||
|
||||
int ValueReductionPass::Run(HIRBuilder* builder) {
|
||||
bool ValueReductionPass::Run(HIRBuilder* builder) {
|
||||
// Walk each block and reuse variable ordinals as much as possible.
|
||||
|
||||
llvm::BitVector ordinals(builder->max_value_ordinal());
|
||||
|
@ -139,7 +139,7 @@ int ValueReductionPass::Run(HIRBuilder* builder) {
|
|||
block = block->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace passes
|
||||
|
|
|
@ -22,7 +22,7 @@ class ValueReductionPass : public CompilerPass {
|
|||
ValueReductionPass();
|
||||
~ValueReductionPass() override;
|
||||
|
||||
int Run(hir::HIRBuilder* builder) override;
|
||||
bool Run(hir::HIRBuilder* builder) override;
|
||||
|
||||
private:
|
||||
void ComputeLastUse(hir::Value* value);
|
||||
|
|
|
@ -73,7 +73,7 @@ void HandleGlobalLock(PPCContext* ppc_state, void* arg0, void* arg1) {
|
|||
}
|
||||
}
|
||||
|
||||
int PPCFrontend::Initialize() {
|
||||
bool PPCFrontend::Initialize() {
|
||||
void* arg0 = reinterpret_cast<void*>(&builtins_.global_lock);
|
||||
void* arg1 = reinterpret_cast<void*>(&builtins_.global_lock_taken);
|
||||
builtins_.check_global_lock = processor_->DefineBuiltin(
|
||||
|
@ -83,24 +83,25 @@ int PPCFrontend::Initialize() {
|
|||
"HandleGlobalLock", (FunctionInfo::ExternHandler)HandleGlobalLock, arg0,
|
||||
arg1);
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
int PPCFrontend::DeclareFunction(FunctionInfo* symbol_info) {
|
||||
bool PPCFrontend::DeclareFunction(FunctionInfo* symbol_info) {
|
||||
// Could scan or something here.
|
||||
// Could also check to see if it's a well-known function type and classify
|
||||
// for later.
|
||||
// Could also kick off a precompiler, since we know it's likely the function
|
||||
// will be demanded soon.
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
int PPCFrontend::DefineFunction(FunctionInfo* symbol_info,
|
||||
uint32_t debug_info_flags, uint32_t trace_flags,
|
||||
Function** out_function) {
|
||||
bool PPCFrontend::DefineFunction(FunctionInfo* symbol_info,
|
||||
uint32_t debug_info_flags,
|
||||
uint32_t trace_flags,
|
||||
Function** out_function) {
|
||||
PPCTranslator* translator = translator_pool_.Allocate(this);
|
||||
int result = translator->Translate(symbol_info, debug_info_flags, trace_flags,
|
||||
out_function);
|
||||
bool result = translator->Translate(symbol_info, debug_info_flags,
|
||||
trace_flags, out_function);
|
||||
translator_pool_.Release(translator);
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -43,16 +43,16 @@ class PPCFrontend {
|
|||
explicit PPCFrontend(Processor* processor);
|
||||
~PPCFrontend();
|
||||
|
||||
int Initialize();
|
||||
bool Initialize();
|
||||
|
||||
Processor* processor() const { return processor_; }
|
||||
Memory* memory() const;
|
||||
ContextInfo* context_info() const { return context_info_.get(); }
|
||||
PPCBuiltins* builtins() { return &builtins_; }
|
||||
|
||||
int DeclareFunction(FunctionInfo* symbol_info);
|
||||
int DefineFunction(FunctionInfo* symbol_info, uint32_t debug_info_flags,
|
||||
uint32_t trace_flags, Function** out_function);
|
||||
bool DeclareFunction(FunctionInfo* symbol_info);
|
||||
bool DefineFunction(FunctionInfo* symbol_info, uint32_t debug_info_flags,
|
||||
uint32_t trace_flags, Function** out_function);
|
||||
|
||||
private:
|
||||
Processor* processor_;
|
||||
|
|
|
@ -45,7 +45,7 @@ void PPCHIRBuilder::Reset() {
|
|||
HIRBuilder::Reset();
|
||||
}
|
||||
|
||||
int PPCHIRBuilder::Emit(FunctionInfo* symbol_info, uint32_t flags) {
|
||||
bool PPCHIRBuilder::Emit(FunctionInfo* symbol_info, uint32_t flags) {
|
||||
SCOPE_profile_cpu_f("cpu");
|
||||
|
||||
Memory* memory = frontend_->memory();
|
||||
|
@ -154,19 +154,19 @@ void PPCHIRBuilder::AnnotateLabel(uint32_t address, Label* label) {
|
|||
FunctionInfo* PPCHIRBuilder::LookupFunction(uint32_t address) {
|
||||
Processor* processor = frontend_->processor();
|
||||
FunctionInfo* symbol_info;
|
||||
if (processor->LookupFunctionInfo(address, &symbol_info)) {
|
||||
return NULL;
|
||||
if (!processor->LookupFunctionInfo(address, &symbol_info)) {
|
||||
return nullptr;
|
||||
}
|
||||
return symbol_info;
|
||||
}
|
||||
|
||||
Label* PPCHIRBuilder::LookupLabel(uint32_t address) {
|
||||
if (address < start_address_) {
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
size_t offset = (address - start_address_) / 4;
|
||||
if (offset >= instr_count_) {
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
Label* label = label_list_[offset];
|
||||
if (label) {
|
||||
|
|
|
@ -36,7 +36,7 @@ class PPCHIRBuilder : public hir::HIRBuilder {
|
|||
// Emit comment nodes.
|
||||
EMIT_DEBUG_COMMENTS = 1 << 0,
|
||||
};
|
||||
int Emit(FunctionInfo* symbol_info, uint32_t flags);
|
||||
bool Emit(FunctionInfo* symbol_info, uint32_t flags);
|
||||
|
||||
FunctionInfo* symbol_info() const { return symbol_info_; }
|
||||
FunctionInfo* LookupFunction(uint32_t address);
|
||||
|
|
|
@ -35,13 +35,13 @@ PPCScanner::~PPCScanner() {}
|
|||
|
||||
bool PPCScanner::IsRestGprLr(uint32_t address) {
|
||||
FunctionInfo* symbol_info;
|
||||
if (frontend_->processor()->LookupFunctionInfo(address, &symbol_info)) {
|
||||
if (!frontend_->processor()->LookupFunctionInfo(address, &symbol_info)) {
|
||||
return false;
|
||||
}
|
||||
return symbol_info->behavior() == FunctionInfo::BEHAVIOR_EPILOG_RETURN;
|
||||
}
|
||||
|
||||
int PPCScanner::FindExtents(FunctionInfo* symbol_info) {
|
||||
bool PPCScanner::Scan(FunctionInfo* symbol_info, DebugInfo* debug_info) {
|
||||
// This is a simple basic block analyizer. It walks the start address to the
|
||||
// end address looking for branches. Each span of instructions between
|
||||
// branches is considered a basic block. When the last blr (that has no
|
||||
|
@ -275,7 +275,7 @@ int PPCScanner::FindExtents(FunctionInfo* symbol_info) {
|
|||
// - record prolog/epilog lengths/stack size/etc
|
||||
|
||||
LOGPPC("Finished analyzing %.8X", start_address);
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<BlockInfo> PPCScanner::FindBlocks(FunctionInfo* symbol_info) {
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include <vector>
|
||||
|
||||
#include "xenia/cpu/debug_info.h"
|
||||
#include "xenia/cpu/symbol_info.h"
|
||||
|
||||
namespace xe {
|
||||
|
@ -30,7 +31,7 @@ class PPCScanner {
|
|||
PPCScanner(PPCFrontend* frontend);
|
||||
~PPCScanner();
|
||||
|
||||
int FindExtents(FunctionInfo* symbol_info);
|
||||
bool Scan(FunctionInfo* symbol_info, DebugInfo* debug_info);
|
||||
|
||||
std::vector<BlockInfo> FindBlocks(FunctionInfo* symbol_info);
|
||||
|
||||
|
|
|
@ -86,9 +86,9 @@ PPCTranslator::PPCTranslator(PPCFrontend* frontend) : frontend_(frontend) {
|
|||
|
||||
PPCTranslator::~PPCTranslator() = default;
|
||||
|
||||
int PPCTranslator::Translate(FunctionInfo* symbol_info,
|
||||
uint32_t debug_info_flags, uint32_t trace_flags,
|
||||
Function** out_function) {
|
||||
bool PPCTranslator::Translate(FunctionInfo* symbol_info,
|
||||
uint32_t debug_info_flags, uint32_t trace_flags,
|
||||
Function** out_function) {
|
||||
SCOPE_profile_cpu_f("cpu");
|
||||
|
||||
// Reset() all caching when we leave.
|
||||
|
@ -97,18 +97,6 @@ int PPCTranslator::Translate(FunctionInfo* symbol_info,
|
|||
xe::make_reset_scope(assembler_);
|
||||
xe::make_reset_scope(&string_buffer_);
|
||||
|
||||
// Scan the function to find its extents. We only need to do this if we
|
||||
// haven't already been provided with them from some other source.
|
||||
if (!symbol_info->has_end_address()) {
|
||||
// TODO(benvanik): find a way to remove the need for the scan. A fixup
|
||||
// scheme acting on branches could go back and modify calls to branches
|
||||
// if they are within the extents.
|
||||
int result = scanner_->FindExtents(symbol_info);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: we only want to do this when required, as it's expensive to build.
|
||||
if (FLAGS_always_disasm) {
|
||||
debug_info_flags |= DEBUG_INFO_ALL_DISASM;
|
||||
|
@ -118,6 +106,11 @@ int PPCTranslator::Translate(FunctionInfo* symbol_info,
|
|||
debug_info.reset(new DebugInfo());
|
||||
}
|
||||
|
||||
// Scan the function to find its extents and gather debug data.
|
||||
if (!scanner_->Scan(symbol_info, debug_info.get())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Stash source.
|
||||
if (debug_info_flags & DEBUG_INFO_SOURCE_DISASM) {
|
||||
DumpSource(symbol_info, &string_buffer_);
|
||||
|
@ -134,9 +127,8 @@ int PPCTranslator::Translate(FunctionInfo* symbol_info,
|
|||
if (debug_info) {
|
||||
emit_flags |= PPCHIRBuilder::EMIT_DEBUG_COMMENTS;
|
||||
}
|
||||
int result = builder_->Emit(symbol_info, emit_flags);
|
||||
if (result) {
|
||||
return result;
|
||||
if (!builder_->Emit(symbol_info, emit_flags)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Stash raw HIR.
|
||||
|
@ -147,9 +139,8 @@ int PPCTranslator::Translate(FunctionInfo* symbol_info,
|
|||
}
|
||||
|
||||
// Compile/optimize/etc.
|
||||
result = compiler_->Compile(builder_.get());
|
||||
if (result) {
|
||||
return result;
|
||||
if (!compiler_->Compile(builder_.get())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Stash optimized HIR.
|
||||
|
@ -160,14 +151,12 @@ int PPCTranslator::Translate(FunctionInfo* symbol_info,
|
|||
}
|
||||
|
||||
// Assemble to backend machine code.
|
||||
result =
|
||||
assembler_->Assemble(symbol_info, builder_.get(), debug_info_flags,
|
||||
std::move(debug_info), trace_flags, out_function);
|
||||
if (result) {
|
||||
return result;
|
||||
if (!assembler_->Assemble(symbol_info, builder_.get(), debug_info_flags,
|
||||
std::move(debug_info), trace_flags, out_function)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
};
|
||||
|
||||
void PPCTranslator::DumpSource(FunctionInfo* symbol_info,
|
||||
|
|
|
@ -30,8 +30,8 @@ class PPCTranslator {
|
|||
PPCTranslator(PPCFrontend* frontend);
|
||||
~PPCTranslator();
|
||||
|
||||
int Translate(FunctionInfo* symbol_info, uint32_t debug_info_flags,
|
||||
uint32_t trace_flags, Function** out_function);
|
||||
bool Translate(FunctionInfo* symbol_info, uint32_t debug_info_flags,
|
||||
uint32_t trace_flags, Function** out_function);
|
||||
|
||||
private:
|
||||
void DumpSource(FunctionInfo* symbol_info, StringBuffer* string_buffer);
|
||||
|
|
|
@ -188,7 +188,7 @@ class TestRunner {
|
|||
bool Setup(TestSuite& suite) {
|
||||
// Load the binary module.
|
||||
auto module = std::make_unique<xe::cpu::RawModule>(processor.get());
|
||||
if (module->LoadFile(START_ADDRESS, suite.bin_file_path)) {
|
||||
if (!module->LoadFile(START_ADDRESS, suite.bin_file_path)) {
|
||||
XELOGE("Unable to load test binary %ls", suite.bin_file_path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
@ -212,9 +212,8 @@ class TestRunner {
|
|||
}
|
||||
|
||||
// Execute test.
|
||||
xe::cpu::Function* fn;
|
||||
processor->ResolveFunction(test_case.address, &fn);
|
||||
if (!fn) {
|
||||
xe::cpu::Function* fn = nullptr;
|
||||
if (!processor->ResolveFunction(test_case.address, &fn)) {
|
||||
XELOGE("Entry function not found");
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ Function::Function(FunctionInfo* symbol_info)
|
|||
|
||||
Function::~Function() = default;
|
||||
|
||||
int Function::AddBreakpoint(Breakpoint* breakpoint) {
|
||||
bool Function::AddBreakpoint(Breakpoint* breakpoint) {
|
||||
std::lock_guard<std::mutex> guard(lock_);
|
||||
bool found = false;
|
||||
for (auto other : breakpoints_) {
|
||||
|
@ -32,25 +32,25 @@ int Function::AddBreakpoint(Breakpoint* breakpoint) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
if (found) {
|
||||
return true;
|
||||
} else {
|
||||
breakpoints_.push_back(breakpoint);
|
||||
AddBreakpointImpl(breakpoint);
|
||||
return AddBreakpointImpl(breakpoint);
|
||||
}
|
||||
return found ? 1 : 0;
|
||||
}
|
||||
|
||||
int Function::RemoveBreakpoint(Breakpoint* breakpoint) {
|
||||
bool Function::RemoveBreakpoint(Breakpoint* breakpoint) {
|
||||
std::lock_guard<std::mutex> guard(lock_);
|
||||
bool found = false;
|
||||
for (auto it = breakpoints_.begin(); it != breakpoints_.end(); ++it) {
|
||||
if (*it == breakpoint) {
|
||||
if (!RemoveBreakpointImpl(breakpoint)) {
|
||||
return false;
|
||||
}
|
||||
breakpoints_.erase(it);
|
||||
RemoveBreakpointImpl(breakpoint);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return found ? 0 : 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
Breakpoint* Function::FindBreakpoint(uint32_t address) {
|
||||
|
@ -65,7 +65,7 @@ Breakpoint* Function::FindBreakpoint(uint32_t address) {
|
|||
return result;
|
||||
}
|
||||
|
||||
int Function::Call(ThreadState* thread_state, uint32_t return_address) {
|
||||
bool Function::Call(ThreadState* thread_state, uint32_t return_address) {
|
||||
// SCOPE_profile_cpu_f("cpu");
|
||||
|
||||
ThreadState* original_thread_state = ThreadState::Get();
|
||||
|
@ -73,7 +73,7 @@ int Function::Call(ThreadState* thread_state, uint32_t return_address) {
|
|||
ThreadState::Bind(thread_state);
|
||||
}
|
||||
|
||||
int result = 0;
|
||||
bool result = true;
|
||||
|
||||
if (symbol_info_->behavior() == FunctionInfo::BEHAVIOR_EXTERN) {
|
||||
auto handler = symbol_info_->extern_handler();
|
||||
|
@ -84,7 +84,7 @@ int Function::Call(ThreadState* thread_state, uint32_t return_address) {
|
|||
} else {
|
||||
XELOGW("undefined extern call to %.8llX %s", symbol_info_->address(),
|
||||
symbol_info_->name().c_str());
|
||||
result = 1;
|
||||
result = false;
|
||||
}
|
||||
} else {
|
||||
CallImpl(thread_state, return_address);
|
||||
|
|
|
@ -36,16 +36,16 @@ class Function {
|
|||
debug_info_ = std::move(debug_info);
|
||||
}
|
||||
|
||||
int AddBreakpoint(debug::Breakpoint* breakpoint);
|
||||
int RemoveBreakpoint(debug::Breakpoint* breakpoint);
|
||||
bool AddBreakpoint(debug::Breakpoint* breakpoint);
|
||||
bool RemoveBreakpoint(debug::Breakpoint* breakpoint);
|
||||
|
||||
int Call(ThreadState* thread_state, uint32_t return_address);
|
||||
bool Call(ThreadState* thread_state, uint32_t return_address);
|
||||
|
||||
protected:
|
||||
debug::Breakpoint* FindBreakpoint(uint32_t address);
|
||||
virtual int AddBreakpointImpl(debug::Breakpoint* breakpoint) { return 0; }
|
||||
virtual int RemoveBreakpointImpl(debug::Breakpoint* breakpoint) { return 0; }
|
||||
virtual int CallImpl(ThreadState* thread_state, uint32_t return_address) = 0;
|
||||
virtual bool AddBreakpointImpl(debug::Breakpoint* breakpoint) { return 0; }
|
||||
virtual bool RemoveBreakpointImpl(debug::Breakpoint* breakpoint) { return 0; }
|
||||
virtual bool CallImpl(ThreadState* thread_state, uint32_t return_address) = 0;
|
||||
|
||||
protected:
|
||||
uint32_t address_;
|
||||
|
|
|
@ -51,7 +51,7 @@ void HIRBuilder::Reset() {
|
|||
arena_->Reset();
|
||||
}
|
||||
|
||||
int HIRBuilder::Finalize() {
|
||||
bool HIRBuilder::Finalize() {
|
||||
// Scan blocks in order and add fallthrough branches. These are needed for
|
||||
// analysis passes to work. We may have also added blocks out of order and
|
||||
// need to ensure they fall through in the right order.
|
||||
|
@ -84,7 +84,7 @@ int HIRBuilder::Finalize() {
|
|||
current_block_ = NULL;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void HIRBuilder::DumpValue(StringBuffer* str, Value* value) {
|
||||
|
|
|
@ -34,7 +34,7 @@ class HIRBuilder {
|
|||
virtual ~HIRBuilder();
|
||||
|
||||
virtual void Reset();
|
||||
virtual int Finalize();
|
||||
virtual bool Finalize();
|
||||
|
||||
void Dump(StringBuffer* str);
|
||||
void AssertNoCycles();
|
||||
|
|
|
@ -175,7 +175,7 @@ void Module::ForEachFunction(size_t since, size_t& version,
|
|||
}
|
||||
}
|
||||
|
||||
int Module::ReadMap(const char* file_name) {
|
||||
bool Module::ReadMap(const char* file_name) {
|
||||
std::ifstream infile(file_name);
|
||||
|
||||
// Skip until ' Address'. Skip the next blank line.
|
||||
|
@ -225,7 +225,7 @@ int Module::ReadMap(const char* file_name) {
|
|||
if (type_str == "f") {
|
||||
// Function.
|
||||
FunctionInfo* fn_info;
|
||||
if (processor_->LookupFunctionInfo(this, address, &fn_info)) {
|
||||
if (!processor_->LookupFunctionInfo(this, address, &fn_info)) {
|
||||
continue;
|
||||
}
|
||||
// Don't overwrite names we've set elsewhere.
|
||||
|
@ -243,7 +243,7 @@ int Module::ReadMap(const char* file_name) {
|
|||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace cpu
|
||||
|
|
|
@ -49,7 +49,7 @@ class Module {
|
|||
void ForEachFunction(size_t since, size_t& version,
|
||||
std::function<void(FunctionInfo*)> callback);
|
||||
|
||||
int ReadMap(const char* file_name);
|
||||
bool ReadMap(const char* file_name);
|
||||
|
||||
private:
|
||||
SymbolInfo::Status DeclareSymbol(SymbolInfo::Type type, uint32_t address,
|
||||
|
|
|
@ -98,7 +98,7 @@ Processor::~Processor() {
|
|||
backend_.reset();
|
||||
}
|
||||
|
||||
int Processor::Setup() {
|
||||
bool Processor::Setup() {
|
||||
debug_info_flags_ = DEBUG_INFO_DEFAULT;
|
||||
trace_flags_ = 0;
|
||||
|
||||
|
@ -116,7 +116,7 @@ int Processor::Setup() {
|
|||
modules_.push_back(std::move(builtin_module));
|
||||
|
||||
if (frontend_ || backend_) {
|
||||
return 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<xe::cpu::backend::Backend> backend;
|
||||
|
@ -136,17 +136,13 @@ int Processor::Setup() {
|
|||
}
|
||||
|
||||
if (!backend) {
|
||||
return 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
int result = backend->Initialize();
|
||||
if (result) {
|
||||
return result;
|
||||
if (!backend->Initialize()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
result = frontend->Initialize();
|
||||
if (result) {
|
||||
return result;
|
||||
if (!frontend->Initialize()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
backend_ = std::move(backend);
|
||||
|
@ -157,13 +153,13 @@ int Processor::Setup() {
|
|||
interrupt_thread_block_ = memory_->SystemHeapAlloc(2048);
|
||||
interrupt_thread_state_->context()->r[13] = interrupt_thread_block_;
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
int Processor::AddModule(std::unique_ptr<Module> module) {
|
||||
bool Processor::AddModule(std::unique_ptr<Module> module) {
|
||||
std::lock_guard<std::mutex> guard(modules_lock_);
|
||||
modules_.push_back(std::move(module));
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
Module* Processor::GetModule(const char* name) {
|
||||
|
@ -205,7 +201,7 @@ std::vector<Function*> Processor::FindFunctionsWithAddress(uint32_t address) {
|
|||
return entry_table_.FindWithAddress(address);
|
||||
}
|
||||
|
||||
int Processor::ResolveFunction(uint32_t address, Function** out_function) {
|
||||
bool Processor::ResolveFunction(uint32_t address, Function** out_function) {
|
||||
*out_function = nullptr;
|
||||
Entry* entry;
|
||||
Entry::Status status = entry_table_.GetOrCreate(address, &entry);
|
||||
|
@ -214,15 +210,13 @@ int Processor::ResolveFunction(uint32_t address, Function** out_function) {
|
|||
|
||||
// Grab symbol declaration.
|
||||
FunctionInfo* symbol_info;
|
||||
int result = LookupFunctionInfo(address, &symbol_info);
|
||||
if (result) {
|
||||
return result;
|
||||
if (!LookupFunctionInfo(address, &symbol_info)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
result = DemandFunction(symbol_info, &entry->function);
|
||||
if (result) {
|
||||
if (!DemandFunction(symbol_info, &entry->function)) {
|
||||
entry->status = Entry::STATUS_FAILED;
|
||||
return result;
|
||||
return false;
|
||||
}
|
||||
entry->end_address = symbol_info->end_address();
|
||||
status = entry->status = Entry::STATUS_READY;
|
||||
|
@ -230,15 +224,15 @@ int Processor::ResolveFunction(uint32_t address, Function** out_function) {
|
|||
if (status == Entry::STATUS_READY) {
|
||||
// Ready to use.
|
||||
*out_function = entry->function;
|
||||
return 0;
|
||||
return true;
|
||||
} else {
|
||||
// Failed or bad state.
|
||||
return 1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int Processor::LookupFunctionInfo(uint32_t address,
|
||||
FunctionInfo** out_symbol_info) {
|
||||
bool Processor::LookupFunctionInfo(uint32_t address,
|
||||
FunctionInfo** out_symbol_info) {
|
||||
*out_symbol_info = nullptr;
|
||||
|
||||
// TODO(benvanik): fast reject invalid addresses/log errors.
|
||||
|
@ -258,14 +252,14 @@ int Processor::LookupFunctionInfo(uint32_t address,
|
|||
}
|
||||
if (!code_module) {
|
||||
// No module found that could contain the address.
|
||||
return 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
return LookupFunctionInfo(code_module, address, out_symbol_info);
|
||||
}
|
||||
|
||||
int Processor::LookupFunctionInfo(Module* module, uint32_t address,
|
||||
FunctionInfo** out_symbol_info) {
|
||||
bool Processor::LookupFunctionInfo(Module* module, uint32_t address,
|
||||
FunctionInfo** out_symbol_info) {
|
||||
// Atomic create/lookup symbol in module.
|
||||
// If we get back the NEW flag we must declare it now.
|
||||
FunctionInfo* symbol_info = nullptr;
|
||||
|
@ -273,20 +267,19 @@ int Processor::LookupFunctionInfo(Module* module, uint32_t address,
|
|||
module->DeclareFunction(address, &symbol_info);
|
||||
if (symbol_status == SymbolInfo::STATUS_NEW) {
|
||||
// Symbol is undeclared, so declare now.
|
||||
int result = frontend_->DeclareFunction(symbol_info);
|
||||
if (result) {
|
||||
if (!frontend_->DeclareFunction(symbol_info)) {
|
||||
symbol_info->set_status(SymbolInfo::STATUS_FAILED);
|
||||
return 1;
|
||||
return false;
|
||||
}
|
||||
symbol_info->set_status(SymbolInfo::STATUS_DECLARED);
|
||||
}
|
||||
|
||||
*out_symbol_info = symbol_info;
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
int Processor::DemandFunction(FunctionInfo* symbol_info,
|
||||
Function** out_function) {
|
||||
bool Processor::DemandFunction(FunctionInfo* symbol_info,
|
||||
Function** out_function) {
|
||||
*out_function = nullptr;
|
||||
|
||||
// Lock function for generation. If it's already being generated
|
||||
|
@ -296,11 +289,10 @@ int Processor::DemandFunction(FunctionInfo* symbol_info,
|
|||
if (symbol_status == SymbolInfo::STATUS_NEW) {
|
||||
// Symbol is undefined, so define now.
|
||||
Function* function = nullptr;
|
||||
int result = frontend_->DefineFunction(symbol_info, debug_info_flags_,
|
||||
trace_flags_, &function);
|
||||
if (result) {
|
||||
if (!frontend_->DefineFunction(symbol_info, debug_info_flags_, trace_flags_,
|
||||
&function)) {
|
||||
symbol_info->set_status(SymbolInfo::STATUS_FAILED);
|
||||
return result;
|
||||
return false;
|
||||
}
|
||||
symbol_info->set_function(function);
|
||||
|
||||
|
@ -313,23 +305,23 @@ int Processor::DemandFunction(FunctionInfo* symbol_info,
|
|||
|
||||
if (symbol_status == SymbolInfo::STATUS_FAILED) {
|
||||
// Symbol likely failed.
|
||||
return 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
*out_function = symbol_info->function();
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
int Processor::Execute(ThreadState* thread_state, uint32_t address) {
|
||||
bool Processor::Execute(ThreadState* thread_state, uint32_t address) {
|
||||
SCOPE_profile_cpu_f("cpu");
|
||||
|
||||
// Attempt to get the function.
|
||||
Function* fn;
|
||||
if (ResolveFunction(address, &fn)) {
|
||||
if (!ResolveFunction(address, &fn)) {
|
||||
// Symbol not found in any module.
|
||||
XELOGCPU("Execute(%.8X): failed to find function", address);
|
||||
return 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
PPCContext* context = thread_state->context();
|
||||
|
@ -342,8 +334,7 @@ int Processor::Execute(ThreadState* thread_state, uint32_t address) {
|
|||
context->lr = lr;
|
||||
|
||||
// Execute the function.
|
||||
fn->Call(thread_state, lr);
|
||||
return 0;
|
||||
return fn->Call(thread_state, lr);
|
||||
}
|
||||
|
||||
uint64_t Processor::Execute(ThreadState* thread_state, uint32_t address,
|
||||
|
@ -355,7 +346,7 @@ uint64_t Processor::Execute(ThreadState* thread_state, uint32_t address,
|
|||
for (size_t i = 0; i < arg_count; ++i) {
|
||||
context->r[3 + i] = args[i];
|
||||
}
|
||||
if (Execute(thread_state, address)) {
|
||||
if (!Execute(thread_state, address)) {
|
||||
return 0xDEADBABE;
|
||||
}
|
||||
return context->r[3];
|
||||
|
|
|
@ -52,9 +52,9 @@ class Processor {
|
|||
backend::Backend* backend() const { return backend_.get(); }
|
||||
ExportResolver* export_resolver() const { return export_resolver_; }
|
||||
|
||||
int Setup();
|
||||
bool Setup();
|
||||
|
||||
int AddModule(std::unique_ptr<Module> module);
|
||||
bool AddModule(std::unique_ptr<Module> module);
|
||||
Module* GetModule(const char* name);
|
||||
Module* GetModule(const std::string& name) { return GetModule(name.c_str()); }
|
||||
std::vector<Module*> GetModules();
|
||||
|
@ -66,12 +66,12 @@ class Processor {
|
|||
|
||||
std::vector<Function*> FindFunctionsWithAddress(uint32_t address);
|
||||
|
||||
int LookupFunctionInfo(uint32_t address, FunctionInfo** out_symbol_info);
|
||||
int LookupFunctionInfo(Module* module, uint32_t address,
|
||||
FunctionInfo** out_symbol_info);
|
||||
int ResolveFunction(uint32_t address, Function** out_function);
|
||||
bool LookupFunctionInfo(uint32_t address, FunctionInfo** out_symbol_info);
|
||||
bool LookupFunctionInfo(Module* module, uint32_t address,
|
||||
FunctionInfo** out_symbol_info);
|
||||
bool ResolveFunction(uint32_t address, Function** out_function);
|
||||
|
||||
int Execute(ThreadState* thread_state, uint32_t address);
|
||||
bool Execute(ThreadState* thread_state, uint32_t address);
|
||||
uint64_t Execute(ThreadState* thread_state, uint32_t address, uint64_t args[],
|
||||
size_t arg_count);
|
||||
|
||||
|
@ -82,7 +82,7 @@ class Processor {
|
|||
size_t arg_count);
|
||||
|
||||
private:
|
||||
int DemandFunction(FunctionInfo* symbol_info, Function** out_function);
|
||||
bool DemandFunction(FunctionInfo* symbol_info, Function** out_function);
|
||||
|
||||
Memory* memory_;
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ RawModule::RawModule(Processor* processor)
|
|||
|
||||
RawModule::~RawModule() {}
|
||||
|
||||
int RawModule::LoadFile(uint32_t base_address, const std::wstring& path) {
|
||||
bool RawModule::LoadFile(uint32_t base_address, const std::wstring& path) {
|
||||
auto fixed_path = xe::to_string(xe::fix_path_separators(path));
|
||||
FILE* file = fopen(fixed_path.c_str(), "rb");
|
||||
fseek(file, 0, SEEK_END);
|
||||
|
@ -49,7 +49,7 @@ int RawModule::LoadFile(uint32_t base_address, const std::wstring& path) {
|
|||
|
||||
low_address_ = base_address;
|
||||
high_address_ = base_address + file_length;
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RawModule::ContainsAddress(uint32_t address) {
|
||||
|
|
|
@ -22,7 +22,7 @@ class RawModule : public Module {
|
|||
RawModule(Processor* processor);
|
||||
~RawModule() override;
|
||||
|
||||
int LoadFile(uint32_t base_address, const std::wstring& path);
|
||||
bool LoadFile(uint32_t base_address, const std::wstring& path);
|
||||
|
||||
const std::string& name() const override { return name_; }
|
||||
|
||||
|
|
|
@ -36,9 +36,9 @@ class ThreadState {
|
|||
uint32_t thread_state_address() const { return thread_state_address_; }
|
||||
xe::cpu::frontend::PPCContext* context() const { return context_; }
|
||||
|
||||
int Suspend() { return Suspend(~0); }
|
||||
int Suspend(uint32_t timeout_ms) { return 1; }
|
||||
int Resume(bool force = false) { return 1; }
|
||||
bool Suspend() { return Suspend(~0); }
|
||||
bool Suspend(uint32_t timeout_ms) { return false; }
|
||||
bool Resume(bool force = false) { return false; }
|
||||
|
||||
static void Bind(ThreadState* thread_state);
|
||||
static ThreadState* Get();
|
||||
|
|
|
@ -40,10 +40,8 @@ XexModule::XexModule(Processor* processor)
|
|||
|
||||
XexModule::~XexModule() { xe_xex2_dealloc(xex_); }
|
||||
|
||||
int XexModule::Load(const std::string& name, const std::string& path,
|
||||
xe_xex2_ref xex) {
|
||||
int result;
|
||||
|
||||
bool XexModule::Load(const std::string& name, const std::string& path,
|
||||
xe_xex2_ref xex) {
|
||||
xex_ = xex;
|
||||
const xe_xex2_header_t* header = xe_xex2_get_header(xex);
|
||||
|
||||
|
@ -66,17 +64,15 @@ int XexModule::Load(const std::string& name, const std::string& path,
|
|||
|
||||
// Add all imports (variables/functions).
|
||||
for (size_t n = 0; n < header->import_library_count; n++) {
|
||||
result = SetupLibraryImports(&header->import_libraries[n]);
|
||||
if (result) {
|
||||
return result;
|
||||
if (!SetupLibraryImports(&header->import_libraries[n])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Find __savegprlr_* and __restgprlr_* and the others.
|
||||
// We can flag these for special handling (inlining/etc).
|
||||
result = FindSaveRest();
|
||||
if (result) {
|
||||
return result;
|
||||
if (!FindSaveRest()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Setup debug info.
|
||||
|
@ -86,20 +82,22 @@ int XexModule::Load(const std::string& name, const std::string& path,
|
|||
|
||||
// Load a specified module map and diff.
|
||||
if (FLAGS_load_module_map.size()) {
|
||||
ReadMap(FLAGS_load_module_map.c_str());
|
||||
if (!ReadMap(FLAGS_load_module_map.c_str())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
int XexModule::SetupLibraryImports(const xe_xex2_import_library_t* library) {
|
||||
bool XexModule::SetupLibraryImports(const xe_xex2_import_library_t* library) {
|
||||
ExportResolver* export_resolver = processor_->export_resolver();
|
||||
|
||||
xe_xex2_import_info_t* import_infos;
|
||||
size_t import_info_count;
|
||||
if (xe_xex2_get_import_infos(xex_, library, &import_infos,
|
||||
&import_info_count)) {
|
||||
return 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
char name[128];
|
||||
|
@ -203,14 +201,14 @@ int XexModule::SetupLibraryImports(const xe_xex2_import_library_t* library) {
|
|||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool XexModule::ContainsAddress(uint32_t address) {
|
||||
return address >= low_address_ && address < high_address_;
|
||||
}
|
||||
|
||||
int XexModule::FindSaveRest() {
|
||||
bool XexModule::FindSaveRest() {
|
||||
// Special stack save/restore functions.
|
||||
// http://research.microsoft.com/en-us/um/redmond/projects/invisible/src/crt/md/ppc/xxx.s.htm
|
||||
// It'd be nice to stash these away and mark them as such to allow for
|
||||
|
@ -523,7 +521,7 @@ int XexModule::FindSaveRest() {
|
|||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace cpu
|
||||
|
|
|
@ -27,16 +27,16 @@ class XexModule : public xe::cpu::Module {
|
|||
|
||||
xe_xex2_ref xex() const { return xex_; }
|
||||
|
||||
int Load(const std::string& name, const std::string& path, xe_xex2_ref xex);
|
||||
bool Load(const std::string& name, const std::string& path, xe_xex2_ref xex);
|
||||
|
||||
const std::string& name() const override { return name_; }
|
||||
|
||||
bool ContainsAddress(uint32_t address) override;
|
||||
|
||||
private:
|
||||
int SetupImports(xe_xex2_ref xex);
|
||||
int SetupLibraryImports(const xe_xex2_import_library_t* library);
|
||||
int FindSaveRest();
|
||||
bool SetupImports(xe_xex2_ref xex);
|
||||
bool SetupLibraryImports(const xe_xex2_import_library_t* library);
|
||||
bool FindSaveRest();
|
||||
|
||||
private:
|
||||
Processor* processor_;
|
||||
|
|
|
@ -5,7 +5,5 @@
|
|||
'debug_server.h',
|
||||
'debugger.cc',
|
||||
'debugger.h',
|
||||
'trace_writer.cc',
|
||||
'trace_writer.h',
|
||||
],
|
||||
}
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2015 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/debug/trace_writer.h"
|
||||
|
||||
namespace xe {
|
||||
namespace debug {
|
||||
|
||||
//
|
||||
|
||||
} // namespace debug
|
||||
} // namespace xe
|
|
@ -1,29 +0,0 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2015 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_DEBUG_TRACE_WRITER_H_
|
||||
#define XENIA_DEBUG_TRACE_WRITER_H_
|
||||
|
||||
namespace xe {
|
||||
namespace debug {
|
||||
|
||||
enum TraceFlags {
|
||||
kTraceFunctionInfo = 1 << 0,
|
||||
kTraceInstructionReferences = 1 << 1,
|
||||
kTraceInstructionResults = 1 << 2,
|
||||
};
|
||||
|
||||
class TraceWriter {
|
||||
public:
|
||||
};
|
||||
|
||||
} // namespace debug
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_DEBUG_TRACE_WRITER_H_
|
|
@ -100,8 +100,7 @@ X_STATUS Emulator::Setup() {
|
|||
}
|
||||
|
||||
// Setup the core components.
|
||||
result = processor_->Setup();
|
||||
if (result) {
|
||||
if (!processor_->Setup()) {
|
||||
return result;
|
||||
}
|
||||
result = audio_system_->Setup();
|
||||
|
|
|
@ -130,10 +130,10 @@ X_STATUS XUserModule::LoadFromMemory(const void* addr, const size_t length) {
|
|||
// Prepare the module for execution.
|
||||
// Runtime takes ownership.
|
||||
auto xex_module = std::make_unique<XexModule>(processor);
|
||||
if (xex_module->Load(name_, path_, xex_)) {
|
||||
if (!xex_module->Load(name_, path_, xex_)) {
|
||||
return X_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
if (processor->AddModule(std::move(xex_module))) {
|
||||
if (!processor->AddModule(std::move(xex_module))) {
|
||||
return X_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue