def ternary_expression(expr, symbol_table): if_false_instr, end_of_conditional_instr = Pass(loc(expr)), Pass(loc(expr)) expression = symbol_table['__ expression __'] return chain( get_jump_false(size_arrays_as_pointers(c_type(exp(expr))))(expression( exp(expr), symbol_table), Offset(if_false_instr, loc(expr)), loc(expr)), expression(left_exp(expr), symbol_table), relative_jump( Offset(end_of_conditional_instr, loc(end_of_conditional_instr)), loc(expr)), (if_false_instr, ), expression(right_exp(expr), symbol_table), (end_of_conditional_instr, ), )
def const_string_expr(expr): # strings are embedded ... data = static_binaries(expr) _initial_data = peek(data) # there should be at least one char, '\0' _push = push(Address(_initial_data, loc(expr)), loc(expr)) return chain( relative_jump(Offset(peek(_push, loc(expr)), loc(expr)), loc(expr)), consume_all(data, _push))
def goto_statement(stmnt, symbol_table): labels, gotos, stack = imap(symbol_table.__getitem__, ('__ LABELS __', '__ GOTOS __', '__ stack __')) if stmnt.label in labels: # Label previously defined either in current or previous scope ... nothing to do ... instr, stack_pointer = labels[stmnt.label] instrs = chain( update_stack(stack_pointer, stack.stack_pointer, loc(stmnt)), relative_jump(Offset(instr, loc(stmnt)), loc(stmnt)) ) else: # Label has yet to be defined ... # Basically we need to update the relative jump and the amount to which we need to update the stack ... # TODO: find/use a better approach, we can't use Address since it'll be translated ... alloc_instr = Allocate(loc(stmnt), Offset(Integer(0), loc(stmnt))) jump_instr = RelativeJump(loc(stmnt), Offset(None, loc(stmnt))) gotos[stmnt.label].append((alloc_instr, jump_instr, stack.stack_pointer)) instrs = (alloc_instr, jump_instr) return instrs
def continue_statement(stmnt, symbol_table): try: instr, stack_pointer = symbol_table['__ continue __'] except KeyError as _: raise ValueError('{l} continue statement outside loop statement, could not calc jump addr'.format( l=loc(stmnt) )) return chain( update_stack(symbol_table['__ stack __'].stack_pointer, stack_pointer, loc(stmnt)), relative_jump(Offset(instr, loc(stmnt)), loc(stmnt)) )
def static_definition(stmnt, symbol_table): def load_address(self, location): return push(Address(self._initial_data, location), location) data = static_def_binaries(stmnt, (Pass(loc(stmnt)),)) stmnt._initial_data = peek(data) stmnt.end_of_data = Pass(loc(stmnt)) stmnt.load_address = bind_load_address_func(load_address, stmnt) symbol_table[declarations.name(stmnt)] = stmnt return chain( # jump over embedded data ... relative_jump(Offset(stmnt.end_of_data, loc(stmnt)), loc(stmnt)), consume_all(data), (stmnt.end_of_data,) )
def if_statement(stmnt, symbol_table): end_of_if, end_of_else = Pass(loc(stmnt)), Pass(loc(stmnt)) expression, statement = imap(symbol_table.__getitem__, ('__ expression __', '__ statement __')) for instr in chain( get_jump_false(size_arrays_as_pointers(c_type(exp(stmnt))))( expression(exp(stmnt), symbol_table), Offset(end_of_if, loc(end_of_if)), loc(end_of_if)), statement(stmnt.statement, symbol_table)): yield instr else_stmnt = stmnt.else_statement.statement if else_stmnt: for instr in chain( relative_jump(Offset(end_of_else, loc(end_of_else)), loc(stmnt)), (end_of_if, ), statement(else_stmnt, symbol_table), (end_of_else, ), ): yield instr else: yield end_of_if
def body(stmnt, symbol_table, end_switch): symbol_table = push(symbol_table) stack, statement = imap(symbol_table.__getitem__, ('__ stack __', '__ statement __')) symbol_table['__ break __'] = (end_switch, stack.stack_pointer) symbol_table['__ switch __'] = True allocation_table = [ ] # create an allocation table to update stack before jump in case of nested definitions switch_body_instrs = [] cases = {'default': Offset(end_switch, loc(stmnt))} for instr in statement(stmnt.statement, symbol_table): if isinstance(getattr(instr, 'case', None), CaseStatement): start = Pass(loc(instr)) allocation_table.append( chain( (start, ), update_stack(stmnt.stack.stack_pointer, instr.case.stack.stack_pointer, loc(instr)), relative_jump(Offset(instr, loc(instr)), loc(instr)), )) cases[error_if_not_type(exp(exp(instr.case)), (int, long, str))] = Offset( start, loc(instr)) del instr.case switch_body_instrs.append(instr) max_switch_value = 2**(8 * size_arrays_as_pointers(c_type(exp(stmnt)))) - 1 for instr in jump_table(loc(stmnt), cases, allocation_table, max_switch_value, switch_body_instrs): yield instr _ = pop(symbol_table)
def call_function(function_call_expr, symbol_table): l, expr = loc(function_call_expr), left_exp(function_call_expr) return chain( # if expression is a simple identifier of function type, no need for AbsoluteJump, use RelativeJump set_base_stack_pointer(load_stack_pointer(l), l), relative_jump( Offset(symbol_table[name(expr)].get_address_obj(l).obj, l), l), ) if isinstance(expr, IdentifierExpression) and isinstance( c_type(expr), FunctionType ) else absolute_jump( chain( symbol_table['__ expression __']( expr, symbol_table), # load callee address # calculate new base stack pointer excluding the callees address ... # give the callee a new frame... if we where to reset the base stack ptr before evaluating the left_expr # we run the risk of failing to properly load function address if it was store as a local function pointer set_base_stack_pointer( add(load_stack_pointer(l), push(size(void_pointer_type), l), l), l)), l)