Files
2026-07-18 19:25:40 +08:00

722 lines
26 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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
# 场景2t.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