Breakpoints triggering.
This commit is contained in:
@@ -25,6 +25,7 @@ using namespace alloy::runtime;
|
||||
|
||||
|
||||
IVMAssembler::IVMAssembler(Backend* backend) :
|
||||
source_map_arena_(128 * 1024),
|
||||
Assembler(backend) {
|
||||
}
|
||||
|
||||
@@ -47,6 +48,7 @@ int IVMAssembler::Initialize() {
|
||||
|
||||
void IVMAssembler::Reset() {
|
||||
intcode_arena_.Reset();
|
||||
source_map_arena_.Reset();
|
||||
scratch_arena_.Reset();
|
||||
Assembler::Reset();
|
||||
}
|
||||
@@ -62,6 +64,8 @@ int IVMAssembler::Assemble(
|
||||
ctx.register_count = 0;
|
||||
ctx.intcode_count = 0;
|
||||
ctx.intcode_arena = &intcode_arena_;
|
||||
ctx.source_map_count = 0;
|
||||
ctx.source_map_arena = &source_map_arena_;
|
||||
ctx.scratch_arena = &scratch_arena_;
|
||||
ctx.label_ref_head = NULL;
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ public:
|
||||
|
||||
private:
|
||||
Arena intcode_arena_;
|
||||
Arena source_map_arena_;
|
||||
Arena scratch_arena_;
|
||||
};
|
||||
|
||||
|
||||
@@ -21,27 +21,86 @@ using namespace alloy::runtime;
|
||||
|
||||
IVMFunction::IVMFunction(FunctionInfo* symbol_info) :
|
||||
register_count_(0), intcode_count_(0), intcodes_(0),
|
||||
source_map_count_(0), source_map_(0),
|
||||
GuestFunction(symbol_info) {
|
||||
}
|
||||
|
||||
IVMFunction::~IVMFunction() {
|
||||
xe_free(intcodes_);
|
||||
xe_free(source_map_);
|
||||
}
|
||||
|
||||
void IVMFunction::Setup(TranslationContext& ctx) {
|
||||
register_count_ = ctx.register_count;
|
||||
intcode_count_ = ctx.intcode_count;
|
||||
intcodes_ = (IntCode*)ctx.intcode_arena->CloneContents();
|
||||
source_map_count_ = ctx.source_map_count;
|
||||
source_map_ = (SourceMapEntry*)ctx.source_map_arena->CloneContents();
|
||||
}
|
||||
|
||||
IntCode* IVMFunction::GetIntCodeAtSourceOffset(uint64_t offset) {
|
||||
for (size_t n = 0; n < source_map_count_; n++) {
|
||||
auto entry = &source_map_[n];
|
||||
if (entry->source_offset == offset) {
|
||||
return &intcodes_[entry->intcode_index];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int IVMFunction::AddBreakpointImpl(Breakpoint* breakpoint) {
|
||||
auto i = GetIntCodeAtSourceOffset(breakpoint->address());
|
||||
if (!i) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// TEMP breakpoints always overwrite normal ones.
|
||||
if (!i->debug_flags ||
|
||||
breakpoint->type() == Breakpoint::TEMP_TYPE) {
|
||||
uint64_t breakpoint_ptr = (uint64_t)breakpoint;
|
||||
i->src2_reg = (uint32_t)breakpoint_ptr;
|
||||
i->src3_reg = (uint32_t)(breakpoint_ptr >> 32);
|
||||
}
|
||||
|
||||
// Increment breakpoint counter.
|
||||
++i->debug_flags;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int IVMFunction::RemoveBreakpointImpl(Breakpoint* breakpoint) {
|
||||
auto i = GetIntCodeAtSourceOffset(breakpoint->address());
|
||||
if (!i) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Decrement breakpoint counter.
|
||||
--i->debug_flags;
|
||||
i->src2_reg = i->src3_reg = 0;
|
||||
|
||||
// If there were other breakpoints, see what they were.
|
||||
if (i->debug_flags) {
|
||||
auto old_breakpoint = FindBreakpoint(breakpoint->address());
|
||||
if (old_breakpoint) {
|
||||
uint64_t breakpoint_ptr = (uint64_t)breakpoint;
|
||||
i->src2_reg = (uint32_t)breakpoint_ptr;
|
||||
i->src3_reg = (uint32_t)(breakpoint_ptr >> 32);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void IVMFunction::OnBreakpointHit(ThreadState* thread_state, IntCode* i) {
|
||||
uint64_t breakpoint_ptr = i->src2_reg | (uint64_t(i->src3_reg) << 32);
|
||||
Breakpoint* breakpoint = (Breakpoint*)breakpoint_ptr;
|
||||
|
||||
// Notify debugger.
|
||||
// The debugger may choose to wait (blocking us).
|
||||
auto debugger = thread_state->runtime()->debugger();
|
||||
debugger->OnBreakpointHit(thread_state, breakpoint);
|
||||
}
|
||||
|
||||
int IVMFunction::CallImpl(ThreadState* thread_state, uint64_t return_address) {
|
||||
// Setup register file on stack.
|
||||
size_t register_file_size = register_count_ * sizeof(Register);
|
||||
@@ -65,7 +124,12 @@ int IVMFunction::CallImpl(ThreadState* thread_state, uint64_t return_address) {
|
||||
|
||||
uint32_t ia = 0;
|
||||
while (true) {
|
||||
const IntCode* i = &intcodes_[ia];
|
||||
IntCode* i = &intcodes_[ia];
|
||||
|
||||
if (i->debug_flags) {
|
||||
OnBreakpointHit(thread_state, i);
|
||||
}
|
||||
|
||||
uint32_t new_ia = i->intcode_fn(ics, i);
|
||||
if (new_ia == IA_NEXT) {
|
||||
ia++;
|
||||
|
||||
@@ -35,13 +35,16 @@ protected:
|
||||
uint64_t return_address);
|
||||
|
||||
private:
|
||||
IntCode* GetIntCodeAtSourceOffset(uint64_t offset);
|
||||
void OnBreakpointHit(runtime::ThreadState* thread_state, IntCode* i);
|
||||
|
||||
private:
|
||||
size_t register_count_;
|
||||
Register* constant_regiters_;
|
||||
size_t intcode_count_;
|
||||
IntCode* intcodes_;
|
||||
// ... source_map_;
|
||||
size_t source_map_count_;
|
||||
SourceMapEntry* source_map_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@ uint32_t AllocConstant(TranslationContext& ctx, uint64_t value,
|
||||
IntCode* ic = ctx.intcode_arena->Alloc<IntCode>();
|
||||
ic->intcode_fn = IntCode_INT_LOAD_CONSTANT;
|
||||
ic->flags = 0;
|
||||
ic->debug_flags = 0;
|
||||
ic->dest_reg = ctx.register_count++;
|
||||
ic->constant.u64 = value;
|
||||
if (out_ic) {
|
||||
@@ -66,6 +67,7 @@ uint32_t AllocConstant(TranslationContext& ctx, Value* value) {
|
||||
IntCode* ic = ctx.intcode_arena->Alloc<IntCode>();
|
||||
ic->intcode_fn = IntCode_INT_LOAD_CONSTANT;
|
||||
ic->flags = 0;
|
||||
ic->debug_flags = 0;
|
||||
ic->dest_reg = ctx.register_count++;
|
||||
ic->constant.v128 = value->constant.v128;
|
||||
return ic->dest_reg;
|
||||
@@ -155,6 +157,7 @@ int DispatchToC(TranslationContext& ctx, Instr* i, IntCodeFn fn) {
|
||||
IntCode* ic = ctx.intcode_arena->Alloc<IntCode>();
|
||||
ic->intcode_fn = fn;
|
||||
ic->flags = i->flags;
|
||||
ic->debug_flags = 0;
|
||||
ic->dest_reg = dest_reg;
|
||||
ic->src1_reg = src1_reg;
|
||||
ic->src2_reg = src2_reg;
|
||||
@@ -210,6 +213,7 @@ int DispatchRegisterRead(
|
||||
IntCode* ic = ctx.intcode_arena->Alloc<IntCode>();
|
||||
ic->intcode_fn = fn;
|
||||
ic->flags = i->flags;
|
||||
ic->debug_flags = 0;
|
||||
ic->dest_reg = dest_reg;
|
||||
ic->src1_reg = src1_reg;
|
||||
ic->src2_reg = (uint32_t)((uint64_t)cbs);
|
||||
@@ -312,6 +316,7 @@ int DispatchRegisterWrite(
|
||||
IntCode* ic = ctx.intcode_arena->Alloc<IntCode>();
|
||||
ic->intcode_fn = fn;
|
||||
ic->flags = i->flags;
|
||||
ic->debug_flags = 0;
|
||||
ic->dest_reg = (uint32_t)(((uint64_t)cbs) >> 32);
|
||||
ic->src1_reg = src1_reg;
|
||||
ic->src2_reg = src2_reg;
|
||||
@@ -391,6 +396,7 @@ int Translate_COMMENT(TranslationContext& ctx, Instr* i) {
|
||||
IntCode* ic = ctx.intcode_arena->Alloc<IntCode>();
|
||||
ic->intcode_fn = IntCode_COMMENT;
|
||||
ic->flags = i->flags;
|
||||
ic->debug_flags = 0;
|
||||
// HACK HACK HACK
|
||||
char* src = xestrdupa((char*)i->src1.offset);
|
||||
uint64_t src_p = (uint64_t)src;
|
||||
@@ -406,6 +412,21 @@ int Translate_NOP(TranslationContext& ctx, Instr* i) {
|
||||
return DispatchToC(ctx, i, IntCode_NOP);
|
||||
}
|
||||
|
||||
uint32_t IntCode_SOURCE_OFFSET(IntCodeState& ics, const IntCode* i) {
|
||||
return IA_NEXT;
|
||||
}
|
||||
int Translate_SOURCE_OFFSET(TranslationContext& ctx, Instr* i) {
|
||||
int result = DispatchToC(ctx, i, IntCode_SOURCE_OFFSET);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
auto entry = ctx.source_map_arena->Alloc<SourceMapEntry>();
|
||||
entry->intcode_index = ctx.intcode_count - 1;
|
||||
entry->source_offset = i->src1.offset;
|
||||
ctx.source_map_count++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t IntCode_DEBUG_BREAK(IntCodeState& ics, const IntCode* i) {
|
||||
DFLUSH();
|
||||
__debugbreak();
|
||||
@@ -3061,6 +3082,8 @@ static const TranslateFn dispatch_table[] = {
|
||||
|
||||
Translate_NOP,
|
||||
|
||||
Translate_SOURCE_OFFSET,
|
||||
|
||||
Translate_DEBUG_BREAK,
|
||||
Translate_DEBUG_BREAK_TRUE,
|
||||
|
||||
|
||||
@@ -63,6 +63,7 @@ typedef uint32_t (*IntCodeFn)(
|
||||
typedef struct IntCode_s {
|
||||
IntCodeFn intcode_fn;
|
||||
uint16_t flags;
|
||||
uint16_t debug_flags;
|
||||
|
||||
uint32_t dest_reg;
|
||||
union {
|
||||
@@ -88,12 +89,20 @@ typedef struct LabelRef_s {
|
||||
} LabelRef;
|
||||
|
||||
|
||||
typedef struct SourceMapEntry_s {
|
||||
uint64_t source_offset;
|
||||
uint64_t intcode_index;
|
||||
} SourceMapEntry;
|
||||
|
||||
|
||||
typedef struct {
|
||||
runtime::RegisterAccessCallbacks* access_callbacks;
|
||||
|
||||
uint32_t register_count;
|
||||
size_t intcode_count;
|
||||
Arena* intcode_arena;
|
||||
size_t source_map_count;
|
||||
Arena* source_map_arena;
|
||||
Arena* scratch_arena;
|
||||
LabelRef* label_ref_head;
|
||||
} TranslationContext;
|
||||
|
||||
Reference in New Issue
Block a user