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 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 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 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 function_definition(dec, symbol_table): """ Function Call Convention: Allocate enough space on the stack for the return type. Push a new Frame (saves (base & stack ptr)) Push all parameters on the stack from right to left. (The values won't be pop but referenced on stack (+) ...) Calculate & Push pointer where to return value. Push pointer where to store return value. Push the return Address so the callee knows where to return to. (Reset Base pointer) creating a new Frame. Jump to callee code segment callee references values passed on the stack by pushing the base_stack_pointer, (+offsets) for previous frame and (-offset) for current frame ... Callee will place the return value in the specified pointer. Caller Pops frame, and uses the set (returned) value. """ symbol = Code(name(dec), None, None, dec.storage_class, loc(dec)) symbol_table[name(dec)] = bind_load_instructions(dec) # bind load/reference instructions, add to symbol table. symbol_table[name(dec)].symbol = symbol 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 ... ) symbol.binaries = binaries(initialization(dec), symbol_table) return symbol
def function_definition(dec, symbol_table): """ Function Call Convention: Allocate enough space on the stack for the return type. Push a new Frame (saves (base & stack ptr)) Push all parameters on the stack from right to left. (The values won't be pop but referenced on stack (+) ...) Calculate & Push pointer where to return value. Push pointer where to store return value. Push the return Address so the callee knows where to return to. (Reset Base pointer) creating a new Frame. Jump to callee code segment callee references values passed on the stack by pushing the base_stack_pointer, (+offsets) for previous frame and (-offset) for current frame ... Callee will place the return value in the specified pointer. Caller Pops frame, and uses the set (returned) value. """ symbol = Code(name(dec), None, None, dec.storage_class, loc(dec)) symbol_table[name(dec)] = bind_load_instructions( dec) # bind load/reference instructions, add to symbol table. symbol_table[name(dec)].symbol = symbol 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 ... ) symbol.binaries = binaries(initialization(dec), symbol_table) return symbol
def non_static_pointer_typed_definition(stmnt, symbol_table): return rules(non_static_pointer_typed_definition)[type(c_type(declarations.initialization(stmnt)))]( stmnt, symbol_table )