def gen_return_statement(ast): assert ast[0] == 'ReturnStatement' if len(ast) >= 3 and ast[2] != ';': # return some expression ret = gen_expression_no_in(ast[2]) builder.inst_st(ret, Registers.fp(), -12) Registers.free([ret]) builder.inst_ret()
def gen_do_statement(ast): assert ast[0] == 'DoStatement' loop_label = Labels.temp() gen_statement(ast[2]) cond = gen_expression_no_in(ast[5]) builder.inst_bnz(cond, loop_label) Registers.free([cond])
def exec_getvar(inst): func_addr = Memory.read_plain(Registers.read_fp() - 4) rs_val = Registers.get_reg(inst['rs']) while True: arg_field = Memory.get_field(func_addr, Constants.get_str('arguments')) arg_obj = Memory.get_prop(arg_field)['value'] var_field = Memory.get_field(arg_obj, rs_val) if var_field: # The field is found in arguments. offset_addr = Memory.get_prop(var_field)['value'] offset = Memory.get_int(offset_addr) Registers.set_reg(inst['rd'], Memory.read_plain(Registers.read_fp() + offset)) break scope_field = Memory.get_field(func_addr, Constants.get_str('scope')) scope_obj = Memory.get_prop(scope_field)['value'] var_field = Memory.get_field(scope_obj, rs_val) if var_field: # The field is found in scope. var_obj = Memory.get_prop(var_field)['value'] Registers.set_reg(inst['rd'], var_obj) break outer_field = Memory.get_field(func_addr, Constants.get_str('outer')) outer_obj = Memory.get_prop(outer_field)['value'] if not outer_obj: # The field 'outer' is empty. func_addr = Memory.read_plain(Registers.read_fp() - 4) scope_field = Memory.get_field(func_addr, Constants.get_str('scope')) scope_obj = Memory.get_prop(scope_field)['value'] prop_addr = Memory.new_field(scope_obj, rs_val) obj_addr = Memory.new_obj() Memory.set_prop(prop_addr, value=obj_addr) Registers.set_reg(inst['rd'], obj_addr) break else: func_addr = outer_obj inc_pc(4)
def gen_variable_statement(ast): assert ast[0] == 'VariableStatement' identifier = gen_identifier(ast[2]) if len(ast) > 4: temp = gen_assignment_expression_no_in(ast[4]) builder.inst_move(identifier, temp) Registers.free([temp]) Registers.free([identifier])
def exec_newfunc(inst): func_addr = Memory.new_func() address_prop = Memory.get_field(func_addr, Constants.get_str('address')) Memory.set_prop(address_prop, value=Memory.new_int(Labels.query(inst['label']))) outer_func = Memory.read_plain(Registers.read_fp() - 4) outer_prop = Memory.get_field(func_addr, Constants.get_str('outer')) Memory.set_prop(outer_prop, value=outer_func) Registers.set_reg(inst['rd'], func_addr) inc_pc(4)
def get_ret(self, rd): """ Get return value after a function call. Also, it modifies fp and sp accordingly. :param rd: register to store the value """ self.inst_ld(rd, Registers.fp(), -12) # get return value self.inst_move(Registers.sp(), Registers.fp()) # reset stack pointer self.pop(Registers.fp())
def exec_mul(inst): rs_obj = Memory.get_obj(Registers.get_reg(inst['rs'])) rt_obj = Memory.get_obj(Registers.get_reg(inst['rt'])) rd_val = Registers.get_reg(inst['rd']) if rs_obj['type'] == 0 and rt_obj['type'] == 0: # both are integers Memory.set_int(rd_val, rs_obj['data'] * rt_obj['data']) elif {rs_obj['type'], rt_obj['type']} == {0, 2}: # an integer and a string str_addr = Memory.new_str(rs_obj['data'] * rt_obj['data']) Memory.set_obj(rd_val, Memory.get_obj(str_addr)) inc_pc(4)
def gen_while_statement(ast): assert ast[0] == 'WhileStatement' exit_label = Labels.temp() loop_label = Labels.temp() builder.insert_label(loop_label) cond = gen_expression_no_in(ast[3]) builder.inst_bez(cond, exit_label) Registers.free([cond]) gen_statement(ast[5]) builder.inst_j(loop_label) builder.insert_label(exit_label)
def gen_object_literal(ast): assert ast[0] == 'ObjectLiteral', str(ast) obj = Registers.allocate(1)[0] builder.inst_newobj(obj) for node in ast[2]: if type(node) != list: continue key = gen_property_name(node[1]) value = gen_assignment_expression_no_in(node[3]) builder.inst_getfield(key, obj, key) builder.inst_move(key, value) Registers.free([key, value]) return obj
def gen_origin_for_statement(ast): assert ast[0] == 'OriginForStatement' exit_label = Labels.temp() loop_label = Labels.temp() gen_expression_no_in(ast[3]) builder.insert_label(loop_label) cond = gen_expression_no_in(ast[5]) builder.inst_bez(cond, exit_label) Registers.free([cond]) gen_statement(ast[9]) gen_expression_no_in(ast[7]) builder.inst_j(loop_label) builder.insert_label(exit_label)
def gen_function_expression(ast): assert ast[0] == 'FunctionExpression' label = Labels.function() func, temp = Registers.allocate(2) builder.inst_newfunc(func, label) context['function'].append(func) if ast[2] != '(': # The function has an identifier identifier = gen_identifier(ast[2], True) builder.inst_getvar(temp, identifier) builder.inst_move(temp, func) Registers.free([identifier]) args, t1, t2 = Registers.allocate(3) builder.inst_la(t1, Constants.string('arguments')) builder.inst_getfield(args, func, t1) if ast[-3] != '(': # The function has arguments offset = -16 for node in ast[-3]: if type(node) == list: arg = gen_identifier(node, True) builder.inst_getfield(t1, args, arg) builder.inst_la(t2, Constants.integer(offset)) builder.inst_move(t1, t2) Registers.free([arg]) offset -= 4 Registers.free([t1, t2]) # The function body starts. builder.enter(label) gen_function_body(ast[-1]) builder.exit(label) context['function'].pop() return func
def gen_member_expression(ast): assert ast[0] == 'MemberExpression' if ast[1][0] == 'PrimaryExpression': return gen_primary_expression(ast[1]) elif ast[1][0] == 'MemberExpression': obj = gen_member_expression(ast[1]) prop = gen_member_expression_part(ast[2]) # TODO check whether need to create a field rd = Registers.allocate(1)[0] builder.inst_getfield(rd, obj, prop) Registers.free([obj, prop]) return rd elif ast[1][0] == 'AllocationExpression': return gen_allocation_expression(ast[1])
def gen_literal(ast): assert ast[0] == 'Literal' if type(ast[1]) == int: label = Constants.integer(ast[1]) rd = Registers.allocate(1)[0] builder.inst_la(rd, label) return rd elif type(ast[1]) == str: return gen_string_literal(ast[1]) elif type(ast[1]) == bool: label = Constants.integer(1 if ast[1] else 0) rd = Registers.allocate(1)[0] builder.inst_la(rd, label) return rd
def exec_add(inst): rs_obj = Memory.get_obj(Registers.get_reg(inst['rs'])) rt_obj = Memory.get_obj(Registers.get_reg(inst['rt'])) rd_val = Registers.get_reg(inst['rd']) if rs_obj['type'] == 0 and rt_obj['type'] == 0: # both are integers Memory.set_int(rd_val, rs_obj['data'] + rt_obj['data']) elif rs_obj['type'] == 3 and rs_obj['data'] == 0: # rs references an empty object Memory.set_obj(rd_val, rt_obj) elif rt_obj['type'] == 3 and rt_obj['data'] == 0: # rt references an empty object Memory.set_obj(rd_val, rs_obj) elif rs_obj['type'] == 2 and rt_obj['type'] == 2: # both are strings str_addr = Memory.new_str(rs_obj['data'] + rt_obj['data']) Memory.set_obj(rd_val, Memory.get_obj(str_addr)) # TODO: more cases in addition inc_pc(4)
def gen_identifier(ast, as_literal=False): assert ast[0] == 'Identifier' ret = Registers.allocate(1)[0] builder.inst_la(ret, Constants.string(ast[1])) if not as_literal: builder.inst_getvar(ret, ret) # TODO: getvar/findvar? return ret
def exec_typeof(inst): obj = Memory.get_obj(Registers.get_reg(inst['rs'])) types = { 0: 'integer', 2: 'string', 3: 'object', 4: 'function', 5: 'null', 6: 'undefined', 7: 'function', 8: 'function', 9: 'function' } res = types[obj['type']] Registers.set_reg(inst['rd'], Constants.get_str(res)) inc_pc(4)
def call_func(self, func, this, args): fp = Registers.fp() sp = Registers.sp() temp, zero = Registers.allocate(2) self.inst_newobj(temp) self.inst_la(zero, Constants.integer(0)) self.inst_add(temp, fp, zero) self.push(temp) # push fp Registers.free([temp, zero]) self.inst_move(fp, sp) self.push(0) # dummy push for return address self.push(func) self.push(this) self.push(0) # dummy push for return value for arg in args: self.push(arg) self.inst_jalr(func)
def gen_if_statement(ast): assert ast[0] == 'IfStatement' exp = gen_expression_no_in(ast[3]) exit_label = Labels.temp() if ast[-2] == 'else': # it has 'else' clause else_label = Labels.temp() builder.inst_bez(exp, else_label) gen_statement(ast[5]) builder.inst_j(exit_label) builder.insert_label(else_label) gen_statement(ast[7]) builder.insert_label(exit_label) else: # It has no 'else' clause builder.inst_bez(exp, exit_label) gen_statement(ast[5]) builder.insert_label(exit_label) Registers.free([exp])
def exec_jalr(inst): Memory.write_plain(Registers.read_fp(), read_pc()) # set return address func_obj = Memory.get_obj(Registers.get_reg(inst['rd'])) if func_obj['type'] == 7: # panel.readInt() num = int(raw_input('Please enter an integer.\n')) num_addr = Memory.new_int(num) Memory.write_plain(Registers.read_fp() - 12, num_addr) inc_pc(4) elif func_obj['type'] == 8: # panel.readStr() string = raw_input('Please enter an string.\n') str_addr = Memory.new_str(string) Memory.write_plain(Registers.read_fp() - 12, str_addr) inc_pc(4) elif func_obj['type'] == 9: # panel.show() arg = Memory.read_plain(Registers.read_fp() - 16) Memory.print_obj(arg) inc_pc(4) else: assert func_obj['type'] == 4 func_addr = Registers.get_reg(inst['rd']) address_field = Memory.get_field(func_addr, Constants.get_str('address')) address_addr = Memory.get_prop(address_field)['value'] address = Memory.get_int(address_addr) Memory.write_plain(Registers.read_fp(), read_pc() + 4) write_pc(address)
def __init__(self, memory_dict): #______ Buses ______ self.Main_bus = Bus.Bus(4) self.Memory_address_bus = Bus.Bus(4) self.ALU_op_bus = Bus.Bus(1) self.Register_address_bus = Bus.Bus(1) self.Output_address_bus = Bus.Bus self.Registers = Registers.Register_bank(self.Main_bus, self.Register_address_bus) self.Memory_address_register = Registers.Memory_address_register( self.Main_bus, self.Memory_address_bus, 4) self.Memory = Memory.Memory(self.Memory_address_bus, self.Main_bus, memory_dict) self.ALU = ALU.ALU(self.Main_bus, self.Main_bus, self.ALU_op_bus) self.Output = Output.IO(self.Main_bus, self.Output_address_bus) self.halt = 0 self.instruction_count = 0
def exec_getfield(inst): name_addr = Registers.get_reg(inst['rt']) obj_addr = Registers.get_reg(inst['rs']) while True: try: field = Memory.get_field(obj_addr, name_addr) except Exception as e: Memory.print_obj(obj_addr) Memory.print_obj(name_addr) raise e if not field: # The field cannot be found. ctor_addr = Memory.get_field(obj_addr, Constants.get_str('constructor')) if not ctor_addr: # There is no constructor field new_field = Memory.new_field(Registers.get_reg(inst['rs']), name_addr) Memory.set_prop(new_field, value=Memory.new_obj()) res = Memory.get_prop(new_field) break ctor_obj = Memory.get_prop(ctor_addr)['value'] proto_addr = Memory.get_field(ctor_obj, Constants.get_str('prototype')) if not proto_addr: # There is no prototype field new_field = Memory.new_field(Registers.get_reg(inst['rs']), name_addr) Memory.set_prop(new_field, value=Memory.new_obj()) res = Memory.get_prop(new_field) break obj_addr = Memory.get_prop(proto_addr)['value'] # Find field in the prototype else: res = Memory.get_prop(field) break Registers.set_reg(inst['rd'], res['value']) inc_pc(4) """
def gen_call_expression(ast, this=None): assert ast[0] == 'CallExpression' if ast[2][0] == 'Arguments': if ast[1][0] == 'MemberExpression': callee = gen_member_expression(ast[1]) elif ast[1][0] == 'CallExpression': callee = gen_call_expression(ast[1]) args = [] if ast[2][-2] != '(': # there are some arguments for node in ast[2][-2]: if type(node) == list: args.append(gen_assignment_expression_no_in(node)) temp = Registers.allocate(1)[0] if not this: builder.get_this(temp) else: temp = this builder.insert_comment('Prepare to call function') builder.call_func(callee, temp, args) Registers.free([callee] + args) builder.get_ret(temp) return temp
def exec_cmp(inst): rs_obj = Memory.get_obj(Registers.get_reg(inst['rs'])) rt_obj = Memory.get_obj(Registers.get_reg(inst['rt'])) if rs_obj['type'] == rt_obj['type'] and rs_obj['data'] == rt_obj['data']: Registers.set_reg(inst['rd'], Constants.get_int(1)) else: Registers.set_reg(inst['rd'], Constants.get_int(0)) inc_pc(4)
def getCode(self, line): elements = line.split(" ") result = "" if elements[0] in self.codes: elements = Service.DeleteCommas(elements) imm = Service.Str2Num(elements[-1]) imm = Service.Addr2BinU(imm, 20) result += imm registers = Registers.Registers() result += registers.getAddress(elements[1]) result += self.opcode else: Service.ERROR("Error: " + Service.InstNotFound + "in line: " + line) return result
def snapshot(pc): cur = state['cur'] if cur == -1: return records = state['records'] if pc == state['block']['exit']: # all infomation has been collected fixed = [False for i in range(34)] # recording whether the register value is fixed for index in sorted(records): # search for constants inst = records[index]['inst'] rd = inst['rd'] if inst['type'] == 'la': records[index]['freeze'] = True fixed[rd] = True elif inst['type'] in ['typeof', 'getvar']: if fixed[inst['rs']]: records[index]['freeze'] = True fixed[rd] = True elif inst['type'] == 'getfield': if fixed[inst['rs']] and fixed[inst['rt']]: records[index]['freeze'] = True fixed[rd] = True else: fixed[rd] = False shortpath = None for index in sorted(records): rd = records[index]['inst'].get('rd', 0) rd_val = records[index].get('rd', 0) frozen = records[index].get('freeze', False) if shortpath is None: if frozen: shortpath = {'regs': {rd: rd_val}} shortpaths[index] = shortpath else: if frozen: shortpath['regs'][rd] = rd_val else: shortpath['exit'] = index shortpath = None # pprint.pprint(shortpaths) # raise Exception() state['cur'] = -1 state['block'] = None state['records'] = {} else: record = {'inst': state['block']['insts'].pop()} if record['inst']['type'] in optimizable: record['rd'] = Registers.get_reg(record['inst']['rd']) records[pc] = record
def gen_primary_expression(ast): assert ast[0] == 'PrimaryExpression' if ast[1] == 'this': this = Registers.allocate(1)[0] builder.get_this(this) return this elif ast[1][0] == 'Literal': return gen_literal(ast[1]) elif ast[1][0] == 'Identifier': return gen_identifier(ast[1]) elif ast[1][0] == 'FunctionExpression': return gen_function_expression(ast[1]) elif ast[1][0] == 'ObjectLiteral': return gen_object_literal(ast[1]) # TODO pass
def getCode(self, line): elements = line.split(" ") result = "" if elements[0] in self.codes: elements = Service.DeleteCommas(elements) result = self.funct7.get(elements[0], "0000000") registers = Registers.Registers() result += registers.getAddress(elements[-1]) result += registers.getAddress(elements[-2]) result += self.funct3[elements[0]] result += registers.getAddress(elements[1]) result += self.opcode else: Service.ERROR("Error: " + Service.InstNotFound + "in line: " + line) return result
def exec_slt(inst): rs_obj = Memory.get_obj(Registers.get_reg(inst['rs'])) rt_obj = Memory.get_obj(Registers.get_reg(inst['rt'])) if (rs_obj['type'] == 0 and rt_obj['type'] == 0) or \ (rs_obj['type'] == 2 and rt_obj['type'] == 2): if rs_obj['data'] < rt_obj['data']: Registers.set_reg(inst['rd'], Constants.get_int(1)) else: Registers.set_reg(inst['rd'], Constants.get_int(0)) else: raise Exception('The following object are not comparable yet.\n' + '%s\n%s' % (str(rs_obj), str(rt_obj))) inc_pc(4)
def getCode(self, line, labels): elements = line.split(" ") result = "" if elements[0] in self.codes: elements = Service.DeleteCommas(elements) addr = labels[elements[-1]] addr = Service.Addr2BinU(addr, 21) addr = addr[::-1] result += addr[20] result += addr[1:11][::-1] result += addr[11] result += addr[12:20][::-1] registers = Registers.Registers() result += registers.getAddress(elements[1]) result += self.opcode else: Service.ERROR("Error: " + Service.InstNotFound + "in line: " + lines) return result
def getCode(self, line): elements = line.split(" ") result = "" if elements[0] in self.codes: elements = Service.DeleteCommas(elements) addr = elements[-1] addr = addr.split("(") offset = Service.Str2Num(addr[0]) offset = Service.Addr2Bin(offset, 12) result += offset addr[-1] = addr[-1][:-1] registers = Registers.Registers() result += registers.getAddress(addr[-1]) result += self.funct3[elements[0]] result += registers.getAddress(elements[1]) result += self.opcode else: Service.ERROR("Error: " + Service.InstNotFound + "in line: " + lines) return result
def getCode(self, line, labels): elements = line.split(" ") result = "" if elements[0] in self.codes: #Тут возможна ошибка (надо проеверять есть ли метка в labels) elements = Service.DeleteCommas(elements) addr = labels[elements[3]] addr = Service.Addr2Bin(addr, 13) addr = addr[::-1] result += addr[12] + addr[5:11][::-1] registers = Registers.Registers() result += registers.getAddress(elements[2]) result += registers.getAddress(elements[1]) result += self.funct3[elements[0]] result += addr[1:5][::-1] result += addr[11] result += self.opcode else: Service.ERROR("Error: " + Service.InstNotFound + "in line: " + line) return result
def gen_allocation_expression(ast): assert ast[0] == 'AllocationExpression' func = gen_member_expression(ast[2]) # it should be a function args = [] if ast[3][-2] != '(': # there are some arguments for node in ast[3][-2]: if type(node) == list: args.append(gen_assignment_expression_no_in(node)) this = Registers.allocate(1)[0] builder.inst_newobj(this) builder.call_func(func, this, args) Registers.free([this] + args) ret, temp = Registers.allocate(2) builder.get_this(ret) builder.get_ret(temp) # temp will be discarded immediately builder.inst_la(temp, Constants.string('constructor')) builder.inst_getfield(temp, ret, temp) builder.inst_move(temp, func) Registers.free([temp, func]) return ret
def save(self, reg): if type(self.regs) == list: # check whether it's None if reg not in [Registers.sp(), Registers.fp()] + self.regs: self.regs.append(reg)
def get_this(self, rd): self.inst_ld(rd, Registers.fp(), -8)
def pop(self, rd): sp = Registers.sp() self.inst_la(rd, Constants.integer(4)) # reuse rd so as not to introduce new register self.inst_add(sp, sp, rd) self.inst_ld(rd, sp, 0)
def gen_assignment_expression_no_in(ast): assert ast[0] == 'AssignmentExpressionNoIn' if len(ast) == 2: if ast[1][0] == 'LeftHandSideExpression': return gen_left_hand_side_expression(ast[1]) elif ast[1][0] == 'CallExpression': return gen_call_expression(ast[1]) elif ast[1][0] == 'MemberExpression': return gen_member_expression(ast[1]) elif len(ast) == 3: if ast[1][0] == 'AssignmentExpressionNoIn': raise Exception('Postfix operator is not supported yet.') rs = gen_assignment_expression_no_in(ast[1]) rt = Registers.allocate(1)[0] builder.inst_la(rt, Constants.integer(1)) if ast[2] == '++': builder.inst_add(rs, rs, rt) elif ast[2] == '--': builder.inst_sub(rs, rs, rt) Registers.free([rt]) return rs elif ast[1] == '++': rs = gen_assignment_expression_no_in(ast[2]) rt = Registers.allocate(1)[0] builder.inst_la(rt, Constants.integer(1)) builder.inst_add(rs, rs, rt) Registers.free([rt]) return rs elif ast[1] == '--': rs = gen_assignment_expression_no_in(ast[2]) rt = Registers.allocate(1)[0] builder.inst_la(rt, Constants.integer(1)) builder.inst_sub(rs, rs, rt) Registers.free([rt]) return rs elif ast[1] == 'typeof': rd = Registers.allocate(1)[0] rs = gen_assignment_expression_no_in(ast[2]) builder.inst_newobj(rd) builder.inst_typeof(rd, rs) Registers.free([rs]) return rd elif ast[1] == '+': return gen_assignment_expression_no_in(ast[2]) elif ast[1] == '-': rs = gen_assignment_expression_no_in(ast[2]) rd, rt = Registers.allocate(2) builder.inst_la(rt, Constants.integer(-1)) builder.inst_mul(rd, rs, rt) Registers.free([rs, rt]) return rd elif ast[1] == '~': rs = gen_assignment_expression_no_in(ast[2]) builder.inst_not(rs, rs) return rs elif ast[1] == '!': rs = gen_assignment_expression_no_in(ast[2]) t1 = Registers.allocate(1)[0] exit_label = Labels.temp() true_label = Labels.temp() builder.inst_newobj(t1) builder.inst_bnz(rs, true_label) builder.inst_la(t1, Constants.integer(1)) builder.inst_j(exit_label) builder.insert_label(true_label) builder.insert_la(t1, Constants.integer(0)) builder.insert_label(exit_label) return t1 elif len(ast) == 4: if ast[2] in ['=', '*=', '/=', '%=', '+=', '-=', '<<=', '>>=', '>>>=', '&=', '^=', '|=']: r1 = gen_left_hand_side_expression(ast[1]) elif ast[2] in ['||', '&&', '|', '&', '^', '==', '!=', '===', '!==', '<', '>', '<=', '>=', '<<', '>>', '>>>', '+', '-', '*', '/']: r1 = gen_assignment_expression_no_in(ast[1]) r2 = gen_assignment_expression_no_in(ast[3]) if ast[2] == '+': rd = Registers.allocate(1)[0] builder.inst_newobj(rd) builder.inst_add(rd, r1, r2) Registers.free([r1, r2]) return rd elif ast[2] == '-': rd = Registers.allocate(1)[0] builder.inst_newobj(rd) builder.inst_sub(rd, r1, r2) Registers.free([r1, r2]) return rd elif ast[2] == '*': rd = Registers.allocate(1)[0] builder.inst_newobj(rd) builder.inst_mul(rd, r1, r2) Registers.free([r1, r2]) return rd elif ast[2] == '/': rd = Registers.allocate(1)[0] builder.inst_newobj(rd) builder.inst_div(rd, r1, r2) Registers.free([r1, r2]) return rd elif ast[2] == '=': builder.inst_move(r1, r2) Registers.free([r2]) return r1 elif ast[2] == '*=': builder.inst_mul(r1, r1, r2) Registers.free([r2]) return r1 elif ast[2] == '/=': builder.inst_div(r1, r1, r2) Registers.free([r2]) return r1 elif ast[2] == '%=': builder.inst_mod(r1, r1, r2) Registers.free([r2]) return r1 elif ast[2] == '+=': builder.inst_add(r1, r1, r2) Registers.free([r2]) return r1 elif ast[2] == '-=': builder.inst_sub(r1, r1, r2) Registers.free([r2]) return r1 elif ast[2] == '<<=': builder.inst_sll(r1, r1, r2) Registers.free([r2]) return r1 elif ast[2] == '>>=': builder.inst_sra(r1, r1, r2) Registers.free([r2]) return r1 elif ast[2] == '>>>=': builder.inst_srl(r1, r1, r2) Registers.free([r2]) return r1 elif ast[2] == '&=': builder.inst_and(r1, r1, r2) Registers.free([r2]) return r1 elif ast[2] == '^=': builder.inst_xor(r1, r1, r2) Registers.free([r2]) return r1 elif ast[2] == '|=': builder.inst_or(r1, r1, r2) Registers.free([r2]) return r1 elif ast[2] == '||': rd = Registers.allocate(1)[0] exit_label = Labels.temp() ret_r1 = Labels.temp() builder.inst_newobj(rd) builder.inst_bnz(r1, ret_r1) builder.inst_move(rd, r2) builder.inst_j(exit_label) builder.insert_label(ret_r1) builder.inst_move(rd, r1) builder.insert_label(exit_label) Registers.free([r1, r2]) return rd elif ast[2] == '&&': rd = Registers.allocate(1)[0] exit_label = Labels.temp() ret_r1 = Labels.temp() builder.inst_newobj(rd) builder.inst_bez(r1, ret_r1) builder.inst_move(rd, r2) builder.inst_j(exit_label) builder.insert_label(ret_r1) builder.inst_move(rd, r1) builder.insert_label(exit_label) Registers.free([r1, r2]) return rd elif ast[2] == '|': rd = Registers.allocate(1)[0] builder.inst_newobj(rd) builder.inst_or(rd, r1, r2) Registers.free([r1, r2]) return rd elif ast[2] == '&': rd = Registers.allocate(1)[0] builder.inst_newobj(rd) builder.inst_and(rd, r1, r2) Registers.free([r1, r2]) return rd elif ast[2] == '^': rd = Registers.allocate(1)[0] builder.inst_newobj(rd) builder.inst_xor(rd, r1, r2) Registers.free([r1, r2]) return rd elif ast[2] == '==' or ast[2] == '===': rd = Registers.allocate(1)[0] builder.inst_newobj(rd) builder.inst_cmp(rd, r1, r2) Registers.free([r1, r2]) return rd elif ast[2] == '!=' or ast[2] == '!==': rd = Registers.allocate(1)[0] builder.inst_newobj(rd) builder.inst_cmp(rd, r1, r2) builder.inst_la(r1, Constants.integer(1)) builder.inst_sub(rd, r1, rd) Registers.free([r1, r2]) return rd elif ast[2] == '<': rd = Registers.allocate(1)[0] builder.inst_newobj(rd) builder.inst_slt(rd, r1, r2) Registers.free([r1, r2]) return rd elif ast[2] == '>': rd = Registers.allocate(1)[0] builder.inst_newobj(rd) builder.inst_slt(rd, r2, r1) Registers.free([r1, r2]) return rd elif ast[2] == '<=': rd = Registers.allocate(1)[0] builder.inst_newobj(rd) builder.inst_slt(rd, r2, r1) builder.inst_la(r1, Constants.integer(1)) # TODO: r1 should not be modified builder.inst_not(rd, r1, rd) Registers.free([r1, r2]) return rd elif ast[2] == '>=': rd = Registers.allocate(1)[0] builder.inst_newobj(rd) builder.inst_slt(rd, r1, r2) builder.inst_la(r1, Constants.integer(1)) # TODO: r1 should not be modified builder.inst_sub(rd, r1, rd) Registers.free([r1, r2]) return rd elif ast[2] == '<<': rd = Registers.allocate(1)[0] builder.inst_newobj(rd) builder.inst_sll(rd, r1, r2) Registers.free([r1, r2]) return rd elif ast[2] == '>>': rd = Registers.allocate(1)[0] builder.inst_newobj(rd) builder.inst_sra(rd, r1, r2) Registers.free([r1, r2]) return rd elif ast[2] == '>>>': rd = Registers.allocate(1)[0] builder.inst_newobj(rd) builder.inst_srl(rd, r1, r2) Registers.free([r1, r2]) return rd
def gen_expression_no_in_statement(ast): assert ast[0] == 'ExpressionNoInStatement' rd = gen_expression_no_in(ast[1]) Registers.free([rd])