added options for making the emulator less attention-demanding.
This commit is contained in:
parent
dda7b25c15
commit
6c38906a51
|
@ -10,7 +10,6 @@ import argparse
|
|||
|
||||
from llvm_emulator import stepper, parser
|
||||
|
||||
|
||||
def main():
|
||||
arg_parser = argparse.ArgumentParser(description='A hacky LLVM-- emulator/debugger')
|
||||
|
||||
|
@ -18,6 +17,16 @@ def main():
|
|||
action='store', type=str, dest='auto_path',
|
||||
help='Automatically step through llvm in the given file')
|
||||
|
||||
arg_parser.add_argument('-s', '--step',
|
||||
action='store', type=int, dest='auto_step',
|
||||
default=100,
|
||||
help='How often to prompt for continuation in auto-mode, 0 is never')
|
||||
|
||||
arg_parser.add_argument('-p', '--print',
|
||||
action='store', type=int, dest='print_level',
|
||||
default=3,
|
||||
help='Verboseness of the emulator')
|
||||
|
||||
parse_res_raw = arg_parser.parse_args()
|
||||
parse_res = vars(parse_res_raw)
|
||||
|
||||
|
@ -26,12 +35,16 @@ def main():
|
|||
llvm_parser.build()
|
||||
|
||||
if parse_res['auto_path'] is not None:
|
||||
go_auto(parse_res['auto_path'])
|
||||
step_behavior = {
|
||||
'step_ask': parse_res['auto_step'],
|
||||
'step_print_level': parse_res['print_level']
|
||||
}
|
||||
go_auto(parse_res['auto_path'], step_behavior)
|
||||
else:
|
||||
enter_interactive_mode()
|
||||
|
||||
|
||||
def go_auto(path_to_file):
|
||||
def go_auto(path_to_file, step_behavior):
|
||||
with open(path_to_file, 'r') as f:
|
||||
file_contents = f.read()
|
||||
print('Parsing {}'
|
||||
|
@ -39,7 +52,7 @@ def go_auto(path_to_file):
|
|||
ast = llvm_parser.parse(file_contents)
|
||||
print('Beginning execution of {}'
|
||||
.format(path_to_file))
|
||||
stepper.auto_step(ast)
|
||||
stepper.auto_step(ast, step_behavior = step_behavior)
|
||||
|
||||
|
||||
def enter_interactive_mode():
|
||||
|
|
|
@ -2,21 +2,43 @@ from enum import Enum
|
|||
|
||||
from llvm_emulator import ll
|
||||
|
||||
import sys
|
||||
|
||||
def TODO(msg):
|
||||
print('TODO: not implemented yet at {}'
|
||||
.format(msg))
|
||||
############
|
||||
# Messages #
|
||||
|
||||
PRINT_LEVEL_NONE = 0
|
||||
PRINT_LEVEL_ERR = 1
|
||||
PRINT_LEVEL_WARN = 2
|
||||
PRINT_LEVEL_INFO = 3
|
||||
|
||||
PRINT_LEVEL = PRINT_LEVEL_NONE
|
||||
|
||||
###
|
||||
|
||||
def eprint(*args, **kwargs):
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
def err(msg):
|
||||
print('ERROR: {}'
|
||||
if PRINT_LEVEL >= PRINT_LEVEL_ERR:
|
||||
eprint('ERROR: {}'
|
||||
.format(msg))
|
||||
|
||||
def TODO(msg):
|
||||
err('TODO: not implemented yet at {}'
|
||||
.format(msg))
|
||||
|
||||
def warn(msg):
|
||||
print('WARNING: {}'
|
||||
if PRINT_LEVEL >= PRINT_LEVEL_WARN:
|
||||
eprint('WARNING: {}'
|
||||
.format(msg))
|
||||
|
||||
def info(*args, **kwargs):
|
||||
if PRINT_LEVEL >= PRINT_LEVEL_INFO:
|
||||
print(*args, **kwargs)
|
||||
|
||||
##########
|
||||
# Stuff? #
|
||||
|
||||
class Garbage(Enum):
|
||||
GARBAGE = '<<Unitialized memory>>'
|
||||
|
@ -50,14 +72,14 @@ def step(insns, terminator, blocks, stack_frames, ssa_env, global_env, heap,
|
|||
.format(ssa_target))
|
||||
else:
|
||||
# TODO
|
||||
print('%{} <- {}'
|
||||
info('%{} <- {}'
|
||||
.format(ssa_target, res))
|
||||
ssa_env[ssa_target] = res
|
||||
|
||||
return insns_rest, terminator, blocks, stack_frames, ssa_env, heap, call_res
|
||||
|
||||
# TODO
|
||||
print('Evaluating {}'
|
||||
info('Evaluating {}'
|
||||
.format(ll.insn2s(next_insn)))
|
||||
|
||||
res = None
|
||||
|
@ -70,7 +92,7 @@ def step(insns, terminator, blocks, stack_frames, ssa_env, global_env, heap,
|
|||
res = eval_binop(bop, left_v, right_v)
|
||||
|
||||
# TODO
|
||||
print('{} {}, {}'
|
||||
info('{} {}, {}'
|
||||
.format(bop, left_v, right_v))
|
||||
elif isinstance(next_insn, ll.Alloca):
|
||||
ty = next_insn.ty
|
||||
|
@ -78,7 +100,7 @@ def step(insns, terminator, blocks, stack_frames, ssa_env, global_env, heap,
|
|||
size = base_ty2size(base_ty)
|
||||
|
||||
# TODO
|
||||
print('alloca {} --> allocating {} cells'
|
||||
info('alloca {} --> allocating {} cells'
|
||||
.format(ll.ty2s(base_ty), size))
|
||||
|
||||
ptr = len(heap)
|
||||
|
@ -94,7 +116,7 @@ def step(insns, terminator, blocks, stack_frames, ssa_env, global_env, heap,
|
|||
location_v = eval_oper(location, ssa_env, global_env)
|
||||
|
||||
# TODO
|
||||
print('load heap[{}]'
|
||||
info('load heap[{}]'
|
||||
.format(location_v))
|
||||
|
||||
if size != 1:
|
||||
|
@ -118,7 +140,7 @@ def step(insns, terminator, blocks, stack_frames, ssa_env, global_env, heap,
|
|||
location_v = eval_oper(location, ssa_env, global_env)
|
||||
|
||||
# TODO
|
||||
print('heap[{}] <- {}'
|
||||
info('heap[{}] <- {}'
|
||||
.format(location_v, value_v))
|
||||
if location_v == 0:
|
||||
err('You are not allowed to store at location 0 (Null)')
|
||||
|
@ -137,7 +159,7 @@ def step(insns, terminator, blocks, stack_frames, ssa_env, global_env, heap,
|
|||
res = eval_icmp(cnd, left_v, right_v)
|
||||
|
||||
# TODO
|
||||
print('icmp {} {}, {}'
|
||||
info('icmp {} {}, {}'
|
||||
.format(cnd, left_v, right_v))
|
||||
elif isinstance(next_insn, ll.Call):
|
||||
callee = next_insn.callee
|
||||
|
@ -174,7 +196,7 @@ def step(insns, terminator, blocks, stack_frames, ssa_env, global_env, heap,
|
|||
return insns_rest, terminator, blocks, stack_frames, ssa_env, heap, call_res
|
||||
|
||||
parameters = function.parameters
|
||||
print('call @{} ({})'
|
||||
info('call @{} ({})'
|
||||
.format(callee.val,
|
||||
', '.join('%{} <- {}'.format(par[1], arg)
|
||||
for par, arg in zip(parameters, arguments_v))))
|
||||
|
@ -196,7 +218,7 @@ def step(insns, terminator, blocks, stack_frames, ssa_env, global_env, heap,
|
|||
res = oper_v
|
||||
|
||||
# TODO
|
||||
print('bitcast {} {} to {}'
|
||||
info('bitcast {} {} to {}'
|
||||
.format(ll.ty2s(from_ty), oper_v, ll.ty2s(to_ty)))
|
||||
elif isinstance(next_insn, ll.Gep):
|
||||
res = 0
|
||||
|
@ -226,12 +248,12 @@ def step(insns, terminator, blocks, stack_frames, ssa_env, global_env, heap,
|
|||
res = gep_res
|
||||
|
||||
# TODO
|
||||
print('Getting adress of {}{}'.
|
||||
info('Getting adress of {}{}'.
|
||||
format(ll.ty2s(actual_base_ty),
|
||||
''.join('[{}]'
|
||||
.format(eval_oper(step_oper, ssa_env, global_env))
|
||||
for _, step_oper in steps)))
|
||||
print('Gep formula: {}'
|
||||
info('Gep formula: {}'
|
||||
.format(formula))
|
||||
elif isinstance(next_insn, ll.Zext):
|
||||
oper = next_insn.oper
|
||||
|
@ -241,7 +263,7 @@ def step(insns, terminator, blocks, stack_frames, ssa_env, global_env, heap,
|
|||
res = oper_v
|
||||
|
||||
# TODO
|
||||
print('zext {} {} to {}'
|
||||
info('zext {} {} to {}'
|
||||
.format(ll.ty2s(from_ty), oper_v, ll.ty2s(to_ty)))
|
||||
elif isinstance(next_insn, ll.Ptrtoint):
|
||||
oper = next_insn.oper
|
||||
|
@ -251,7 +273,7 @@ def step(insns, terminator, blocks, stack_frames, ssa_env, global_env, heap,
|
|||
res = oper_v
|
||||
|
||||
# TODO
|
||||
print('ptrtoint {}* {} to {}'
|
||||
info('ptrtoint {}* {} to {}'
|
||||
.format(ll.ty2s(pointer_ty), oper_v, ll.ty2s(to_ty)))
|
||||
elif isinstance(next_insn, ll.CallResult):
|
||||
res = next_insn.val
|
||||
|
@ -269,7 +291,7 @@ def terminate(terminator, blocks, stack_frames, ssa_env, global_env, heap, call_
|
|||
if id is not None and id in ssa_env:
|
||||
del ssa_env[id]
|
||||
|
||||
print('Evaluating {}'
|
||||
info('Evaluating {}'
|
||||
.format(ll.terminator2s(terminator)))
|
||||
|
||||
if isinstance(terminator, ll.Ret):
|
||||
|
@ -280,7 +302,7 @@ def terminate(terminator, blocks, stack_frames, ssa_env, global_env, heap, call_
|
|||
oper_v = eval_oper(oper, ssa_env, global_env)
|
||||
|
||||
# TODO
|
||||
print('Returning {}'
|
||||
info('Returning {}'
|
||||
.format(oper_v))
|
||||
|
||||
if len(stack_frames) == 0:
|
||||
|
@ -309,7 +331,7 @@ def terminate(terminator, blocks, stack_frames, ssa_env, global_env, heap, call_
|
|||
clear_block_from_ssa_env(new_insns, ssa_env)
|
||||
|
||||
# TODO
|
||||
print('Jumping unconditionally to {}'
|
||||
info('Jumping unconditionally to {}'
|
||||
.format(label))
|
||||
|
||||
return (new_insns, new_terminator, blocks, stack_frames,
|
||||
|
@ -333,7 +355,7 @@ def terminate(terminator, blocks, stack_frames, ssa_env, global_env, heap, call_
|
|||
clear_block_from_ssa_env(new_insns, ssa_env)
|
||||
|
||||
# TODO
|
||||
print('Operand was {}. Branching to {}'
|
||||
info('Operand was {}. Branching to {}'
|
||||
.format(operand_v, label))
|
||||
|
||||
return (new_insns, new_terminator, blocks, stack_frames,
|
||||
|
@ -532,7 +554,7 @@ def alloc_globals(gdecls, heap):
|
|||
|
||||
for gdecl in gdecls.values():
|
||||
location = alloc_global(gdecl.body)
|
||||
print('heap[{}] <- {}'
|
||||
info('heap[{}] <- {}'
|
||||
.format(location, ll.gdecl2s(gdecl)))
|
||||
global_env[gdecl.name] = location
|
||||
|
||||
|
@ -549,7 +571,7 @@ def emulate_builtin(name, arguments_v, ssa_env, heap):
|
|||
.format(name))
|
||||
else:
|
||||
size = max(arguments_v[0], 1)
|
||||
print('Allocating {} cells'
|
||||
info('Allocating {} cells'
|
||||
.format(size))
|
||||
res = len(heap)
|
||||
for i in range(size):
|
||||
|
@ -562,7 +584,7 @@ def emulate_builtin(name, arguments_v, ssa_env, heap):
|
|||
num_elements = arguments_v[0]
|
||||
cells_per_element = arguments_v[1]
|
||||
init_ptr = arguments_v[2]
|
||||
print('Allocating {} + {} + {} (size + pointer + content) cells'
|
||||
info('Allocating {} + {} + {} (size + pointer + content) cells'
|
||||
.format(1, 1, num_elements * cells_per_element))
|
||||
struct_begin = len(heap)
|
||||
heap.append(num_elements)
|
||||
|
@ -588,7 +610,7 @@ def emulate_builtin(name, arguments_v, ssa_env, heap):
|
|||
.format(array_begin, array_last,
|
||||
init_ptr, init_val_s))
|
||||
# TODO
|
||||
print('heap[{}] <- {}, heap[{}] <- {}, --- {}'
|
||||
info('heap[{}] <- {}, heap[{}] <- {}, --- {}'
|
||||
.format(struct_begin, num_elements,
|
||||
struct_begin + 1, array_begin,
|
||||
array_init_s))
|
||||
|
@ -599,10 +621,10 @@ def emulate_builtin(name, arguments_v, ssa_env, heap):
|
|||
.format(name))
|
||||
else:
|
||||
struct_begin = arguments_v[1]
|
||||
print('Printing string, heap[{}]:'
|
||||
info('Printing string, heap[{}]:'
|
||||
.format(struct_begin))
|
||||
printee = heap[struct_begin + 1]
|
||||
print(printee)
|
||||
info(printee)
|
||||
if not isinstance(printee, str):
|
||||
warn('What was printed, was not stored as a string in the heap')
|
||||
elif name in builtins:
|
||||
|
@ -616,7 +638,14 @@ def emulate_builtin(name, arguments_v, ssa_env, heap):
|
|||
return res, new_heap, should_exit
|
||||
|
||||
|
||||
def auto_step(ast, function_name='tigermain', function_args=[1234, 5678]):
|
||||
def auto_step(ast, function_name='tigermain', function_args=[1234, 5678], step_behavior={}):
|
||||
# Set info-level
|
||||
if True:
|
||||
global PRINT_LEVEL
|
||||
PRINT_LEVEL = step_behavior['step_print_level']
|
||||
print(PRINT_LEVEL)
|
||||
|
||||
#
|
||||
tdecls = ast.tdecls
|
||||
fdecls = ast.fdecls
|
||||
gdecls = ast.gdecls
|
||||
|
@ -633,9 +662,9 @@ def auto_step(ast, function_name='tigermain', function_args=[1234, 5678]):
|
|||
call_res = []
|
||||
|
||||
global_env = alloc_globals(gdecls, heap)
|
||||
print('Heap after globals are allocated:')
|
||||
print(heap)
|
||||
print()
|
||||
info('Heap after globals are allocated:')
|
||||
info(heap)
|
||||
info()
|
||||
|
||||
step_cnt = 0
|
||||
while True:
|
||||
|
@ -644,18 +673,18 @@ def auto_step(ast, function_name='tigermain', function_args=[1234, 5678]):
|
|||
stack_frames, ssa_env,
|
||||
global_env, heap, tdecls,
|
||||
fdecls, call_res)
|
||||
print()
|
||||
info()
|
||||
step_cnt += 1
|
||||
if terminator is None:
|
||||
print('Stepping done!\nFinal ssa_env: {}'
|
||||
info('Stepping done!\nFinal ssa_env: {}'
|
||||
.format(ssa_env))
|
||||
print('Final heap: {}'
|
||||
info('Final heap: {}'
|
||||
.format(heap))
|
||||
print('Program resulted in {} after {} steps'.
|
||||
info('Program resulted in {} after {} steps'.
|
||||
format(insns[0][1].val, step_cnt))
|
||||
break
|
||||
|
||||
if step_cnt % 100 == 0:
|
||||
if step_behavior['step_ask'] != 0 and step_cnt % step_behavior['step_ask'] == 0:
|
||||
while True:
|
||||
stop_q = input('We have now done {} steps. Continue? [Y/n]: '
|
||||
.format(step_cnt)).lower()
|
||||
|
|
Loading…
Reference in New Issue
Block a user