Add function calls.
This commit is contained in:
parent
d48042b01e
commit
0aa427ac02
16
ll.py
16
ll.py
|
@ -60,6 +60,8 @@ Gep = namedtuple('Gep', ['base_ty', 'oper_ty', 'oper', 'steps'])
|
||||||
Zext = namedtuple('Zext', ['from_ty', 'oper', 'to_ty'])
|
Zext = namedtuple('Zext', ['from_ty', 'oper', 'to_ty'])
|
||||||
Ptrtoint = namedtuple('Ptrtoint', ['pointer_ty', 'oper', 'to_ty'])
|
Ptrtoint = namedtuple('Ptrtoint', ['pointer_ty', 'oper', 'to_ty'])
|
||||||
|
|
||||||
|
CallResult = namedtuple('CallResult', ['val'])
|
||||||
|
|
||||||
Ret = namedtuple('Ret', ['ty', 'oper'])
|
Ret = namedtuple('Ret', ['ty', 'oper'])
|
||||||
Br = namedtuple('Br', ['label'])
|
Br = namedtuple('Br', ['label'])
|
||||||
Cbr = namedtuple('Cbr', ['ty', 'oper', 'then_label', 'else_label'])
|
Cbr = namedtuple('Cbr', ['ty', 'oper', 'then_label', 'else_label'])
|
||||||
|
@ -87,12 +89,19 @@ def oper2s(operand):
|
||||||
return str(operand.val)
|
return str(operand.val)
|
||||||
elif isinstance(operand, Id):
|
elif isinstance(operand, Id):
|
||||||
return '%' + operand.val
|
return '%' + operand.val
|
||||||
|
elif isinstance(operand, Gid):
|
||||||
|
return '@' + operand.val
|
||||||
else:
|
else:
|
||||||
# TODO
|
# TODO
|
||||||
print('oper2s: Unknown operand: {}'
|
print('oper2s: Unknown operand: {}'
|
||||||
.format(operand))
|
.format(operand))
|
||||||
|
|
||||||
|
|
||||||
|
def tyopers2s(ty_oper_list):
|
||||||
|
return ', '.join('{} {}'.format(ty2s(ty), oper2s(oper))
|
||||||
|
for ty, oper in ty_oper_list)
|
||||||
|
|
||||||
|
|
||||||
def insn2s(insn):
|
def insn2s(insn):
|
||||||
if isinstance(insn, Binop):
|
if isinstance(insn, Binop):
|
||||||
return ('{} {} {}, {}'
|
return ('{} {} {}, {}'
|
||||||
|
@ -102,6 +111,10 @@ def insn2s(insn):
|
||||||
return ('icmp {} {} {}, {}'
|
return ('icmp {} {} {}, {}'
|
||||||
.format(insn.cnd, ty2s(insn.ty),
|
.format(insn.cnd, ty2s(insn.ty),
|
||||||
oper2s(insn.left), oper2s(insn.right)))
|
oper2s(insn.left), oper2s(insn.right)))
|
||||||
|
elif isinstance(insn, Call):
|
||||||
|
return ('call {} {} ({})'
|
||||||
|
.format(ty2s(insn.return_ty), oper2s(insn.callee),
|
||||||
|
tyopers2s(insn.arguments)))
|
||||||
elif isinstance(insn, Bitcast):
|
elif isinstance(insn, Bitcast):
|
||||||
return ('bitcast {} {} to {}'
|
return ('bitcast {} {} to {}'
|
||||||
.format(ty2s(insn.from_ty), oper2s(insn.oper),
|
.format(ty2s(insn.from_ty), oper2s(insn.oper),
|
||||||
|
@ -114,6 +127,9 @@ def insn2s(insn):
|
||||||
return ('ptrtoint {}* {} to {}'
|
return ('ptrtoint {}* {} to {}'
|
||||||
.format(ty2s(insn.pointer_ty), oper2s(insn.oper),
|
.format(ty2s(insn.pointer_ty), oper2s(insn.oper),
|
||||||
ty2s(insn.to_ty)))
|
ty2s(insn.to_ty)))
|
||||||
|
elif isinstance(insn, CallResult):
|
||||||
|
return ('<<internal>>: function return {}'
|
||||||
|
.format(insn.val))
|
||||||
else:
|
else:
|
||||||
# TODO
|
# TODO
|
||||||
print('insn2s: Unknown insn: {}'
|
print('insn2s: Unknown insn: {}'
|
||||||
|
|
75
stepper.py
75
stepper.py
|
@ -20,7 +20,8 @@ def warn(msg):
|
||||||
def step(insns, terminator, blocks, stack_frames, ssa_env, global_env, memory,
|
def step(insns, terminator, blocks, stack_frames, ssa_env, global_env, memory,
|
||||||
tdecs, fdecs, call_res):
|
tdecs, fdecs, call_res):
|
||||||
if len(insns) == 0:
|
if len(insns) == 0:
|
||||||
return terminate(terminator, blocks, stack_frames, ssa_env, global_env, memory)
|
return terminate(terminator, blocks, stack_frames, ssa_env, global_env, memory,
|
||||||
|
call_res)
|
||||||
ssa_target, next_insn = insns[0]
|
ssa_target, next_insn = insns[0]
|
||||||
insns_rest = insns[1:]
|
insns_rest = insns[1:]
|
||||||
|
|
||||||
|
@ -51,6 +52,40 @@ def step(insns, terminator, blocks, stack_frames, ssa_env, global_env, memory,
|
||||||
# TODO
|
# TODO
|
||||||
print('icmp {} {}, {}'
|
print('icmp {} {}, {}'
|
||||||
.format(cnd, left_v, right_v))
|
.format(cnd, left_v, right_v))
|
||||||
|
elif isinstance(next_insn, ll.Call):
|
||||||
|
callee = next_insn.callee
|
||||||
|
arguments = next_insn.arguments
|
||||||
|
|
||||||
|
if not isinstance(callee, ll.Gid):
|
||||||
|
err('Cannot call anything but global identifiers: {}'
|
||||||
|
.format(ll.oper2s(callee)))
|
||||||
|
return insns_rest, terminator, blocks, stack_frames, ssa_env, memory, call_res
|
||||||
|
|
||||||
|
arguments_v = [eval_oper(oper, ssa_env, global_env)
|
||||||
|
for ty, oper in arguments]
|
||||||
|
|
||||||
|
try:
|
||||||
|
function = fdecs[callee.val]
|
||||||
|
except KeyError:
|
||||||
|
err('Could not find function {} in environment:\n{}'
|
||||||
|
.format(callee.val, fdecs.keys()))
|
||||||
|
return insns_rest, terminator, blocks, stack_frames, ssa_env, memory, call_res
|
||||||
|
|
||||||
|
parameters = function.parameters
|
||||||
|
print('call @{} ({})'
|
||||||
|
.format(callee.val,
|
||||||
|
', '.join('%{} <- {}'.format(par[1], arg)
|
||||||
|
for par, arg in zip(parameters, arguments_v))))
|
||||||
|
child_insns = function.body.first_block.insns
|
||||||
|
child_terminator = function.body.first_block.terminator
|
||||||
|
child_blocks = function.body.named_blocks
|
||||||
|
child_stack_frames = [(insns_rest, terminator, blocks, ssa_env)] + stack_frames
|
||||||
|
child_ssa_env = {par[1]: arg for par, arg in zip(parameters, arguments_v)}
|
||||||
|
child_memory = memory
|
||||||
|
child_call_res = [ssa_target] + call_res
|
||||||
|
return (child_insns, child_terminator, child_blocks, child_stack_frames,
|
||||||
|
child_ssa_env, child_memory, child_call_res)
|
||||||
|
|
||||||
elif isinstance(next_insn, ll.Bitcast):
|
elif isinstance(next_insn, ll.Bitcast):
|
||||||
oper = next_insn.oper
|
oper = next_insn.oper
|
||||||
from_ty = next_insn.from_ty
|
from_ty = next_insn.from_ty
|
||||||
|
@ -81,6 +116,8 @@ def step(insns, terminator, blocks, stack_frames, ssa_env, global_env, memory,
|
||||||
# TODO
|
# TODO
|
||||||
print('ptrtoint {}* {} to {}'
|
print('ptrtoint {}* {} to {}'
|
||||||
.format(ll.ty2s(pointer_ty), oper_v, ll.ty2s(to_ty)))
|
.format(ll.ty2s(pointer_ty), oper_v, ll.ty2s(to_ty)))
|
||||||
|
elif isinstance(next_insn, ll.CallResult):
|
||||||
|
res = next_insn.val
|
||||||
else:
|
else:
|
||||||
err('Unknown LLVM instruction: {}'
|
err('Unknown LLVM instruction: {}'
|
||||||
.format(next_insn))
|
.format(next_insn))
|
||||||
|
@ -95,10 +132,10 @@ def step(insns, terminator, blocks, stack_frames, ssa_env, global_env, memory,
|
||||||
.format(ssa_target, res))
|
.format(ssa_target, res))
|
||||||
ssa_env[ssa_target] = res
|
ssa_env[ssa_target] = res
|
||||||
|
|
||||||
return insns_rest, terminator, blocks, stack_frames, ssa_env, memory, None
|
return insns_rest, terminator, blocks, stack_frames, ssa_env, memory, call_res
|
||||||
|
|
||||||
|
|
||||||
def terminate(terminator, blocks, stack_frames, ssa_env, global_env, memory):
|
def terminate(terminator, blocks, stack_frames, ssa_env, global_env, memory, call_res):
|
||||||
def clear_block_from_ssa_env(insns, ssa_env):
|
def clear_block_from_ssa_env(insns, ssa_env):
|
||||||
for (id, insn) in insns:
|
for (id, insn) in insns:
|
||||||
if id is not None and id in ssa_env:
|
if id is not None and id in ssa_env:
|
||||||
|
@ -117,17 +154,21 @@ def terminate(terminator, blocks, stack_frames, ssa_env, global_env, memory):
|
||||||
# TODO
|
# TODO
|
||||||
print('Returning {}'
|
print('Returning {}'
|
||||||
.format(oper_v))
|
.format(oper_v))
|
||||||
|
|
||||||
if len(stack_frames) == 0:
|
if len(stack_frames) == 0:
|
||||||
new_insns = []
|
new_insns = [(None, ll.CallResult(oper_v))]
|
||||||
new_terminator = None
|
new_terminator = None
|
||||||
new_blocks = {}
|
new_blocks = {}
|
||||||
new_ssa_env = ssa_env
|
new_ssa_env = ssa_env
|
||||||
new_stack_frames = []
|
new_stack_frames = []
|
||||||
|
new_call_res = []
|
||||||
else:
|
else:
|
||||||
new_insns, new_terminator, new_blocks, new_ssa_env = stack_frames[0]
|
new_insns, new_terminator, new_blocks, new_ssa_env = stack_frames[0]
|
||||||
|
new_insns = [(call_res[0], ll.CallResult(oper_v))] + new_insns
|
||||||
new_stack_frames = stack_frames[1:]
|
new_stack_frames = stack_frames[1:]
|
||||||
|
new_call_res = call_res[1:]
|
||||||
return (new_insns, new_terminator, new_blocks, new_stack_frames,
|
return (new_insns, new_terminator, new_blocks, new_stack_frames,
|
||||||
new_ssa_env, memory, oper_v)
|
new_ssa_env, memory, new_call_res)
|
||||||
elif isinstance(terminator, ll.Br):
|
elif isinstance(terminator, ll.Br):
|
||||||
label = terminator.label
|
label = terminator.label
|
||||||
next_block = blocks[label]
|
next_block = blocks[label]
|
||||||
|
@ -144,7 +185,7 @@ def terminate(terminator, blocks, stack_frames, ssa_env, global_env, memory):
|
||||||
.format(label))
|
.format(label))
|
||||||
|
|
||||||
return (new_insns, new_terminator, blocks, stack_frames,
|
return (new_insns, new_terminator, blocks, stack_frames,
|
||||||
ssa_env, memory, None)
|
ssa_env, memory, call_res)
|
||||||
elif isinstance(terminator, ll.Cbr):
|
elif isinstance(terminator, ll.Cbr):
|
||||||
ty = terminator.ty
|
ty = terminator.ty
|
||||||
if ty != ll.SimpleType.I1:
|
if ty != ll.SimpleType.I1:
|
||||||
|
@ -168,7 +209,7 @@ def terminate(terminator, blocks, stack_frames, ssa_env, global_env, memory):
|
||||||
.format(operand_v, label))
|
.format(operand_v, label))
|
||||||
|
|
||||||
return (new_insns, new_terminator, blocks, stack_frames,
|
return (new_insns, new_terminator, blocks, stack_frames,
|
||||||
ssa_env, memory, None)
|
ssa_env, memory, call_res)
|
||||||
else:
|
else:
|
||||||
err('Unknown LLVM terminator: {}'
|
err('Unknown LLVM terminator: {}'
|
||||||
.format(terminator))
|
.format(terminator))
|
||||||
|
@ -241,15 +282,17 @@ def gogo():
|
||||||
data = r'''
|
data = r'''
|
||||||
define i64 @tigermain (i64 %U_mainSL_8, i64 %U_mainDummy_9) {
|
define i64 @tigermain (i64 %U_mainSL_8, i64 %U_mainDummy_9) {
|
||||||
%a = add i64 3, 5 ; please be 8
|
%a = add i64 3, 5 ; please be 8
|
||||||
%c = icmp eq i64 %a, 9
|
%c = icmp eq i64 %a, 8
|
||||||
br i1 %c, label %L1, label %L2
|
br i1 %c, label %L1, label %L1
|
||||||
L1:
|
L1:
|
||||||
%b = add i64 %a, %a
|
%b = call i64 @f (i64 7, i64 %a)
|
||||||
ret i1 %c
|
ret i1 %c
|
||||||
L2:
|
}
|
||||||
%d = add i64 %a, 1
|
|
||||||
%e = add i64 10, %d
|
define i64 @f (i64 %x, i64 %y) {
|
||||||
ret i64 %e
|
%a = mul i64 2, %y
|
||||||
|
%b = mul i64 %x, %a
|
||||||
|
ret i64 %b
|
||||||
}
|
}
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
@ -269,7 +312,7 @@ L2:
|
||||||
ssa_env = {}
|
ssa_env = {}
|
||||||
# TODO: memory structure has not been decided yet
|
# TODO: memory structure has not been decided yet
|
||||||
memory = [None]
|
memory = [None]
|
||||||
call_res = None
|
call_res = []
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
(insns, terminator, blocks,
|
(insns, terminator, blocks,
|
||||||
|
@ -282,7 +325,7 @@ L2:
|
||||||
print('Stepping done! Final ssa_env:\n{}'
|
print('Stepping done! Final ssa_env:\n{}'
|
||||||
.format(ssa_env))
|
.format(ssa_env))
|
||||||
print('Program resulted in {}'.
|
print('Program resulted in {}'.
|
||||||
format(call_res))
|
format(insns[0][1].val))
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user