Esempio n. 1
0
 def _gen_code_boolop(self, **kwargs):
     self.label_true = kwargs.get('on_true', CC.new_label())
     self.label_false = kwargs.get('on_false', CC.new_label())
     self.label_right = CC.new_label(
     )  # additional label to jump to the right operand
     for case in switch(self.type.type):
         if case(LP.AND):
             self.add_child_by_idx(0,
                                   on_true=self.label_right,
                                   on_false=self.label_false)
             self.add_instr(CC.LABEL, label=self.label_right)
             self.add_child_by_idx(1,
                                   on_true=self.label_true,
                                   on_false=self.label_false)
             break
         if case(LP.OR):
             self.add_child_by_idx(0,
                                   on_true=self.label_true,
                                   on_false=self.label_right)
             self.add_instr(CC.LABEL, label=self.label_right)
             self.add_child_by_idx(1,
                                   on_true=self.label_true,
                                   on_false=self.label_false)
             break
         if case():
             raise InternalError('wrong bool op type %s' % str(self.type))
     # if no jump keywords were given, the result will be used as a value -- push it
     if not self.has_jump_codes(kwargs):
         self.label_after = CC.new_label()
         self.add_instr(CC.LABEL, label=self.label_true)
         self.add_instr(CC.PUSH, src=Loc.const(1))
         self.add_instr(CC.JUMP, label=self.label_after)
         self.add_instr(CC.LABEL, label=self.label_false)
         self.add_instr(CC.PUSH, src=Loc.const(0))
         self.add_instr(CC.LABEL, label=self.label_after)
Esempio n. 2
0
 def print_codes(self):
     """ Debug: print the current codes list. """
     for i in xrange(len(self.codes)):
         code = self.codes[i]
         if (code['type'] == CC.EMPTY):
             debug('\n', no_hdr=True)
             continue
         d = code.copy()
         del d['type']
         debug('[%d]' % i, CC._code_name(code['type']) + '\t' + CC._str_code(d), no_hdr=True)
Esempio n. 3
0
 def codes(self):
     """ A generator that yields the intermediate codes. """
     for instr in self.instr:
         if CC.is_child(instr):
             for child_instr in instr['child'].codes():
                 yield child_instr
         else:
             yield instr
Esempio n. 4
0
 def mark_deleted(self, pos_or_iter, **kwargs):
     """ Mark code for deletion, at a single index or whole iterable. """
     if isinstance(pos_or_iter, int):
         self.codes[pos_or_iter]['_type'] = CC._code_name(self.codes[pos_or_iter]['type'])
         self.codes[pos_or_iter].update(kwargs)  # just for debugging, to put more indicators
         self.codes[pos_or_iter]['type'] = CC.DELETED
     else:
         for pos in pos_or_iter:
             self.mark_deleted(pos)
Esempio n. 5
0
 def output_assembly(cls):
     """ Output the assembly code. """
     debug('-------------- ASM OUTPUT ---------------------')
     try:
         asm_file = sys.stdout if Flags.output_to_stdout() else open(
             Flags.asm_file, 'w')
         for instr in Codes.gen_asm(cls.optimizer.codes):
             print(str(instr), file=asm_file)
         if not Flags.output_to_stdout():
             asm_file.close()
     except IOError as err:
         Status.add_error(err, fatal=True)
Esempio n. 6
0
 def __init__(self, tree, **kwargs):
     super(FunCode, self).__init__(tree, **kwargs)
     self.ret_type = tree.ret_type
     self.name = tree.name
     self.args = tree.args
     self.add_child(BlockCode(tree.children[0]))
     self.ret_label = CC.new_label()
     for i in xrange(len(self.args)):
         arg = self.args[i]
         self.tree.add_symbol(Symbol(arg.name, arg.type, Loc.arg_addr(i)))
     self.var_count = self.children[0].count_local_vars()
     debug('fun ', self.name, 'VAR COUNT: ', self.var_count)
     self.used_vars = 0  # how many local variables are currently allocated
Esempio n. 7
0
 def _insert_apply_pockets(self):
     """ Child function of propagate_constants, used to insert assignments before pocket
     indicators, because they can't be inserted before when iterating through the list. """
     start_pos = 0
     debug('APPLY POCKETS')
     for pos in self.matcher.gen_next(start_pos, attrlist=['apply_pocket']):
         # Generate the move instructions and insert them inside codes list.
         moves = map(lambda (reg, val): CC.mkcode(CC.MOV, src=val, dest=reg,
                                                  comment=CC.S_PROPAGATED),
                     self.codes[pos]['apply_pocket'].iteritems())
         debug('apply pocket: insert %d moves at %d' % (len(moves), pos))
         del self.codes[pos]['apply_pocket']
         self.codes[pos:pos] = moves
         start_pos = pos + len(moves) - 1
     # rebuild the jump maps
     self.scan_labels()
Esempio n. 8
0
 def _do_push_pop_reduction(self, indexes):
     """ Child function of reduce_push_pop, that does the actual reduction. Separate function
     just for code reuse. `indexes` should be a two-element position list."""
     p_push, p_pop = indexes
     src, dest = self.codes[p_push]['src'], self.codes[p_pop]['dest']
     if src == dest:
         debug('   deleting push-pop with same attrs at', str(indexes))
         self.mark_deleted(indexes)
         return 1
     else:
         debug('   combining [push, pop] to mov at', str(indexes))
         self.mark_deleted(p_push, _type='[push,pop]', dest=dest)
         self.codes[p_pop] = CC.mkcode(CC.MOV, src=src, dest=dest,
                                       comment='combined from [push,pop]')
         return 1
     return 0
Esempio n. 9
0
 def _cp_empty_pocket_if_needed(self, pos, code):
     """ Constant propagation: empty the pocket in case of calls or jumps. """
     # [1] On function call, empty the pocket.
     if len(self.pocket) and code['type'] == CC.CALL:
         debug('function call at %d, emptying pocket' % pos)
         self.pocket = {}
     # [2] On function exit, drop %eax and empty pocket.
     if len(self.pocket) and code['type'] == CC.ENDFUNC:
         if Loc.reg('a') in self.pocket.keys():
             self._add_to_apply_pocket(pos, {Loc.reg('a'): self.pocket[Loc.reg('a')]})
             debug('ENDFUNC at %d, dropping reg a' % pos)
         self.pocket = {}
     # [3] On jump instructions (both in-/out-bound) assign the pocket values anyway.
     if len(self.pocket) and code['type'] in [CC.JUMP, CC.IF_JUMP, CC.LABEL]:
         debug('%s at %d, reassigning pocket values' % (CC._code_name(code['type']),
                                                        pos))
         # We can't insert into a list while iterating, so save the pocket for now
         # TODO we could later skip at least some of pocket's values, if we check that
         # a value is the same at label and all jumps to it, or the register is not live.
         self._add_to_apply_pocket(pos, self.pocket.copy())
         self.pocket = {}
Esempio n. 10
0
 def _cp_two_const_operator(self, pos, code):
     """ Constant propagation for operators: if both operands are consts, calculate the result
     and propagate it instead."""
     # 'lhs' and 'rhs' are both registers with values stored in pocket, or only 'rhs' is and
     # 'lhs' is an actual constant (e.g. propagated there in previous loop iteration, when 'rhs'
     # was not yet propagated).
     if (self.matcher.match(
             code, type=self.BIN_OPS, lhs=self.CONST_OR_REG, rhs=Loc.reg(Loc.ANY)) and
             (code['lhs'].is_constant() or code['lhs'] in self.pocket) and
             code['rhs'] in self.pocket):
         debug('two-const operator %s at %d' % (CC._code_name(code['type']), pos))
         if code['type'] == CC.BOOL_OP:
             cmp_fun = {
                 'sete': operator.eq, 'setne': operator.ne,
                 'setg': operator.gt, 'setge': operator.ge,
                 'setl': operator.lt, 'setle': operator.le,
             }[code['op']]
             # The operator.* bool functions return bool, we want an int to push.
             op_fun = lambda x, y: int(cmp_fun(x, y))
         else:
             op_fun = {
                 CC.ADD: operator.add, CC.SUB: operator.sub,
                 CC.MUL: operator.mul, CC.DIV: operator.floordiv, CC.MOD: c_modulo
             }[code['type']]
         arg1 = int(self.pocket[code['rhs']].value)
         if code['lhs'].is_constant():
             arg2 = int(code['lhs'].value)
         else:
             arg2 = int(self.pocket[code['lhs']].value)
         res_val = op_fun(arg1, arg2)
         debug('   -> args %d, %d res %d' % (arg1, arg2, res_val))
         res_reg = code['dest'] if code['type'] in [CC.DIV, CC.MOD] else code['rhs']
         # Delete and re-insert value, to maintain hash properties.
         if res_reg in self.pocket:
             del self.pocket[res_reg]
         self.pocket[res_reg] = Loc.const(res_val)
         self.mark_deleted(pos, comment=CC.S_PROPAGATED, value=res_val)
         self.prop_consts += 1
         return True
Esempio n. 11
0
 def __init__(self, tree, **kwargs):
     super(StmtCode, self).__init__(tree, **kwargs)
     self.type = tree.type
     if 'no_children' not in kwargs:
         for child in tree.children:
             self.add_child(StmtFactory(child))
     for case in switch(self.type.type):
         if case(LP.IF):
             self.label_after = CC.new_label()
             # if there are less blocks, just evaluate condition and jump to label_after
             self.label_then = CC.new_label() if len(
                 self.children) > 1 else self.label_after
             self.label_else = CC.new_label() if len(
                 self.children) > 2 else self.label_after
             break
         if case(LP.WHILE):
             self.label_after = CC.new_label()
             self.label_cond = CC.new_label()
             self.label_block = CC.new_label() if len(
                 self.children) > 1 else self.label_cond
             break
Esempio n. 12
0
 def add_instr(self, type, **kwargs):
     """ Appends a code. """
     self.instr.append(CC.mkcode(type, **kwargs))