Add support for allocRecord and initArray from runtime.c.

This commit is contained in:
cfreksen 2017-11-09 14:28:02 +01:00
parent 53ee6d3ef6
commit bef14dfa24
No known key found for this signature in database
GPG Key ID: EAC13EE101008978

View File

@ -25,6 +25,9 @@ class Garbage(Enum):
return '<<Garbage>>'
builtins = ['allocRecord', 'initArray']
def step(insns, terminator, blocks, stack_frames, ssa_env, global_env, heap,
tdecs, fdecs, call_res):
if len(insns) == 0:
@ -33,6 +36,23 @@ def step(insns, terminator, blocks, stack_frames, ssa_env, global_env, heap,
ssa_target, next_insn = insns[0]
insns_rest = insns[1:]
def store_in_ssa(res, insns_rest, terminator, blocks, stack_frames, ssa_env, heap,
call_res):
if ssa_target is not None:
if ssa_target in ssa_env:
err('Cannot assign to variable twice: {}'
.format(ssa_target))
elif res is None:
err('Cannot assign empty value to %{}'
.format(ssa_target))
else:
# TODO
print('%{} <- {}'
.format(ssa_target, res))
ssa_env[ssa_target] = res
return insns_rest, terminator, blocks, stack_frames, ssa_env, heap, call_res
# TODO
print('Evaluating {}'
.format(ll.insn2s(next_insn)))
@ -128,11 +148,26 @@ def step(insns, terminator, blocks, stack_frames, ssa_env, global_env, heap,
arguments_v = [eval_oper(oper, ssa_env, global_env)
for ty, oper in arguments]
try:
if callee.val in fdecs:
function = fdecs[callee.val]
except KeyError:
elif callee.val in builtins:
res, new_heap, should_exit = emulate_builtin(callee.val, arguments_v, ssa_env,
heap)
if should_exit:
new_insns = [(None, ll.CallResult(res))]
new_terminator = None
new_blocks = {}
new_ssa_env = ssa_env
new_stack_frames = []
new_call_res = []
return (new_insns, new_terminator, new_blocks, new_stack_frames,
new_ssa_env, heap, new_call_res)
else:
return store_in_ssa(res, insns_rest, terminator, blocks, stack_frames,
ssa_env, new_heap, call_res)
else:
err('Could not find function {} in environment:\n{}'
.format(callee.val, list(fdecs.keys())))
.format(callee.val, list(fdecs.keys()) + builtins))
return insns_rest, terminator, blocks, stack_frames, ssa_env, heap, call_res
parameters = function.parameters
@ -214,20 +249,8 @@ def step(insns, terminator, blocks, stack_frames, ssa_env, global_env, heap,
err('Unknown LLVM instruction: {}'
.format(next_insn))
if ssa_target is not None:
if ssa_target in ssa_env:
err('Cannot assign to variable twice: {}'
.format(ssa_target))
elif res is None:
err('Cannot assign empty value to %{}'
.format(ssa_target))
else:
# TODO
print('%{} <- {}'
.format(ssa_target, res))
ssa_env[ssa_target] = res
return insns_rest, terminator, blocks, stack_frames, ssa_env, heap, call_res
return store_in_ssa(res, insns_rest, terminator, blocks, stack_frames, ssa_env, heap,
call_res)
def terminate(terminator, blocks, stack_frames, ssa_env, global_env, heap, call_res):
@ -503,6 +526,71 @@ def alloc_globals(gdecls, heap):
return global_env
def emulate_builtin(name, arguments_v, ssa_env, heap):
new_heap = heap
res = None
should_exit = False
if name == 'allocRecord':
if len(arguments_v) != 1:
err('Number of arguments to {} should be 1'
.format(name))
else:
size = max(arguments_v[0], 1)
print('Allocating {} cells'
.format(size))
res = len(heap)
for i in range(size):
heap.append(Garbage.GARBAGE)
elif name == 'initArray':
if len(arguments_v) != 3:
err('Number of arguments to {} should be 3'
.format(name))
else:
num_elements = arguments_v[0]
cells_per_element = arguments_v[1]
init_ptr = arguments_v[2]
print('Allocating {} + {} + {} (size + pointer + content) cells'
.format(1, 1, num_elements * cells_per_element))
struct_begin = len(heap)
heap.append(num_elements)
heap.append(Garbage.GARBAGE) # pointer to array contents
array_begin = len(heap)
heap[struct_begin + 1] = array_begin
init_val = [heap[init_ptr + j]
for j in range(cells_per_element)]
if len(init_val) == 1:
init_val_s = init_val[0]
else:
init_val_s = '{{}}'.format(', '.join(init_val))
for i in range(num_elements):
array_last = len(heap)
for j in init_val:
heap.append(j)
if num_elements <= 0:
array_init_s = 'No elements initialized for zero length array'
else:
array_init_s = ('heap[{}..{}] <- heap[{}] = {}'
.format(array_begin, array_last,
init_ptr, init_val_s))
# TODO
print('heap[{}] <- {}, heap[{}] <- {}, --- {}'
.format(struct_begin, num_elements,
struct_begin + 1, array_begin,
array_init_s))
res = struct_begin
elif name in builtins:
TODO('Have not implemented builtin function {}, yet.'
.format(name))
else:
err('Unknown builtin function {}.'
.format(name))
return None, heap
return res, new_heap, should_exit
def auto_step(ast, function_name='tigermain', function_args=[1234, 5678]):
tdecls = ast.tdecls
fdecls = ast.fdecls