def setUp(self): super(TestOptimizeInclusions, self).setUp() name = type(self).__name__ src = Source(name.lower() + ".c") ah = Header("a.h") bh = Header("b.h") ch = Header("c.h") ah.add_type(Type("a")) bh.add_type(Type("b")).add_reference(Type["a"]) ch.add_type(Type("c")).add_reference(Type["b"]).add_inclusion(ah) src.add_type(Pointer(Type["c"], "cpointer")) # c.h includes a.h but inclusion of a.h cannot be substituted with c.h # inclusion because it creating reference loop between inclusions of # c.h and b.h. This test checks inclusions optimization correctness and # ordering of chunks. src_content = """\ /* {} */ #include "a.h" #include "b.h" #include "c.h" typedef c *cpointer; """.format(src.path) self.files = [(src, src_content)]
def gen_net_client_info(self, index): helpers = [] code = {} for helper_name, cbtn in [ ("link_status_changed", "LinkStatusChanged"), ("can_receive", "NetCanReceive"), ("receive", "NetReceive"), ("cleanup", "NetCleanup") ]: helper = self.gen_nic_helper(helper_name, cbtn, index) self.source.add_type(helper) helpers.append(helper) code[helper_name] = helper # Define relative order of helpers: link, can recv, recv, cleanup line_origins(helpers) code["type"] = Type.lookup("NET_CLIENT_DRIVER_NIC") types = set([Type.lookup("NICState")] + list(code.values())) code["size"] = "sizeof(NICState)" init = Initializer(code, used_types = types) return Type.lookup("NetClientInfo").gen_var( self.net_client_info_name(index), initializer = init, static = True )
def gen_nic_helper(self, helper, cbtn, index): cbt = Type.lookup(cbtn) return cbt.use_as_prototype( self.nic_helper_name(helper, index), body=" return 0;\n" if cbt.ret_type.name != "void" else "", static=True, used_types=[Type.lookup(self.struct_name)])
def gen_vmstate_initializer(self, state_struct): type_macro = Type.lookup(self.qtn.type_macro) code = ("""{ .name@b=@s%s, .version_id@b=@s1, .fields@b=@s(VMStateField[])@b{ """ % type_macro.name ) used_macros = set() global type2vmstate for f in self.state_fields: if not f.save: continue if f.num is not None: raise Exception( "VMState field generation for arrays is not supported" ) try: vms_macro_name = type2vmstate[f.type.name] except KeyError: raise Exception( "VMState generation for type %s is not implemented" % \ f.type.name ) vms_macro = Type.lookup(vms_macro_name) used_macros.add(vms_macro) init = Initializer( # code of macro initializer is dict { "_f": f.name, "_s": state_struct.name, # Macros may use different argument names "_field": f.name, "_state": state_struct.name } ) code += " " * 8 + vms_macro.gen_usage_string(init) + ",\n" # Generate VM state list terminator macro. code += " " * 8 + Type.lookup("VMSTATE_END_OF_LIST").gen_usage_string() code += "\n }\n}" init = Initializer( code = code, used_types = used_macros.union([ type_macro, Type.lookup("VMStateField"), state_struct ]) ) return init
def gen_prop_declaration(field, decl_macro_name, state_struct, default_default=None): decl_macro = Type.lookup(decl_macro_name) used_types = set([decl_macro]) bool_true = Type.lookup("true") bool_false = Type.lookup("false") init_code = { "_f": field.name, "_s": state_struct, } if field.prop_macro_name is not None: init_code["_n"] = Type.lookup(field.prop_macro_name) init_code["_name"] = init_code["_n"] init_code["_state"] = init_code["_s"] init_code["_field"] = init_code["_f"] # _conf is name of argument of macro DEFINE_NIC_PROPERTIES that # corresponds to structure filed name init_code["_conf"] = init_code["_f"] if default_default is not None: if field.default is None: val = default_default else: val = field.default if isinstance(val, str): try: val_macro = Type.lookup(val) except TypeNotRegistered: val = '"%s"' % val else: val = val_macro elif isinstance(val, bool): if val: val = bool_true else: val = bool_false elif isinstance(val, integer_types): if field.type.name[0] == "u": val = "0x%X" % val else: val = str(val) else: val = str(val) init_code["_d"] = val init_code["_defval"] = val initializer = Initializer(code=init_code) usage_str = decl_macro.gen_usage_string(initializer) return (usage_str, used_types)
def char_declare_fields(self): field_type = (Type.lookup("CharBackend") if get_vp()["v2.8 chardev"] else Pointer(Type.lookup("CharDriverState"))) for index in range(self.char_num): self.add_state_field( QOMStateField(field_type, self.char_name(index), save=False, prop=True))
def nic_declare_field(self, index): self.add_state_field( QOMStateField(Pointer(Type.lookup("NICState")), self.nic_name(index), save=False)) f = QOMStateField(Type.lookup("NICConf"), self.nic_conf_name(index), save=False, prop=True) self.add_state_field(f) # NIC properties have standard names f.prop_macro_name = None
def gen_instance_init_fn(self, state_struct, code = "", s_is_used = False, used_types = [], used_globals = [] ): type_cast_macro = Type.lookup(self.qtn.for_macros) total_used_types = set([state_struct, type_cast_macro]) total_used_types.update(used_types) if self.timer_num > 0: total_used_types.update([ Type.lookup("QEMU_CLOCK_VIRTUAL"), Type.lookup("timer_new_ns") ]) s_is_used = True code += "\n" for timerN in range(self.timer_num): cb = self.timer_gen_cb(timerN, self.source, state_struct, self.type_cast_macro ) total_used_types.add(cb) code += """\ s->%s@b=@stimer_new_ns(@aQEMU_CLOCK_VIRTUAL,@s%s,@ss); """ % (self.timer_name(timerN), cb.name, ) fn = Function( name = self.gen_instance_init_name(), body = """\ {used}{Struct}@b*s@b=@s{UPPER}(obj); {extra_code}\ """.format( Struct = state_struct.name, UPPER = type_cast_macro.name, extra_code = code, used = "" if s_is_used else "__attribute__((unused))@b" ), static = True, args = [ Type.lookup("Object").gen_var("obj", pointer = True) ], used_types = total_used_types, used_globals = used_globals ) return fn
def setUp(self): super(TestPointerReferences, self).setUp() name = type(self).__name__ try: h = Header["type_a.h"] except: h = Header("type_a.h") h.add_type(Type("a", incomplete=False, base=False)) src = Source(name.lower() + ".c").add_type( Structure("s", Pointer(Type["a"])("next"))) src_content = """\ /* {} */ #include "type_a.h" typedef struct s {{ a *next; }} s; """.format(src.path) self.files = [(src, src_content)]
def gen_prop_val(self, prop): if isinstance(prop.prop_val, str) and Type.exists(prop.prop_val): self.use_type_name(prop.prop_val) return prop.prop_val if prop.prop_type == QOMPropertyTypeString: return "\"%s\"" % str(prop.prop_val) elif prop.prop_type == QOMPropertyTypeBoolean: if not isinstance(prop.prop_val, (bool, ) + integer_types): raise IncorrectPropertyValue( "%s is %s, expected bool" % (prop.prop_name, type(prop.prop_val).__name__)) self.use_type_name("bool") return "true" if prop.prop_val else "false" elif prop.prop_type == QOMPropertyTypeInteger: if not isinstance(prop.prop_val, integer_types): raise IncorrectPropertyValue() return "0x%x" % prop.prop_val elif prop.prop_type == QOMPropertyTypeLink: if prop.prop_val is None: self.use_type_name("NULL") return "NULL" else: self.use_type_name("OBJECT") return "OBJECT(%s)" % self.node_map[prop.prop_val] else: raise UnknownPropertyType()
def setUp(self): super(TestAddingTypeToLockedHeader, self).setUp() name = type(self).__name__ Header("some_types.h").add_type(Type("t")) # Without locking "some_types.h" header will be included in # "lockedheader.h". Header("lockedheader.h", locked=True).add_type(Structure("S", Pointer(Type["t"])("f"))) hdr = Header(name.lower() + ".h") hdr.add_type(Pointer(Type["S"], name="ps")) hdr_content = """\ /* {path} */ #ifndef INCLUDE_{fname_upper}_H #define INCLUDE_{fname_upper}_H #include "some_types.h" #include "lockedheader.h" typedef S *ps; #endif /* INCLUDE_{fname_upper}_H */ """.format(path=hdr.path, fname_upper=name.upper()) self.files = [(hdr, hdr_content)]
def machine_register_2_6(mach): # machine class definition function mach.class_init = Function( name="machine_%s_class_init" % mach.qtn.for_id_name, static=True, ret_type=Type.lookup("void"), args=[ Type.lookup("ObjectClass").gen_var("oc", pointer=True), Type.lookup("void").gen_var("opaque", pointer=True) ], body="""\ MachineClass *mc = MACHINE_CLASS(oc); mc->desc = \"{desc}\"; mc->init = {instance_init}; """.format(desc=mach.desc, instance_init=mach.instance_init.name), used_types=[ Type.lookup("MachineClass"), Type.lookup("MACHINE_CLASS"), mach.instance_init ]) mach.source.add_type(mach.class_init) # machine type definition structure type_machine_macro = Type.lookup("TYPE_MACHINE") type_machine_type_name_macro = Type.lookup("MACHINE_TYPE_NAME") mach.type_info = Type.lookup("TypeInfo").gen_var( name="machine_type_%s" % mach.qtn.for_id_name, static=True, initializer=Initializer( { "name": type_machine_type_name_macro.gen_usage_string( Initializer({"machinename": '"%s"' % mach.qtn.for_id_name })), "parent": type_machine_macro, "class_init": mach.class_init }, used_types=[type_machine_type_name_macro])) mach.source.add_global_variable(mach.type_info) # machine type registration function mach.type_reg_func = mach.gen_register_types_fn(mach.type_info) mach.source.add_type(mach.type_reg_func) # Main machine registration macro machine_init_def = Type.lookup("type_init").gen_var() machine_init_def_args = Initializer({"function": mach.type_reg_func}) mach.source.add_usage(machine_init_def.gen_usage(machine_init_def_args))
def gen_properties_global(self, state_struct): init = self.gen_properties_initializer(state_struct) prop_type = Type.lookup("Property") var = prop_type.gen_var(name=self.qtn.for_id_name + "_properties", initializer=init, static=True, array_size=0) return var
def char_gen_cb(self, proto_name, handler_name, index, source, state_struct, type_cast_macro): proto = Type.lookup(proto_name) cb = proto.use_as_prototype(handler_name, body = """\ __attribute__((unused))@b%s@b*s@b=@s%s(opaque);%s """ % ( state_struct.name, self.type_cast_macro.name, "\n\n return 0;" \ if proto.ret_type not in [ None, Type.lookup("void") ] else "", ), static = True, used_types = set([state_struct, type_cast_macro]) ) source.add_type(cb) return cb
def gen_mmio_write(name, struct_name, type_cast_macro, regs = None): func = Type["MemoryRegionOps"].write.type.type.use_as_prototype(name, body = BodyTree(), static = True ) root = func.body s = Type.lookup(struct_name).gen_var("s", pointer = True) root.add_child( Declare( OpAssign( s, MCall( type_cast_macro, func.args[0] ) ) ) ) root.add_child(NewLine()) if regs: cases = gen_reg_cases( regs, "w", func.args[1], func.args[2], None, s ) else: cases = [] switch = BranchSwitch(func.args[1], cases = cases, separate_cases = True ) case_default = SwitchCase("default") case_default.add_child( Call( "printf", StrConcat( "%s: unimplemented write to 0x%", MCall("HWADDR_PRIx"), StrConcat( ", size %d, ", "value 0x%", delim = "@s" ), MCall("PRIx64"), "\\n", delim = "@s" ), MCall("__FUNCTION__"), func.args[1], func.args[3], func.args[2] ) ) switch.add_child(case_default) root.add_child(switch) return func
def gen_irq_connect(self, irq, var_name): src = irq[0] if isinstance(src, IRQHub): raise RuntimeError("Cannot connect an IRQ to a hub (%u)." " A hub does use each its IRQ by itself." % src.id ) if irq[2] is None: self.use_type_name("DEVICE") self.use_type_name("qdev_connect_gpio_out") return """\ qdev_connect_gpio_out(@aDEVICE({src_name}),@s{src_index},@s{irq_name}); """.format( irq_name = var_name, src_name = self.node_map[src], src_index = irq[1] ) else: sysbus_name = Type.lookup("SYSBUS_DEVICE_GPIO_IRQ").text if sysbus_name == "\"%s\"" % irq[2] or "SYSBUS_DEVICE_GPIO_IRQ" == irq[2]: self.use_type_name("sysbus_connect_irq") self.use_type_name("SYS_BUS_DEVICE") return """\ sysbus_connect_irq(@aSYS_BUS_DEVICE({src_name}),@s{src_index},@s{irq_name}); """.format( irq_name = var_name, src_name = self.node_map[src], src_index = irq[1] ) else: self.use_type_name("DEVICE") self.use_type_name("qdev_connect_gpio_out_named") if Type.exists(irq[2]): self.use_type_name(irq[2]) return """\ qdev_connect_gpio_out_named(@aDEVICE({src_name}),@s{gpio_name},@s{src_index},@s{irq_name}); """.format( irq_name = var_name, src_name = self.node_map[src], src_index = irq[1], gpio_name = irq[2] if Type.exists(irq[2]) else "\"%s\"" % irq[2] )
def gen_vmstate_var(self, state_struct): init = self.gen_vmstate_initializer(state_struct) vmstate = Type.lookup("VMStateDescription").gen_var( name="vmstate_%s" % self.qtn.for_id_name, static=True, initializer=init) return vmstate
def block_declare_fields(self): for index in range(self.block_num): f = QOMStateField(Pointer(Type.lookup("BlockBackend")), self.block_name(index), save=False, prop=True) self.add_state_field(f) # override macro name assigned by `add_state_field` f.prop_macro_name = self.block_prop_name(index)
def setUp(self): super(TestGlobalHeadersInclusion, self).setUp() name = type(self).__name__ hg = Header("global_types.h", is_global=True) hl = Header("local_types.h") hg.add_type(Type("GT", incomplete=False)) hl.add_type(Type("LT", incomplete=False)) hdr = Header(name.lower() + ".h").add_type( Structure("Fields", Type["GT"]("f1"), Type["LT"]("f2"))) hdr_content = """\ /* {path} */ #ifndef INCLUDE_{fname_upper}_H #define INCLUDE_{fname_upper}_H #include "local_types.h" typedef struct Fields {{ GT f1; LT f2; }} Fields; #endif /* INCLUDE_{fname_upper}_H */ """.format(path=hdr.path, fname_upper=name.upper()) src = Source(name.lower() + ".c").add_global_variable( Type["Fields"]("fv")) src_content = """\ /* {} */ #include <global_types.h> #include "{}" Fields fv __attribute__((unused)); """.format(src.path, hdr.path) self.files = [(hdr, hdr_content), (src, src_content)]
def timer_gen_cb(self, index, source, state_struct, type_cast_macro): timer_cb = Function( self.timer_cb_name(index), body="""\ __attribute__((unused))@b%s@b*s@b=@s%s(opaque); """ % (state_struct.name, self.type_cast_macro.name), args=[Type.lookup("void").gen_var("opaque", pointer=True)], static=True, used_types=set([state_struct, type_cast_macro])) source.add_type(timer_cb) return timer_cb
def gen_register_types_fn(self, *infos): body = "" for info in infos: body += " type_register_static(&%s);\n" % info.name fn = Function(name=self.gen_register_types_name(), body=body, static=True, used_types=[Type.lookup("type_register_static")], used_globals=list(infos)) return fn
def gen_irq_get(self, irq, var_name): dst = irq[0] if isinstance(dst, IRQHub): raise RuntimeError("Cannot get an IRQ from a hub (%u)." " A hub _is_ an IRQ itself." % dst.id ) self.use_type_name("DEVICE") if irq[2] is None: self.use_type_name("qdev_get_gpio_in") return """\ {irq_name} = qdev_get_gpio_in(@aDEVICE({dst_name}),@s{dst_index}); """.format( irq_name = var_name, dst_name = self.node_map[dst], dst_index = irq[1], ) else: gpio_name = irq[2] try: gpio_name_type = Type.lookup(gpio_name) except TypeNotRegistered: gpio_name = '"%s"' % gpio_name else: self.use_type(gpio_name_type) irq_get = Type.lookup("qdev_get_gpio_in_named") self.use_type(irq_get) return """\ {irq_name} = {irq_get}(@aDEVICE({dst_name}),@s{gpio_name},@s{dst_index}); """.format( irq_name = var_name, irq_get = irq_get.name, dst_name = self.node_map[dst], gpio_name = gpio_name, dst_index = irq[1], )
def gen_mmio_write(name, struct_name, type_cast_macro, regs=None): write = Type.lookup("MemoryRegionOps_write") used_types = set([ write.args[1].type, write.args[2].type, Type.lookup("uint64_t"), Type.lookup("printf"), Type.lookup("HWADDR_PRIx"), Type.lookup("PRIx64") ]) context = {"s_is_used": False} regs = "" if regs is None else ( "\n" + gen_reg_cases(regs, "w", used_types, write.args[1].name, write.args[2].name, context)) body = """\ {unused}{Struct}@b*s@b=@s{UPPER}(opaque); switch@b({offset})@b{{{regs} default: printf(@a"%s:@bunimplemented@bwrite@bto@b0x%"HWADDR_PRIx",@bsize@b%d,@b" @a"value@b0x%"PRIx64"\\n",@s__FUNCTION__,@s{offset},@ssize,\ @s{value}); break; }} """.format(regs=regs, unused="" if context["s_is_used"] else "__attribute__((unused))@b", offset=write.args[1].name, value=write.args[2].name, Struct=struct_name, UPPER=type_cast_macro) return write.use_as_prototype(name=name, static=True, body=body, used_types=used_types)
def gen_type_info_var(self, state_struct, instance_init_fn, class_init_fn, parent_tn="TYPE_OBJECT"): used_types = [state_struct, instance_init_fn, class_init_fn] try: parent_macro = Type.lookup(parent_tn) except TypeNotRegistered: parent_macro = None else: used_types.append(parent_macro) # Type info initializer tii = Initializer( code = """{{ .name@b@b@b@b@b@b@b@b@b@b=@sTYPE_{UPPER}, .parent@b@b@b@b@b@b@b@b=@s{parent_tn}, .instance_size@b=@ssizeof({Struct}), .instance_init@b=@s{instance_init}, .class_init@b@b@b@b=@s{class_init} }}""".format( UPPER = self.qtn.for_macros, parent_tn = ('"%s"' % parent_tn) if parent_macro is None \ else parent_macro.name, Struct = state_struct.name, instance_init = instance_init_fn.name, class_init = class_init_fn.name ), used_types = used_types ) # TypeInfo variable tiv = Type.lookup("TypeInfo").gen_var(name=self.gen_type_info_name(), static=True, initializer=tii) return tiv
def add_state_field_h(self, type_name, field_name, num = None, save = True, prop = False, default = None ): t = Type.lookup(type_name) f = QOMStateField(t, field_name, num = num, save = save, prop = prop, default = default ) self.add_state_field(f)
def gen_mmio_read(name, struct_name, type_cast_macro, regs=None): read = Type.lookup("MemoryRegionOps_read") used_types = set([ read.args[1].type, Type.lookup("uint64_t"), Type.lookup("printf"), Type.lookup("HWADDR_PRIx") ]) context = {"s_is_used": False} regs = "" if regs is None else ("\n" + gen_reg_cases( regs, "r", used_types, read.args[1].name, None, context)) body = """\ {unused}{Struct}@b*s@b=@s{UPPER}(opaque); uint64_t@bret@b=@s0; switch@b({offset})@b{{{regs} default: printf(@a"%s:@bunimplemented@bread@bfrom@b0x%"HWADDR_PRIx",@bsize@b%d\ \\n",@s__FUNCTION__,@s{offset},@ssize); break; }} return@sret; """.format(regs=regs, unused="" if context["s_is_used"] else "__attribute__((unused))@b", offset=read.args[1].name, Struct=struct_name, UPPER=type_cast_macro) return read.use_as_prototype(name=name, static=True, body=body, used_types=used_types)
def define_msi_init_2_6_5(): Header.lookup("hw/pci/msi.h").add_type( Function(name="msi_init", ret_type=Type.lookup("int"), args=[ Type.lookup("PCIDevice").gen_var("dev", pointer=True), Type.lookup("uint8_t").gen_var("offset"), Type.lookup("unsigned int").gen_var("nr_vectors"), Type.lookup("bool").gen_var("msi64bit"), Type.lookup("bool").gen_var("msi_per_vector_mask"), Pointer(Type.lookup("Error")).gen_var("errp", pointer=True) ]))
def setUp(self): super(TestReferencingToTypeInAnotherHeader, self).setUp() name = type(self).__name__ hdr = Header(name.lower() + ".h") h1 = Header("some_types.h") h2 = Header("another_some_types.h") h1.add_type(Type("f1", incomplete=False)) h2.add_type(Type("f2", incomplete=False)) # Without reference headers `another_some_types` and `some_types` would # be in alphabetical order. h2.add_reference(Type["f1"]) s = Structure("S", Type["f1"]("field1"), Type["f2"]("field2")) hdr.add_type(s) hdr_content = """\ /* {path} */ #ifndef INCLUDE_{fname_upper}_H #define INCLUDE_{fname_upper}_H #include "some_types.h" #include "another_some_types.h" typedef struct S {{ f1 field1; f2 field2; }} S; #endif /* INCLUDE_{fname_upper}_H */ """.format(path=hdr.path, fname_upper=name.upper()) self.files = [(hdr, hdr_content)]
def char_gen_cb(self, proto_name, handler_name, index, source, state_struct, type_cast_macro, ret ): proto = Type.lookup(proto_name) cb = proto.use_as_prototype(handler_name, body = """\ __attribute__((unused))@b%s@b*s@b=@s%s(opaque);%s """ % ( state_struct.name, self.type_cast_macro.name, ("\n\n return %s;" % ret) if ret is not None else "", ), static = True, used_types = set([state_struct, type_cast_macro]) ) source.add_type(cb) return cb
def gen_properties_initializer(self, state_struct): used_types = set() global type2prop code = "{" first = True for f in self.state_fields: if not f.prop: continue try: helper = type2prop[f.type.name] except KeyError: raise Exception( "Property generation for type %s is not implemented" % \ f.type.name ) decl_code, decl_types = helper(f, state_struct) used_types |= decl_types if first: first = False code += "\n" else: code += ",\n" code += " " + decl_code # generate property list terminator terminator_macro = Type.lookup("DEFINE_PROP_END_OF_LIST") if first: code += "\n" else: code += ",\n" code += " " + terminator_macro.gen_usage_string() + "\n}" init = Initializer( code = code, used_types = used_types.union([ terminator_macro, state_struct ]) ) return init