Mostly complete tracing. Probably a lot of bugs.
This commit is contained in:
@@ -43,6 +43,7 @@ class Assembler {
|
||||
virtual int Assemble(runtime::FunctionInfo* symbol_info,
|
||||
hir::HIRBuilder* builder, uint32_t debug_info_flags,
|
||||
std::unique_ptr<runtime::DebugInfo> debug_info,
|
||||
uint32_t trace_flags,
|
||||
runtime::Function** out_function) = 0;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -50,7 +50,7 @@ void IVMAssembler::Reset() {
|
||||
int IVMAssembler::Assemble(FunctionInfo* symbol_info, HIRBuilder* builder,
|
||||
uint32_t debug_info_flags,
|
||||
std::unique_ptr<DebugInfo> debug_info,
|
||||
Function** out_function) {
|
||||
uint32_t trace_flags, Function** out_function) {
|
||||
SCOPE_profile_cpu_f("alloy");
|
||||
|
||||
// Reset when we leave.
|
||||
|
||||
@@ -31,7 +31,7 @@ class IVMAssembler : public Assembler {
|
||||
int Assemble(runtime::FunctionInfo* symbol_info, hir::HIRBuilder* builder,
|
||||
uint32_t debug_info_flags,
|
||||
std::unique_ptr<runtime::DebugInfo> debug_info,
|
||||
runtime::Function** out_function) override;
|
||||
uint32_t trace_flags, runtime::Function** out_function) override;
|
||||
|
||||
private:
|
||||
Arena intcode_arena_;
|
||||
|
||||
@@ -11,11 +11,12 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <poly/poly.h>
|
||||
#include <alloy/hir/label.h>
|
||||
#include <alloy/runtime/runtime.h>
|
||||
#include <alloy/runtime/symbol_info.h>
|
||||
#include <alloy/runtime/thread_state.h>
|
||||
#include <poly/poly.h>
|
||||
#include <xdb/protocol.h>
|
||||
|
||||
// TODO(benvanik): make a compile time flag?
|
||||
//#define DYNAMIC_REGISTER_ACCESS_CHECK(address) false
|
||||
@@ -246,6 +247,22 @@ int Translate_SOURCE_OFFSET(TranslationContext& ctx, Instr* i) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO(benvanik): dispatch of register forms.
|
||||
uint32_t IntCode_TRACE_SOURCE(IntCodeState& ics, const IntCode* i) {
|
||||
// TODO(benvanik): append to active trace writer.
|
||||
uint64_t trace_base = ics.thread_state->memory()->trace_base();
|
||||
if (trace_base) {
|
||||
auto ev = xdb::protocol::InstrEvent::Append(trace_base);
|
||||
ev->type = xdb::protocol::EventType::INSTR;
|
||||
ev->thread_id = ics.thread_state->thread_id();
|
||||
ev->address = ics.rf[i->src1_reg].i32;
|
||||
}
|
||||
return IA_NEXT;
|
||||
}
|
||||
int Translate_TRACE_SOURCE(TranslationContext& ctx, Instr* i) {
|
||||
return DispatchToC(ctx, i, IntCode_TRACE_SOURCE);
|
||||
}
|
||||
|
||||
uint32_t IntCode_DEBUG_BREAK(IntCodeState& ics, const IntCode* i) {
|
||||
DFLUSH();
|
||||
__debugbreak();
|
||||
@@ -4174,33 +4191,33 @@ int Translate_ATOMIC_EXCHANGE(TranslationContext& ctx, Instr* i) {
|
||||
typedef int (*TranslateFn)(TranslationContext& ctx, Instr* i);
|
||||
static const TranslateFn dispatch_table[] = {
|
||||
Translate_COMMENT, Translate_NOP,
|
||||
Translate_SOURCE_OFFSET, Translate_DEBUG_BREAK,
|
||||
Translate_DEBUG_BREAK_TRUE, Translate_TRAP,
|
||||
Translate_TRAP_TRUE, Translate_CALL,
|
||||
Translate_CALL_TRUE, Translate_CALL_INDIRECT,
|
||||
Translate_CALL_INDIRECT_TRUE, Translate_CALL_EXTERN,
|
||||
Translate_RETURN, Translate_RETURN_TRUE,
|
||||
Translate_SET_RETURN_ADDRESS, Translate_BRANCH,
|
||||
Translate_BRANCH_TRUE, Translate_BRANCH_FALSE,
|
||||
Translate_ASSIGN, Translate_CAST,
|
||||
Translate_ZERO_EXTEND, Translate_SIGN_EXTEND,
|
||||
Translate_TRUNCATE, Translate_CONVERT,
|
||||
Translate_ROUND, Translate_VECTOR_CONVERT_I2F,
|
||||
Translate_VECTOR_CONVERT_F2I, Translate_LOAD_VECTOR_SHL,
|
||||
Translate_LOAD_VECTOR_SHR, Translate_LOAD_CLOCK,
|
||||
Translate_LOAD_LOCAL, Translate_STORE_LOCAL,
|
||||
Translate_LOAD_CONTEXT, Translate_STORE_CONTEXT,
|
||||
Translate_LOAD, Translate_STORE,
|
||||
Translate_PREFETCH, Translate_MAX,
|
||||
Translate_VECTOR_MAX, Translate_MIN,
|
||||
Translate_VECTOR_MIN, Translate_SELECT,
|
||||
Translate_IS_TRUE, Translate_IS_FALSE,
|
||||
Translate_COMPARE_EQ, Translate_COMPARE_NE,
|
||||
Translate_COMPARE_SLT, Translate_COMPARE_SLE,
|
||||
Translate_COMPARE_SGT, Translate_COMPARE_SGE,
|
||||
Translate_COMPARE_ULT, Translate_COMPARE_ULE,
|
||||
Translate_COMPARE_UGT, Translate_COMPARE_UGE,
|
||||
Translate_DID_CARRY,
|
||||
Translate_SOURCE_OFFSET, Translate_TRACE_SOURCE,
|
||||
Translate_DEBUG_BREAK, Translate_DEBUG_BREAK_TRUE,
|
||||
Translate_TRAP, Translate_TRAP_TRUE,
|
||||
Translate_CALL, Translate_CALL_TRUE,
|
||||
Translate_CALL_INDIRECT, Translate_CALL_INDIRECT_TRUE,
|
||||
Translate_CALL_EXTERN, Translate_RETURN,
|
||||
Translate_RETURN_TRUE, Translate_SET_RETURN_ADDRESS,
|
||||
Translate_BRANCH, Translate_BRANCH_TRUE,
|
||||
Translate_BRANCH_FALSE, Translate_ASSIGN,
|
||||
Translate_CAST, Translate_ZERO_EXTEND,
|
||||
Translate_SIGN_EXTEND, Translate_TRUNCATE,
|
||||
Translate_CONVERT, Translate_ROUND,
|
||||
Translate_VECTOR_CONVERT_I2F, Translate_VECTOR_CONVERT_F2I,
|
||||
Translate_LOAD_VECTOR_SHL, Translate_LOAD_VECTOR_SHR,
|
||||
Translate_LOAD_CLOCK, Translate_LOAD_LOCAL,
|
||||
Translate_STORE_LOCAL, Translate_LOAD_CONTEXT,
|
||||
Translate_STORE_CONTEXT, Translate_LOAD,
|
||||
Translate_STORE, Translate_PREFETCH,
|
||||
Translate_MAX, Translate_VECTOR_MAX,
|
||||
Translate_MIN, Translate_VECTOR_MIN,
|
||||
Translate_SELECT, Translate_IS_TRUE,
|
||||
Translate_IS_FALSE, Translate_COMPARE_EQ,
|
||||
Translate_COMPARE_NE, Translate_COMPARE_SLT,
|
||||
Translate_COMPARE_SLE, Translate_COMPARE_SGT,
|
||||
Translate_COMPARE_SGE, Translate_COMPARE_ULT,
|
||||
Translate_COMPARE_ULE, Translate_COMPARE_UGT,
|
||||
Translate_COMPARE_UGE, Translate_DID_CARRY,
|
||||
TranslateInvalid, // Translate_DID_OVERFLOW,
|
||||
Translate_DID_SATURATE, Translate_VECTOR_COMPARE_EQ,
|
||||
Translate_VECTOR_COMPARE_SGT, Translate_VECTOR_COMPARE_SGE,
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
'ivm_backend.cc',
|
||||
'ivm_backend.h',
|
||||
'ivm_function.cc',
|
||||
'ivm_function.h',
|
||||
'ivm_stack.cc',
|
||||
'ivm_stack.h',
|
||||
],
|
||||
|
||||
@@ -58,7 +58,7 @@ void X64Assembler::Reset() {
|
||||
int X64Assembler::Assemble(FunctionInfo* symbol_info, HIRBuilder* builder,
|
||||
uint32_t debug_info_flags,
|
||||
std::unique_ptr<DebugInfo> debug_info,
|
||||
Function** out_function) {
|
||||
uint32_t trace_flags, Function** out_function) {
|
||||
SCOPE_profile_cpu_f("alloy");
|
||||
|
||||
// Reset when we leave.
|
||||
@@ -68,7 +68,7 @@ int X64Assembler::Assemble(FunctionInfo* symbol_info, HIRBuilder* builder,
|
||||
void* machine_code = 0;
|
||||
size_t code_size = 0;
|
||||
int result = emitter_->Emit(builder, debug_info_flags, debug_info.get(),
|
||||
machine_code, code_size);
|
||||
trace_flags, machine_code, code_size);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ class X64Assembler : public Assembler {
|
||||
int Assemble(runtime::FunctionInfo* symbol_info, hir::HIRBuilder* builder,
|
||||
uint32_t debug_info_flags,
|
||||
std::unique_ptr<runtime::DebugInfo> debug_info,
|
||||
runtime::Function** out_function) override;
|
||||
uint32_t trace_flags, runtime::Function** out_function) override;
|
||||
|
||||
private:
|
||||
void DumpMachineCode(runtime::DebugInfo* debug_info, void* machine_code,
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <alloy/runtime/runtime.h>
|
||||
#include <alloy/runtime/symbol_info.h>
|
||||
#include <alloy/runtime/thread_state.h>
|
||||
#include <xdb/protocol.h>
|
||||
|
||||
namespace alloy {
|
||||
namespace backend {
|
||||
@@ -66,8 +67,8 @@ X64Emitter::~X64Emitter() {}
|
||||
int X64Emitter::Initialize() { return 0; }
|
||||
|
||||
int X64Emitter::Emit(HIRBuilder* builder, uint32_t debug_info_flags,
|
||||
runtime::DebugInfo* debug_info, void*& out_code_address,
|
||||
size_t& out_code_size) {
|
||||
runtime::DebugInfo* debug_info, uint32_t trace_flags,
|
||||
void*& out_code_address, size_t& out_code_size) {
|
||||
SCOPE_profile_cpu_f("alloy");
|
||||
|
||||
// Reset.
|
||||
@@ -75,6 +76,7 @@ int X64Emitter::Emit(HIRBuilder* builder, uint32_t debug_info_flags,
|
||||
source_map_count_ = 0;
|
||||
source_map_arena_.Reset();
|
||||
}
|
||||
trace_flags_ = trace_flags;
|
||||
|
||||
// Fill the generator with code.
|
||||
size_t stack_size = 0;
|
||||
@@ -151,6 +153,19 @@ int X64Emitter::Emit(HIRBuilder* builder, size_t& out_stack_size) {
|
||||
mov(rdx, qword[rcx + 8]); // membase
|
||||
}
|
||||
|
||||
uint64_t trace_base = runtime_->memory()->trace_base();
|
||||
if (trace_base && trace_flags_ & TRACE_USER_CALLS) {
|
||||
mov(rax, trace_base);
|
||||
mov(r8d, static_cast<uint32_t>(sizeof(xdb::protocol::UserCallEvent)));
|
||||
lock();
|
||||
xadd(qword[rax], r8);
|
||||
mov(rax, static_cast<uint64_t>(xdb::protocol::EventType::USER_CALL) |
|
||||
(static_cast<uint64_t>(0) << 8) | (0ull << 32));
|
||||
mov(qword[r8], rax);
|
||||
EmitGetCurrentThreadId();
|
||||
mov(word[r8 + 2], ax);
|
||||
}
|
||||
|
||||
// Body.
|
||||
auto block = builder->first_block();
|
||||
while (block) {
|
||||
@@ -165,6 +180,16 @@ int X64Emitter::Emit(HIRBuilder* builder, size_t& out_stack_size) {
|
||||
const Instr* instr = block->instr_head;
|
||||
while (instr) {
|
||||
const Instr* new_tail = instr;
|
||||
|
||||
// Special handling of TRACE_SOURCE.
|
||||
if (instr->opcode == &OPCODE_TRACE_SOURCE_info) {
|
||||
if (trace_flags_ & TRACE_SOURCE) {
|
||||
EmitTraceSource(instr);
|
||||
}
|
||||
instr = instr->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!SelectSequence(*this, instr, &new_tail)) {
|
||||
// No sequence found!
|
||||
assert_always();
|
||||
@@ -179,6 +204,7 @@ int X64Emitter::Emit(HIRBuilder* builder, size_t& out_stack_size) {
|
||||
|
||||
// Function epilog.
|
||||
L("epilog");
|
||||
EmitTraceUserCallReturn();
|
||||
if (emit_prolog) {
|
||||
mov(rcx, qword[rsp + StackLayout::GUEST_RCX_HOME]);
|
||||
add(rsp, (uint32_t)stack_size);
|
||||
@@ -204,6 +230,129 @@ void X64Emitter::MarkSourceOffset(const Instr* i) {
|
||||
source_map_count_++;
|
||||
}
|
||||
|
||||
void X64Emitter::EmitTraceSource(const Instr* instr) {
|
||||
uint64_t trace_base = runtime_->memory()->trace_base();
|
||||
if (!trace_base || !(trace_flags_ & TRACE_SOURCE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO(benvanik): make this a function call to some append fn.
|
||||
|
||||
uint8_t dest_reg_0 = instr->flags & 0xFF;
|
||||
uint8_t dest_reg_1 = instr->flags >> 8;
|
||||
|
||||
xdb::protocol::EventType event_type;
|
||||
size_t event_size;
|
||||
if (dest_reg_0 == 100) {
|
||||
event_type = xdb::protocol::EventType::INSTR;
|
||||
event_size = sizeof(xdb::protocol::InstrEvent);
|
||||
} else if (dest_reg_1 == 100) {
|
||||
if (dest_reg_0 & (1 << 7)) {
|
||||
event_type = xdb::protocol::EventType::INSTR_R16;
|
||||
event_size = sizeof(xdb::protocol::InstrEventR16);
|
||||
} else {
|
||||
event_type = xdb::protocol::EventType::INSTR_R8;
|
||||
event_size = sizeof(xdb::protocol::InstrEventR8);
|
||||
}
|
||||
} else {
|
||||
if (dest_reg_0 & (1 << 7) && dest_reg_1 & (1 << 7)) {
|
||||
event_type = xdb::protocol::EventType::INSTR_R16_R16;
|
||||
event_size = sizeof(xdb::protocol::InstrEventR16R16);
|
||||
} else if (dest_reg_0 & (1 << 7) && !(dest_reg_1 & (1 << 7))) {
|
||||
event_type = xdb::protocol::EventType::INSTR_R16_R8;
|
||||
event_size = sizeof(xdb::protocol::InstrEventR16R8);
|
||||
} else if (!(dest_reg_0 & (1 << 7)) && dest_reg_1 & (1 << 7)) {
|
||||
event_type = xdb::protocol::EventType::INSTR_R8_R16;
|
||||
event_size = sizeof(xdb::protocol::InstrEventR8R16);
|
||||
} else if (!(dest_reg_0 & (1 << 7)) && !(dest_reg_1 & (1 << 7))) {
|
||||
event_type = xdb::protocol::EventType::INSTR_R8_R8;
|
||||
event_size = sizeof(xdb::protocol::InstrEventR8R8);
|
||||
}
|
||||
}
|
||||
|
||||
mov(rax, trace_base);
|
||||
mov(r8d, static_cast<uint32_t>(event_size));
|
||||
lock();
|
||||
xadd(qword[rax], r8);
|
||||
// r8 is now the pointer where we can write our event.
|
||||
|
||||
// Write the header, which is the same for everything (pretty much).
|
||||
// Some event types ignore the dest reg, and that's fine.
|
||||
uint64_t qword_0 = static_cast<uint64_t>(event_type) |
|
||||
(static_cast<uint64_t>(dest_reg_0) << 8) |
|
||||
(instr->src1.offset << 32);
|
||||
mov(rax, qword_0);
|
||||
mov(qword[r8], rax);
|
||||
|
||||
// Write thread ID.
|
||||
EmitGetCurrentThreadId();
|
||||
mov(word[r8 + 2], ax);
|
||||
|
||||
switch (event_type) {
|
||||
case xdb::protocol::EventType::INSTR:
|
||||
break;
|
||||
case xdb::protocol::EventType::INSTR_R8:
|
||||
case xdb::protocol::EventType::INSTR_R16:
|
||||
if (dest_reg_0 & (1 << 7)) {
|
||||
EmitTraceSourceAppendValue(instr->src2.value, 8);
|
||||
} else {
|
||||
EmitTraceSourceAppendValue(instr->src2.value, 8);
|
||||
}
|
||||
break;
|
||||
case xdb::protocol::EventType::INSTR_R8_R8:
|
||||
case xdb::protocol::EventType::INSTR_R8_R16:
|
||||
case xdb::protocol::EventType::INSTR_R16_R8:
|
||||
case xdb::protocol::EventType::INSTR_R16_R16:
|
||||
mov(word[r8 + 8], dest_reg_0 | static_cast<uint16_t>(dest_reg_1 << 8));
|
||||
size_t offset = 8;
|
||||
if (dest_reg_0 & (1 << 7)) {
|
||||
EmitTraceSourceAppendValue(instr->src2.value, offset);
|
||||
offset += 16;
|
||||
} else {
|
||||
EmitTraceSourceAppendValue(instr->src2.value, offset);
|
||||
offset += 8;
|
||||
}
|
||||
if (dest_reg_1 & (1 << 7)) {
|
||||
EmitTraceSourceAppendValue(instr->src3.value, offset);
|
||||
offset += 16;
|
||||
} else {
|
||||
EmitTraceSourceAppendValue(instr->src3.value, offset);
|
||||
offset += 8;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void X64Emitter::EmitTraceSourceAppendValue(const Value* value,
|
||||
size_t r8_offset) {
|
||||
//
|
||||
}
|
||||
|
||||
void X64Emitter::EmitGetCurrentThreadId() {
|
||||
// rcx must point to context. We could fetch from the stack if needed.
|
||||
mov(ax,
|
||||
word[rcx + runtime_->frontend()->context_info()->thread_id_offset()]);
|
||||
}
|
||||
|
||||
void X64Emitter::EmitTraceUserCallReturn() {
|
||||
auto trace_base = runtime_->memory()->trace_base();
|
||||
if (!trace_base || !(trace_flags_ & TRACE_USER_CALLS)) {
|
||||
return;
|
||||
}
|
||||
mov(rdx, rax);
|
||||
mov(rax, trace_base);
|
||||
mov(r8d, static_cast<uint32_t>(sizeof(xdb::protocol::UserCallReturnEvent)));
|
||||
lock();
|
||||
xadd(qword[rax], r8);
|
||||
mov(rax, static_cast<uint64_t>(xdb::protocol::EventType::USER_CALL_RETURN) |
|
||||
(static_cast<uint64_t>(0) << 8) | (0ull << 32));
|
||||
mov(qword[r8], rax);
|
||||
EmitGetCurrentThreadId();
|
||||
mov(word[r8 + 2], ax);
|
||||
mov(rax, rdx);
|
||||
ReloadEDX();
|
||||
}
|
||||
|
||||
void X64Emitter::DebugBreak() {
|
||||
// TODO(benvanik): notify debugger.
|
||||
db(0xCC);
|
||||
@@ -258,7 +407,7 @@ uint64_t ResolveFunctionSymbol(void* raw_context, uint64_t symbol_info_ptr) {
|
||||
#else
|
||||
uint64_t return_address =
|
||||
reinterpret_cast<uint64_t>(__builtin_return_address(0));
|
||||
#endif // XE_WIN32_LIKE
|
||||
#endif // XE_LIKE_WIN32
|
||||
#pragma pack(push, 1)
|
||||
struct Asm {
|
||||
uint16_t mov_rax;
|
||||
@@ -301,6 +450,9 @@ void X64Emitter::Call(const hir::Instr* instr,
|
||||
|
||||
// Actually jump/call to rax.
|
||||
if (instr->flags & CALL_TAIL) {
|
||||
// Since we skip the prolog we need to mark the return here.
|
||||
EmitTraceUserCallReturn();
|
||||
|
||||
// Pass the callers return address over.
|
||||
mov(rdx, qword[rsp + StackLayout::GUEST_RET_ADDR]);
|
||||
|
||||
@@ -338,7 +490,7 @@ uint64_t ResolveFunctionAddress(void* raw_context, uint64_t target_address) {
|
||||
#else
|
||||
uint64_t return_address =
|
||||
reinterpret_cast<uint64_t>(__builtin_return_address(0));
|
||||
#endif // XE_WIN32_LIKE
|
||||
#endif // XE_LIKE_WIN32
|
||||
#pragma pack(push, 1)
|
||||
struct Asm {
|
||||
uint16_t cmp_rdx;
|
||||
@@ -426,6 +578,9 @@ void X64Emitter::CallIndirect(const hir::Instr* instr, const Reg64& reg) {
|
||||
// Actually jump/call to rax.
|
||||
L(skip_resolve);
|
||||
if (instr->flags & CALL_TAIL) {
|
||||
// Since we skip the prolog we need to mark the return here.
|
||||
EmitTraceUserCallReturn();
|
||||
|
||||
// Pass the callers return address over.
|
||||
mov(rdx, qword[rsp + StackLayout::GUEST_RET_ADDR]);
|
||||
|
||||
@@ -449,6 +604,24 @@ uint64_t UndefinedCallExtern(void* raw_context, uint64_t symbol_info_ptr) {
|
||||
void X64Emitter::CallExtern(const hir::Instr* instr,
|
||||
const FunctionInfo* symbol_info) {
|
||||
assert_true(symbol_info->behavior() == FunctionInfo::BEHAVIOR_EXTERN);
|
||||
|
||||
uint64_t trace_base = runtime_->memory()->trace_base();
|
||||
if (trace_base & trace_flags_ & TRACE_EXTERN_CALLS) {
|
||||
mov(rax, trace_base);
|
||||
mov(r8d, static_cast<uint32_t>(sizeof(xdb::protocol::KernelCallEvent)));
|
||||
lock();
|
||||
xadd(qword[rax], r8);
|
||||
// TODO(benvanik): get module/ordinal.
|
||||
uint32_t module_id = 0;
|
||||
uint32_t ordinal = 0;
|
||||
mov(rax, static_cast<uint64_t>(xdb::protocol::EventType::KERNEL_CALL) |
|
||||
(static_cast<uint64_t>(0) << 8) | (module_id << 16) |
|
||||
(ordinal));
|
||||
mov(qword[r8], rax);
|
||||
EmitGetCurrentThreadId();
|
||||
mov(word[r8 + 2], ax);
|
||||
}
|
||||
|
||||
if (!symbol_info->extern_handler()) {
|
||||
CallNative(UndefinedCallExtern, reinterpret_cast<uint64_t>(symbol_info));
|
||||
} else {
|
||||
@@ -466,6 +639,21 @@ void X64Emitter::CallExtern(const hir::Instr* instr,
|
||||
ReloadEDX();
|
||||
// rax = host return
|
||||
}
|
||||
if (trace_base && trace_flags_ & TRACE_EXTERN_CALLS) {
|
||||
mov(rax, trace_base);
|
||||
mov(r8d,
|
||||
static_cast<uint32_t>(sizeof(xdb::protocol::KernelCallReturnEvent)));
|
||||
lock();
|
||||
xadd(qword[rax], r8);
|
||||
uint32_t module_id = 0;
|
||||
uint32_t ordinal = 0;
|
||||
mov(rax,
|
||||
static_cast<uint64_t>(xdb::protocol::EventType::KERNEL_CALL_RETURN) |
|
||||
(static_cast<uint64_t>(0) << 8) | (0));
|
||||
mov(qword[r8], rax);
|
||||
EmitGetCurrentThreadId();
|
||||
mov(word[r8 + 2], ax);
|
||||
}
|
||||
}
|
||||
|
||||
void X64Emitter::CallNative(void* fn) {
|
||||
|
||||
@@ -84,8 +84,8 @@ class X64Emitter : public Xbyak::CodeGenerator {
|
||||
int Initialize();
|
||||
|
||||
int Emit(hir::HIRBuilder* builder, uint32_t debug_info_flags,
|
||||
runtime::DebugInfo* debug_info, void*& out_code_address,
|
||||
size_t& out_code_size);
|
||||
runtime::DebugInfo* debug_info, uint32_t trace_flags,
|
||||
void*& out_code_address, size_t& out_code_size);
|
||||
|
||||
public:
|
||||
// Reserved: rsp
|
||||
@@ -163,6 +163,10 @@ class X64Emitter : public Xbyak::CodeGenerator {
|
||||
protected:
|
||||
void* Emplace(size_t stack_size);
|
||||
int Emit(hir::HIRBuilder* builder, size_t& out_stack_size);
|
||||
void EmitTraceSource(const hir::Instr* instr);
|
||||
void EmitTraceSourceAppendValue(const hir::Value* value, size_t r8_offset);
|
||||
void EmitGetCurrentThreadId();
|
||||
void EmitTraceUserCallReturn();
|
||||
|
||||
protected:
|
||||
runtime::Runtime* runtime_;
|
||||
@@ -177,6 +181,8 @@ class X64Emitter : public Xbyak::CodeGenerator {
|
||||
|
||||
size_t stack_size_;
|
||||
|
||||
uint32_t trace_flags_;
|
||||
|
||||
static const uint32_t gpr_reg_map_[GPR_COUNT];
|
||||
static const uint32_t xmm_reg_map_[XMM_COUNT];
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user