Cleanup and tracing.

This commit is contained in:
Ben Vanik 2013-05-23 23:22:27 -07:00
parent d7d0b94aab
commit 74ae66aa0a
2 changed files with 144 additions and 129 deletions

View File

@ -51,6 +51,9 @@ DEFINE_bool(log_codegen, false,
X64Emitter::X64Emitter(xe_memory_ref memory) {
memory_ = memory;
// I don't like doing this, but there's no public access to these members.
assembler_._properties = compiler_._properties;
// Grab global exports.
cpu::GetGlobalExports(&global_exports_);
@ -117,9 +120,11 @@ int X64Emitter::PrepareFunction(FunctionSymbol* symbol) {
// Arguments passed as RCX, RDX, R8, R9
assembler_.push(rcx); // ppc_state
assembler_.push(rdx); // lr
assembler_.mov(rcx, (uint64_t)this);
assembler_.mov(rdx, (uint64_t)symbol);
assembler_.sub(rsp, imm(0x20));
assembler_.mov(rcx, imm((uint64_t)this));
assembler_.mov(rdx, imm((uint64_t)symbol));
assembler_.call(X64Emitter::OnDemandCompileTrampoline);
assembler_.add(rsp, imm(0x20));
assembler_.pop(rdx); // lr
assembler_.pop(rcx); // ppc_state
assembler_.jmp(rax);
@ -128,9 +133,11 @@ int X64Emitter::PrepareFunction(FunctionSymbol* symbol) {
// Arguments passed as RDI, RSI, RDX, RCX, R8, R9
assembler_.push(rdi); // ppc_state
assembler_.push(rsi); // lr
assembler_.mov(rdi, (uint64_t)this);
assembler_.mov(rsi, (uint64_t)symbol);
assembler_.sub(rsp, imm(0x20));
assembler_.mov(rdi, imm((uint64_t)this));
assembler_.mov(rsi, imm((uint64_t)symbol));
assembler_.call(X64Emitter::OnDemandCompileTrampoline);
assembler_.add(rsp, imm(0x20));
assembler_.pop(rsi); // lr
assembler_.pop(rdi); // ppc_state
assembler_.jmp(rax);
@ -244,9 +251,6 @@ int X64Emitter::MakeFunction(FunctionSymbol* symbol) {
//compiler_.setPriority(compiler_.getGpArg(0), 100);
switch (symbol->type) {
case FunctionSymbol::User:
result_code = MakeUserFunction();
break;
case FunctionSymbol::Kernel:
if (symbol->kernel_export && symbol->kernel_export->is_implemented) {
result_code = MakePresentImportFunction();
@ -254,6 +258,9 @@ int X64Emitter::MakeFunction(FunctionSymbol* symbol) {
result_code = MakeMissingImportFunction();
}
break;
case FunctionSymbol::User:
result_code = MakeUserFunction();
break;
default:
XEASSERTALWAYS();
result_code = 1;
@ -263,10 +270,6 @@ int X64Emitter::MakeFunction(FunctionSymbol* symbol) {
compiler_.endFunc();
// I don't like doing this, but there's no public access to these members.
assembler_._properties = compiler_._properties;
assembler_.setLogger(compiler_.getLogger());
// Serialize to the assembler.
compiler_.serialize(assembler_);
if (compiler_.getError()) {
@ -311,48 +314,8 @@ XECLEANUP:
return result_code;
}
int X64Emitter::MakeUserFunction() {
// if (FLAGS_trace_user_calls) {
// jit_value_t trace_args[] = {
// jit_value_get_param(fn_, 0),
// jit_value_create_long_constant(fn_, jit_type_ulong,
// (jit_ulong)symbol_->start_address),
// jit_value_get_param(fn_, 1),
// jit_value_create_long_constant(fn_, jit_type_ulong,
// (jit_ulong)symbol_),
// };
// jit_insn_call_native(
// fn_,
// "XeTraceUserCall",
// global_exports_.XeTraceUserCall,
// global_export_signature_4_,
// trace_args, XECOUNT(trace_args),
// 0);
// }
// Emit.
GenerateBasicBlocks();
return 0;
}
int X64Emitter::MakePresentImportFunction() {
// if (FLAGS_trace_kernel_calls) {
// jit_value_t trace_args[] = {
// jit_value_get_param(fn_, 0),
// jit_value_create_long_constant(fn_, jit_type_ulong,
// (jit_ulong)symbol_->start_address),
// jit_value_get_param(fn_, 1),
// jit_value_create_long_constant(fn_, jit_type_ulong,
// (jit_ulong)symbol_->kernel_export),
// };
// jit_insn_call_native(
// fn_,
// "XeTraceKernelCall",
// global_exports_.XeTraceKernelCall,
// global_export_signature_4_,
// trace_args, XECOUNT(trace_args),
// 0);
// }
TraceKernelCall();
// // void shim(ppc_state*, shim_data*)
// jit_value_t shim_args[] = {
@ -374,46 +337,21 @@ int X64Emitter::MakePresentImportFunction() {
}
int X64Emitter::MakeMissingImportFunction() {
// if (FLAGS_trace_kernel_calls) {
// jit_value_t trace_args[] = {
// jit_value_get_param(fn_, 0),
// jit_value_create_long_constant(fn_, jit_type_ulong,
// (jit_ulong)symbol_->start_address),
// jit_value_get_param(fn_, 1),
// jit_value_create_long_constant(fn_, jit_type_ulong,
// (jit_ulong)symbol_->kernel_export),
// };
// jit_insn_call_native(
// fn_,
// "XeTraceKernelCall",
// global_exports_.XeTraceKernelCall,
// global_export_signature_4_,
// trace_args, XECOUNT(trace_args),
// 0);
// }
TraceKernelCall();
// TODO(benvanik): log better?
// jit_insn_return(fn_, NULL);
return 0;
}
X86Compiler& X64Emitter::compiler() {
return compiler_;
}
int X64Emitter::MakeUserFunction() {
TraceUserCall();
FunctionSymbol* X64Emitter::symbol() {
return symbol_;
}
FunctionBlock* X64Emitter::fn_block() {
return fn_block_;
}
void X64Emitter::GenerateBasicBlocks() {
// If this function is empty, abort!
if (!symbol_->blocks.size()) {
// jit_insn_return(fn_, NULL);
return;
return 0;
}
// Pass 1 creates all of the labels - this way we can branch to them.
@ -445,6 +383,20 @@ void X64Emitter::GenerateBasicBlocks() {
// Setup the shared return/indirection/etc blocks now that we know all the
// blocks we need and all the registers used.
GenerateSharedBlocks();
return 0;
}
X86Compiler& X64Emitter::compiler() {
return compiler_;
}
FunctionSymbol* X64Emitter::symbol() {
return symbol_;
}
FunctionBlock* X64Emitter::fn_block() {
return fn_block_;
}
void X64Emitter::GenerateSharedBlocks() {
@ -558,39 +510,15 @@ void X64Emitter::GenerateBasicBlock(FunctionBlock* block) {
i.code = XEGETUINT32BE(p + ia);
i.type = ppc::GetInstrType(i.code);
// jit_value_t trace_args[] = {
// jit_value_get_param(fn_, 0),
// jit_value_create_long_constant(fn_, jit_type_ulong,
// (jit_ulong)i.address),
// jit_value_create_long_constant(fn_, jit_type_ulong,
// (jit_ulong)i.code),
// };
// Add debugging tag.
// TODO(benvanik): mark type.
//jit_insn_mark_breakpoint(fn_, 1, ia);
if (FLAGS_trace_instructions) {
SpillRegisters();
// jit_insn_call_native(
// fn_,
// "XeTraceInstruction",
// global_exports_.XeTraceInstruction,
// global_export_signature_3_,
// trace_args, XECOUNT(trace_args),
// 0);
}
TraceInstruction(i);
if (!i.type) {
XELOGCPU("Invalid instruction %.8X %.8X", ia, i.code);
SpillRegisters();
// jit_insn_call_native(
// fn_,
// "XeInvalidInstruction",
// global_exports_.XeInvalidInstruction,
// global_export_signature_3_,
// trace_args, XECOUNT(trace_args),
// 0);
TraceInvalidInstruction(i);
continue;
}
@ -614,14 +542,7 @@ void X64Emitter::GenerateBasicBlock(FunctionBlock* block) {
XELOGCPU("Unimplemented instr %.8X %.8X %s",
ia, i.code, i.type->name);
SpillRegisters();
// jit_insn_call_native(
// fn_,
// "XeInvalidInstruction",
// global_exports_.XeInvalidInstruction,
// global_export_signature_3_,
// trace_args, XECOUNT(trace_args),
// 0);
TraceInvalidInstruction(i);
}
}
@ -824,7 +745,99 @@ void X64Emitter::GenerateBasicBlock(FunctionBlock* block) {
// return 1;
// }
void X64Emitter::TraceKernelCall() {
X86Compiler& c = compiler_;
if (!FLAGS_trace_kernel_calls) {
return;
}
SpillRegisters();
GpVar arg1 = c.newGpVar(kX86VarTypeGpd);
c.mov(arg1, imm((uint64_t)symbol_->start_address));
GpVar arg3 = c.newGpVar(kX86VarTypeGpd);
c.mov(arg3, imm((uint64_t)symbol_->kernel_export));
X86CompilerFuncCall* call = c.call(global_exports_.XeTraceKernelCall);
call->setComment("XeTraceKernelCall");
call->setPrototype(kX86FuncConvDefault,
FuncBuilder4<void, void*, uint64_t, uint64_t, uint64_t>());
call->setArgument(0, c.getGpArg(0));
call->setArgument(1, arg1);
call->setArgument(2, c.getGpArg(1));
call->setArgument(3, arg3);
}
void X64Emitter::TraceUserCall() {
X86Compiler& c = compiler_;
if (!FLAGS_trace_user_calls) {
return;
}
SpillRegisters();
GpVar arg1 = c.newGpVar(kX86VarTypeGpd);
c.mov(arg1, imm((uint64_t)symbol_->start_address));
GpVar arg3 = c.newGpVar(kX86VarTypeGpd);
c.mov(arg3, imm((uint64_t)symbol_));
X86CompilerFuncCall* call = c.call(global_exports_.XeTraceUserCall);
call->setComment("XeTraceUserCall");
call->setPrototype(kX86FuncConvDefault,
FuncBuilder4<void, void*, uint64_t, uint64_t, uint64_t>());
call->setArgument(0, c.getGpArg(0));
call->setArgument(1, arg1);
call->setArgument(2, c.getGpArg(1));
call->setArgument(3, arg3);
}
void X64Emitter::TraceInstruction(InstrData& i) {
X86Compiler& c = compiler_;
if (!FLAGS_trace_instructions) {
return;
}
SpillRegisters();
GpVar arg1 = c.newGpVar(kX86VarTypeGpd);
c.mov(arg1, imm((uint64_t)i.address));
GpVar arg2 = c.newGpVar(kX86VarTypeGpd);
c.mov(arg2, imm((uint64_t)i.code));
X86CompilerFuncCall* call = c.call(global_exports_.XeTraceInstruction);
call->setComment("XeTraceInstruction");
call->setPrototype(kX86FuncConvDefault,
FuncBuilder3<void, void*, uint64_t, uint64_t>());
call->setArgument(0, c.getGpArg(0));
call->setArgument(1, arg1);
call->setArgument(2, arg2);
}
void X64Emitter::TraceInvalidInstruction(InstrData& i) {
X86Compiler& c = compiler_;
SpillRegisters();
GpVar arg1 = c.newGpVar(kX86VarTypeGpd);
c.mov(arg1, imm((uint64_t)i.address));
GpVar arg2 = c.newGpVar(kX86VarTypeGpd);
c.mov(arg2, imm((uint64_t)i.code));
X86CompilerFuncCall* call = c.call(global_exports_.XeInvalidInstruction);
call->setComment("XeInvalidInstruction");
call->setPrototype(kX86FuncConvDefault,
FuncBuilder3<void, void*, uint64_t, uint64_t>());
call->setArgument(0, c.getGpArg(0));
call->setArgument(1, arg1);
call->setArgument(2, arg2);
}
void X64Emitter::TraceBranch(uint32_t cia) {
X86Compiler& c = compiler_;
if (!FLAGS_trace_branches) {
return;
}
SpillRegisters();
// Pick target. If it's an indirection the tracing function will handle it.
@ -848,18 +861,17 @@ void X64Emitter::TraceBranch(uint32_t cia) {
break;
}
// jit_value_t trace_args[] = {
// jit_value_get_param(fn_, 0),
// jit_value_create_long_constant(fn_, jit_type_ulong, cia),
// jit_value_create_long_constant(fn_, jit_type_ulong, target),
// };
// jit_insn_call_native(
// fn_,
// "XeTraceBranch",
// global_exports_.XeTraceBranch,
// global_export_signature_3_,
// trace_args, XECOUNT(trace_args),
// 0);
GpVar arg1 = c.newGpVar(kX86VarTypeGpd);
c.mov(arg1, imm((uint64_t)cia));
GpVar arg2 = c.newGpVar(kX86VarTypeGpd);
c.mov(arg2, imm((uint64_t)target));
X86CompilerFuncCall* call = c.call(global_exports_.XeTraceBranch);
call->setComment("XeTraceBranch");
call->setPrototype(kX86FuncConvDefault,
FuncBuilder3<void, void*, uint64_t, uint64_t>());
call->setArgument(0, c.getGpArg(0));
call->setArgument(1, arg1);
call->setArgument(2, arg2);
}
// int X64Emitter::GenerateIndirectionBranch(uint32_t cia, jit_value_t target,

View File

@ -63,6 +63,10 @@ public:
// int call_function(sdb::FunctionSymbol* target_symbol, jit_value_t lr,
// bool tail);
void TraceKernelCall();
void TraceUserCall();
void TraceInstruction(ppc::InstrData& i);
void TraceInvalidInstruction(ppc::InstrData& i);
void TraceBranch(uint32_t cia);
// int GenerateIndirectionBranch(uint32_t cia, jit_value_t target,
@ -113,7 +117,6 @@ private:
int MakePresentImportFunction();
int MakeMissingImportFunction();
void GenerateBasicBlocks();
void GenerateSharedBlocks();
int PrepareBasicBlock(sdb::FunctionBlock* block);
void GenerateBasicBlock(sdb::FunctionBlock* block);