def visit_FuncDef(self, node): # Skip if no loop counters exist if self.loop_counter_size == 0: return # Create loop_counter declaration/initialization constants = [c_ast.Constant("int", '0') for i in range(self.loop_counter_size)] init_list = c_ast.InitList(constants) identifier_type = c_ast.IdentifierType(["int"]) type_decl = c_ast.TypeDecl("loop_counter", [], identifier_type) dim = c_ast.Constant("int", str(self.loop_counter_size)) array_decl = c_ast.ArrayDecl(type_decl, dim, []) decl = c_ast.Decl("loop_counter", [], [], [], array_decl, init_list, None) node.body.block_items.insert(0, decl) # Label for return values to goto start_label = c_ast.Label("print_loop_counter", c_ast.EmptyStatement()) # Start and end labels used for inserting preprocessor commands for #if DEBUG_EN end_label = c_ast.Label("print_loop_counter_end", c_ast.EmptyStatement()) # Write to file if self.write_to_file: stmt = c_ast.ID("write_array(loop_counter, %d)\n" % (self.loop_counter_size)) compound = c_ast.Compound([start_label, stmt, end_label]) # Print to stdout else: # Add printf to the end of function # Start of printing stmt_start = c_ast.ID("printf(\"loop counter = (\")") # For loop # int i; identifier_type = c_ast.IdentifierType(["int"]) type_decl = c_ast.TypeDecl("i", [], identifier_type) for_decl = c_ast.Decl("i", [], [], [], type_decl, [], None) # i = 0 init = c_ast.Assignment("=", c_ast.ID("i"), c_ast.Constant("int", '0')) # i < self.loop_counter_size cond = c_ast.BinaryOp("<", c_ast.ID("i"), c_ast.Constant("int", str(self.loop_counter_size))) # i++ next_stmt = c_ast.UnaryOp("p++", c_ast.ID("i")) # printf in for stmt = c_ast.ID("printf(\"%d, \", loop_counter[i])") # Cosntruct for loop stmt_for = c_ast.For(init, cond, next_stmt, stmt) # End of printing stmt_end = c_ast.ID("printf(\")\\n\")") # Put it all together body = c_ast.Compound([stmt_start, for_decl, stmt_for, stmt_end]) # Surround with labels compound = c_ast.Compound([start_label, body, end_label]) node.body.block_items.append(compound)
def __init__(self, func, variable_declaration, structs): self.func = func self.variable_declaration = variable_declaration if variable_declaration.storage is not None: variable_declaration.storage.append("static") else: variable_declaration.storage = ["static"] if self.variable_declaration.init is None: if "extern" in variable_declaration.storage: variable_declaration.storage.remove("extern") if type(self.variable_declaration.type) is c_ast.ArrayDecl or \ any(x in structs for x in self.variable_declaration.type.type.names): self.variable_declaration.init = c_ast.InitList( exprs=[c_ast.Constant(type="int", value="0")]) else: self.variable_declaration.init = c_ast.Constant(type="int", value="0")
def ConvertConvertAddressTakenScalarsToArray(ast, meta_info: meta.MetaInfo): """ Rewrite address taken scalar vars as one element arrays After this transform we can keep all scalars in registers. """ def IsAddressTakenScalarOrGlobalScalar(node, parent): if isinstance(node, c_ast.Decl) and IsScalarType(node.type): # return isinstance(parent, c_ast.FileAST) return (isinstance(parent, c_ast.FileAST) or "static" in node.storage) if not isinstance(node, c_ast.UnaryOp): return False if node.op != "&": return False if not isinstance(node.expr, c_ast.ID): return False type = meta_info.type_links[node.expr] return IsScalarType(type) candidates = common.FindMatchingNodesPreOrder(ast, ast, IsAddressTakenScalarOrGlobalScalar) ids = set() for node, _ in candidates: if isinstance(node, c_ast.UnaryOp): ids.add(meta_info.sym_links[node.expr]) else: ids.add(node) one = c_ast.Constant("int", "1") meta_info.type_links[one] = meta.INT_IDENTIFIER_TYPE for node in ids: assert isinstance(node, c_ast.Decl) node.type = c_ast.ArrayDecl(node.type, one, []) if node.init: node.init = c_ast.InitList([node.init]) def IsAddressTakenScalarId(node, _): return isinstance(node, c_ast.ID) and meta_info.sym_links[node] in ids candidates = common.FindMatchingNodesPreOrder(ast, ast, IsAddressTakenScalarId) for node, parent in candidates: original_type = meta_info.type_links[node] meta_info.type_links[node] = meta.GetTypeForDecl(meta_info.sym_links[node].type) array_ref = c_ast.UnaryOp("*", node) meta_info.type_links[array_ref] = original_type common.ReplaceNode(parent, node, array_ref)
def replace_enum_values(self, enum_object, storage_lvalue=None): constants = [] for enum in enum_object.members.enumerators: constants.append( c_ast.Constant(type="int", value=str(enum.value.value))) init_list = c_ast.InitList(exprs=constants) init_count = c_ast.Constant(type="int", value=str(len(constants))) values = None values_len = None for node in self.get_nodes(self.ast): if type(node) == c_ast.Decl: if node.name == "values": values = node if node.name == "values_len": values_len = node if node.name == "idx": idx = node if type(node) == c_ast.ID: if node.name == "values_len": values_len_id = node if node.name == "values": values_id = node if node.name == "idx": idx_id = node if type(node) == c_ast.Assignment: if node.lvalue.expr.name == "storage": storage_expr = node values.init = init_list new_values_name = values.name + str(nesting_context.values_count) values.name = new_values_name change_declname(values, new_values_name) values_id.name = new_values_name values_len.init = init_count new_values_len_name = values_len.name + str( nesting_context.values_count) values_len.name = new_values_len_name change_declname(values_len, new_values_len_name) values_len_id.name = new_values_len_name new_idx_name = idx.name + str(nesting_context.values_count) idx.name = new_values_name change_declname(idx, new_idx_name) idx_id.name = new_idx_name if storage_lvalue: storage_expr.lvalue = storage_lvalue nesting_context.values_count += 1
def work(self, function_node): ret_num = len(self.rets) # if more than 1 return if ret_num > 1: if isinstance(function_node, c_ast.FuncDef): f_type = function_node.decl.type while not isinstance(f_type, c_ast.TypeDecl): f_type = f_type.type new_type = copy.deepcopy(f_type) new_type.type.names = ['int'] function_node.decl.type.type = c_ast.PtrDecl(type=new_type, quals=[]) new_ret_decl = c_ast.Decl(name="CLEVER_RET", funcspec=[], bitsize=None, storage=[], quals=[], init=c_ast.InitList(exprs=self.ret_exps), type=c_ast.ArrayDecl( dim=c_ast.Constant(type='int', value=str(ret_num)), dim_quals=[], type=c_ast.TypeDecl(declname="CLEVER_RET", quals=[], type=c_ast.IdentifierType(names=['int'])))) ret_state = c_ast.Return(expr=c_ast.ID(name=new_ret_decl.name)) for node in self.rets: function_node.body.block_items.remove(node) function_node.body.block_items.append(new_ret_decl) function_node.body.block_items.append(ret_state) return
def initlist(arg): if type(arg) is not list: raise utils.BugError('non-list passed') return c_ast.InitList(arg)
def new_ilist(self, exprs, parent=None): il = c_ast.InitList(exprs) il.parent = parent for e in exprs: e.parent = il return il
def __init__(self, annotations, struct, json_annotations, ext): """ Describes the property list for a struct Also create a list of c_ast.Decl to append to the struct decls """ self.json_annotations = json_annotations self.annotated_properties = None self.annotations = annotations self.ext = ext self.init_list = None self.decls = None self.struct = struct self.extra_decls = None def make_extra_decl(name, t): idtype = c_ast.IdentifierType([t]) td = c_ast.TypeDecl(name, [], idtype) return c_ast.Decl( name, [], # quals [], # storage [], # funcspec td, # type None, # init None, # bitsize ) fi = getframeinfo(currentframe()) annotated_properties = [ AnnotatedProperty(self, d) for d in struct.decls ] out_ap = [] for ap in annotated_properties: inline_annotation = ap.values.get('inline', False) if inline_annotation: astruct = self.inline_struct_annotated(inline_annotation, ap.decl) out_ap += astruct.annotated_properties else: out_ap.append(ap) self.annotated_properties = out_ap init_lists = [ ap.init_list for ap in out_ap # 'private' and 'inline' have no init_list if ap.init_list is not None ] # NULL terminator init_lists.append(c_ast.InitList([c_ast.Constant('int', '0')])) self.init_list = c_ast.InitList(init_lists, Coord(fi.filename, fi.lineno)) decls = [ap.decl for ap in out_ap] extra_decls = chain.from_iterable( (ap.extra_decls.iteritems() for ap in out_ap)) extra_decls = [make_extra_decl(name, t) for name, t in extra_decls] decls += extra_decls self.decls = decls
def __init__(self, annotated_struct, decl): self.init_list = None self.decl = decl self.extra_decls = {} self.values = {} init_exprs = [] self.struct = annotated_struct annotations = self.struct.annotations.get(decl, self.struct.json_annotations) try: for a in annotations: expr = self.expand_annotation(a, self.values) if expr is not None: init_exprs.append(expr) except StopIteration: name = a.name a = next(annotations, None) if a is not None: raise ExpansionError(a, decl, 'Unexpected annotation after ' + name) return init_list = [] prop_name = type_find(decl, c_ast.TypeDecl).declname # name the property if it hasn't already been named if 'name' not in self.values: self.values['name'] = prop_name # add string initializers for init_name in ('name', 'schema'): if init_name in self.values: literal = str_literal(self.values[init_name]) init_exprs.append( c_ast.NamedInitializer([c_ast.ID(init_name)], c_ast.Constant('string', literal))) # assign types type_annotations = { name: t for name, t in self.values.iteritems() if isinstance(t, Annotation) } types, arraydecl = self.struct.annotations.get_types( decl, type_annotations) type_inits = [ c_ast.NamedInitializer([c_ast.ID(ttype)], c_ast.ID(t)) for ttype, t in types.iteritems() ] fi = getframeinfo(currentframe()) init_exprs.append( c_ast.NamedInitializer([c_ast.ID('type')], c_ast.InitList( type_inits, Coord(fi.filename, fi.lineno)))) struct = annotated_struct.struct # calculate struct offset init_exprs.append( c_ast.NamedInitializer([c_ast.ID('offset')], self.offsetof(struct.name, prop_name))) if 'nullable' in self.values and self.values['nullable']: self.extra_decls[AnnotatedProperty.NULLABLE_NAME( decl.name)] = 'bool' init_exprs.append( c_ast.NamedInitializer( [c_ast.ID('null_offset')], self.offsetof(struct.name, AnnotatedProperty.NULLABLE_NAME(prop_name)))) if arraydecl: # static array init_exprs.append( c_ast.NamedInitializer([c_ast.ID('length')], arraydecl.dim)) elif types['json'] == 'json_type_array': # calculate length offset len_prop = AnnotatedProperty.LENGTH_NAME(prop_name) self.extra_decls[len_prop] = 'int' init_exprs.append( c_ast.NamedInitializer([c_ast.ID('length_offset')], self.offsetof(struct.name, len_prop))) init_exprs.append( c_ast.NamedInitializer([c_ast.ID('dereference')], c_ast.Constant('int', '1'))) if types['json'] == 'json_type_array': # assume PtrDecl for now init_exprs.append( c_ast.NamedInitializer([c_ast.ID('stride')], self.sizeof(decl.type.type))) fi = getframeinfo(currentframe()) self.init_list = c_ast.InitList(init_exprs, Coord(fi.filename, fi.lineno))