From f286845463159054b293d977e9ca5ce115d7f3fe Mon Sep 17 00:00:00 2001 From: lixuanwang Date: Tue, 27 May 2025 12:03:26 +0800 Subject: [PATCH] [lab3]addl movl ret passes clang test --- src/pysrc/sysy/backend/x86_emitter.py | 64 ++++++++++++++++++++------ src/pysrc/sysy/middle_ir.py | 30 +++++++++++- src/pysrc/sysyc.py | 13 +++--- src/pysrc/test_add_exec | Bin 0 -> 15880 bytes 4 files changed, 85 insertions(+), 22 deletions(-) create mode 100755 src/pysrc/test_add_exec diff --git a/src/pysrc/sysy/backend/x86_emitter.py b/src/pysrc/sysy/backend/x86_emitter.py index 71c5d08..b4d1991 100644 --- a/src/pysrc/sysy/backend/x86_emitter.py +++ b/src/pysrc/sysy/backend/x86_emitter.py @@ -12,23 +12,57 @@ class X86Emitter: asm.append(self.emit_instruction(instr)) return "\n".join(asm) - def emit_instruction(self, instr: MiddleInstruction) -> str: - op = instr.opcode - if op == "add": - src1, src2 = instr.operands - dest = instr.dest - #TODO(Lixuan Wang): src1 src2 的类型标签还没有去除,如i32 5,会出现在汇编文件中,这是不对的 - return ( - f" movl ${src1}, %{self.map_operand(dest)}\n" - f" addl ${src2}, %{self.map_operand(dest)}" - ) - elif op == "ret": - return " ret" + def is_register(self, operand): + return operand.startswith("%") + + def get_operand_asm(self, operand): + if self.is_register(operand): + return "%" + self.map_operand(operand) else: - raise NotImplementedError(f"Unsupported opcode: {op}") + # 移除类型信息(如 'i32'),提取数值 + # 假设操作数格式为 'i32 5' 或直接为 '5' + parts = operand.split() + # 如果包含类型信息,取最后一个部分(数值) + value = parts[-1] if len(parts) > 1 else operand + try: + # 验证是有效整数 + int(value) + return "$" + value + except ValueError: + # 如果不是有效整数,抛出错误 + raise ValueError(f"Invalid immediate operand: {operand}") def map_operand(self, operand: str) -> str: """将虚拟寄存器映射到物理寄存器(简化版)""" - if operand.startswith('%.'): - return self.reg_pool[int(operand[2:]) % len(self.reg_pool)] + if operand.startswith('%'): + # 去掉 '%' 和 '.'(如果有) + reg_num = operand[1:].replace('.', '') + try: + idx = int(reg_num) + return self.reg_pool[idx % len(self.reg_pool)] + except ValueError: + return "eax" # 默认 return operand + + def emit_instruction(self, instr: MiddleInstruction) -> str: + op = instr.opcode + if op in ["add", "sub", "mul"]: + dest_reg = self.map_operand(instr.dest) + src1, src2 = instr.operands + if op == "add": + op_asm = "addl" + elif op == "sub": + op_asm = "subl" + elif op == "mul": + op_asm = "imull" + asm = f" movl {self.get_operand_asm(src1)}, %{dest_reg}\n" + asm += f" {op_asm} {self.get_operand_asm(src2)}, %{dest_reg}" + return asm + elif op == "ret": + if instr.operands: + op = instr.operands[0] + return f" movl {self.get_operand_asm(op)}, %eax\n ret" + else: + return " ret" + else: + raise NotImplementedError(f"Unsupported opcode: {op}") \ No newline at end of file diff --git a/src/pysrc/sysy/middle_ir.py b/src/pysrc/sysy/middle_ir.py index d6fe352..01fdbbc 100644 --- a/src/pysrc/sysy/middle_ir.py +++ b/src/pysrc/sysy/middle_ir.py @@ -2,17 +2,40 @@ class MiddleFunction: def __init__(self, name: str): self.name = name self.basic_blocks = [] # List[MiddleBasicBlock] + def __repr__(self): return f"Function({self.name}):\n" + "\n".join(str(block) for block in self.basic_blocks) + def __str__(self): return self.__repr__() + def collect_used_registers(self): + used = set() + for block in self.basic_blocks: + for instr in block.instructions: + for op in instr.operands: + if op.startswith("%"): + used.add(op) + # For ret, if it has operands + if instr.opcode == "ret" and instr.operands: + op = instr.operands[0] + if op.startswith("%"): + used.add(op) + return used + + def dead_code_elimination(self): + used = self.collect_used_registers() + for block in self.basic_blocks: + block.instructions = [instr for instr in block.instructions if instr.dest is None or instr.dest in used] + class MiddleBasicBlock: def __init__(self, name: str): self.name = name self.instructions = [] # List[MiddleInstruction] + def __repr__(self): return f"BasicBlock({self.name}):\n" + "\n".join(str(instr) for instr in self.instructions) + def __str__(self): return self.__repr__() @@ -21,7 +44,12 @@ class MiddleInstruction: self.opcode = opcode # e.g., 'add' self.operands = operands # e.g., ['5', '7'] self.dest = dest # e.g., '%0' + def __repr__(self): - return f"{self.dest} = {self.opcode} " + ", ".join(self.operands) if self.dest else f"{self.opcode} " + ", ".join(self.operands) + if self.dest: + return f"{self.dest} = {self.opcode} " + ", ".join(self.operands) + else: + return f"{self.opcode} " + ", ".join(self.operands) + def __str__(self): return self.__repr__() \ No newline at end of file diff --git a/src/pysrc/sysyc.py b/src/pysrc/sysyc.py index db62eee..5de1c27 100644 --- a/src/pysrc/sysyc.py +++ b/src/pysrc/sysyc.py @@ -4,7 +4,6 @@ from sysy.backend.x86_emitter import X86Emitter def main(): if len(sys.argv) != 2: - # print("Usage: sysyc.py ") print("Usage: sysyc.py ") sys.exit(1) @@ -14,12 +13,14 @@ def main(): # 解析并生成汇编 func = parse_llvm_ir(ir_text) - print(func) + # print("Before optimization:") + # print(func) + # func.dead_code_elimination() + # print("After optimization:") + # print(func) asm = X86Emitter().emit_function(func) - # 写入文件 - # with open(sys.argv[2], 'w') as f: - # f.write(asm) print(asm) + if __name__ == "__main__": - main() + main() \ No newline at end of file diff --git a/src/pysrc/test_add_exec b/src/pysrc/test_add_exec new file mode 100755 index 0000000000000000000000000000000000000000..051d8f9776904a4000ddf3d46f9e9f6d1b1f39e4 GIT binary patch literal 15880 zcmeHOTWlOx89uwYctcZr6Pn^CB^iN>5*kl@i*aZ!>-ds&C>L{NcYc6V&Av=_5G z+t^i9f(%lkDpEiQ=tHISg;o_3h)dP-v{6wBh*k;Wp-;#HDuswkP`RX~WcmL&|F<3w zYf)7Q@oDt8hZUC40gtWKX zbx?@EpoCZLDdaPQ1A7X&?n1s)o9~_<8tfh%u&ZUeFKC|o#clAII&$okil0+;=Ah^N zJ#=tb*?u$o{A0QG?|dij^^Csy!xz-UC+}^b4%V;_C-z5|xXgKOgMEVWq`pWw8Owy% zz1NBXvC0SQHn*^i5NEaEomKeKD*XG2|4@s1l;cnYvrg4_E51{7^Ce=k^R6?UFS&*M zd?LaxNrj1& z*hP+V{g5X38uB$kx*Foc*Zo?E*FD#Y*F!vyAEc!a&*Q};69E$e69E$e69E$e69E$e z6M?ym2kP_~XROfqP@`&xme3@N@d?*pZ^#^OT#u zgt}PY`-h1O*FT%S@ay#AZ*M&^HP&12{b~B*fmg|=vE@;6|I4)9vExgDg!re3Nnc#| zRfc`H{Vmk=LC#at8yZU;JI=A=%Yx*e5B&FL7UWpau=enQ3Old)|Z z+Y*=PMHch?j{f$a8jX*z!)ROZCajCH19a4h4~X{Uczfr=9e15coKuIkKJ?N4uHdyH z+dfUlbL5A2Y*aMKM8HJAM8HJAM8HJAM8HJAM8HJAM8HJgzZ?OqXTxveORoqsEGg8i>|8f7kDmPL+OyLeg_H|jO7N?jHE z``DS%c@63=!A`*~f&h`J8?rtUYltmr2>qywfEI%W3HAM>q5DT<;Ce^Ox1@jcW;p0S z;zmE0gYuHt-;y%=A=UrS0qe(CYZ&WPkBp3b+}e36Q!Dv3tGD0ow|lw=YeBK^iM|25 zXJD7mtJS1=j>lT{=SI|v;~OK(SqX?G4!n-ImH&3)8@p~yy z7Mwyj9Po6Pq(UTR`-o4f&Ssop-ADZ9c!$Ds1N z)UvWPBe$PALwu61duIxs8pnv=OxHIh<0tsv6`9V8KgJ1E=L7!Vuj57Hxj#|=r--*8 z4&nES$Fns=tJjF%9H*yQWIU^r*^1w5mubbjo5?%AJEMrG`nBn4JFAvg$2)$}$@2R6 zDtYG0&P<`4aSKk)FITFLTbozea&fNU`CiWMY3;!)^Ye~dskjS{SMng5zgfIgf|wJKWK!9bf3a7Mg4q2-o?mHQl;-R9j5 zLEvalP<5f`yBR{iqHz|ve2KO?%qhE6_C0&1RI}$QMW@;RY~4^MRS zxCq>5-Ri8ea|r|>j-)7QsU8qofjrgg7V}wZwCr=u)Fr++HU(DMG$e~OSi-l#d(QK`gKi;u zX6w``-!DMSJH#CLBG33?I(TjX{gCK^7TLlH^9FFdJua+2EqY)V90l=w0?pq~VLiSd zffgJEqxw%0|2LXzp#PXp0nt9@Q_=prr02O5^q6k}FG;)HM~*Y}m?!0l<5Pwn^EV)W zZ-x`s5l)|{0?(zOUy>69VjhbA!w>ib>3MF3GUjK%9%(GvfArxZWw=S`F+T*>#S!gC z&;J`_=W~L+`5c$$Ip)PuP0$wdjDM#ithYo5lwwnYGVtk$zDEo|^cNMN4E$C^pAtRr zZ3qR?F6eJZ^!T0!;&%i5qvMz7NqqjzIfx~mf>D2zfj=U5*5mqN-UIBC>HyH8e3dd` z{Z30;fOBvZMBG6Cf->!N$ZfwoKjh`6l%oD91Aj$69dtmC`Do%@>Ti;k#~$>U4`LrF z_KWiP=Y)1~9iJhN&mVg1SF7(~Z>4r>XnsNue3L9;J$`T95Ivp~r~o?PI}yD~iD!>S z^i$Yo|51)p<6IZ|kNH?q^k@hE+}ChwBZ4_`ZanuS>r~Lt=~+Y3|!v@9))uWJC}ts(%478H76k literal 0 HcmV?d00001