import ll import parser def TODO(msg): print('TODO, not implemented yet at {}' .format(msg)) def err(msg): print('ERROR: {}' .format(msg)) def step(insns, terminator, blocks, stack_frames, ssa_env, global_env, memory, tdecs, fdecs, call_res): if len(insns) == 0: return terminate(terminator, blocks, stack_frames, ssa_env, global_env, memory) ssa_target, next_insn = insns[0] insns_rest = insns[1:] # TODO print('Evaluating {}' .format(ll.insn2s(next_insn))) res = None if isinstance(next_insn, ll.Binop): bop = next_insn.bop ty = next_insn.ty left = next_insn.left right = next_insn.right left_v = eval_oper(left, ssa_env, global_env) right_v = eval_oper(right, ssa_env, global_env) res = eval_binop(bop, left_v, right_v) # TODO print('{} {}, {}' .format(bop, left_v, right_v)) else: 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)) else: # TODO print('%{} <- {}' .format(ssa_target, res)) ssa_env[ssa_target] = res return insns_rest, terminator, blocks, stack_frames, ssa_env, memory, None def terminate(terminator, blocks, stack_frames, ssa_env, global_env, memory): if isinstance(terminator, ll.Ret): oper = terminator.oper if oper is None: oper_v = None else: oper_v = eval_oper(oper, ssa_env, global_env) if len(stack_frames) == 0: return [], None, [], [], ssa_env, memory, oper_v else: new_insns, new_terminator, new_blocks, new_ssa_env = stack_frames[0] new_stack_frames = stack_frames[1:] return (new_insns, new_terminator, new_blocks, new_stack_frames, new_ssa_env, memory, oper_v) else: err('Unknown LLVM terminator: {}' .format(terminator)) def eval_oper(operand, ssa_env, global_env): if isinstance(operand, ll.Null): return 0 elif isinstance(operand, ll.Const): return operand.val elif isinstance(operand, ll.Gid): TODO('eval_oper Gid') elif isinstance(operand, ll.Id): id = operand.val try: return ssa_env[id] except KeyError: err('Unable to find %{} in environment:\n{}' .format(id, ssa_env)) def eval_binop(bop, left, right): if bop == 'add': return left + right else: err('Unknown LLVM Binary operator: {}' .format(bop)) def gogo(): p = parser.LLVMParser() p.build() data = r''' define i64 @tigermain (i64 %U_mainSL_8, i64 %U_mainDummy_9) { %a = add i64 3, 5 ; please be 8 %b = add i64 %a, %a %c = add i64 %a, %b %d = add i64 100, %c ret i64 %d } ''' ast = p.parse(data) tdecs = ast.tdecls fdecs = ast.fdecls global_env = ast.gdecls tigermain = ast.fdecls['tigermain'] first_block = tigermain.body.first_block blocks = tigermain.body.named_blocks insns = first_block.insns terminator = first_block.terminator stack_frames = [] ssa_env = {} # TODO: memory structure has not been decided yet memory = [None] call_res = None while True: (insns, terminator, blocks, stack_frames, ssa_env, memory, call_res) = step(insns, terminator, blocks, stack_frames, ssa_env, global_env, memory, tdecs, fdecs, call_res) if terminator is None: print('Stepping done! Final ssa_env:\n{}' .format(ssa_env)) print('Program resulted in {}'. format(call_res)) break if __name__ == '__main__': gogo()