# C语法定义模块 from __future__ import annotations import ast import logging from typing import Any, Optional from . import t from lib.constants.config import mode as _config_mode def _to_str(node: Any) -> str: if node is None: return '' if isinstance(node, str): return node if isinstance(node, list): return ' && '.join([_to_str(n) for n in node]) NodeType: str = type(node).__name__ if NodeType == 'Constant': return node.value elif NodeType == 'ID': return node.name elif NodeType == 'BinaryOp': left: str = _to_str(node.left) right: str = _to_str(node.right) return f'{left} {node.op} {right}' elif NodeType == 'UnaryOp': expr: str = _to_str(node.expr) return f'{node.op}{expr}' else: return repr(node) class Asm: @staticmethod def _parse_asm_descr(expr: ast.AST) -> str: """递归解析AST节点,确保获取t.ASM_DESCR的实际值,支持|组合 处理场景: 1. t.ASM_DESCR.XXX → 取属性值 2. t.ASM_DESCR.XXX | t.ASM_DESCR.YYY → 拼接两个值 3. 常量字符串 → 直接返回 """ # 场景1:位或组合(XXX | YYY) if isinstance(expr, ast.BinOp): left_val: str = Asm._parse_asm_descr(expr.left) right_val: str = Asm._parse_asm_descr(expr.right) return left_val + right_val # 场景2:t.ASM_DESCR.XXX 多层属性访问 elif isinstance(expr, ast.Attribute): # 第一步:判断是否是 t.ASM_DESCR 的属性 if isinstance(expr.value, ast.Attribute): # 内层是 t.ASM_DESCR if (isinstance(expr.value.value, ast.Name) and expr.value.value.id == 't' and expr.value.attr == 'ASM_DESCR'): # 取 t.ASM_DESCR.XXX 的实际值 AttrName: str = expr.attr if hasattr(t.ASM_DESCR, AttrName): return getattr(t.ASM_DESCR, AttrName, "") # 兼容 t.XXX 简化写法(如果有的话) elif isinstance(expr.value, ast.Name) and expr.value.id == 't': AttrName: str = expr.attr if hasattr(t.ASM_DESCR, AttrName): return getattr(t.ASM_DESCR, AttrName, "") # 场景3:直接传常量(如 "r"、"cc") elif isinstance(expr, ast.Constant): return expr.value # 其他场景返回空 return "" @staticmethod def _extract_val_expr(translator: Any, expr_node: ast.AST) -> str: """从AST表达式节点提取值表达式的字符串形式""" val_ExprNode: Any = translator.HandleExpr(expr_node)[0] if isinstance(val_ExprNode, str): return val_ExprNode try: return str(val_ExprNode) except Exception as _e: if _config_mode == "strict": logging.warning(f"异常被忽略: {_e}") return '' @staticmethod def _parse_asm_template(translator: Any, args: list[ast.AST]) -> tuple[str, list[tuple[str, str]], list[tuple[str, str]], int]: """解析f-string或常量模板字符串,返回(asm_code, output_ops, input_ops, operand_seq)""" output_ops: list[tuple[str, str]] = [] input_ops: list[tuple[str, str]] = [] operand_seq: int = 0 asm_code: str = "" first_arg: ast.AST = args[0] if isinstance(first_arg, ast.JoinedStr): asm_parts: list[str] = [] for part in first_arg.values: if isinstance(part, ast.Constant): asm_parts.append(part.value) elif isinstance(part, ast.FormattedValue): expr: ast.AST = part.value if isinstance(expr, ast.Call) and isinstance(expr.func, ast.Attribute) and expr.func.value.id == 'c': # 解析内联的AsmInp/AsmOut call_node: ast.Call = expr val_expr: str = Asm._extract_val_expr(translator, call_node.args[0]) if len(call_node.args)>=1 else "" constraint: str = Asm._parse_asm_descr(call_node.args[1]) if len(call_node.args)>=2 else "" if call_node.func.attr == 'AsmOut': output_ops.append((val_expr, constraint)) asm_parts.append(f"%{operand_seq}") operand_seq += 1 elif call_node.func.attr == 'AsmInp': input_ops.append((val_expr, constraint)) asm_parts.append(f"%{operand_seq}") operand_seq += 1 else: asm_parts.append(translator.HandleExpr(expr)[0]) asm_code = ''.join(asm_parts) elif isinstance(first_arg, ast.Constant): asm_code = first_arg.value return asm_code, output_ops, input_ops, operand_seq @staticmethod def _parse_asm_operands(translator: Any, args: list[ast.AST], keywords: list[ast.keyword], output_ops: list[tuple[str, str]], input_ops: list[tuple[str, str]], operand_seq: int) -> tuple[list[tuple[str, str]], list[tuple[str, str]], int]: """解析位置参数和关键字参数中的输出/输入操作数""" def parse_operand(arg: ast.AST) -> Optional[tuple[str, str, str]]: """解析 AsmInp/AsmOut 参数""" if isinstance(arg, ast.Call) and isinstance(arg.func, ast.Attribute) and arg.func.value.id == 'c': call_node: ast.Call = arg val_expr: str = Asm._extract_val_expr(translator, call_node.args[0]) if len(call_node.args)>=1 else "" constraint: str = Asm._parse_asm_descr(call_node.args[1]) if len(call_node.args)>=2 else "" if call_node.func.attr == 'AsmOut': return ('out', val_expr, constraint) elif call_node.func.attr == 'AsmInp': return ('in', val_expr, constraint) return None # 处理位置参数中的操作数 for arg in args[1:]: result: Optional[tuple[str, str, str]] = parse_operand(arg) if result: direction, val_expr, constraint = result if direction == 'out': output_ops.append((val_expr, constraint)) operand_seq += 1 elif direction == 'in': input_ops.append((val_expr, constraint)) operand_seq += 1 # 处理关键字参数中的操作数 for kw in keywords: if kw.arg == 'out': # 处理 out 关键字参数 (输出操作数) if isinstance(kw.value, ast.List): for elt in kw.value.elts: result = parse_operand(elt) if result and result[0] == 'out': output_ops.append((result[1], result[2])) operand_seq += 1 elif isinstance(kw.value, ast.Call): result = parse_operand(kw.value) if result and result[0] == 'out': output_ops.append((result[1], result[2])) operand_seq += 1 elif kw.arg == 'inp' or kw.arg == 'inputs': # 处理 inp/inputs 关键字参数 (输入操作数,追加到f-string中已有输入之后) if isinstance(kw.value, ast.List): for elt in kw.value.elts: if isinstance(elt, ast.Tuple): # 处理列表中的 (value, constraint) 元组格式 if len(elt.elts) >= 2: val_expr: str = Asm._extract_val_expr(translator, elt.elts[0]) if len(elt.elts) >= 1 else "" constraint: str = Asm._parse_asm_descr(elt.elts[1]) input_ops.append((val_expr, constraint)) operand_seq += 1 else: result = parse_operand(elt) if result and result[0] == 'in': input_ops.append((result[1], result[2])) operand_seq += 1 elif isinstance(kw.value, ast.Call): result = parse_operand(kw.value) if result and result[0] == 'in': input_ops.append((result[1], result[2])) operand_seq += 1 elif isinstance(kw.value, ast.Tuple): # 处理 (value, constraint) 元组格式 if len(kw.value.elts) >= 2: val_expr: str = Asm._extract_val_expr(translator, kw.value.elts[0]) if len(kw.value.elts) >= 1 else "" constraint: str = Asm._parse_asm_descr(kw.value.elts[1]) input_ops.append((val_expr, constraint)) operand_seq += 1 return output_ops, input_ops, operand_seq @staticmethod def _parse_asm_clobbers(args: list[ast.AST], keywords: list[ast.keyword]) -> list[str]: """解析位置参数和关键字参数中的破坏列表""" clobbers: list[str] = [] # 处理位置参数中的破坏列表 for arg in args[1:]: if isinstance(arg, ast.List): # 解析破坏列表(支持|组合) for elt in arg.elts: clobber_val: str = Asm._parse_asm_descr(elt) if clobber_val: clobbers.append(clobber_val) # 处理关键字参数中的破坏列表 for kw in keywords: if kw.arg == 'op': # 处理 op 关键字参数 (clobber,破坏列表) if isinstance(kw.value, ast.List): for elt in kw.value.elts: clobber_val: str = Asm._parse_asm_descr(elt) if clobber_val: clobbers.append(clobber_val) elif kw.arg == 'clobber': # 处理 clobber 关键字参数 if isinstance(kw.value, ast.List): for elt in kw.value.elts: clobber_val: str = Asm._parse_asm_descr(elt) if clobber_val: clobbers.append(clobber_val) return clobbers @staticmethod def _generate_asm_code(asm_code: str, output_ops: list[tuple[str, str]], input_ops: list[tuple[str, str]], clobbers: list[str], asm_format: str) -> list[str]: """格式化汇编代码并生成最终的__asm__代码字符串""" # 格式化汇编代码 asm_lines: list[str] = [line.strip() for line in asm_code.split('\n') if line.strip()] formatted_asm: str = '\n '.join([f'"{line}\\n"' for line in asm_lines]) # 拼接约束字符串 # 输出约束:如果约束已包含 = 或 +,直接使用;否则添加 = def format_constraint(constraint: str, is_output: bool = True) -> str: if not constraint: return "" # 如果约束已包含修饰符,直接返回 if '=' in constraint or '+' in constraint: return constraint # 否则添加适当的修饰符 return ('=' if is_output else '') + constraint out_const: str = ', '.join([f'"{format_constraint(c, True)}"({v})' for v, c in output_ops]) if output_ops else "" in_const: str = ', '.join([f'"{format_constraint(c, False)}"({v})' for v, c in input_ops]) if input_ops else "" clobber_const: str = ', '.join([f'"{x}"' for x in clobbers]) if clobbers else "" # 构建约束部分:确保冒号格式正确 constraint_parts: list[str] = [] # 输出约束 if output_ops: constraint_parts.append(f': {out_const}') elif input_ops or clobbers: constraint_parts.append(':') # 输入约束 if input_ops: constraint_parts.append(f': {in_const}') elif clobbers: constraint_parts.append(':') # 破坏列表 if clobbers: constraint_parts.append(f': {clobber_const}') constraint_str: str = ' '.join(constraint_parts) # 生成最终代码 if asm_format == 'ARM': # ARM 使用 .arch 指令和不同的内联汇编语法 final_asm: str = f'__asm__ __volatile__ (\n {formatted_asm} {constraint_str});' elif asm_format == 'AT&T': # AT&T 语法不需要额外标记,GCC 默认就是 AT&T final_asm = f'__asm__ __volatile__ (\n {formatted_asm} {constraint_str});' else: # Intel 语法需要 .intel_syntax 指令 final_asm = f'__asm__ __volatile__ (".intel_syntax noprefix\\n\\t"\n {formatted_asm} ".att_syntax prefix" {constraint_str});' return [final_asm] @staticmethod def HandleCall(translator: Any, args: list[ast.AST], keywords: list[ast.keyword]) -> list[str]: if not args: return ['__asm__ volatile ("nop");'] # 解析模板 asm_code: str output_ops: list[tuple[str, str]] input_ops: list[tuple[str, str]] operand_seq: int asm_code, output_ops, input_ops, operand_seq = Asm._parse_asm_template(translator, args) # 解析操作数 output_ops, input_ops, operand_seq = Asm._parse_asm_operands( translator, args, keywords, output_ops, input_ops, operand_seq) # 解析破坏列表 clobbers: list[str] = Asm._parse_asm_clobbers(args, keywords) # 解析汇编格式 asm_format: str = 'Intel' for kw in keywords: if kw.arg == 'format': if isinstance(kw.value, ast.Constant) and isinstance(kw.value.value, str): asm_format = kw.value.value # 生成最终代码 return Asm._generate_asm_code(asm_code, output_ops, input_ops, clobbers, asm_format) class AsmInp: def __init__(self, value: Any, constraint: Any) -> None: self.value: Any = value self.constraint: Any = constraint @staticmethod def HandleCall(translator: Any, args: Any, keywords: Any) -> list[Any]: return [] class AsmOut: def __init__(self, value: Any, constraint: Any) -> None: self.value: Any = value self.constraint: Any = constraint @staticmethod def HandleCall(translator: Any, args: Any, keywords: Any) -> list[Any]: return [] class NoBreak: """ switch 分支无break """ pass class Break: """ switch 分支提前break """ pass class Load: """解引用a写入b,等价于 *b = *a,无拷贝副作用""" def __init__(self, src: Any, dst: Any) -> None: self.src: Any = src self.dst: Any = dst @staticmethod def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]: if len(args) >= 2: src: Any = translator.HandleExpr(args[0])[0] dst: Any = translator.HandleExpr(args[1])[0] return [f'*({dst}) = *({src})'] return [] class Addr: """取地址""" def __init__(self, addr: Any) -> None: self.addr: Any = addr @staticmethod def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]: """处理 c.Addr() 调用""" if args: expr: Any = translator.HandleExpr(args[0])[0] if isinstance(expr, str): return [f'&{expr}'] return [f'&{_to_str(expr)}'] return ['0'] class Deref: """解引用""" def __init__(self, ptr: Any) -> None: self.ptr: Any = ptr @staticmethod def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]: """处理 c.Deref() 调用""" if args: expr: Any = translator.HandleExpr(args[0])[0] if hasattr(expr, 'op') and expr.op == '*': return [expr] return [f'*({_to_str(expr)})'] return ['0'] class DerefAs: """解引用写入,等价于 *ptr = value""" def __init__(self, ptr: Any, value: Any) -> None: self.ptr: Any = ptr self.value: Any = value @staticmethod def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]: """处理 c.DerefAs() 调用""" if len(args) >= 2: ptr: Any = translator.HandleExpr(args[0])[0] val: Any = translator.HandleExpr(args[1])[0] return [f'*({_to_str(ptr)}) = {_to_str(val)}'] return [] class Set: """设置值""" def __init__(self, key: Any, value: Any) -> None: self.key: Any = key self.value: Any = value @staticmethod def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]: """处理 c.Set() 调用""" if len(args) >= 2: target: Any = translator.HandleExpr(args[0])[0] value: Any = translator.HandleExpr(args[1])[0] return [f'{_to_str(target)} = {_to_str(value)}'] return [] class CReturn: """多返回值装饰器 用于实现函数多返回值,通过匿名结构体返回实现。 例如:@c.CReturn(t.CInt, t.CInt) 表示函数返回两个 int 值。 等价于 -> tuple[t.CInt, t.CInt] 返回类型注解。 规则: 1. CReturn 中有几个类型就说明要返回几个值 2. 函数返回类型为匿名结构体 { type1, type2, ... } 3. return 语句使用 insert_value 构建结构体 4. 调用处使用 extract_value 提取各字段 """ def __init__(self, *ReturnTypes: Any) -> None: self.ReturnTypes: tuple[Any, ...] = ReturnTypes def __call__(self, func: Any) -> Any: """装饰器调用""" # 将返回类型信息附加到函数上 func._CreturnTypes = self.ReturnTypes return func class CDefine: """#define 宏定义""" def __init__(self, name: Any, value: Any) -> None: self.name: Any = name self.value: Any = value @staticmethod def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]: """处理 c.CDefine() 调用""" if len(args) >= 1: if isinstance(args[0], ast.Constant): name: Any = args[0].value else: name = 'MACRO' if len(args) >= 2: value: Any = translator.HandleExpr(args[1])[0] return ['#define ' + str(name) + ' ' + _to_str(value)] return ['#define ' + str(name)] return [] class CIfndef: """#ifndef 条件编译""" def __init__(self, condition: Any) -> None: self.condition: Any = condition @staticmethod def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]: """处理 c.CIfndef() 调用""" if args: condition: Any = translator.HandleExpr(args[0])[0] return ['#ifndef ' + _to_str(condition)] return ['#if 0'] class CIfdef: """#ifdef 条件编译""" def __init__(self, condition: Any) -> None: self.condition: Any = condition @staticmethod def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]: """处理 c.CIfdef() 调用""" if args: condition: Any = translator.HandleExpr(args[0])[0] return ['#ifdef ' + _to_str(condition)] return ['#if 0'] class CError: """#error 错误信息""" def __init__(self, condition: Any) -> None: self.condition: Any = condition @staticmethod def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]: """处理 c.CError() 调用""" if args: # 如果是字符串常量,保留引号 if isinstance(args[0], ast.Constant) and isinstance(args[0].value, str): return ['#error "' + args[0].value + '"'] else: condition: Any = translator.HandleExpr(args[0])[0] return ['#error ' + _to_str(condition)] return ['#error "Error: Condition is not met."'] class TokenPast: """## 连接符""" def __init__(self, left: Any, right: Any) -> None: self.left: Any = left self.right: Any = right @staticmethod def HandleCall(translator: Any, args: Any, keywords: Any) -> list[Any]: """处理 c.TokenPast() 调用""" if len(args) >= 2: # 处理左操作数 - 去掉引号 if isinstance(args[0], ast.Constant): left: str = str(args[0].value) elif isinstance(args[0], ast.Name): left = args[0].id else: left = _to_str(translator.HandleExpr(args[0])[0]) # 处理右操作数 - 去掉引号 if isinstance(args[1], ast.Constant): right: str = str(args[1].value) elif isinstance(args[1], ast.Name): right = args[1].id else: right = _to_str(translator.HandleExpr(args[1])[0]) # 返回字符串,但用特殊标记包装,让 _AstNodeToStr 能正确处理 result: str = left + ' ## ' + right # 使用一个特殊的类来包装结果,让 _AstNodeToStr 直接返回其值 class TokenPastResult: def __init__(self, value: str) -> None: self.value: str = value def __str__(self) -> str: return self.value return [TokenPastResult(result)] return [''] class CIf: """#if 条件编译""" def __init__(self, condition: Any) -> None: self.condition: Any = condition @staticmethod def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]: """处理 c.CIf() 调用""" if args: condition: Any = translator.HandleExpr(args[0])[0] return ['#if ' + _to_str(condition)] return ['#if 0'] class CElif: """#elif 条件编译""" def __init__(self, condition: Any) -> None: self.condition: Any = condition @staticmethod def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]: """处理 c.CElif() 调用""" if args: condition: Any = translator.HandleExpr(args[0])[0] return ['#elif ' + _to_str(condition)] return ['#else'] class CElse: """#else 条件编译""" def __init__(self) -> None: pass @staticmethod def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]: """处理 c.CElse() 调用""" return ['#else'] class CEndif: """#endif 条件编译""" def __init__(self) -> None: pass @staticmethod def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]: """处理 c.CEndif() 调用""" return ['#endif'] class CUndef: """#undef 取消宏定义""" def __init__(self, name: Any) -> None: self.name: Any = name @staticmethod def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]: """处理 c.CUndef(name) 调用""" if args: arg: Any = args[0] if isinstance(arg, str): name: str = arg elif isinstance(arg, ast.Name): name = arg.id elif isinstance(arg, ast.Constant): name = str(arg.value) else: name = str(arg) return [f'#undef {name}'] return ['#undef'] class LLVMIR: """内联 LLVM IR 用法: c.LLVMIR(f"add i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt) 或: c.LLVMIR(f"%{c.LOut(result)} = add i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt) c.LInp(expr) - 输入操作数,翻译后替换为对应的 LLVM 临时变量名 c.LOut(expr) - 输出操作数,翻译后替换为对应的 LLVM 临时变量名 """ def __init__(self, ir_template: Any, ret_type: Any = None) -> None: self.ir_template: Any = ir_template self.ret_type: Any = ret_type @staticmethod def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]: return ['/* LLVMIR */'] class LInp: """LLVM IR 输入操作数标记 用法: c.LInp(expr) - 标记 expr 为输入操作数 在 c.LLVMIR 的 f-string 中使用,翻译后替换为 %N 形式的操作数引用 """ def __init__(self, value: Any) -> None: self.value: Any = value @staticmethod def HandleCall(translator: Any, args: Any, keywords: Any) -> list[Any]: return [] class LOut: """LLVM IR 输出操作数标记 用法: c.LOut(expr) - 标记 expr 为输出操作数 在 c.LLVMIR 的 f-string 中使用,翻译后替换为 %N 形式的操作数引用 """ def __init__(self, value: Any) -> None: self.value: Any = value @staticmethod def HandleCall(translator: Any, args: Any, keywords: Any) -> list[Any]: return [] class CPragma: """#pragma 指令 用于生成 C 语言的 #pragma 指令。 例如:c.CPragma("GCC diagnostic push") 生成 #pragma GCC diagnostic push """ def __init__(self, directive: Any) -> None: self.directive: Any = directive @staticmethod def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]: """处理 c.CPragma() 调用""" if args: arg: Any = args[0] if isinstance(arg, ast.Constant): directive: Any = arg.value else: expr: Any = translator.HandleExpr(arg)[0] directive = _to_str(expr) return [f'#pragma {directive}'] return ['#pragma'] # C 库类字典,用于 HandleCSpecialCall Library_C = { 'Asm': Asm, 'Load': Load, 'Addr': Addr, 'Deref': Deref, 'Set': Set, 'AsmInp': AsmInp, 'AsmOut': AsmOut, 'CDefine': CDefine, 'CIfndef': CIfndef, 'CIfdef': CIfdef, 'CIf': CIf, 'CElif': CElif, 'CElse': CElse, 'CEndif': CEndif, 'CUndef': CUndef, 'CError': CError, 'TokenPast': TokenPast, 'CReturn': CReturn, 'CPragma': CPragma, 'LLVMIR': LLVMIR, 'LInp': LInp, 'LOut': LOut, } class Attribute: """函数/变量属性装饰器""" def __init__(self, *attrs: Any) -> None: self.attrs: tuple[Any, ...] = attrs def __call__(self, func: Any) -> Any: # 将属性附加到函数上 func._c_attributes = self.attrs return func