def binaries(body, symbol_table): symbol_table = push(symbol_table) symbol_table['__ stack __'] = Stack() # Each function call has its own Frame which is nothing more than a stack # Skip return address ... offset = size_arrays_as_pointers(void_pointer_type) + ( # if function has zero return size then the return pointer will be omitted ... size_arrays_as_pointers(void_pointer_type) * bool(size_arrays_as_pointers(c_type(c_type(dec)), overrides={VoidType: 0})) ) for parameter in c_type(dec): # monkey patch declarator objects add Load commands according to stack state; add to symbol table. symbol_table[name(parameter)] = bind_instructions(parameter, offset) assert not type(parameter) is ArrayType # TODO: fix this. offset += size_arrays_as_pointers(c_type(parameter)) symbol_table.update( izip(('__ CURRENT FUNCTION __', '__ LABELS __', '__ GOTOS __'), (dec, SymbolTable(), defaultdict(list))) ) def pop_symbol_table(symbol_table, location=loc(dec)): # pop symbol table once all binaries have being emitted yield (pop(symbol_table) or 1) and Pass(location) return chain( # body of function ... chain.from_iterable(imap(symbol_table['__ statement __'], chain.from_iterable(body), repeat(symbol_table))), return_instrs(loc(dec)), # default return instructions, in case one was not giving ... pop_symbol_table(symbol_table) # pop symbol_table once complete ... )
def non_static_pointer_typed_definition_initialized_by_array_type(stmnt, symbol_table): stack, expression = utils.symbol_table.get_symbols(symbol_table, '__ stack __', '__ expression __') expr = declarations.initialization(stmnt) assert not isinstance(expr, (expressions.Initializer, expressions.CompoundLiteral)) return chain( # evaluate stack expression, which will push values on the stack and initialized pointer with sp cast(expression(expr, symbol_table), c_type(expr), c_type(stmnt), loc(stmnt)), load_stack_pointer(loc(stmnt)) )
def element_selection(expr, symbol_table): instrs = symbol_table['__ expression __'](left_exp(expr), symbol_table) # if we are loading the structure then just remove the Load instr, calculate the elements offset and Load that elem if is_load(instrs): return element_instrs(c_type(left_exp(expr)), right_exp(expr), loc(expr), load_instrs=all_but_last(instrs, Loads, loc(expr))) struct_size, member_size = size(c_type( left_exp(expr))), size_arrays_as_pointers(c_type(expr)) addr_instrs = add( # calculate the loaded structured members address load_stack_pointer(loc(expr)), push(struct_member_offset(c_type(left_exp(expr)), right_exp(expr)), loc(expr)), loc(expr)) return chain( # copy the element then move it to the base of the structure and deallocate everything else set_instr( chain( # load the value in question if its not an array (which is just an address ...) (addr_instrs if isinstance(c_type(expr), ArrayType) else load( addr_instrs, member_size, loc(expr))), add(load_stack_pointer(loc(expr)), push((struct_size + member_size), loc(expr)), loc(expr)), ), member_size, loc(expr)), allocate(-(struct_size - member_size), loc( expr)) # deallocate structure and copied member (set leaves value) )
def __init__(self, left_exp, operator, right_exp, ctype, location=LocationNotSet): # error_if_not_assignable(left_exp, location) TODO: implement. if not safe_type_coercion(c_type(right_exp), c_type(left_exp)) or isinstance(c_type(left_exp), ArrayType): raise ValueError('{l} Cannot assign from type {from_type} to {to_type}'.format( l=location, from_type=c_type(right_exp), to_type=c_type(left_exp), )) super(AssignmentExpression, self).__init__(left_exp, operator, right_exp, ctype, location)
def element_selection(expr, symbol_table): instrs = symbol_table['__ expression __'](left_exp(expr), symbol_table) # if we are loading the structure then just remove the Load instr, calculate the elements offset and Load that elem if is_load(instrs): return element_instrs( c_type(left_exp(expr)), right_exp(expr), loc(expr), load_instrs=all_but_last(instrs, Loads, loc(expr)) ) struct_size, member_size = size(c_type(left_exp(expr))), size_arrays_as_pointers(c_type(expr)) addr_instrs = add( # calculate the loaded structured members address load_stack_pointer(loc(expr)), push(struct_member_offset(c_type(left_exp(expr)), right_exp(expr)), loc(expr)), loc(expr) ) return chain( # copy the element then move it to the base of the structure and deallocate everything else set_instr( chain( # load the value in question if its not an array (which is just an address ...) (addr_instrs if isinstance(c_type(expr), ArrayType) else load(addr_instrs, member_size, loc(expr))), add(load_stack_pointer(loc(expr)), push((struct_size + member_size), loc(expr)), loc(expr)), ), member_size, loc(expr) ), allocate(-(struct_size - member_size), loc(expr)) # deallocate structure and copied member (set leaves value) )
def arguments(func_type): return chain( takewhile(lambda arg: not isinstance(c_type(arg), VAListType), func_type), # emit all non-variable arguments ... takewhile(lambda arg: isinstance(c_type(arg), VAListType), repeat(func_type[-1])) # continuously emit last parameter )
def element_section_pointer(expr, symbol_table): return element_instrs( c_type(c_type(left_exp(expr))), right_exp(expr), loc(expr), load_instrs=symbol_table['__ expression __'](left_exp(expr), symbol_table) )
def __init__(self, c_decl, body): _ = error_if_not_type(c_type(c_decl), FunctionType) if not all(isinstance(arg, Declarator) for arg in c_type(c_decl)): raise ValueError('{l} FunctionDef must have concrete declarators as params'.format(l=loc(c_type(c_decl)))) if not isinstance(body, CompoundStatement): raise ValueError('{l} FunctionDef body is not a compound statement, got {g}'.format(l=loc(c_decl), g=body)) super(FunctionDefinition, self).__init__(name(c_decl), c_type(c_decl), body, loc(c_decl), c_decl.storage_class)
def non_static_default_typed_definition(stmnt, symbol_table): return cast( symbol_table['__ expression __'](declarations.initialization(stmnt), symbol_table), c_type(declarations.initialization(stmnt)), c_type(stmnt), loc(stmnt) )
def argument_address(func_type, cpu, mem): index = size(void_pointer_type) + (size(void_pointer_type) if size( c_type(c_type(func_type)), overrides={VoidType: 0}) else 0) for ctype in imap(c_type, func_type): yield cpu.base_pointer + index index += size(ctype)
def get_declaration_or_definition(decl, storage_class): _ = initialization(decl) and isinstance(storage_class, Extern) and raise_error( '{l} {ident} has both initialization expr and extern storage class'.format(l=loc(decl), ident=name(decl))) if isinstance(c_type(decl), (FunctionType, StructType)) and not name(decl) or isinstance(storage_class, Extern): return Declaration(name(decl), c_type(decl), loc(decl), storage_class) return Definition(name(decl), c_type(decl), initialization(decl), loc(decl), storage_class or Auto(loc(decl)))
def function_call(tokens, symbol_table, primary_exp): l = loc(consume(tokens)) func_type = error_if_not_type(c_type(c_type(primary_exp)), FunctionType) # get expression arguments. expression_argument_list = ArgumentExpressionList(tuple(get_args(tokens, symbol_table, func_type)), l) return error_if_not_value(tokens, TOKENS.RIGHT_PARENTHESIS) and FunctionCallExpression( primary_exp, expression_argument_list, c_type(func_type)(l), l )
def dot_oper(tokens, symbol_table, primary_exp): l = (error_if_not_type(c_type(primary_exp), (StructType, UnionType)) or 1) and loc( consume(tokens)) member_name = error_if_not_type(consume(tokens, ''), IDENTIFIER) return ElementSelectionExpression( primary_exp, member_name, c_type(member(c_type(primary_exp), member_name))(l), l)
def definition(dec, symbol_table): # Global definition. assert not isinstance(c_type(dec), FunctionType) symbol_table[name(dec)] = bind_load_instructions(dec) symbol_table[name(dec)].symbol = Data( # Add reference of symbol to definition to keep track of references # static binaries, (packed binaries since machine may require alignment ...) name(dec), static_def_binaries(dec), size(c_type(dec)), dec.storage_class, loc(dec), ) return symbol_table[name(dec)].symbol
def argument_address(func_type, cpu, mem): index = size(void_pointer_type) + ( size(void_pointer_type) if size(c_type(c_type(func_type)), overrides={VoidType: 0}) else 0 ) for ctype in imap(c_type, func_type): yield cpu.base_pointer + index index += size(ctype)
def declaration(stmnt, symbol_table): # This are non-global declarations they don't require any space # but they could be referenced (extern, or function type) symbol_type = Code if isinstance(c_type(stmnt), FunctionType) else Data stmnt.symbol = symbol_type(declarations.name(stmnt), (), None, stmnt.storage_class, loc(stmnt)) stmnt.symbol.size = size(c_type(stmnt), overrides={FunctionType: None}) symbol_table[declarations.name(stmnt)] = stmnt yield Pass(loc(stmnt))
def inc_dec(value, expr, symbol_table): return symbol_table['__ expression __']( CompoundAssignmentExpression( exp(expr), TOKENS.PLUS_EQUAL, ConstantExpression( value, IntegerType(loc(expr), unsigned=unsigned(c_type(expr))), loc(expr)), c_type(expr)(loc(expr)), loc(expr)), symbol_table, )
def expand_defaults(desig_expr, default_values): desig, ctype = max_designation_mag(desig_expr), c_type(default_values) length_diff = getattr(ctype, 'length', 0) is None and (desig - len(default_values) + 1) _ = length_diff > 0 and default_values.update( # expand defaults if incomplete ArrayType ... enumerate( initializer_defaults(ArrayType(c_type(ctype), length_diff)).itervalues(), len(default_values)))
def subscript_oper(tokens, symbol_table, primary_exp): location = error_if_not_type(c_type(primary_exp), PointerType) and loc( consume(tokens)) expr = symbol_table['__ expression __']( tokens, symbol_table) # subscript must be of Integral Type. _ = error_if_not_value(tokens, TOKENS.RIGHT_BRACKET) and error_if_not_type( c_type(expr), IntegralType) return ArraySubscriptingExpression(primary_exp, expr, c_type(c_type(primary_exp))(location), location)
def function_call(tokens, symbol_table, primary_exp): l = loc(consume(tokens)) func_type = error_if_not_type(c_type(c_type(primary_exp)), FunctionType) # get expression arguments. expression_argument_list = ArgumentExpressionList( tuple(get_args(tokens, symbol_table, func_type)), l) return error_if_not_value( tokens, TOKENS.RIGHT_PARENTHESIS) and FunctionCallExpression( primary_exp, expression_argument_list, c_type(func_type)(l), l)
def identifier_expression(expr, symbol_table): # Defaults to Load, assignment expression will update it to set. dec = symbol_table[name(expr)] if isinstance( c_type(dec), (FunctionType, ArrayType)): # Function/Array Types are nothing more than addresses. return dec.load_address(loc(expr)) return load(dec.load_address(loc(expr)), size_arrays_as_pointers(c_type(expr)), loc(expr))
def __return__(value, cpu, mem, os, func_signature=FunctionType(IntegerType(SysCallLocation), (), SysCallLocation)): cpu.instr_pointer = mem[cpu.base_pointer + word_size] # get return instruction ... assert size(c_type(c_type(func_signature))) == word_size mem[cpu.base_pointer + 2 * word_size] = value
def convert_declaration_to_definition(decl): _ = isinstance(decl, FunctionDefinition) and raise_error( '{l} Nested function definitions are not allowed.'.format(l=loc(decl))) # Non Function declaration without storage class is set to auto if type(decl) is Declaration and not isinstance( c_type(decl), FunctionType) and decl.storage_class is not Extern: decl = Definition( # all non-function-declarations within compound statements are definitions ... name(decl), c_type(decl), EmptyExpression(c_type(decl), loc(decl)), loc(decl), decl.storage_class or Auto(loc(decl))) return decl
def subtract(l_instrs, r_instrs, location, operand_types): exp_c_type, left_exp_c_type, right_exp_c_type = operand_types if all(imap(isinstance, operand_types[1:], repeat(PointerType))): # subtracting two pointers ... return divide( subtract.rules[base_c_type(void_pointer_type)][size(void_pointer_type)](l_instrs, r_instrs, location), push(size_extended(c_type(c_type(left_exp_c_type))), location), location, operand_types ) return pointer_arithmetic(l_instrs, r_instrs, location, operand_types)
def assign(expr, symbol_table): expression = symbol_table['__ expression __'] return set_instr( chain( cast(expression(right_exp(expr), symbol_table), c_type(right_exp(expr)), c_type(expr), loc(expr)), # remove default Load instruction, emit Set instruction ... all_but_last(expression(left_exp(expr), symbol_table), Loads, loc(expr)), ), size_arrays_as_pointers(c_type(expr)), # get the size exp returns an array make sure its treated as pointer ... loc(expr), )
def calculate_pointer_offset(instrs, pointer_type, location): return multiply( instrs, push(size_extended(c_type(pointer_type)), location), location, ( PointerType(c_type(pointer_type), location=location), pointer_type, LongType(LongType(location=location), location=location, unsigned=True) ) )
def inc_dec(value, expr, symbol_table): return symbol_table['__ expression __']( CompoundAssignmentExpression( exp(expr), TOKENS.PLUS_EQUAL, ConstantExpression(value, IntegerType(loc(expr), unsigned=unsigned(c_type(expr))), loc(expr)), c_type(expr)(loc(expr)), loc(expr) ), symbol_table, )
def convert_declaration_to_definition(decl): _ = isinstance(decl, FunctionDefinition) and raise_error( '{l} Nested function definitions are not allowed.'.format(l=loc(decl))) # Non Function declaration without storage class is set to auto if type(decl) is Declaration and not isinstance(c_type(decl), FunctionType) and decl.storage_class is not Extern: decl = Definition( # all non-function-declarations within compound statements are definitions ... name(decl), c_type(decl), EmptyExpression(c_type(decl), loc(decl)), loc(decl), decl.storage_class or Auto(loc(decl)) ) return decl
def get_declaration_or_definition(decl, storage_class): _ = initialization(decl) and isinstance( storage_class, Extern) and raise_error( '{l} {ident} has both initialization expr and extern storage class' .format(l=loc(decl), ident=name(decl))) if isinstance(c_type(decl), (FunctionType, StructType)) and not name(decl) or isinstance( storage_class, Extern): return Declaration(name(decl), c_type(decl), loc(decl), storage_class) return Definition(name(decl), c_type(decl), initialization(decl), loc(decl), storage_class or Auto(loc(decl)))
def set_default_initializer(initializer, default_values): # Complete ArrayTypes with initializer containing a single non designated expression assign the value through out if isinstance(c_type(default_values), ArrayType) \ and not isinstance(initializer[0], DesignatedExpression) \ and len(initializer) == 1 \ and c_type(default_values).length is not None: initializer = Initializer( enumerate(repeat(initializer[0], len(c_type(default_values)))), c_type(default_values)(loc(initializer)), loc(initializer) ) exhaust(imap(parse_designated_expr, initializer_desig_exprs(initializer, default_values), repeat(default_values))) return default_values
def __init__(self, c_decl, body): _ = error_if_not_type(c_type(c_decl), FunctionType) if not all(isinstance(arg, Declarator) for arg in c_type(c_decl)): raise ValueError( '{l} FunctionDef must have concrete declarators as params'. format(l=loc(c_type(c_decl)))) if not isinstance(body, CompoundStatement): raise ValueError( '{l} FunctionDef body is not a compound statement, got {g}'. format(l=loc(c_decl), g=body)) super(FunctionDefinition, self).__init__(name(c_decl), c_type(c_decl), body, loc(c_decl), c_decl.storage_class)
def defaults(ctype, designations=None): designations = designations or OrderedDict() if isinstance(ctype, NumericType): designations[0] = ConstantExpression(0, ctype(loc(ctype)), loc(ctype)) elif isinstance(ctype, ArrayType): for index in xrange(len(ctype)): designations[index] = defaults(c_type(ctype)) elif isinstance(ctype, StructType): for offset, member_name in enumerate(ctype.members): designations[offset] = defaults(c_type(ctype.members[member_name])) else: raise ValueError('{l} Unable to generate default expression for ctype {c}'.format(l=loc(ctype), c=ctype)) return designations
def exclamation_operator(expr, symbol_table): if not isinstance(c_type(exp(expr)), NumericType): raise ValueError('{l} exclamation operator only supports numeric types got {g}'.format( l=loc(expr), g=c_type(exp(expr)) )) assert not isinstance(c_type(exp(expr)), ArrayType) expression = symbol_table['__ expression __'] return get_compare(size_arrays_as_pointers(c_type(exp(expr))))( expression(exp(expr), symbol_table), expression(ConstantExpression(0, c_type(exp(expr))(loc(expr)), loc(expr),), symbol_table), loc(expr), (load_zero_flag(loc(expr)),) )
def get_binary_expression(tokens, symbol_table, l_exp, right_exp_func, exp_type): operator = consume(tokens) r_exp = right_exp_func(tokens, symbol_table) exp_type = max(imap(error_if_not_type, imap(c_type, (l_exp, r_exp)), repeat(exp_type))) if operator in LOGICAL_OPERATIONS: exp_type = logical_type if operator not in supported_operations(c_type(l_exp)): raise ValueError('{l} ctype {g} does not support {o}'.format(l=loc(l_exp), g=c_type(l_exp), o=operator)) if operator not in supported_operations(c_type(r_exp)): raise ValueError('{l} ctype {g} does not support {o}'.format(l=loc(r_exp), g=c_type(r_exp), o=operator)) return BinaryExpression(l_exp, operator, r_exp, exp_type(location=loc(operator)), loc(operator))
def definition(dec, symbol_table): # Global definition. assert not isinstance(c_type(dec), FunctionType) symbol_table[name(dec)] = bind_load_instructions(dec) symbol_table[name( dec )].symbol = Data( # Add reference of symbol to definition to keep track of references # static binaries, (packed binaries since machine may require alignment ...) name(dec), static_def_binaries(dec), size(c_type(dec)), dec.storage_class, loc(dec), ) return symbol_table[name(dec)].symbol
def cast_exp(expr): if c_type(expr) == c_type(exp(expr)): return exp(expr) if isinstance(exp(expr), ConstantExpression) and not isinstance(c_type(exp(expr)), ArrayType): to_type = c_type(expr) expr = exp(expr) location = loc(expr) if isinstance(expr, EmptyExpression): return EmptyExpression(to_type, loc(expr)) if isinstance(to_type, IntegralType): return ConstantExpression(int(exp(expr)), to_type(location), location) if isinstance(to_type, FloatType): return ConstantExpression(float(exp(expr)), to_type(location), location) return expr
def init_declarator(tokens, symbol_table, base_type=CType(''), storage_class=None): # : declarator ('=' assignment_expression or initializer)? decl = set_core_type( symbol_table['__ declarator __'](tokens, symbol_table), base_type) if peek_or_terminal(tokens) == TOKENS.EQUAL and consume(tokens): decl = Definition(name(decl), c_type(decl), EmptyExpression(c_type(decl)), loc(decl), storage_class) symbol_table[name( decl )] = decl # we have to add it to the symbol table for things like `int a = a;` expr = initializer_or_assignment_expression(tokens, symbol_table) # if declaration is an array type and the expression is of string_type then convert to initializer for parsing if isinstance(c_type(decl), ArrayType) and isinstance( c_type(expr), StringType): expr = Initializer( enumerate(exp(expr)), ArrayType(c_type(c_type(expr)), len(c_type(expr)), loc(expr)), loc(expr)) decl.initialization = parse_initializer(expr, decl) if isinstance( expr, Initializer) else expr else: symbol_table[name(decl)] = decl = Declaration(name(decl), c_type(decl), loc(decl)) return decl
def update_default_value(desig_expr, default_values): ctype, desig, expr = c_type(default_values), designation(desig_expr), exp(desig_expr) if desig >= len(default_values): logger.warning( '{0} Excess element {1} {2} in initializer, it will be ignored ... '.format( loc(desig_expr), desig, expr )) else: _ = (not safe_type_coercion(c_type(expr), c_type(default_values[desig]))) and raise_error( '{l} Unable to coerce from {f} to {t}'.format(l=loc(expr), f=c_type(expr), t=c_type(default_values[desig])) ) update_func = update_composite_type_initializer \ if isinstance(ctype, (StructType, ArrayType)) else update_scalar_type_initializer update_func(desig_expr, default_values)
def set_default_initializer(initializer, default_values): # Complete ArrayTypes with initializer containing a single non designated expression assign the value through out if isinstance(c_type(default_values), ArrayType) \ and not isinstance(initializer[0], DesignatedExpression) \ and len(initializer) == 1 \ and c_type(default_values).length is not None: initializer = Initializer( enumerate(repeat(initializer[0], len(c_type(default_values)))), c_type(default_values)(loc(initializer)), loc(initializer)) exhaust( imap(parse_designated_expr, initializer_desig_exprs(initializer, default_values), repeat(default_values))) return default_values
def defaults(ctype, designations=None): designations = designations or OrderedDict() if isinstance(ctype, NumericType): designations[0] = ConstantExpression(0, ctype(loc(ctype)), loc(ctype)) elif isinstance(ctype, ArrayType): for index in xrange(len(ctype)): designations[index] = defaults(c_type(ctype)) elif isinstance(ctype, StructType): for offset, member_name in enumerate(ctype.members): designations[offset] = defaults(c_type(ctype.members[member_name])) else: raise ValueError( '{l} Unable to generate default expression for ctype {c}'.format( l=loc(ctype), c=ctype)) return designations
def exclamation_operator(expr, symbol_table): if not isinstance(c_type(exp(expr)), NumericType): raise ValueError( '{l} exclamation operator only supports numeric types got {g}'. format(l=loc(expr), g=c_type(exp(expr)))) assert not isinstance(c_type(exp(expr)), ArrayType) expression = symbol_table['__ expression __'] return get_compare(size_arrays_as_pointers(c_type(exp(expr))))( expression(exp(expr), symbol_table), expression( ConstantExpression( 0, c_type(exp(expr))(loc(expr)), loc(expr), ), symbol_table), loc(expr), (load_zero_flag(loc(expr)), ))
def switch_statement(stmnt, symbol_table): _ = (not isinstance(c_type(exp(stmnt)), IntegralType)) and raise_error( '{l} Expected an integral type got {g}'.format(g=c_type(exp(stmnt)), l=loc(stmnt))) end_switch = Pass(loc(stmnt)) stmnt.stack = deepcopy(symbol_table['__ stack __']) # if switch inside loop, only update end_instruct, since continue jumps to start of loop break goes to end of switch 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) return chain(symbol_table['__ expression __'](exp(stmnt), symbol_table), body(stmnt, symbol_table, end_switch), (end_switch, ))
def update_scalar_type_initializer(desig_expr, default_values): assert len(default_values) == 1 expr, desig = exp(desig_expr), designation(desig_expr, 0) if desig != 0: logger.warning('Excess Elements in initializer ...') else: default_values[0] = cast(expr, c_type(default_values[0]))
def update_scalar_type_initializer(desig_expr, default_values): assert len(default_values) == 1 expr, desig = exp(desig_expr), designation(desig_expr, 0) if desig != 0: logger.warning('Excess Elements in initializer ...') else: default_values[0] = cast(expr, c_type(default_values[0]))
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 update_composite_type_initializer(desig_expr, default_values): desig = designation(desig_expr) if desig > default_values: logger.warning('Excess elements in initializer ...') else: assert len(default_values[desig]) == 1 default_values[desig][0] = cast(exp(desig_expr), c_type(default_values[desig][0]))
def func_type(expr): if isinstance(c_type(expr), FunctionType): return c_type(expr) elif isinstance(c_type(expr), PointerType) and isinstance(c_type(c_type(expr)), FunctionType): return c_type(c_type(expr)) else: raise ValueError('{l} Expected FunctionType or Pointer to FunctionType got {g}'.format( l=loc(expr), g=c_type(expr) ))
def cast_exp(expr): if c_type(expr) == c_type(exp(expr)): return exp(expr) if isinstance(exp(expr), ConstantExpression) and not isinstance( c_type(exp(expr)), ArrayType): to_type = c_type(expr) expr = exp(expr) location = loc(expr) if isinstance(expr, EmptyExpression): return EmptyExpression(to_type, loc(expr)) if isinstance(to_type, IntegralType): return ConstantExpression(int(exp(expr)), to_type(location), location) if isinstance(to_type, FloatType): return ConstantExpression(float(exp(expr)), to_type(location), location) return expr
def update_composite_type_initializer(desig_expr, default_values): desig = designation(desig_expr) if desig > default_values: logger.warning('Excess elements in initializer ...') else: assert len(default_values[desig]) == 1 default_values[desig][0] = cast(exp(desig_expr), c_type(default_values[desig][0]))
def parse_identifier_designated_expr(desig_expr, default_values): return parse_designated_expr( OffsetDesignatedExpression( offset(c_type(default_values), designation(desig_expr)), # get offset ... exp(desig_expr), loc(desig_expr)), default_values)
def update_default_value(desig_expr, default_values): ctype, desig, expr = c_type(default_values), designation(desig_expr), exp( desig_expr) if desig >= len(default_values): logger.warning( '{0} Excess element {1} {2} in initializer, it will be ignored ... ' .format(loc(desig_expr), desig, expr)) else: _ = (not safe_type_coercion(c_type(expr), c_type( default_values[desig]))) and raise_error( '{l} Unable to coerce from {f} to {t}'.format( l=loc(expr), f=c_type(expr), t=c_type(default_values[desig]))) update_func = update_composite_type_initializer \ if isinstance(ctype, (StructType, ArrayType)) else update_scalar_type_initializer update_func(desig_expr, default_values)
def parse_identifier_designated_expr(desig_expr, default_values): return parse_designated_expr( OffsetDesignatedExpression( offset(c_type(default_values), designation(desig_expr)), # get offset ... exp(desig_expr), loc(desig_expr) ), default_values )
def statement(stmnt, symbol_table): is_expression = isinstance(stmnt, expressions.Expression) # Set entry point to False if its an expression or use statement function if present otherwise None. instrs = rules(statement)[type(stmnt)](stmnt, symbol_table) # Almost all Expression statements leave a value on the stack, so we must remove it. if stmnt and is_expression: instrs = chain(instrs, allocate(-size(c_type(stmnt), overrides={VoidType: 0}), loc(stmnt))) return instrs
def parse_enum_members(tokens, symbol_table): constant_expression = symbol_table['__ constant_expression __'] location, members, current_value = loc(consume(tokens)), OrderedDict(), 0 while peek(tokens, TOKENS.RIGHT_BRACE) != TOKENS.RIGHT_BRACE: ident = error_if_not_type(consume(tokens, ''), IDENTIFIER) value = ConstantExpression(current_value, IntegerType(location), location) if peek_or_terminal(tokens) == TOKENS.EQUAL and consume(tokens): value = constant_expression(tokens, symbol_table) _ = error_if_not_type(c_type(value), IntegerType) current_value = error_if_not_type(exp(value), (int, long)) symbol_table[ident] = value # Add value to symbol_table members[ident] = Definition(ident, c_type(value), value, location) _ = peek_or_terminal(tokens) == TOKENS.COMMA and consume(tokens) _ = error_if_not_value(tokens, TOKENS.RIGHT_BRACE) return members