diff options
author | Luke T. Shumaker <lukeshu@lukeshu.com> | 2025-03-28 11:31:26 -0600 |
---|---|---|
committer | Luke T. Shumaker <lukeshu@lukeshu.com> | 2025-03-29 18:25:49 -0600 |
commit | 9096e2d9cb6f438e49aa29aa2cfaef1717466a05 (patch) | |
tree | 3ecce9bac17d3a4b89b11f1df281c0587d4443d4 /lib9p/protogen/h.py | |
parent | fc462d13cb2f49b4c4745742dfaed994596a54b8 (diff) |
lib9p: idl: Rework bitfields, allow full exprs more places
Diffstat (limited to 'lib9p/protogen/h.py')
-rw-r--r-- | lib9p/protogen/h.py | 138 |
1 files changed, 105 insertions, 33 deletions
diff --git a/lib9p/protogen/h.py b/lib9p/protogen/h.py index b0d38bf..13c3f89 100644 --- a/lib9p/protogen/h.py +++ b/lib9p/protogen/h.py @@ -362,42 +362,49 @@ enum {c9util.ident('version')} {{ def gen_number(typ: idl.Number) -> str: ret = f"typedef {c9util.typename(typ.prim)} {c9util.typename(typ)};\n" + def lookup_sym(sym: str) -> str: + assert False + def cname(base: str) -> str: prefix = f"{typ.typname}_".upper() return c9util.Ident(c9util.add_prefix(prefix, base)) namewidth = max(len(cname(name)) for name in typ.vals) for name, val in typ.vals.items(): - ret += f"#define {cname(name):<{namewidth}} (({c9util.typename(typ)})UINT{typ.static_size*8}_C({val}))\n" + c_name = cname(name) + c_val = c9util.idl_expr(val, lookup_sym) + ret += f"#define {c_name:<{namewidth}} (({c9util.typename(typ)})({c_val}))\n" return ret def gen_bitfield(typ: idl.Bitfield) -> str: ret = f"typedef {c9util.typename(typ.prim)} {c9util.typename(typ)};\n" - def bitname(val: idl.Bit | idl.BitAlias) -> str: - s = val.bitname - match val: - case idl.Bit(cat=idl.BitCat.RESERVED): - s = "_RESERVED_" + s - case idl.Bit(cat=idl.BitCat.SUBFIELD): - assert isinstance(typ, idl.Bitfield) - n = sum( - 1 - for b in typ.bits[: val.num] - if b.cat == idl.BitCat.SUBFIELD and b.bitname == val.bitname - ) - s = f"_{s}_{n}" - case idl.Bit(cat=idl.BitCat.UNUSED): - return "" - return c9util.Ident(c9util.add_prefix(typ.typname.upper() + "_", s)) - - namewidth = max(len(bitname(val)) for val in [*typ.bits, *typ.names.values()]) + def lookup_sym(sym: str) -> str: + assert False - ret += "\n" + # There are 4 parts here: bits, aliases, masks, and numbers. + + # 1. bits + + def bitname(bit: idl.Bit) -> str: + prefix = f"{typ.typname}_".upper() + base = bit.bitname + match bit: + case idl.Bit(cat="RESERVED"): + base = "_RESERVED_" + base + case idl.Bit(cat=idl.BitNum()): + base += "_*" + case idl.Bit(cat="UNUSED"): + base = f"_UNUSED_{bit.num}" + return c9util.Ident(c9util.add_prefix(prefix, base)) + + namewidth = max(len(bitname(bit)) for bit in typ.bits) + + ret += "/* bits */\n" for bit in reversed(typ.bits): vers = bit.in_versions - if bit.cat == idl.BitCat.UNUSED: + if bit.cat == "UNUSED": vers = typ.in_versions ret += cutil.ifdef_push(2, c9util.ver_ifdef(vers)) @@ -405,26 +412,32 @@ def gen_bitfield(typ: idl.Bitfield) -> str: # the same length. end = "" match bit.cat: - case idl.BitCat.USED | idl.BitCat.RESERVED | idl.BitCat.SUBFIELD: + case "USED" | "RESERVED" | "UNUSED": if cutil.ifdef_leaf_is_noop(): beg = "#define " else: beg = "# define" - case idl.BitCat.UNUSED: - beg = "/* unused" + case idl.BitNum(): + beg = "/* number" end = " */" c_name = bitname(bit) - c_val = f"1<<{bit.num}" + c_val = f"UINT{typ.static_size*8}_C(1)<<{bit.num}" ret += ( f"{beg} {c_name:<{namewidth}} (({c9util.typename(typ)})({c_val})){end}\n" ) - if aliases := [ - alias for alias in typ.names.values() if isinstance(alias, idl.BitAlias) - ]: - ret += "\n" + ret += cutil.ifdef_pop(1) + + # 2. aliases + if typ.aliases: - for alias in aliases: + def aliasname(alias: idl.BitAlias) -> str: + prefix = f"{typ.typname}_".upper() + base = alias.bitname + return c9util.Ident(c9util.add_prefix(prefix, base)) + + ret += "/* aliases */\n" + for alias in typ.aliases.values(): ret += cutil.ifdef_push(2, c9util.ver_ifdef(alias.in_versions)) end = "" @@ -433,10 +446,69 @@ def gen_bitfield(typ: idl.Bitfield) -> str: else: beg = "# define" - c_name = bitname(alias) - c_val = alias.val + c_name = aliasname(alias) + c_val = c9util.idl_expr(alias.val, lookup_sym) ret += f"{beg} {c_name:<{namewidth}} (({c9util.typename(typ)})({c_val})){end}\n" - ret += cutil.ifdef_pop(1) + + ret += cutil.ifdef_pop(1) + + # 3. masks + if typ.masks: + + def maskname(mask: idl.BitAlias) -> str: + prefix = f"{typ.typname}_".upper() + base = mask.bitname + return c9util.Ident(c9util.add_prefix(prefix, base) + "_MASK") + + ret += "/* masks */\n" + for mask in typ.masks.values(): + ret += cutil.ifdef_push(2, c9util.ver_ifdef(mask.in_versions)) + + end = "" + if cutil.ifdef_leaf_is_noop(): + beg = "#define " + else: + beg = "# define" + + c_name = maskname(mask) + c_val = c9util.idl_expr(mask.val, lookup_sym, bitwidth=typ.static_size * 8) + ret += f"{beg} {c_name:<{namewidth}} (({c9util.typename(typ)})({c_val})){end}\n" + + ret += cutil.ifdef_pop(1) + + # 4. numbers + def numname(num: idl.BitNum, base: str) -> str: + prefix = f"{typ.typname}_{num.numname}_".upper() + return c9util.Ident(c9util.add_prefix(prefix, base)) + + for num in typ.nums.values(): + namewidth = max( + len(numname(num, base)) + for base in [ + *[alias.bitname for alias in num.vals.values()], + "MASK", + ] + ) + ret += f"/* number: {num.numname} */\n" + for alias in num.vals.values(): + ret += cutil.ifdef_push(2, c9util.ver_ifdef(alias.in_versions)) + + end = "" + if cutil.ifdef_leaf_is_noop(): + beg = "#define " + else: + beg = "# define" + + c_name = numname(num, alias.bitname) + c_val = c9util.idl_expr(alias.val, lookup_sym) + ret += f"{beg} {c_name:<{namewidth}} (({c9util.typename(typ)})({c_val})){end}\n" + ret += cutil.ifdef_pop(1) + c_name = numname(num, "MASK") + c_val = f"{num.mask:#0{typ.static_size*8}b}" + ret += ( + f"{beg} {c_name:<{namewidth}} (({c9util.typename(typ)})({c_val})){end}\n" + ) + return ret |