diff --git a/.gitignore b/.gitignore index 3649ac4..1c41982 100644 --- a/.gitignore +++ b/.gitignore @@ -44,4 +44,8 @@ tmp GPATH GRTAGS -GTAGS \ No newline at end of file +GTAGS + +__init__.py + +*.pyc \ No newline at end of file diff --git a/src/pysrc/requirements.txt b/src/pysrc/requirements.txt new file mode 100644 index 0000000..e7d0682 --- /dev/null +++ b/src/pysrc/requirements.txt @@ -0,0 +1 @@ +llvmlite==0.41.0 diff --git a/src/pysrc/sysy/backend/x86_emitter.py b/src/pysrc/sysy/backend/x86_emitter.py new file mode 100644 index 0000000..a58d981 --- /dev/null +++ b/src/pysrc/sysy/backend/x86_emitter.py @@ -0,0 +1,27 @@ +class X86Emitter: + def __init__(self): + self.reg_pool = ["eax", "ebx", "ecx", "edx"] # 简化寄存器分配 + + def emit_function(self, func: MiddleFunction) -> str: + asm = [f".globl {func.name}", f"{func.name}:"] + for block in func.basic_blocks: + asm.append(f".{block.name}:") + for instr in block.instructions: + asm.append(self.emit_instruction(instr)) + return "\n".join(asm) + + def emit_instruction(self, instr: MiddleInstruction) -> str: + op = instr.opcode + if op == "add": + dest, src1, src2 = instr.operands + return f" addl {self.map_operand(src2)}, {self.map_operand(dest)}" + elif op == "ret": + return " ret" + else: + raise NotImplementedError(f"Unsupported opcode: {op}") + + def map_operand(self, operand: str) -> str: + """将虚拟寄存器映射到物理寄存器(简化版)""" + if operand.startswith('%'): + return self.reg_pool[int(operand[1:]) % len(self.reg_pool)] + return operand diff --git a/src/pysrc/sysy/middle_ir.py b/src/pysrc/sysy/middle_ir.py new file mode 100644 index 0000000..ddc5859 --- /dev/null +++ b/src/pysrc/sysy/middle_ir.py @@ -0,0 +1,14 @@ +class MiddleFunction: + def __init__(self, name: str): + self.name = name + self.basic_blocks = [] # List[MiddleBasicBlock] + +class MiddleBasicBlock: + def __init__(self, name: str): + self.name = name + self.instructions = [] # List[MiddleInstruction] + +class MiddleInstruction: + def __init__(self, opcode: str, operands: list): + self.opcode = opcode # e.g., 'add', 'ret' + self.operands = operands # e.g., ['%0', '%1', '%2'] diff --git a/src/pysrc/sysy/utils/ir_parser.py b/src/pysrc/sysy/utils/ir_parser.py new file mode 100644 index 0000000..479803f --- /dev/null +++ b/src/pysrc/sysy/utils/ir_parser.py @@ -0,0 +1,22 @@ +from llvmlite import ir + +def parse_llvm_ir(ir_text: str) -> MiddleFunction: + """将 LLVM IR 文本转换为 MiddleIR 结构(简化版)""" + module = ir.Module() + module.parse(ir_text) + + # 提取第一个函数 + func = list(module.functions)[0] + middle_func = MiddleFunction(func.name) + + # 转换基本块和指令 + for block in func.blocks: + mid_block = MiddleBasicBlock(block.name) + for instr in block.instructions: + opcode = instr.opcode + operands = [str(op) for op in instr.operands] + mid_instr = MiddleInstruction(opcode, operands) + mid_block.instructions.append(mid_instr) + middle_func.basic_blocks.append(mid_block) + + return middle_func diff --git a/src/pysrc/sysyc.py b/src/pysrc/sysyc.py new file mode 100644 index 0000000..3716b7a --- /dev/null +++ b/src/pysrc/sysyc.py @@ -0,0 +1,23 @@ +import sys +from sysy.utils.ir_parser import parse_llvm_ir +from sysy.backend.x86_emitter import X86Emitter + +def main(): + if len(sys.argv) != 3: + print("Usage: sysyc.py ") + sys.exit(1) + + # 读取 LLVM IR + with open(sys.argv[1], 'r') as f: + ir_text = f.read() + + # 解析并生成汇编 + func = parse_llvm_ir(ir_text) + asm = X86Emitter().emit_function(func) + + # 写入文件 + with open(sys.argv[2], 'w') as f: + f.write(asm) + +if __name__ == "__main__": + main() diff --git a/src/pysrc/tests/test_add.ll b/src/pysrc/tests/test_add.ll new file mode 100644 index 0000000..1ca881f --- /dev/null +++ b/src/pysrc/tests/test_add.ll @@ -0,0 +1,5 @@ +define i32 @add(i32 %a, i32 %b) { +entry: + %sum = add i32 %a, %b + ret i32 %sum +}