722 lines
26 KiB
Python
722 lines
26 KiB
Python
# 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
|