mips without optimize

This commit is contained in:
colden
2025-12-12 20:14:00 +08:00
parent 84827838e2
commit c94bebf37b
130 changed files with 5462 additions and 4182 deletions

90
Compiler.java Normal file → Executable file
View File

@@ -1,42 +1,48 @@
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
import frontend.lexer.Lexer;
import frontend.lexer.TokenStream; import backend.BackEnd;
import frontend.parser.Parser; import frontend.lexer.Lexer;
import midend.Midend; import frontend.lexer.TokenStream;
import midend.errorhandle.ErrorHandler; import frontend.parser.Parser;
import midend.Midend;
import error.Errors; import midend.errorhandle.ErrorHandler;
import midend.symbol.SymbolManager;
import error.Errors;
public class Compiler { import midend.symbol.SymbolManager;
public static void main(String[] args) {
Errors errors = new Errors(); public class Compiler {
try { public static void main(String[] args) {
String content = new String(Files.readAllBytes(Paths.get("testfile.txt"))); Errors errors = new Errors();
String llvmFile = "llvm_ir.txt"; try {
String errorFile = "error.txt"; String content = new String(Files.readAllBytes(Paths.get("testfile.txt")));
Lexer lexer = new Lexer(content); String llvmFile = "llvm_ir.txt";
lexer.lex(errors); String mipsFile = "mips.txt";
TokenStream ts = new TokenStream(lexer.getTokens()); String errorFile = "error.txt";
Parser parser = new Parser(ts); Lexer lexer = new Lexer(content);
parser.parse(errors); lexer.lex(errors);
ErrorHandler errorHandler = new ErrorHandler(parser.getCompUnit()); TokenStream ts = new TokenStream(lexer.getTokens());
errorHandler.visit(errors); Parser parser = new Parser(ts);
// for (int i : SymbolManager.getSequence()) { parser.parse(errors);
// System.out.print(i + " "); ErrorHandler errorHandler = new ErrorHandler(parser.getCompUnit());
// } errorHandler.visit(errors);
// System.out.println(); // TODO:debug // for (int i : SymbolManager.getSequence()) {
if (errors.size() > 0) { // System.out.print(i + " ");
StringBuilder sb = errors.toStringBuilder(); // }
Files.write(Paths.get(errorFile), sb.toString().getBytes()); // System.out.println(); // TODO:debug
} else { if (errors.size() > 0) {
Midend midend = new Midend(parser.getCompUnit()); StringBuilder sb = errors.toStringBuilder();
midend.generateLLvmIr(); Files.write(Paths.get(errorFile), sb.toString().getBytes());
midend.writeToFile(llvmFile); } else {
} Midend midend = new Midend(parser.getCompUnit());
} catch (Exception e) { midend.generateLLvmIr();
e.printStackTrace(); // midend.writeToFile(llvmFile);
} BackEnd backEnd = new BackEnd(midend.getModule());
} backEnd.toMips();
} backEnd.writeToFile(mipsFile);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

32
backend/BackEnd.java Normal file
View File

@@ -0,0 +1,32 @@
package backend;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import backend.mips.MipsBuilder;
import backend.mips.MipsModule;
import midend.llvm.IrModule;
public class BackEnd {
private MipsModule mipsModule;
private IrModule irModule;
public BackEnd(IrModule irModule) {
this.irModule = irModule;
this.mipsModule = new MipsModule();
}
public void toMips() {
MipsBuilder.setModule(mipsModule);
irModule.toMips();
}
public void writeToFile(String fileName) {
try {
Files.write(Paths.get(fileName), mipsModule.toString().getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,93 @@
package backend.mips;
import java.util.HashMap;
import java.util.ArrayList;
import backend.mips.instr.MipsInstr;
import backend.mips.instr.data.MipsAsciiz;
import backend.mips.instr.data.MipsSpace;
import backend.mips.instr.data.MipsWord;
import midend.llvm.value.IrFuncValue;
import midend.llvm.value.IrValue;
public class MipsBuilder {
private static MipsModule module = null;
private static int offset = 0;
private static HashMap<IrValue, Integer> valueOffsetMap = new HashMap<>();
private static HashMap<IrValue, Register> valueRegisterMap = new HashMap<>();
public static void setModule(MipsModule module) {
MipsBuilder.module = module;
}
public static int getOffset() {
return offset;
}
public static void setOffset(int offset) {
MipsBuilder.offset = offset;
}
public static void setValueOffsetMap(HashMap<IrValue, Integer> valueOffsetMap) {
MipsBuilder.valueOffsetMap = valueOffsetMap;
}
public static HashMap<IrValue, Integer> getValueOffsetMap() {
return valueOffsetMap;
}
public static void setValueRegisterMap(HashMap<IrValue, Register> valueRegisterMap) {
MipsBuilder.valueRegisterMap = valueRegisterMap;
}
public static HashMap<IrValue, Register> getValueRegisterMap() {
return valueRegisterMap;
}
public static MipsModule getModule() {
return module;
}
public static void addMipsInstr(MipsInstr instr) {
if (instr instanceof MipsAsciiz || instr instanceof MipsWord || instr instanceof MipsSpace) { //data段
module.addData(instr);
} else {
module.addText(instr);
}
}
public static void enterNewFunc(IrFuncValue func) {
offset = 0;
valueOffsetMap = func.getValueOffsetMap();
valueOffsetMap.clear(); //TODO是否需要清空
valueRegisterMap = func.getValueRegisterMap();
}
public static Register getRegister(IrValue value) {
return valueRegisterMap.get(value);
}
public static Integer getOffset(IrValue value) {
return valueOffsetMap.get(value);
}
public static void allocaRegister(IrValue value, Register reg) {
valueRegisterMap.put(value, reg);
}
public static void allocaOffset(IrValue value) {
if (!valueOffsetMap.containsKey(value)) {
offset -= 4;
int valueOffset = offset;
valueOffsetMap.put(value, valueOffset);
}
}
public static void allocaOffset(int extra) {
offset -= extra;
}
public static ArrayList<Register> getUsedRegisters() {
return new ArrayList<>(valueRegisterMap.values());
}
}

View File

@@ -0,0 +1,51 @@
package backend.mips;
import java.util.ArrayList;
import backend.mips.instr.MipsAnnotation;
import backend.mips.instr.MipsLabel;
import backend.mips.instr.MipsInstr;
public class MipsModule {
private ArrayList<MipsInstr> dataList;
private ArrayList<MipsInstr> textList;
public MipsModule() {
this.dataList = new ArrayList<MipsInstr>();
this.textList = new ArrayList<MipsInstr>();
}
public ArrayList<MipsInstr> getDataList() {
return dataList;
}
public ArrayList<MipsInstr> getTextList() {
return textList;
}
public void addData(MipsInstr instr) {
dataList.add(instr);
}
public void addText(MipsInstr instr) {
textList.add(instr);
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(".data\n");
for (MipsInstr instr : dataList) {
sb.append("\t" + instr.toString());
}
sb.append("\n.text\n");
for (MipsInstr instr : textList) {
if (instr instanceof MipsLabel || instr instanceof MipsAnnotation) {
sb.append(instr.toString());
continue;
}
sb.append("\t" + instr.toString());
}
return sb.toString();
}
}

58
backend/mips/Register.java Executable file
View File

@@ -0,0 +1,58 @@
package backend.mips;
import java.util.ArrayList;
public enum Register {
ZERO("$zero"),
AT("$at"),
V0("$v0"),
V1("$v1"),
A0("$a0"),
A1("$a1"),
A2("$a2"),
A3("$a3"),
T0("$t0"),
T1("$t1"),
T2("$t2"),
T3("$t3"),
T4("$t4"),
T5("$t5"),
T6("$t6"),
T7("$t7"),
S0("$s0"),
S1("$s1"),
S2("$s2"),
S3("$s3"),
S4("$s4"),
S5("$s5"),
S6("$s6"),
S7("$s7"),
T8("$t8"),
T9("$t9"),
K0("$k0"),
K1("$k1"),
GP("$gp"),
SP("$sp"),
FP("$fp"),
RA("$ra");
private String regName;
Register(String regName) {
this.regName = regName;
}
public String toString() {
return regName;
}
public static ArrayList<Register> availableRegisters() {
ArrayList<Register> regs = new ArrayList<>();
for (Register reg : Register.values()) {
if (reg.toString().charAt(1) == 't' || reg.toString().charAt(1) == 's') {
regs.add(reg);
}
}
return regs;
}
}

39
backend/mips/instr/MipsAlu.java Executable file
View File

@@ -0,0 +1,39 @@
package backend.mips.instr;
import backend.mips.Register;
import backend.mips.instr.type.MipsAluType;
import backend.mips.instr.type.MipsType;
public class MipsAlu extends MipsInstr {
private MipsAluType aluType;
private Register rd;
private Register rs;
private Register rt;
private int immediate;
private boolean isImInstr;
public MipsAlu(MipsAluType aluType, Register rd, Register rs, Register rt) {
super(MipsType.ALU);
this.aluType = aluType;
this.rd = rd;
this.rs = rs;
this.rt = rt;
this.immediate = 0;
this.isImInstr = false;
}
public MipsAlu(MipsAluType aluType, Register rd, Register rs, int immediate) {
super(MipsType.ALU);
this.aluType = aluType;
this.rd = rd;
this.rs = rs;
this.rt = null;
this.immediate = immediate;
this.isImInstr = true;
}
public String toString() {
return isImInstr ? aluType.toString() + " " + rd + ", " + rs + ", " + immediate + "\n"
: aluType.toString() + " " + rd + ", " + rs + ", " + rt + "\n";
}
}

View File

@@ -0,0 +1,16 @@
package backend.mips.instr;
import backend.mips.instr.type.MipsType;
public class MipsAnnotation extends MipsInstr {
private String annotation;
public MipsAnnotation(String anno) {
super(MipsType.ANNOTATION);
this.annotation = anno;
}
public String toString() {
return "# " + this.annotation + "\n";
}
}

View File

@@ -0,0 +1,36 @@
package backend.mips.instr;
import backend.mips.instr.type.MipsBranchType;
import backend.mips.instr.type.MipsType;
import backend.mips.Register;
public class MipsBranch extends MipsInstr{
private MipsBranchType branchType;
private Register rs;
private Register rt;
private String label;
public MipsBranch(MipsBranchType branchType, Register rs, Register rt, String label) {
super(MipsType.BRANCH);
this.branchType = branchType;
this.rs = rs;
this.rt = rt;
this.label = label;
}
public MipsBranch(MipsBranchType branchType, Register rs, String label) {
super(MipsType.BRANCH);
this.branchType = branchType;
this.rs = rs;
this.rt = null;
this.label = label;
}
public String toString() {
if (this.rt == null) {
return this.branchType.toString() + " " + this.rs + ", " + this.label + "\n";
} else {
return this.branchType.toString() + " " + this.rs + ", " + this.rt + ", " + this.label + "\n";
}
}
}

View File

@@ -0,0 +1,42 @@
package backend.mips.instr;
import backend.mips.instr.type.MipsCompareType;
import backend.mips.instr.type.MipsType;
import backend.mips.Register;
public class MipsComp extends MipsInstr {
private MipsCompareType compareType;
private Register rd;
private Register rs;
private Register rt;
private int immediate;
private boolean isImmediate;
public MipsComp(MipsCompareType compareType, Register rd, Register rs, Register rt) {
super(MipsType.COMPARE);
this.compareType = compareType;
this.rd = rd;
this.rs = rs;
this.rt = rt;
this.immediate = 0;
this.isImmediate = false;
}
public MipsComp(MipsCompareType compareType, Register rd, Register rs, int immediate) {
super(MipsType.COMPARE);
this.compareType = compareType;
this.rd = rd;
this.rs = rs;
this.rt = null;
this.immediate = immediate;
this.isImmediate = true;
}
public String toString() {
if (this.isImmediate) {
return this.compareType.toString() + " " + this.rd + ", " + this.rs + ", " + this.immediate + "\n";
} else {
return this.compareType.toString() + " " + this.rd + ", " + this.rs + ", " + this.rt + "\n";
}
}
}

View File

@@ -0,0 +1,21 @@
package backend.mips.instr;
import backend.mips.instr.type.MipsType;
import backend.mips.MipsBuilder;
public class MipsInstr {
private MipsType mt;
public MipsInstr(MipsType mt) {
this.mt = mt;
MipsBuilder.addMipsInstr(this);
}
public String toString() {
return "";
}
public MipsType getType() {
return mt;
}
}

View File

@@ -0,0 +1,33 @@
package backend.mips.instr;
import backend.mips.Register;
import backend.mips.instr.type.MipsJumpType;
import backend.mips.instr.type.MipsType;
public class MipsJump extends MipsInstr {
private MipsJumpType jumpType;
private String label;
private Register rd;
public MipsJump(MipsJumpType jumpType, String label) {
super(MipsType.JUMP);
this.jumpType = jumpType;
this.label = label;
this.rd = null;
}
public MipsJump(MipsJumpType jumpType, Register rd) {
super(MipsType.JUMP);
this.jumpType = jumpType;
this.label = null;
this.rd = rd;
}
public String toString() {
if (this.rd == null) {
return this.jumpType.toString() + " " + this.label + "\n";
} else {
return this.jumpType.toString() + " " + this.rd + "\n";
}
}
}

View File

@@ -0,0 +1,16 @@
package backend.mips.instr;
import backend.mips.instr.type.MipsType;
public class MipsLabel extends MipsInstr {
private String label;
public MipsLabel(String label) {
super(MipsType.LABEL);
this.label = label;
}
public String toString() {
return this.label + ":\n";
}
}

View File

@@ -0,0 +1,39 @@
package backend.mips.instr;
import backend.mips.instr.type.MipsLsType;
import backend.mips.instr.type.MipsType;
import backend.mips.Register;
public class MipsLs extends MipsInstr {
private MipsLsType lsType;
private Register rd;
private Register rt;
private int offset;
private String label;
public MipsLs(MipsLsType lsType, Register rd, Register rt, int offset) {
super(MipsType.LS);
this.lsType = lsType;
this.rd = rd;
this.rt = rt;
this.offset = offset;
this.label = null;
}
public MipsLs(MipsLsType lsType, Register rd, int offset, String label) {
super(MipsType.LS);
this.lsType = lsType;
this.rd = rd;
this.rt = null;
this.offset = offset;
this.label = label;
}
public String toString() {
if (this.label == null) {
return this.lsType.toString() + " " + this.rd + ", " + this.offset + "(" + this.rt + ")\n";
} else {
return this.lsType.toString() + " " + this.rd + ", " + this.label + " + " + this.offset + "\n";
}
}
}

View File

@@ -0,0 +1,33 @@
package backend.mips.instr;
import backend.mips.instr.type.MipsMdType;
import backend.mips.instr.type.MipsType;
import backend.mips.Register;
public class MipsMd extends MipsInstr {
private MipsMdType mdType;
private Register rd;
private Register rt;
public MipsMd(MipsMdType mdType, Register rd, Register rt) {
super(MipsType.MD);
this.mdType = mdType;
this.rd = rd;
this.rt = rt;
}
public MipsMd(MipsMdType mdType, Register rd) {
super(MipsType.MD);
this.mdType = mdType;
this.rd = rd;
this.rt = null;
}
public String toString() {
if (this.rt == null) {
return this.mdType.toString() + " " + this.rd + "\n";
} else {
return this.mdType.toString() + " " + this.rd + ", " + this.rt + "\n";
}
}
}

View File

@@ -0,0 +1,13 @@
package backend.mips.instr;
import backend.mips.instr.type.MipsType;
public class MipsSyscall extends MipsInstr {
public MipsSyscall() {
super(MipsType.SYSCALL);
}
public String toString() {
return "syscall\n";
}
}

View File

@@ -0,0 +1,19 @@
package backend.mips.instr.data;
import backend.mips.instr.MipsInstr;
import backend.mips.instr.type.MipsType;
public class MipsAsciiz extends MipsInstr {
private String name;
private String str;
public MipsAsciiz(String name, String str) {
super(MipsType.DATA);
this.name = name;
this.str = str;
}
public String toString() {
return name + ": .asciiz \"" + str.replaceAll("\n", "\\n") + "\"\n";
}
}

View File

@@ -0,0 +1,19 @@
package backend.mips.instr.data;
import backend.mips.instr.MipsInstr;
import backend.mips.instr.type.MipsType;
public class MipsSpace extends MipsInstr {
private int size;
private String name;
public MipsSpace(int size, String name) {
super(MipsType.DATA);
this.size = size;
this.name = name;
}
public String toString() {
return name + ": .space " + size + "\n";
}
}

View File

@@ -0,0 +1,39 @@
package backend.mips.instr.data;
import java.util.ArrayList;
import backend.mips.instr.MipsInstr;
import backend.mips.instr.type.MipsType;
public class MipsWord extends MipsInstr {
private String name;
private ArrayList<Integer> valueList;
public MipsWord(String name, ArrayList<Integer> valueList) {
super(MipsType.DATA);
this.name = name;
this.valueList = valueList;
}
public MipsWord(String name, int value) {
super(MipsType.DATA);
this.name = name;
this.valueList = new ArrayList<Integer>();
this.valueList.add(value);
}
public int getValueNum() {
return valueList.size();
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(name).append(": .word ");
for (int value : valueList) {
sb.append(value).append(", ");
}
sb.delete(sb.length() - 2, sb.length());
sb.append("\n");
return sb.toString();
}
}

View File

@@ -0,0 +1,28 @@
package backend.mips.instr.fake;
import backend.mips.instr.MipsInstr;
import backend.mips.instr.type.MipsType;
import backend.mips.Register;
public class MipsLa extends MipsInstr {
private Register rd;
private String label;
public MipsLa(Register rd, String label) {
super(MipsType.FAKE);
this.rd = rd;
this.label = label;
}
public Register getRd() {
return rd;
}
public String getLabel() {
return label;
}
public String toString() {
return "la " + rd + ", " + label + "\n";
}
}

View File

@@ -0,0 +1,29 @@
package backend.mips.instr.fake;
import backend.mips.instr.MipsInstr;
import backend.mips.instr.type.MipsType;
import backend.mips.Register;
public class MipsLi extends MipsInstr {
private Register rd;
private int value;
public MipsLi(Register rd, int value) {
super(MipsType.FAKE);
this.rd = rd;
this.value = value;
}
public Register getRd() {
return rd;
}
public int getValue() {
return value;
}
public String toString() {
return "li " + rd + ", " + value + "\n";
}
}

View File

@@ -0,0 +1,28 @@
package backend.mips.instr.fake;
import backend.mips.instr.MipsInstr;
import backend.mips.instr.type.MipsType;
import backend.mips.Register;
public class MipsMove extends MipsInstr {
private Register rd;
private Register rt;
public MipsMove(Register rd, Register rt) {
super(MipsType.FAKE);
this.rd = rd;
this.rt = rt;
}
public Register getDest() {
return rd;
}
public Register getSrc() {
return rt;
}
public String toString() {
return "move " + rd + ", " + rt + "\n";
}
}

View File

@@ -0,0 +1,16 @@
package backend.mips.instr.type;
public enum MipsAluType {
// calc_R
ADD, SUB, ADDU, SUBU, AND, OR, NOR, XOR, SLT, SLTU,
// shiftv
SLLV, SRAV, SRLV,
// calc_I
ADDI, ADDIU, ANDI, ORI, XORI, SLTI, SLTIU,
// shift
SLL, SRA, SRL;
public String toString() {
return this.name().toLowerCase();
}
}

View File

@@ -0,0 +1,9 @@
package backend.mips.instr.type;
public enum MipsBranchType {
BEQ, BNE, BLEZ, BGTZ, BLTZ, BGEZ;
public String toString() {
return this.name().toLowerCase();
}
}

View File

@@ -0,0 +1,9 @@
package backend.mips.instr.type;
public enum MipsCompareType {
SLT, SLE, SGT, SGE, SEQ, SNE, SLTI;
public String toString() {
return this.name().toLowerCase();
}
}

View File

@@ -0,0 +1,9 @@
package backend.mips.instr.type;
public enum MipsJumpType {
J, JAL, JR;
public String toString() {
return this.name().toLowerCase();
}
}

View File

@@ -0,0 +1,9 @@
package backend.mips.instr.type;
public enum MipsLsType {
LW, SW, LH, SH, LHU, LB, SB, LBU;
public String toString() {
return this.name().toLowerCase();
}
}

View File

@@ -0,0 +1,9 @@
package backend.mips.instr.type;
public enum MipsMdType {
MFHI, MFLO, MULT, DIV, MTHI, MTLO;
public String toString() {
return this.name().toLowerCase();
}
}

View File

@@ -0,0 +1,15 @@
package backend.mips.instr.type;
public enum MipsType {
ALU,
COMPARE,
BRANCH,
JUMP,
SYSCALL,
DATA,
LABEL,
ANNOTATION,
LS,
MD,
FAKE
}

4
config.json Executable file
View File

@@ -0,0 +1,4 @@
{
"programming language": "java",
"object code": "mips"
}

54
error/Error.java Normal file → Executable file
View File

@@ -1,27 +1,27 @@
package error; package error;
public class Error { public class Error {
private int line; private int line;
private ErrorType type; private ErrorType type;
public Error(int line, ErrorType type) { public Error(int line, ErrorType type) {
this.line = line; this.line = line;
this.type = type; this.type = type;
} }
public void printError() { public void printError() {
System.out.println(this.line + " " + this.type); System.out.println(this.line + " " + this.type);
} }
public int getLine() { public int getLine() {
return this.line; return this.line;
} }
public ErrorType getType() { public ErrorType getType() {
return this.type; return this.type;
} }
public String toString() { public String toString() {
return this.line + " " + this.type + "\n"; return this.line + " " + this.type + "\n";
} }
} }

34
error/ErrorType.java Normal file → Executable file
View File

@@ -1,17 +1,17 @@
package error; package error;
public enum ErrorType { public enum ErrorType {
a, a,
b, b,
c, c,
d, d,
e, e,
f, f,
g, g,
h, h,
i, i,
j, j,
k, k,
l, l,
m m
} }

0
error/Errors.java Normal file → Executable file
View File

0
frontend/.DS_Store vendored Normal file → Executable file
View File

0
frontend/ast/.DS_Store vendored Normal file → Executable file
View File

0
frontend/ast/CompUnit.java Normal file → Executable file
View File

0
frontend/ast/Node.java Normal file → Executable file
View File

46
frontend/ast/NodeStack.java Normal file → Executable file
View File

@@ -1,23 +1,23 @@
package frontend.ast; package frontend.ast;
import java.util.ArrayList; import java.util.ArrayList;
public class NodeStack { public class NodeStack {
private ArrayList<Node> stack; private ArrayList<Node> stack;
public NodeStack() { public NodeStack() {
stack = new ArrayList<Node>(); stack = new ArrayList<Node>();
} }
public void push(Node node) { public void push(Node node) {
stack.add(node); stack.add(node);
} }
public Node pop() { public Node pop() {
return stack.remove(stack.size() - 1); return stack.remove(stack.size() - 1);
} }
public int size() { public int size() {
return stack.size(); return stack.size();
} }
} }

0
frontend/ast/SyntaxType.java Normal file → Executable file
View File

0
frontend/ast/block/Block.java Normal file → Executable file
View File

56
frontend/ast/block/BlockItem.java Normal file → Executable file
View File

@@ -1,28 +1,28 @@
package frontend.ast.block; package frontend.ast.block;
import error.Errors; import error.Errors;
import frontend.ast.Node; import frontend.ast.Node;
import frontend.ast.SyntaxType; import frontend.ast.SyntaxType;
import frontend.lexer.TokenStream; import frontend.lexer.TokenStream;
import frontend.lexer.TokenType; import frontend.lexer.TokenType;
import frontend.ast.decl.Decl; import frontend.ast.decl.Decl;
public class BlockItem extends Node { public class BlockItem extends Node {
public BlockItem(TokenStream ts) { public BlockItem(TokenStream ts) {
super(SyntaxType.BLOCK_ITEM, ts); super(SyntaxType.BLOCK_ITEM, ts);
} }
public void parse(Errors errors) { public void parse(Errors errors) {
if (getCurrToken().getType() == TokenType.CONSTTK if (getCurrToken().getType() == TokenType.CONSTTK
|| getCurrToken().getType() == TokenType.STATICTK || getCurrToken().getType() == TokenType.STATICTK
|| getCurrToken().getType() == TokenType.INTTK) { || getCurrToken().getType() == TokenType.INTTK) {
Decl decl = new Decl(this.ts); Decl decl = new Decl(this.ts);
decl.parse(errors); decl.parse(errors);
addChild(decl); addChild(decl);
} else { } else {
Stmt stmt = new Stmt(this.ts); Stmt stmt = new Stmt(this.ts);
stmt.parse(errors); stmt.parse(errors);
addChild(stmt); addChild(stmt);
} }
} }
} }

114
frontend/ast/block/ForStmt.java Normal file → Executable file
View File

@@ -1,57 +1,57 @@
package frontend.ast.block; package frontend.ast.block;
import frontend.ast.SyntaxType; import frontend.ast.SyntaxType;
import frontend.ast.token.TokenNode; import frontend.ast.token.TokenNode;
import frontend.lexer.TokenStream; import frontend.lexer.TokenStream;
import frontend.lexer.TokenType; import frontend.lexer.TokenType;
import frontend.ast.Node; import frontend.ast.Node;
import frontend.ast.exp.Exp; import frontend.ast.exp.Exp;
import frontend.ast.exp.LVal; import frontend.ast.exp.LVal;
import java.util.ArrayList; import java.util.ArrayList;
import error.Errors; import error.Errors;
public class ForStmt extends Node { public class ForStmt extends Node {
public ForStmt(TokenStream ts) { public ForStmt(TokenStream ts) {
super(SyntaxType.FOR_STMT, ts); super(SyntaxType.FOR_STMT, ts);
} }
public void parse(Errors errors) { public void parse(Errors errors) {
handleAssign(errors); handleAssign(errors);
while (getCurrToken().getType() == TokenType.COMMA) { while (getCurrToken().getType() == TokenType.COMMA) {
addChild(new TokenNode(ts)); // comma addChild(new TokenNode(ts)); // comma
handleAssign(errors); handleAssign(errors);
} }
} }
public void handleAssign(Errors errors) { public void handleAssign(Errors errors) {
LVal lval = new LVal(this.ts); LVal lval = new LVal(this.ts);
lval.parse(errors); lval.parse(errors);
addChild(lval); addChild(lval);
addChild(new TokenNode(ts)); // assign addChild(new TokenNode(ts)); // assign
Exp exp = new Exp(this.ts); Exp exp = new Exp(this.ts);
exp.parse(errors); exp.parse(errors);
addChild(exp); addChild(exp);
} }
public ArrayList<LVal> getLValList() { public ArrayList<LVal> getLValList() {
ArrayList<LVal> lvalList = new ArrayList<>(); ArrayList<LVal> lvalList = new ArrayList<>();
for (int i = 0; i < getChildren().size(); i++) { for (int i = 0; i < getChildren().size(); i++) {
if (getChild(i) instanceof LVal) { if (getChild(i) instanceof LVal) {
lvalList.add((LVal) getChild(i)); lvalList.add((LVal) getChild(i));
} }
} }
return lvalList; return lvalList;
} }
public ArrayList<Exp> getExpList() { public ArrayList<Exp> getExpList() {
ArrayList<Exp> expList = new ArrayList<>(); ArrayList<Exp> expList = new ArrayList<>();
for (int i = 0; i < getChildren().size(); i++) { for (int i = 0; i < getChildren().size(); i++) {
if (getChild(i) instanceof Exp) { if (getChild(i) instanceof Exp) {
expList.add((Exp) getChild(i)); expList.add((Exp) getChild(i));
} }
} }
return expList; return expList;
} }
} }

548
frontend/ast/block/Stmt.java Normal file → Executable file
View File

@@ -1,274 +1,274 @@
package frontend.ast.block; package frontend.ast.block;
import error.Errors; import error.Errors;
import java.util.ArrayList; import java.util.ArrayList;
import error.Error; import error.Error;
import error.ErrorType; import error.ErrorType;
import frontend.ast.Node; import frontend.ast.Node;
import frontend.ast.SyntaxType; import frontend.ast.SyntaxType;
import frontend.lexer.TokenStream; import frontend.lexer.TokenStream;
import frontend.lexer.TokenType; import frontend.lexer.TokenType;
import frontend.ast.token.TokenNode; import frontend.ast.token.TokenNode;
import frontend.ast.exp.Exp; import frontend.ast.exp.Exp;
import frontend.ast.exp.Cond; import frontend.ast.exp.Cond;
import frontend.ast.exp.LVal; import frontend.ast.exp.LVal;
public class Stmt extends Node { public class Stmt extends Node {
private boolean getint; private boolean getint;
public Stmt(TokenStream ts) { public Stmt(TokenStream ts) {
super(SyntaxType.STMT, ts); super(SyntaxType.STMT, ts);
getint = false; getint = false;
} }
public void parse(Errors errors) { public void parse(Errors errors) {
if (getCurrToken().getType() == TokenType.LBRACE) { if (getCurrToken().getType() == TokenType.LBRACE) {
Block block = new Block(this.ts); Block block = new Block(this.ts);
block.parse(errors); block.parse(errors);
addChild(block); addChild(block);
} else if (getCurrToken().getType() == TokenType.IFTK) { } else if (getCurrToken().getType() == TokenType.IFTK) {
handleIf(errors); handleIf(errors);
} else if (getCurrToken().getType() == TokenType.FORTK) { } else if (getCurrToken().getType() == TokenType.FORTK) {
handleFor(errors); handleFor(errors);
} else if (getCurrToken().getType() == TokenType.BREAKTK) { } else if (getCurrToken().getType() == TokenType.BREAKTK) {
TokenNode breakkk = new TokenNode(this.ts); TokenNode breakkk = new TokenNode(this.ts);
addChild(breakkk); addChild(breakkk);
if (getCurrToken().getType() == TokenType.SEMICN) { if (getCurrToken().getType() == TokenType.SEMICN) {
TokenNode semicolon = new TokenNode(this.ts); TokenNode semicolon = new TokenNode(this.ts);
addChild(semicolon); addChild(semicolon);
} else { } else {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i)); errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i));
} }
} else if (getCurrToken().getType() == TokenType.CONTINUETK) { } else if (getCurrToken().getType() == TokenType.CONTINUETK) {
TokenNode continuekk = new TokenNode(this.ts); TokenNode continuekk = new TokenNode(this.ts);
addChild(continuekk); addChild(continuekk);
if (getCurrToken().getType() == TokenType.SEMICN) { if (getCurrToken().getType() == TokenType.SEMICN) {
TokenNode semicolon = new TokenNode(this.ts); TokenNode semicolon = new TokenNode(this.ts);
addChild(semicolon); addChild(semicolon);
} else { } else {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i)); errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i));
} }
} else if (getCurrToken().getType() == TokenType.RETURNTK) { } else if (getCurrToken().getType() == TokenType.RETURNTK) {
handleReturn(errors); handleReturn(errors);
} else if (getCurrToken().getType() == TokenType.PRINTFTK) { } else if (getCurrToken().getType() == TokenType.PRINTFTK) {
handlePrintf(errors); handlePrintf(errors);
} else { } else {
handleAssign(errors); handleAssign(errors);
} }
} }
public void handleIf(Errors errors) { public void handleIf(Errors errors) {
TokenNode ifkk = new TokenNode(this.ts); TokenNode ifkk = new TokenNode(this.ts);
addChild(ifkk); addChild(ifkk);
TokenNode lparent = new TokenNode(this.ts); TokenNode lparent = new TokenNode(this.ts);
addChild(lparent); addChild(lparent);
Cond cond = new Cond(this.ts); Cond cond = new Cond(this.ts);
cond.parse(errors); cond.parse(errors);
addChild(cond); addChild(cond);
if (getCurrToken().getType() == TokenType.RPARENT) { if (getCurrToken().getType() == TokenType.RPARENT) {
TokenNode rparent = new TokenNode(this.ts); TokenNode rparent = new TokenNode(this.ts);
addChild(rparent); addChild(rparent);
} else { } else {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.j)); errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.j));
} }
Stmt stmt = new Stmt(this.ts); Stmt stmt = new Stmt(this.ts);
stmt.parse(errors); stmt.parse(errors);
addChild(stmt); addChild(stmt);
if (getCurrToken().getType() == TokenType.ELSETK) { if (getCurrToken().getType() == TokenType.ELSETK) {
TokenNode elsekk = new TokenNode(this.ts); TokenNode elsekk = new TokenNode(this.ts);
addChild(elsekk); addChild(elsekk);
Stmt elseStmt = new Stmt(this.ts); Stmt elseStmt = new Stmt(this.ts);
elseStmt.parse(errors); elseStmt.parse(errors);
addChild(elseStmt); addChild(elseStmt);
} }
} }
public void handleFor(Errors errors) { public void handleFor(Errors errors) {
TokenNode forkk = new TokenNode(this.ts); TokenNode forkk = new TokenNode(this.ts);
addChild(forkk); addChild(forkk);
TokenNode lparent = new TokenNode(this.ts); TokenNode lparent = new TokenNode(this.ts);
addChild(lparent); addChild(lparent);
if (getCurrToken().getType() == TokenType.SEMICN) { if (getCurrToken().getType() == TokenType.SEMICN) {
TokenNode semicolon = new TokenNode(this.ts); TokenNode semicolon = new TokenNode(this.ts);
addChild(semicolon); addChild(semicolon);
} else { } else {
ForStmt fst = new ForStmt(this.ts); ForStmt fst = new ForStmt(this.ts);
fst.parse(errors); fst.parse(errors);
addChild(fst); addChild(fst);
TokenNode semicolon = new TokenNode(this.ts); TokenNode semicolon = new TokenNode(this.ts);
addChild(semicolon); addChild(semicolon);
} }
if (getCurrToken().getType() == TokenType.SEMICN) { if (getCurrToken().getType() == TokenType.SEMICN) {
TokenNode semicolon = new TokenNode(this.ts); TokenNode semicolon = new TokenNode(this.ts);
addChild(semicolon); addChild(semicolon);
} else { } else {
Cond cond = new Cond(this.ts); Cond cond = new Cond(this.ts);
cond.parse(errors); cond.parse(errors);
addChild(cond); addChild(cond);
TokenNode semicolon = new TokenNode(this.ts); TokenNode semicolon = new TokenNode(this.ts);
addChild(semicolon); addChild(semicolon);
} }
if (getCurrToken().getType() == TokenType.RPARENT) { if (getCurrToken().getType() == TokenType.RPARENT) {
TokenNode rparent = new TokenNode(this.ts); TokenNode rparent = new TokenNode(this.ts);
addChild(rparent); addChild(rparent);
} else { } else {
ForStmt fst = new ForStmt(this.ts); ForStmt fst = new ForStmt(this.ts);
fst.parse(errors); fst.parse(errors);
addChild(fst); addChild(fst);
TokenNode rparent = new TokenNode(this.ts); TokenNode rparent = new TokenNode(this.ts);
addChild(rparent); addChild(rparent);
} }
Stmt stmt = new Stmt(this.ts); Stmt stmt = new Stmt(this.ts);
stmt.parse(errors); stmt.parse(errors);
addChild(stmt); addChild(stmt);
} }
public void handleReturn(Errors errors) { public void handleReturn(Errors errors) {
TokenNode returnkk = new TokenNode(this.ts); TokenNode returnkk = new TokenNode(this.ts);
addChild(returnkk); addChild(returnkk);
if (currentIsExp()) { if (currentIsExp()) {
Exp exp = new Exp(this.ts); Exp exp = new Exp(this.ts);
exp.parse(errors); exp.parse(errors);
addChild(exp); addChild(exp);
} }
if (getCurrToken().getType() == TokenType.SEMICN) { if (getCurrToken().getType() == TokenType.SEMICN) {
TokenNode semicolon = new TokenNode(this.ts); TokenNode semicolon = new TokenNode(this.ts);
addChild(semicolon); addChild(semicolon);
} else { } else {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i)); errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i));
} }
} }
public void handlePrintf(Errors errors) { public void handlePrintf(Errors errors) {
TokenNode printfkk = new TokenNode(this.ts); TokenNode printfkk = new TokenNode(this.ts);
addChild(printfkk); addChild(printfkk);
addChild(new TokenNode(this.ts)); // lparent addChild(new TokenNode(this.ts)); // lparent
addChild(new TokenNode(this.ts)); // strconst addChild(new TokenNode(this.ts)); // strconst
while (getCurrToken().getType() == TokenType.COMMA) { while (getCurrToken().getType() == TokenType.COMMA) {
addChild(new TokenNode(this.ts)); // comma addChild(new TokenNode(this.ts)); // comma
Exp exp = new Exp(this.ts); Exp exp = new Exp(this.ts);
exp.parse(errors); exp.parse(errors);
addChild(exp); addChild(exp);
} }
if (getCurrToken().getType() != TokenType.RPARENT) { if (getCurrToken().getType() != TokenType.RPARENT) {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.j)); errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.j));
} else { } else {
addChild(new TokenNode(this.ts)); // rparent addChild(new TokenNode(this.ts)); // rparent
} }
if (getCurrToken().getType() != TokenType.SEMICN) { if (getCurrToken().getType() != TokenType.SEMICN) {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i)); errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i));
} else { } else {
addChild(new TokenNode(this.ts)); // semicolon addChild(new TokenNode(this.ts)); // semicolon
} }
} }
public void handleAssign(Errors errors) { public void handleAssign(Errors errors) {
if (getCurrToken().getType() == TokenType.IDENFR) { if (getCurrToken().getType() == TokenType.IDENFR) {
if (this.ts.peek(1).getType() == TokenType.ASSIGN) { if (this.ts.peek(1).getType() == TokenType.ASSIGN) {
LVal lval = new LVal(this.ts); LVal lval = new LVal(this.ts);
lval.parse(errors); lval.parse(errors);
addChild(lval); addChild(lval);
addChild(new TokenNode(this.ts)); // assign addChild(new TokenNode(this.ts)); // assign
if (getCurrToken().getValue().equals("getint")) { if (getCurrToken().getValue().equals("getint")) {
getint = true; getint = true;
} }
Exp exp = new Exp(this.ts); Exp exp = new Exp(this.ts);
exp.parse(errors); exp.parse(errors);
addChild(exp); addChild(exp);
if (getCurrToken().getType() == TokenType.SEMICN) { if (getCurrToken().getType() == TokenType.SEMICN) {
addChild(new TokenNode(this.ts)); // semicolon addChild(new TokenNode(this.ts)); // semicolon
} else { } else {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i)); errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i));
} }
} else if (this.ts.peek(1).getType() == TokenType.LBRACK) { } else if (this.ts.peek(1).getType() == TokenType.LBRACK) {
int start = this.ts.getCurrentIndex(); int start = this.ts.getCurrentIndex();
LVal lval = new LVal(this.ts); LVal lval = new LVal(this.ts);
lval.parse(errors); lval.parse(errors);
if (getCurrToken().getType() == TokenType.ASSIGN) { if (getCurrToken().getType() == TokenType.ASSIGN) {
addChild(lval); addChild(lval);
addChild(new TokenNode(this.ts)); // assign addChild(new TokenNode(this.ts)); // assign
if (getCurrToken().getValue().equals("getint")) { if (getCurrToken().getValue().equals("getint")) {
getint = true; getint = true;
} }
handleExpInAssign(errors); handleExpInAssign(errors);
} else { } else {
this.ts.resetIndex(start); this.ts.resetIndex(start);
// parse exp ; // parse exp ;
handleExpInAssign(errors); handleExpInAssign(errors);
} }
} else { } else {
handleExpInAssign(errors); handleExpInAssign(errors);
} }
} else { } else {
if (currentIsExp()) { if (currentIsExp()) {
handleExpInAssign(errors); handleExpInAssign(errors);
} else { } else {
if (getCurrToken().getType() == TokenType.SEMICN) { if (getCurrToken().getType() == TokenType.SEMICN) {
addChild(new TokenNode(this.ts)); // semicolon addChild(new TokenNode(this.ts)); // semicolon
} else { } else {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i)); errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i));
} }
} }
} }
} }
public void handleExpInAssign(Errors errors) { public void handleExpInAssign(Errors errors) {
Exp exp = new Exp(this.ts); Exp exp = new Exp(this.ts);
exp.parse(errors); exp.parse(errors);
addChild(exp); addChild(exp);
if (getCurrToken().getType() == TokenType.SEMICN) { if (getCurrToken().getType() == TokenType.SEMICN) {
addChild(new TokenNode(this.ts)); // semicolon addChild(new TokenNode(this.ts)); // semicolon
} else { } else {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i)); errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i));
} }
} }
public boolean currentIsExp() { public boolean currentIsExp() {
TokenType t = getCurrToken().getType(); TokenType t = getCurrToken().getType();
return t == TokenType.PLUS || t == TokenType.MINU || t == TokenType.NOT return t == TokenType.PLUS || t == TokenType.MINU || t == TokenType.NOT
|| t == TokenType.IDENFR || t == TokenType.LPARENT || t == TokenType.INTCON; || t == TokenType.IDENFR || t == TokenType.LPARENT || t == TokenType.INTCON;
} }
public boolean isGetint() { public boolean isGetint() {
return getint; return getint;
} }
public ArrayList<Exp> getExpList() { public ArrayList<Exp> getExpList() {
ArrayList<Exp> expList = new ArrayList<>(); ArrayList<Exp> expList = new ArrayList<>();
for (int i = 0; i < getChildren().size(); i++) { for (int i = 0; i < getChildren().size(); i++) {
if (getChild(i) instanceof Exp) { if (getChild(i) instanceof Exp) {
expList.add((Exp) getChild(i)); expList.add((Exp) getChild(i));
} }
} }
return expList; return expList;
} }
public Cond getCond() { //just for fortype stmt public Cond getCond() { //just for fortype stmt
for (int i = 0; i < getChildren().size(); i++) { for (int i = 0; i < getChildren().size(); i++) {
if (getChild(i) instanceof Cond) { if (getChild(i) instanceof Cond) {
return (Cond) getChild(i); return (Cond) getChild(i);
} }
} }
return null; return null;
} }
public ForStmt getinitStmt() { public ForStmt getinitStmt() {
if (getChild(2) instanceof ForStmt) { if (getChild(2) instanceof ForStmt) {
return (ForStmt) getChild(2); return (ForStmt) getChild(2);
} }
return null; return null;
} }
public ForStmt getStepStmt() { public ForStmt getStepStmt() {
if (getChild(getChildren().size() - 3) instanceof ForStmt) { if (getChild(getChildren().size() - 3) instanceof ForStmt) {
return (ForStmt) getChild(getChildren().size() - 3); return (ForStmt) getChild(getChildren().size() - 3);
} }
return null; return null;
} }
public Stmt getBodyStmt() { public Stmt getBodyStmt() {
return (Stmt) getChild(getChildren().size() - 1); return (Stmt) getChild(getChildren().size() - 1);
} }
} }

0
frontend/ast/decl/ConstDecl.java Normal file → Executable file
View File

0
frontend/ast/decl/ConstDef.java Normal file → Executable file
View File

0
frontend/ast/decl/Decl.java Normal file → Executable file
View File

0
frontend/ast/decl/VarDecl.java Normal file → Executable file
View File

0
frontend/ast/decl/VarDef.java Normal file → Executable file
View File

146
frontend/ast/exp/AddExp.java Normal file → Executable file
View File

@@ -1,73 +1,73 @@
package frontend.ast.exp; package frontend.ast.exp;
import frontend.ast.Node; import frontend.ast.Node;
import frontend.ast.NodeStack; import frontend.ast.NodeStack;
import frontend.ast.SyntaxType; import frontend.ast.SyntaxType;
import frontend.lexer.TokenStream; import frontend.lexer.TokenStream;
import frontend.lexer.TokenType; import frontend.lexer.TokenType;
import frontend.ast.token.TokenNode; import frontend.ast.token.TokenNode;
import midend.symbol.SymbolManager; import midend.symbol.SymbolManager;
import error.Errors; import error.Errors;
public class AddExp extends Node { public class AddExp extends Node {
public AddExp(TokenStream ts) { public AddExp(TokenStream ts) {
super(SyntaxType.ADD_EXP, ts); super(SyntaxType.ADD_EXP, ts);
} }
public void parse(Errors errors) { public void parse(Errors errors) {
NodeStack stack = new NodeStack(); NodeStack stack = new NodeStack();
while (true) { while (true) {
MulExp mep = new MulExp(this.ts); MulExp mep = new MulExp(this.ts);
mep.parse(errors); mep.parse(errors);
stack.push(mep); stack.push(mep);
if (isAddOp()) { if (isAddOp()) {
stack.push(new TokenNode(ts)); // addop stack.push(new TokenNode(ts)); // addop
} else { } else {
break; break;
} }
} }
if (stack.size() == 1) { if (stack.size() == 1) {
this.addChild((MulExp) stack.pop()); this.addChild((MulExp) stack.pop());
} else { } else {
AddExp temp = this; AddExp temp = this;
while (stack.size() > 1) { while (stack.size() > 1) {
AddExp ae = new AddExp(this.ts); AddExp ae = new AddExp(this.ts);
MulExp mep = (MulExp) stack.pop(); MulExp mep = (MulExp) stack.pop();
TokenNode op = (TokenNode) stack.pop(); TokenNode op = (TokenNode) stack.pop();
temp.addChild(ae); temp.addChild(ae);
temp.addChild(op); temp.addChild(op);
temp.addChild(mep); temp.addChild(mep);
temp = ae; temp = ae;
} }
temp.addChild((MulExp) stack.pop()); temp.addChild((MulExp) stack.pop());
} }
} }
public boolean isAddOp() { public boolean isAddOp() {
TokenType t = getCurrToken().getType(); TokenType t = getCurrToken().getType();
return t == TokenType.PLUS || t == TokenType.MINU; return t == TokenType.PLUS || t == TokenType.MINU;
} }
public int getType() { public int getType() {
if (getChildren().size() == 1) { if (getChildren().size() == 1) {
return ((MulExp) getChild(0)).getType(); return ((MulExp) getChild(0)).getType();
} else { } else {
return ((AddExp) getChild(0)).getType() return ((AddExp) getChild(0)).getType()
| ((MulExp) getChild(2)).getType(); | ((MulExp) getChild(2)).getType();
} }
} }
public int getValue() { public int getValue() {
if (getChild(0) instanceof MulExp) { if (getChild(0) instanceof MulExp) {
return ((MulExp) getChild(0)).getValue(); return ((MulExp) getChild(0)).getValue();
} else { } else {
int left = ((AddExp) getChild(0)).getValue(); int left = ((AddExp) getChild(0)).getValue();
int right = ((MulExp) getChild(2)).getValue(); int right = ((MulExp) getChild(2)).getValue();
if (((TokenNode) getChild(1)).getType() == TokenType.PLUS) { if (((TokenNode) getChild(1)).getType() == TokenType.PLUS) {
return left + right; return left + right;
} else { } else {
return left - right; return left - right;
} }
} }
} }
} }

36
frontend/ast/exp/Cond.java Normal file → Executable file
View File

@@ -1,18 +1,18 @@
package frontend.ast.exp; package frontend.ast.exp;
import frontend.ast.SyntaxType; import frontend.ast.SyntaxType;
import error.Errors; import error.Errors;
import frontend.lexer.TokenStream; import frontend.lexer.TokenStream;
import frontend.ast.Node; import frontend.ast.Node;
public class Cond extends Node { public class Cond extends Node {
public Cond(TokenStream ts) { public Cond(TokenStream ts) {
super(SyntaxType.COND_EXP, ts); super(SyntaxType.COND_EXP, ts);
} }
public void parse(Errors errors) { public void parse(Errors errors) {
LOrExp lep = new LOrExp(this.ts); LOrExp lep = new LOrExp(this.ts);
lep.parse(errors); lep.parse(errors);
addChild(lep); addChild(lep);
} }
} }

0
frontend/ast/exp/ConstExp.java Normal file → Executable file
View File

98
frontend/ast/exp/EqExp.java Normal file → Executable file
View File

@@ -1,49 +1,49 @@
package frontend.ast.exp; package frontend.ast.exp;
import frontend.ast.Node; import frontend.ast.Node;
import frontend.ast.NodeStack; import frontend.ast.NodeStack;
import frontend.ast.SyntaxType; import frontend.ast.SyntaxType;
import frontend.lexer.TokenStream; import frontend.lexer.TokenStream;
import frontend.lexer.TokenType; import frontend.lexer.TokenType;
import frontend.ast.token.TokenNode; import frontend.ast.token.TokenNode;
import error.Errors; import error.Errors;
public class EqExp extends Node { public class EqExp extends Node {
public EqExp(TokenStream ts) { public EqExp(TokenStream ts) {
super(SyntaxType.EQ_EXP, ts); super(SyntaxType.EQ_EXP, ts);
} }
public void parse(Errors errors) { public void parse(Errors errors) {
NodeStack stack = new NodeStack(); NodeStack stack = new NodeStack();
while (true) { while (true) {
RelExp relexp = new RelExp(this.ts); RelExp relexp = new RelExp(this.ts);
relexp.parse(errors); relexp.parse(errors);
stack.push(relexp); stack.push(relexp);
if (isEqOp()) { if (isEqOp()) {
stack.push(new TokenNode(ts)); // eqop stack.push(new TokenNode(ts)); // eqop
} else { } else {
break; break;
} }
} }
if(stack.size() == 1) { if(stack.size() == 1) {
this.addChild((RelExp)stack.pop()); this.addChild((RelExp)stack.pop());
} else { } else {
EqExp temp = this; EqExp temp = this;
while (stack.size() > 1) { while (stack.size() > 1) {
EqExp eep = new EqExp(this.ts); EqExp eep = new EqExp(this.ts);
RelExp relexp = (RelExp)stack.pop(); RelExp relexp = (RelExp)stack.pop();
TokenNode eqop = (TokenNode)stack.pop(); TokenNode eqop = (TokenNode)stack.pop();
temp.addChild(eep); temp.addChild(eep);
temp.addChild(eqop); temp.addChild(eqop);
temp.addChild(relexp); temp.addChild(relexp);
temp = eep; temp = eep;
} }
temp.addChild((RelExp)stack.pop()); temp.addChild((RelExp)stack.pop());
} }
} }
public boolean isEqOp() { public boolean isEqOp() {
TokenType t = getCurrToken().getType(); TokenType t = getCurrToken().getType();
return t == TokenType.EQL || t == TokenType.NEQ; return t == TokenType.EQL || t == TokenType.NEQ;
} }
} }

0
frontend/ast/exp/Exp.java Normal file → Executable file
View File

88
frontend/ast/exp/LAndExp.java Normal file → Executable file
View File

@@ -1,44 +1,44 @@
package frontend.ast.exp; package frontend.ast.exp;
import frontend.ast.Node; import frontend.ast.Node;
import frontend.ast.NodeStack; import frontend.ast.NodeStack;
import frontend.ast.SyntaxType; import frontend.ast.SyntaxType;
import frontend.lexer.TokenStream; import frontend.lexer.TokenStream;
import frontend.lexer.TokenType; import frontend.lexer.TokenType;
import frontend.ast.token.TokenNode; import frontend.ast.token.TokenNode;
import error.Errors; import error.Errors;
public class LAndExp extends Node { public class LAndExp extends Node {
public LAndExp(TokenStream ts) { public LAndExp(TokenStream ts) {
super(SyntaxType.LAND_EXP, ts); super(SyntaxType.LAND_EXP, ts);
} }
public void parse(Errors errors) { public void parse(Errors errors) {
NodeStack stack = new NodeStack(); NodeStack stack = new NodeStack();
while (true) { while (true) {
EqExp eep = new EqExp(this.ts); EqExp eep = new EqExp(this.ts);
eep.parse(errors); eep.parse(errors);
stack.push(eep); stack.push(eep);
if (getCurrToken().getType() == TokenType.AND) { if (getCurrToken().getType() == TokenType.AND) {
stack.push(new TokenNode(ts)); // landop stack.push(new TokenNode(ts)); // landop
} else { } else {
break; break;
} }
} }
if (stack.size() == 1) { if (stack.size() == 1) {
this.addChild((EqExp)stack.pop()); this.addChild((EqExp)stack.pop());
} else { } else {
LAndExp temp = this; LAndExp temp = this;
while(stack.size() > 1) { while(stack.size() > 1) {
LAndExp lae = new LAndExp(this.ts); LAndExp lae = new LAndExp(this.ts);
EqExp eep = (EqExp)stack.pop(); EqExp eep = (EqExp)stack.pop();
TokenNode landop = (TokenNode)stack.pop(); TokenNode landop = (TokenNode)stack.pop();
temp.addChild(lae); temp.addChild(lae);
temp.addChild(landop); temp.addChild(landop);
temp.addChild(eep); temp.addChild(eep);
temp = lae; temp = lae;
} }
temp.addChild((EqExp)stack.pop()); temp.addChild((EqExp)stack.pop());
} }
} }
} }

88
frontend/ast/exp/LOrExp.java Normal file → Executable file
View File

@@ -1,44 +1,44 @@
package frontend.ast.exp; package frontend.ast.exp;
import frontend.ast.Node; import frontend.ast.Node;
import frontend.ast.NodeStack; import frontend.ast.NodeStack;
import frontend.ast.SyntaxType; import frontend.ast.SyntaxType;
import frontend.lexer.TokenStream; import frontend.lexer.TokenStream;
import frontend.lexer.TokenType; import frontend.lexer.TokenType;
import frontend.ast.token.TokenNode; import frontend.ast.token.TokenNode;
import error.Errors; import error.Errors;
public class LOrExp extends Node { public class LOrExp extends Node {
public LOrExp(TokenStream ts) { public LOrExp(TokenStream ts) {
super(SyntaxType.LOR_EXP, ts); super(SyntaxType.LOR_EXP, ts);
} }
public void parse(Errors errors) { public void parse(Errors errors) {
NodeStack stack = new NodeStack(); NodeStack stack = new NodeStack();
while (true) { while (true) {
LAndExp andexp = new LAndExp(this.ts); LAndExp andexp = new LAndExp(this.ts);
andexp.parse(errors); andexp.parse(errors);
stack.push(andexp); stack.push(andexp);
if (getCurrToken().getType() == TokenType.OR) { if (getCurrToken().getType() == TokenType.OR) {
stack.push(new TokenNode(ts)); // lorop stack.push(new TokenNode(ts)); // lorop
} else { } else {
break; break;
} }
} }
if (stack.size() == 1) { if (stack.size() == 1) {
this.addChild((LAndExp)stack.pop()); this.addChild((LAndExp)stack.pop());
} else { } else {
LOrExp temp = this; LOrExp temp = this;
while(stack.size() > 1) { while(stack.size() > 1) {
LOrExp loe = new LOrExp(this.ts); LOrExp loe = new LOrExp(this.ts);
LAndExp lae = (LAndExp)stack.pop(); LAndExp lae = (LAndExp)stack.pop();
TokenNode lorop = (TokenNode)stack.pop(); TokenNode lorop = (TokenNode)stack.pop();
temp.addChild(loe); temp.addChild(loe);
temp.addChild(lorop); temp.addChild(lorop);
temp.addChild(lae); temp.addChild(lae);
temp = loe; temp = loe;
} }
temp.addChild((LAndExp)stack.pop()); temp.addChild((LAndExp)stack.pop());
} }
} }
} }

118
frontend/ast/exp/LVal.java Normal file → Executable file
View File

@@ -1,59 +1,59 @@
package frontend.ast.exp; package frontend.ast.exp;
import frontend.ast.Node; import frontend.ast.Node;
import frontend.ast.SyntaxType; import frontend.ast.SyntaxType;
import frontend.ast.token.TokenNode; import frontend.ast.token.TokenNode;
import frontend.lexer.TokenStream; import frontend.lexer.TokenStream;
import frontend.lexer.TokenType; import frontend.lexer.TokenType;
import midend.symbol.SymbolManager; import midend.symbol.SymbolManager;
import midend.symbol.Symbol; import midend.symbol.Symbol;
import midend.symbol.ArraySymbol; import midend.symbol.ArraySymbol;
import error.Errors; import error.Errors;
import error.Error; import error.Error;
import error.ErrorType; import error.ErrorType;
public class LVal extends Node { public class LVal extends Node {
public LVal(TokenStream ts) { public LVal(TokenStream ts) {
super(SyntaxType.LVAL_EXP, ts); super(SyntaxType.LVAL_EXP, ts);
} }
public void parse(Errors errors) { public void parse(Errors errors) {
addChild(new TokenNode(this.ts)); // idenfr addChild(new TokenNode(this.ts)); // idenfr
if (getCurrToken().getType() == TokenType.LBRACK) { if (getCurrToken().getType() == TokenType.LBRACK) {
addChild(new TokenNode(this.ts)); // lbrack addChild(new TokenNode(this.ts)); // lbrack
Exp exp = new Exp(this.ts); Exp exp = new Exp(this.ts);
exp.parse(errors); exp.parse(errors);
addChild(exp); addChild(exp);
if (getCurrToken().getType() == TokenType.RBRACK) { if (getCurrToken().getType() == TokenType.RBRACK) {
addChild(new TokenNode(this.ts)); // rbrack addChild(new TokenNode(this.ts)); // rbrack
} else { } else {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.k)); errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.k));
} }
} }
} }
public int getType() { public int getType() {
if (getChildren().size() == 1) { if (getChildren().size() == 1) {
TokenNode idenfr = (TokenNode) getChild(0); TokenNode idenfr = (TokenNode) getChild(0);
Symbol symbol = SymbolManager.getSymbol(idenfr.getName()); Symbol symbol = SymbolManager.getSymbol(idenfr.getName());
if (symbol instanceof ArraySymbol) { if (symbol instanceof ArraySymbol) {
return 1; return 1;
} }
return 0; return 0;
} else { } else {
return 0; return 0;
} }
} }
public int getValue() { public int getValue() {
TokenNode idenfr = (TokenNode) getChild(0); //idenfr一定是个常量可在符号表找到且有值 TokenNode idenfr = (TokenNode) getChild(0); //idenfr一定是个常量可在符号表找到且有值
if (getChildren().size() == 1) { if (getChildren().size() == 1) {
Symbol symbol = SymbolManager.getSymbol(idenfr.getName()); Symbol symbol = SymbolManager.getSymbol(idenfr.getName());
return symbol.getValue(0); return symbol.getValue(0);
} else { } else {
int index = ((Exp) getChild(2)).getValue(); int index = ((Exp) getChild(2)).getValue();
Symbol symbol = SymbolManager.getSymbol(idenfr.getName()); Symbol symbol = SymbolManager.getSymbol(idenfr.getName());
return symbol.getValue(index); return symbol.getValue(index);
} }
} }
} }

150
frontend/ast/exp/MulExp.java Normal file → Executable file
View File

@@ -1,75 +1,75 @@
package frontend.ast.exp; package frontend.ast.exp;
import frontend.ast.Node; import frontend.ast.Node;
import frontend.ast.SyntaxType; import frontend.ast.SyntaxType;
import frontend.lexer.TokenStream; import frontend.lexer.TokenStream;
import frontend.lexer.TokenType; import frontend.lexer.TokenType;
import frontend.ast.token.TokenNode; import frontend.ast.token.TokenNode;
import frontend.ast.NodeStack; import frontend.ast.NodeStack;
import midend.symbol.SymbolManager; import midend.symbol.SymbolManager;
import error.Errors; import error.Errors;
public class MulExp extends Node { public class MulExp extends Node {
public MulExp(TokenStream ts) { public MulExp(TokenStream ts) {
super(SyntaxType.MUL_EXP, ts); super(SyntaxType.MUL_EXP, ts);
} }
public void parse(Errors errors) { public void parse(Errors errors) {
NodeStack stack = new NodeStack(); NodeStack stack = new NodeStack();
while (true) { while (true) {
UnaryExp uep = new UnaryExp(this.ts); UnaryExp uep = new UnaryExp(this.ts);
uep.parse(errors); uep.parse(errors);
stack.push(uep); stack.push(uep);
if (isMulOp()) { if (isMulOp()) {
stack.push(new TokenNode(ts)); // mulop stack.push(new TokenNode(ts)); // mulop
} else { } else {
break; break;
} }
} }
if (stack.size() == 1) { if (stack.size() == 1) {
addChild((UnaryExp)stack.pop()); addChild((UnaryExp)stack.pop());
} else { } else {
MulExp temp = this; MulExp temp = this;
while (stack.size() > 1) { while (stack.size() > 1) {
MulExp mep = new MulExp(this.ts); MulExp mep = new MulExp(this.ts);
UnaryExp uep = (UnaryExp) stack.pop(); UnaryExp uep = (UnaryExp) stack.pop();
TokenNode mulop = (TokenNode) stack.pop(); TokenNode mulop = (TokenNode) stack.pop();
temp.addChild(mep); temp.addChild(mep);
temp.addChild(mulop); temp.addChild(mulop);
temp.addChild(uep); temp.addChild(uep);
temp = mep; temp = mep;
} }
temp.addChild((UnaryExp)stack.pop()); temp.addChild((UnaryExp)stack.pop());
} }
} }
public boolean isMulOp() { public boolean isMulOp() {
TokenType t = getCurrToken().getType(); TokenType t = getCurrToken().getType();
return t == TokenType.MULT || t == TokenType.DIV || t == TokenType.MOD; return t == TokenType.MULT || t == TokenType.DIV || t == TokenType.MOD;
} }
public int getType() { public int getType() {
if (getChildren().size() == 1) { if (getChildren().size() == 1) {
return ((UnaryExp) getChild(0)).getType(); return ((UnaryExp) getChild(0)).getType();
} else { } else {
return ((MulExp) getChild(0)).getType() return ((MulExp) getChild(0)).getType()
| ((UnaryExp) getChild(2)).getType(); | ((UnaryExp) getChild(2)).getType();
} }
} }
public int getValue() { public int getValue() {
if (getChild(0) instanceof UnaryExp) { if (getChild(0) instanceof UnaryExp) {
return ((UnaryExp) getChild(0)).getValue(); return ((UnaryExp) getChild(0)).getValue();
} else { } else {
int left = ((MulExp) getChild(0)).getValue(); int left = ((MulExp) getChild(0)).getValue();
int right = ((UnaryExp) getChild(2)).getValue(); int right = ((UnaryExp) getChild(2)).getValue();
if (((TokenNode) getChild(1)).getType() == TokenType.MULT) { if (((TokenNode) getChild(1)).getType() == TokenType.MULT) {
return left * right; return left * right;
} else if (((TokenNode) getChild(1)).getType() == TokenType.DIV) { } else if (((TokenNode) getChild(1)).getType() == TokenType.DIV) {
return left / right; return left / right;
} else { } else {
return left % right; return left % right;
} }
} }
} }
} }

42
frontend/ast/exp/NumberExp.java Normal file → Executable file
View File

@@ -1,21 +1,21 @@
package frontend.ast.exp; package frontend.ast.exp;
import frontend.ast.Node; import frontend.ast.Node;
import frontend.ast.SyntaxType; import frontend.ast.SyntaxType;
import frontend.lexer.TokenStream; import frontend.lexer.TokenStream;
import error.Errors; import error.Errors;
import frontend.ast.token.TokenNode; import frontend.ast.token.TokenNode;
public class NumberExp extends Node { public class NumberExp extends Node {
public NumberExp(TokenStream ts) { public NumberExp(TokenStream ts) {
super(SyntaxType.NUMBER, ts); super(SyntaxType.NUMBER, ts);
} }
public void parse(Errors errors) { public void parse(Errors errors) {
addChild(new TokenNode(ts)); //intconst addChild(new TokenNode(ts)); //intconst
} }
public int getValue() { public int getValue() {
return Integer.parseInt(((TokenNode) getChild(0)).getValue()); return Integer.parseInt(((TokenNode) getChild(0)).getValue());
} }
} }

116
frontend/ast/exp/PrimaryExp.java Normal file → Executable file
View File

@@ -1,58 +1,58 @@
package frontend.ast.exp; package frontend.ast.exp;
import frontend.ast.Node; import frontend.ast.Node;
import frontend.ast.SyntaxType; import frontend.ast.SyntaxType;
import frontend.lexer.TokenStream; import frontend.lexer.TokenStream;
import frontend.lexer.TokenType; import frontend.lexer.TokenType;
import frontend.ast.token.TokenNode; import frontend.ast.token.TokenNode;
import error.Errors; import error.Errors;
import error.Error; import error.Error;
import error.ErrorType; import error.ErrorType;
public class PrimaryExp extends Node { public class PrimaryExp extends Node {
public PrimaryExp(TokenStream ts) { public PrimaryExp(TokenStream ts) {
super(SyntaxType.PRIMARY_EXP, ts); super(SyntaxType.PRIMARY_EXP, ts);
} }
public void parse(Errors errors) { public void parse(Errors errors) {
if (getCurrToken().getType() == TokenType.LPARENT) { if (getCurrToken().getType() == TokenType.LPARENT) {
addChild(new TokenNode(ts)); // lparent addChild(new TokenNode(ts)); // lparent
Exp exp = new Exp(this.ts); Exp exp = new Exp(this.ts);
exp.parse(errors); exp.parse(errors);
addChild(exp); addChild(exp);
if (getCurrToken().getType() == TokenType.RPARENT) { if (getCurrToken().getType() == TokenType.RPARENT) {
addChild(new TokenNode(ts)); // rparent addChild(new TokenNode(ts)); // rparent
} else { } else {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.j)); errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.j));
} }
} else if (getCurrToken().getType() == TokenType.IDENFR) { } else if (getCurrToken().getType() == TokenType.IDENFR) {
LVal lval = new LVal(this.ts); LVal lval = new LVal(this.ts);
lval.parse(errors); lval.parse(errors);
addChild(lval); addChild(lval);
} else { } else {
NumberExp num = new NumberExp(this.ts); NumberExp num = new NumberExp(this.ts);
num.parse(errors); num.parse(errors);
addChild(num); addChild(num);
} }
} }
public int getType() { public int getType() {
if (getChild(0) instanceof TokenNode) { if (getChild(0) instanceof TokenNode) {
return ((Exp) getChild(1)).getType(); return ((Exp) getChild(1)).getType();
} else if (getChild(0) instanceof LVal) { } else if (getChild(0) instanceof LVal) {
return ((LVal) getChild(0)).getType(); return ((LVal) getChild(0)).getType();
} else { } else {
return 0; return 0;
} }
} }
public int getValue() { public int getValue() {
if (getChild(0) instanceof TokenNode) { if (getChild(0) instanceof TokenNode) {
return ((Exp) getChild(1)).getValue(); return ((Exp) getChild(1)).getValue();
} else if (getChild(0) instanceof LVal) { } else if (getChild(0) instanceof LVal) {
return ((LVal) getChild(0)).getValue(); return ((LVal) getChild(0)).getValue();
} else { } else {
return ((NumberExp) getChild(0)).getValue(); return ((NumberExp) getChild(0)).getValue();
} }
} }
} }

100
frontend/ast/exp/RelExp.java Normal file → Executable file
View File

@@ -1,50 +1,50 @@
package frontend.ast.exp; package frontend.ast.exp;
import frontend.ast.Node; import frontend.ast.Node;
import frontend.ast.NodeStack; import frontend.ast.NodeStack;
import frontend.ast.SyntaxType; import frontend.ast.SyntaxType;
import frontend.lexer.TokenStream; import frontend.lexer.TokenStream;
import frontend.lexer.TokenType; import frontend.lexer.TokenType;
import frontend.ast.token.TokenNode; import frontend.ast.token.TokenNode;
import error.Errors; import error.Errors;
public class RelExp extends Node { public class RelExp extends Node {
public RelExp(TokenStream ts) { public RelExp(TokenStream ts) {
super(SyntaxType.REL_EXP, ts); super(SyntaxType.REL_EXP, ts);
} }
public void parse(Errors errors) { public void parse(Errors errors) {
NodeStack stack = new NodeStack(); NodeStack stack = new NodeStack();
while (true) { while (true) {
AddExp addexp = new AddExp(this.ts); AddExp addexp = new AddExp(this.ts);
addexp.parse(errors); addexp.parse(errors);
stack.push(addexp); stack.push(addexp);
if (isRelOp()) { if (isRelOp()) {
stack.push(new TokenNode(ts)); // relop stack.push(new TokenNode(ts)); // relop
} else { } else {
break; break;
} }
} }
if (stack.size() == 1) { if (stack.size() == 1) {
this.addChild((AddExp)stack.pop()); this.addChild((AddExp)stack.pop());
} else { } else {
RelExp temp = this; RelExp temp = this;
while(stack.size() > 1) { while(stack.size() > 1) {
RelExp rexp = new RelExp(this.ts); RelExp rexp = new RelExp(this.ts);
AddExp addexp = (AddExp)stack.pop(); AddExp addexp = (AddExp)stack.pop();
TokenNode relop = (TokenNode)stack.pop(); TokenNode relop = (TokenNode)stack.pop();
temp.addChild(rexp); temp.addChild(rexp);
temp.addChild(relop); temp.addChild(relop);
temp.addChild(addexp); temp.addChild(addexp);
temp = rexp; temp = rexp;
} }
temp.addChild((AddExp)stack.pop()); temp.addChild((AddExp)stack.pop());
} }
} }
public boolean isRelOp() { public boolean isRelOp() {
TokenType t = getCurrToken().getType(); TokenType t = getCurrToken().getType();
return t == TokenType.LSS || t == TokenType.GRE return t == TokenType.LSS || t == TokenType.GRE
|| t == TokenType.LEQ || t == TokenType.GEQ; || t == TokenType.LEQ || t == TokenType.GEQ;
} }
} }

248
frontend/ast/exp/UnaryExp.java Normal file → Executable file
View File

@@ -1,124 +1,124 @@
package frontend.ast.exp; package frontend.ast.exp;
import java.util.ArrayList; import java.util.ArrayList;
import frontend.ast.Node; import frontend.ast.Node;
import frontend.ast.SyntaxType; import frontend.ast.SyntaxType;
import frontend.lexer.TokenStream; import frontend.lexer.TokenStream;
import frontend.lexer.TokenType; import frontend.lexer.TokenType;
import frontend.ast.token.TokenNode; import frontend.ast.token.TokenNode;
import frontend.ast.func.FuncRParams; import frontend.ast.func.FuncRParams;
import midend.symbol.FuncSymbol; import midend.symbol.FuncSymbol;
import midend.symbol.SymbolManager; import midend.symbol.SymbolManager;
import error.Errors; import error.Errors;
import error.Error; import error.Error;
import error.ErrorType; import error.ErrorType;
public class UnaryExp extends Node { public class UnaryExp extends Node {
public UnaryExp(TokenStream ts) { public UnaryExp(TokenStream ts) {
super(SyntaxType.UNARY_EXP, ts); super(SyntaxType.UNARY_EXP, ts);
} }
public void parse(Errors errors) { public void parse(Errors errors) {
if (isUnaryOp()) { if (isUnaryOp()) {
UnaryOp uop = new UnaryOp(ts); UnaryOp uop = new UnaryOp(ts);
uop.parse(errors); uop.parse(errors);
addChild(uop); addChild(uop);
UnaryExp uep = new UnaryExp(ts); UnaryExp uep = new UnaryExp(ts);
uep.parse(errors); uep.parse(errors);
addChild(uep); addChild(uep);
} else if (getCurrToken().getType() == TokenType.IDENFR } else if (getCurrToken().getType() == TokenType.IDENFR
&& this.ts.peek(1).getType() == TokenType.LPARENT) { && this.ts.peek(1).getType() == TokenType.LPARENT) {
addChild(new TokenNode(ts)); // idenfr addChild(new TokenNode(ts)); // idenfr
addChild(new TokenNode(ts)); // lparent addChild(new TokenNode(ts)); // lparent
if (isExp()) { if (isExp()) {
FuncRParams frp = new FuncRParams(ts); FuncRParams frp = new FuncRParams(ts);
frp.parse(errors); frp.parse(errors);
addChild(frp); addChild(frp);
} }
if (getCurrToken().getType() == TokenType.RPARENT) { if (getCurrToken().getType() == TokenType.RPARENT) {
addChild(new TokenNode(ts)); // rparent addChild(new TokenNode(ts)); // rparent
} else { } else {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.j)); errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.j));
} }
} else { } else {
PrimaryExp pme = new PrimaryExp(ts); PrimaryExp pme = new PrimaryExp(ts);
pme.parse(errors); pme.parse(errors);
addChild(pme); addChild(pme);
} }
} }
public boolean isUnaryOp() { public boolean isUnaryOp() {
return getCurrToken().getType() == TokenType.PLUS return getCurrToken().getType() == TokenType.PLUS
|| getCurrToken().getType() == TokenType.MINU || getCurrToken().getType() == TokenType.MINU
|| getCurrToken().getType() == TokenType.NOT; || getCurrToken().getType() == TokenType.NOT;
} }
public boolean isExp() { public boolean isExp() {
TokenType t = getCurrToken().getType(); TokenType t = getCurrToken().getType();
return t == TokenType.PLUS || t == TokenType.MINU || t == TokenType.NOT return t == TokenType.PLUS || t == TokenType.MINU || t == TokenType.NOT
|| t == TokenType.IDENFR || t == TokenType.LPARENT || t == TokenType.INTCON; || t == TokenType.IDENFR || t == TokenType.LPARENT || t == TokenType.INTCON;
} }
public void handleFuncCall(Errors errors) { // 当其为函数调用形式时才会调用 public void handleFuncCall(Errors errors) { // 当其为函数调用形式时才会调用
TokenNode funcIdenfr = (TokenNode) getChild(0); TokenNode funcIdenfr = (TokenNode) getChild(0);
if (funcIdenfr.getName().equals("getint")) { if (funcIdenfr.getName().equals("getint")) {
if (getChildren().size() == 4) { if (getChildren().size() == 4) {
errors.addError(new Error(funcIdenfr.getLine(), ErrorType.d)); errors.addError(new Error(funcIdenfr.getLine(), ErrorType.d));
} }
return; return;
} }
FuncSymbol funcSymbol = (FuncSymbol) SymbolManager.getSymbol(funcIdenfr.getName()); FuncSymbol funcSymbol = (FuncSymbol) SymbolManager.getSymbol(funcIdenfr.getName());
if (funcSymbol == null) { if (funcSymbol == null) {
errors.addError(new Error(funcIdenfr.getLine(), ErrorType.c)); errors.addError(new Error(funcIdenfr.getLine(), ErrorType.c));
return; return;
} }
int fparaNum = funcSymbol.getParamNum(); int fparaNum = funcSymbol.getParamNum();
int rparaNum = 0; int rparaNum = 0;
if (getChildren().size() >= 3 && getChild(2) instanceof FuncRParams) { if (getChildren().size() >= 3 && getChild(2) instanceof FuncRParams) {
FuncRParams frp = (FuncRParams) getChild(2); FuncRParams frp = (FuncRParams) getChild(2);
rparaNum = frp.getParamNum(); rparaNum = frp.getParamNum();
if (rparaNum == fparaNum) { if (rparaNum == fparaNum) {
frp.checkParamType(funcSymbol, errors, funcIdenfr.getLine()); frp.checkParamType(funcSymbol, errors, funcIdenfr.getLine());
} }
} }
if (fparaNum != rparaNum) { if (fparaNum != rparaNum) {
errors.addError(new Error(funcIdenfr.getLine(), ErrorType.d)); errors.addError(new Error(funcIdenfr.getLine(), ErrorType.d));
} }
} }
public int getType() { public int getType() {
if (getChild(0) instanceof PrimaryExp) { if (getChild(0) instanceof PrimaryExp) {
return ((PrimaryExp) getChild(0)).getType(); return ((PrimaryExp) getChild(0)).getType();
} else if (getChild(0) instanceof TokenNode) { } else if (getChild(0) instanceof TokenNode) {
return 0; return 0;
} else { } else {
return ((UnaryExp) getChild(1)).getType(); return ((UnaryExp) getChild(1)).getType();
} }
} }
public int getValue() { public int getValue() {
if (getChild(0) instanceof UnaryOp) { if (getChild(0) instanceof UnaryOp) {
UnaryOp uop = (UnaryOp) getChild(0); UnaryOp uop = (UnaryOp) getChild(0);
TokenNode opToken = (TokenNode) uop.getChild(0); TokenNode opToken = (TokenNode) uop.getChild(0);
return opToken.getType() == TokenType.PLUS ? ((UnaryExp) getChild(1)).getValue() return opToken.getType() == TokenType.PLUS ? ((UnaryExp) getChild(1)).getValue()
: -((UnaryExp) getChild(1)).getValue(); : -((UnaryExp) getChild(1)).getValue();
} else if (getChild(0) instanceof PrimaryExp) { } else if (getChild(0) instanceof PrimaryExp) {
return ((PrimaryExp) getChild(0)).getValue(); return ((PrimaryExp) getChild(0)).getValue();
} else { } else {
return 0; // 0表示这个是函数getvalue只是对于常量或常量表达式取值所以正常情况调用getvalue函数时是不会跳转到这个分支的 return 0; // 0表示这个是函数getvalue只是对于常量或常量表达式取值所以正常情况调用getvalue函数时是不会跳转到这个分支的
} }
} }
public ArrayList<Exp> getParamList() { public ArrayList<Exp> getParamList() {
if (!(getChild(0) instanceof TokenNode)) { if (!(getChild(0) instanceof TokenNode)) {
return null; return null;
} else { } else {
if (getChildren().size() >= 3 && (getChild(2) instanceof FuncRParams)) { if (getChildren().size() >= 3 && (getChild(2) instanceof FuncRParams)) {
return ((FuncRParams) getChild(2)).getParamList(); return ((FuncRParams) getChild(2)).getParamList();
} }
return new ArrayList<Exp>(); return new ArrayList<Exp>();
} }
} }
} }

34
frontend/ast/exp/UnaryOp.java Normal file → Executable file
View File

@@ -1,17 +1,17 @@
package frontend.ast.exp; package frontend.ast.exp;
import frontend.ast.Node; import frontend.ast.Node;
import frontend.ast.SyntaxType; import frontend.ast.SyntaxType;
import frontend.lexer.TokenStream; import frontend.lexer.TokenStream;
import error.Errors; import error.Errors;
import frontend.ast.token.TokenNode; import frontend.ast.token.TokenNode;
public class UnaryOp extends Node { public class UnaryOp extends Node {
public UnaryOp(TokenStream ts) { public UnaryOp(TokenStream ts) {
super(SyntaxType.UNARY_OP, ts); super(SyntaxType.UNARY_OP, ts);
} }
public void parse(Errors errors) { public void parse(Errors errors) {
addChild(new TokenNode(ts)); // unary op addChild(new TokenNode(ts)); // unary op
} }
} }

0
frontend/ast/func/FuncDef.java Normal file → Executable file
View File

96
frontend/ast/func/FuncFParam.java Normal file → Executable file
View File

@@ -1,49 +1,49 @@
package frontend.ast.func; package frontend.ast.func;
import frontend.ast.Node; import frontend.ast.Node;
import frontend.ast.SyntaxType; import frontend.ast.SyntaxType;
import frontend.lexer.TokenStream; import frontend.lexer.TokenStream;
import frontend.lexer.TokenType; import frontend.lexer.TokenType;
import midend.symbol.Symbol; import midend.symbol.Symbol;
import midend.symbol.SymbolType; import midend.symbol.SymbolType;
import midend.symbol.ArraySymbol; import midend.symbol.ArraySymbol;
import error.Errors; import error.Errors;
import frontend.ast.token.TokenNode; import frontend.ast.token.TokenNode;
import error.ErrorType; import error.ErrorType;
import error.Error; import error.Error;
public class FuncFParam extends Node { public class FuncFParam extends Node {
public FuncFParam(TokenStream ts) { public FuncFParam(TokenStream ts) {
super(SyntaxType.FUNC_FORMAL_PARAM, ts); super(SyntaxType.FUNC_FORMAL_PARAM, ts);
} }
public void parse(Errors errors) { public void parse(Errors errors) {
TokenNode intkk = new TokenNode(this.ts); TokenNode intkk = new TokenNode(this.ts);
addChild(intkk); addChild(intkk);
TokenNode ident = new TokenNode(this.ts); TokenNode ident = new TokenNode(this.ts);
addChild(ident); addChild(ident);
if (getCurrToken().getType() == TokenType.LBRACK) { if (getCurrToken().getType() == TokenType.LBRACK) {
TokenNode lbrack = new TokenNode(this.ts); TokenNode lbrack = new TokenNode(this.ts);
addChild(lbrack); addChild(lbrack);
if (getCurrToken().getType() == TokenType.RBRACK) { if (getCurrToken().getType() == TokenType.RBRACK) {
TokenNode rbrack = new TokenNode(this.ts); TokenNode rbrack = new TokenNode(this.ts);
addChild(rbrack); addChild(rbrack);
} else { } else {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.k)); errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.k));
} }
} }
} }
public Symbol getSymbol() { public Symbol getSymbol() {
if (getChildren().size() == 2) { if (getChildren().size() == 2) {
TokenNode tn = (TokenNode) getChild(1); TokenNode tn = (TokenNode) getChild(1);
return new Symbol(tn.getName(), SymbolType.INT, tn.getLine()); return new Symbol(tn.getName(), SymbolType.INT, tn.getLine());
} else { } else {
TokenNode tn = (TokenNode) getChild(1); TokenNode tn = (TokenNode) getChild(1);
return new ArraySymbol(tn.getName(), SymbolType.INT_ARRAY, tn.getLine(), -1); return new ArraySymbol(tn.getName(), SymbolType.INT_ARRAY, tn.getLine(), -1);
//这里不求维数,因为函数形参为数组只是相当于一个指针 //这里不求维数,因为函数形参为数组只是相当于一个指针
} }
} }
} }

0
frontend/ast/func/FuncFParams.java Normal file → Executable file
View File

114
frontend/ast/func/FuncRParams.java Normal file → Executable file
View File

@@ -1,57 +1,57 @@
package frontend.ast.func; package frontend.ast.func;
import java.util.ArrayList; import java.util.ArrayList;
import frontend.ast.Node; import frontend.ast.Node;
import frontend.ast.SyntaxType; import frontend.ast.SyntaxType;
import frontend.lexer.TokenStream; import frontend.lexer.TokenStream;
import frontend.lexer.TokenType; import frontend.lexer.TokenType;
import error.Errors; import error.Errors;
import error.Error; import error.Error;
import error.ErrorType; import error.ErrorType;
import frontend.ast.token.TokenNode; import frontend.ast.token.TokenNode;
import frontend.ast.exp.Exp; import frontend.ast.exp.Exp;
import midend.symbol.FuncSymbol; import midend.symbol.FuncSymbol;
public class FuncRParams extends Node { public class FuncRParams extends Node {
public FuncRParams(TokenStream ts) { public FuncRParams(TokenStream ts) {
super(SyntaxType.FUNC_REAL_PARAM_S, ts); super(SyntaxType.FUNC_REAL_PARAM_S, ts);
} }
public void parse(Errors errors) { public void parse(Errors errors) {
while (true) { while (true) {
Exp ep = new Exp(ts); Exp ep = new Exp(ts);
ep.parse(errors); ep.parse(errors);
addChild(ep); addChild(ep);
if (getCurrToken().getType() == TokenType.COMMA) { if (getCurrToken().getType() == TokenType.COMMA) {
addChild(new TokenNode(ts)); // comma addChild(new TokenNode(ts)); // comma
} else { } else {
break; break;
} }
} }
} }
public int getParamNum() { public int getParamNum() {
return (getChildren().size() + 1) / 2; return (getChildren().size() + 1) / 2;
} }
public void checkParamType(FuncSymbol funcSymbol, Errors errors, int line) { public void checkParamType(FuncSymbol funcSymbol, Errors errors, int line) {
int fparaNum = funcSymbol.getParamNum(); int fparaNum = funcSymbol.getParamNum();
int rparaNum = getParamNum(); int rparaNum = getParamNum();
int size = rparaNum < fparaNum ? rparaNum : fparaNum; int size = rparaNum < fparaNum ? rparaNum : fparaNum;
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
Exp exp = (Exp) getChild(i * 2); Exp exp = (Exp) getChild(i * 2);
if (exp.getType() != funcSymbol.getParamType(i)) { if (exp.getType() != funcSymbol.getParamType(i)) {
errors.addError(new Error(line, ErrorType.e)); errors.addError(new Error(line, ErrorType.e));
} }
} }
} }
public ArrayList<Exp> getParamList() { public ArrayList<Exp> getParamList() {
ArrayList<Exp> paramList = new ArrayList<Exp>(); ArrayList<Exp> paramList = new ArrayList<Exp>();
for (int i = 0; i < getChildren().size(); i += 2) { for (int i = 0; i < getChildren().size(); i += 2) {
paramList.add((Exp) getChild(i)); paramList.add((Exp) getChild(i));
} }
return paramList; return paramList;
} }
} }

0
frontend/ast/func/FuncType.java Normal file → Executable file
View File

0
frontend/ast/func/MainFuncDef.java Normal file → Executable file
View File

0
frontend/ast/token/TokenNode.java Normal file → Executable file
View File

0
frontend/ast/val/ConstInitVal.java Normal file → Executable file
View File

0
frontend/ast/val/InitVal.java Normal file → Executable file
View File

490
frontend/lexer/Lexer.java Normal file → Executable file
View File

@@ -1,245 +1,245 @@
package frontend.lexer; package frontend.lexer;
import java.util.ArrayList; import java.util.ArrayList;
import error.Error; import error.Error;
import error.ErrorType; import error.ErrorType;
import error.Errors; import error.Errors;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.io.IOException; import java.io.IOException;
public class Lexer { public class Lexer {
private String input; private String input;
private ArrayList<Token> tokens; private ArrayList<Token> tokens;
private int position; private int position;
private int line; private int line;
private char currentChar; private char currentChar;
public Lexer(String input) { public Lexer(String input) {
this.input = input; this.input = input;
this.tokens = new ArrayList<Token>(); this.tokens = new ArrayList<Token>();
this.position = 0; this.position = 0;
this.line = 1; this.line = 1;
} }
public void lex(Errors errors) { public void lex(Errors errors) {
int sigComment = 0; int sigComment = 0;
while (this.position < this.input.length()) { while (this.position < this.input.length()) {
currentChar = this.input.charAt(this.position); currentChar = this.input.charAt(this.position);
if (currentChar == ' ' || currentChar == '\t') { if (currentChar == ' ' || currentChar == '\t') {
this.position++; this.position++;
continue; continue;
} }
if (currentChar == '\n' || currentChar == '\r') { if (currentChar == '\n' || currentChar == '\r') {
if (currentChar == '\r') { if (currentChar == '\r') {
if (this.position + 1 < this.input.length() && if (this.position + 1 < this.input.length() &&
this.input.charAt(this.position + 1) == '\n') { this.input.charAt(this.position + 1) == '\n') {
this.position++; this.position++;
} }
} }
this.line++; this.line++;
this.position++; this.position++;
if (sigComment == 1) { if (sigComment == 1) {
sigComment = 0; sigComment = 0;
} }
continue; continue;
} }
if (sigComment == 0) { if (sigComment == 0) {
if (currentChar == '/') { if (currentChar == '/') {
if (this.position + 1 < this.input.length() && if (this.position + 1 < this.input.length() &&
this.input.charAt(this.position + 1) == '/') { this.input.charAt(this.position + 1) == '/') {
sigComment = 1; sigComment = 1;
this.position += 2; this.position += 2;
continue; continue;
} }
if (this.position + 1 < this.input.length() && if (this.position + 1 < this.input.length() &&
this.input.charAt(this.position + 1) == '*') { this.input.charAt(this.position + 1) == '*') {
sigComment = 2; sigComment = 2;
this.position += 2; this.position += 2;
continue; continue;
} }
} }
if (this.isIntCons()) { if (this.isIntCons()) {
lexInt(); lexInt();
continue; continue;
} }
if (this.isStrCons()) { if (this.isStrCons()) {
lexStr(); lexStr();
continue; continue;
} }
if (this.isIdenfr()) { if (this.isIdenfr()) {
lexIdenfr(); lexIdenfr();
continue; continue;
} }
lexOp(errors); lexOp(errors);
} }
if (sigComment == 2) { if (sigComment == 2) {
if (this.position + 1 < this.input.length() && if (this.position + 1 < this.input.length() &&
this.currentChar == '*' && this.input.charAt(this.position + 1) == '/') { this.currentChar == '*' && this.input.charAt(this.position + 1) == '/') {
sigComment = 0; sigComment = 0;
this.position += 2; this.position += 2;
continue; continue;
} }
} }
if (sigComment != 0) { if (sigComment != 0) {
this.position++; this.position++;
} }
} }
} }
public boolean isIntCons() { public boolean isIntCons() {
return Character.isDigit(this.currentChar); return Character.isDigit(this.currentChar);
} }
public boolean isStrCons() { public boolean isStrCons() {
return this.currentChar == '"'; return this.currentChar == '"';
} }
public boolean isIdenfr() { public boolean isIdenfr() {
return Character.isLowerCase(this.currentChar) || Character.isUpperCase(this.currentChar) return Character.isLowerCase(this.currentChar) || Character.isUpperCase(this.currentChar)
|| this.currentChar == '_'; || this.currentChar == '_';
} }
public boolean isNotWp() { public boolean isNotWp() {
return !Character.isWhitespace(this.currentChar); return !Character.isWhitespace(this.currentChar);
} }
public boolean isOp() { public boolean isOp() {
return !this.isIntCons() && !this.isStrCons() && !this.isIdenfr(); return !this.isIntCons() && !this.isStrCons() && !this.isIdenfr();
} }
public void lexInt() { public void lexInt() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
while (this.position < this.input.length() && this.isIntCons()) { while (this.position < this.input.length() && this.isIntCons()) {
sb.append(this.currentChar); sb.append(this.currentChar);
this.position++; this.position++;
updateCurrentChar(); updateCurrentChar();
} }
this.tokens.add(new Token(sb.toString(), this.line)); this.tokens.add(new Token(sb.toString(), this.line));
} }
public void lexStr() { public void lexStr() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append(this.currentChar); sb.append(this.currentChar);
this.position++; this.position++;
updateCurrentChar(); updateCurrentChar();
while (this.position < this.input.length() && this.currentChar != '"') { while (this.position < this.input.length() && this.currentChar != '"') {
sb.append(this.currentChar); sb.append(this.currentChar);
this.position++; this.position++;
updateCurrentChar(); updateCurrentChar();
} }
if (this.position < this.input.length() && this.currentChar == '"') { if (this.position < this.input.length() && this.currentChar == '"') {
sb.append(this.currentChar); sb.append(this.currentChar);
this.position++; this.position++;
} }
this.tokens.add(new Token(sb.toString(), this.line)); this.tokens.add(new Token(sb.toString(), this.line));
} }
public void lexIdenfr() { public void lexIdenfr() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
while (this.position < this.input.length() && (this.isIdenfr() || this.isIntCons())) { while (this.position < this.input.length() && (this.isIdenfr() || this.isIntCons())) {
sb.append(this.currentChar); sb.append(this.currentChar);
this.position++; this.position++;
updateCurrentChar(); updateCurrentChar();
} }
this.tokens.add(new Token(sb.toString(), this.line)); this.tokens.add(new Token(sb.toString(), this.line));
} }
public void lexOp(Errors errors) { public void lexOp(Errors errors) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
if (this.currentChar == '/' && this.position + 1 < this.input.length() && if (this.currentChar == '/' && this.position + 1 < this.input.length() &&
(this.input.charAt(this.position + 1) == '/' || (this.input.charAt(this.position + 1) == '/' ||
this.input.charAt(this.position + 1) == '*')) { this.input.charAt(this.position + 1) == '*')) {
return; return;
} }
sb.append(this.currentChar); sb.append(this.currentChar);
switch (this.currentChar) { switch (this.currentChar) {
case '&': case '&':
readAnd(sb); readAnd(sb);
break; break;
case '|': case '|':
readOr(sb); readOr(sb);
break; break;
case '<': case '<':
readEq(sb); readEq(sb);
break; break;
case '>': case '>':
readEq(sb); readEq(sb);
break; break;
case '=': case '=':
readEq(sb); readEq(sb);
break; break;
case '!': case '!':
readEq(sb); readEq(sb);
break; break;
default: default:
break; break;
} }
this.position++; this.position++;
if (sb.toString().equals("&") || sb.toString().equals("|")) { if (sb.toString().equals("&") || sb.toString().equals("|")) {
errors.addError(new Error(this.line, ErrorType.a)); errors.addError(new Error(this.line, ErrorType.a));
} }
this.tokens.add(new Token(sb.toString(), this.line)); this.tokens.add(new Token(sb.toString(), this.line));
} }
public void readAnd(StringBuilder sb) { public void readAnd(StringBuilder sb) {
if (this.position + 1 < this.input.length() && if (this.position + 1 < this.input.length() &&
this.input.charAt(this.position + 1) == '&') { this.input.charAt(this.position + 1) == '&') {
this.position++; this.position++;
currentChar = this.input.charAt(this.position); currentChar = this.input.charAt(this.position);
sb.append(currentChar); sb.append(currentChar);
} }
} }
public void readOr(StringBuilder sb) { public void readOr(StringBuilder sb) {
if (this.position + 1 < this.input.length() && if (this.position + 1 < this.input.length() &&
this.input.charAt(this.position + 1) == '|') { this.input.charAt(this.position + 1) == '|') {
this.position++; this.position++;
currentChar = this.input.charAt(this.position); currentChar = this.input.charAt(this.position);
sb.append(currentChar); sb.append(currentChar);
} }
} }
public void readEq(StringBuilder sb) { public void readEq(StringBuilder sb) {
if (this.position + 1 < this.input.length() && if (this.position + 1 < this.input.length() &&
this.input.charAt(this.position + 1) == '=') { this.input.charAt(this.position + 1) == '=') {
this.position++; this.position++;
currentChar = this.input.charAt(this.position); currentChar = this.input.charAt(this.position);
sb.append(currentChar); sb.append(currentChar);
} }
} }
public void updateCurrentChar() { public void updateCurrentChar() {
if (this.position < this.input.length()) { if (this.position < this.input.length()) {
currentChar = this.input.charAt(this.position); currentChar = this.input.charAt(this.position);
} }
} }
public void printTokens() { public void printTokens() {
for (Token token : this.tokens) { for (Token token : this.tokens) {
token.adjustType(); token.adjustType();
System.out.println(token.getType() + " " + token.getValue() + " " + token.getLine()); System.out.println(token.getType() + " " + token.getValue() + " " + token.getLine());
} }
} }
public void writeToFile(String fileName) { public void writeToFile(String fileName) {
try { try {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
for (Token token : this.tokens) { for (Token token : this.tokens) {
token.adjustType(); token.adjustType();
sb.append(token.toString()); sb.append(token.toString());
} }
Files.write(Paths.get(fileName), sb.toString().getBytes()); Files.write(Paths.get(fileName), sb.toString().getBytes());
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
public ArrayList<Token> getTokens() { public ArrayList<Token> getTokens() {
for (Token token : this.tokens) { for (Token token : this.tokens) {
token.adjustType(); token.adjustType();
} }
return this.tokens; return this.tokens;
} }
} }

84
frontend/lexer/Token.java Normal file → Executable file
View File

@@ -1,42 +1,42 @@
package frontend.lexer; package frontend.lexer;
public class Token { public class Token {
private TokenType type; private TokenType type;
private String value; private String value;
private int line; private int line;
public Token(String value, int line) { public Token(String value, int line) {
this.value = value; this.value = value;
this.type = TokenType.isWhatType(value); this.type = TokenType.isWhatType(value);
this.line = line; this.line = line;
} }
public void adjustType() { public void adjustType() {
if (this.type == TokenType.IDENFR) { if (this.type == TokenType.IDENFR) {
if (this.value.charAt(0) == '\"' && if (this.value.charAt(0) == '\"' &&
this.value.charAt(this.value.length() - 1) == '\"') { this.value.charAt(this.value.length() - 1) == '\"') {
this.type = TokenType.STRCON; this.type = TokenType.STRCON;
} }
String regex = "^\\d+$"; String regex = "^\\d+$";
if (this.value.matches(regex)) { if (this.value.matches(regex)) {
this.type = TokenType.INTCON; this.type = TokenType.INTCON;
} }
} }
} }
public String getValue() { public String getValue() {
return this.value; return this.value;
} }
public TokenType getType() { public TokenType getType() {
return this.type; return this.type;
} }
public int getLine() { public int getLine() {
return this.line; return this.line;
} }
public String toString() { public String toString() {
return this.type + " " + this.value + "\n"; return this.type + " " + this.value + "\n";
} }
} }

0
frontend/lexer/TokenStream.java Normal file → Executable file
View File

246
frontend/lexer/TokenType.java Normal file → Executable file
View File

@@ -1,123 +1,123 @@
package frontend.lexer; package frontend.lexer;
public enum TokenType { public enum TokenType {
IDENFR, IDENFR,
INTCON, INTCON,
STRCON, STRCON,
CONSTTK, CONSTTK,
INTTK, INTTK,
STATICTK, STATICTK,
BREAKTK, BREAKTK,
CONTINUETK, CONTINUETK,
IFTK, IFTK,
MAINTK, MAINTK,
ELSETK, ELSETK,
NOT, NOT,
AND, AND,
OR, OR,
FORTK, FORTK,
RETURNTK, RETURNTK,
VOIDTK, VOIDTK,
PLUS, PLUS,
MINU, MINU,
PRINTFTK, PRINTFTK,
MULT, MULT,
DIV, DIV,
MOD, MOD,
LSS, LSS,
LEQ, LEQ,
GRE, GRE,
GEQ, GEQ,
EQL, EQL,
NEQ, NEQ,
SEMICN, SEMICN,
COMMA, COMMA,
LPARENT, LPARENT,
RPARENT, RPARENT,
LBRACK, LBRACK,
RBRACK, RBRACK,
LBRACE, LBRACE,
RBRACE, RBRACE,
ASSIGN; ASSIGN;
public static TokenType isWhatType(String str) { public static TokenType isWhatType(String str) {
switch (str) { switch (str) {
case "const": case "const":
return TokenType.CONSTTK; return TokenType.CONSTTK;
case "int": case "int":
return TokenType.INTTK; return TokenType.INTTK;
case "static": case "static":
return TokenType.STATICTK; return TokenType.STATICTK;
case "break": case "break":
return TokenType.BREAKTK; return TokenType.BREAKTK;
case "continue": case "continue":
return TokenType.CONTINUETK; return TokenType.CONTINUETK;
case "if": case "if":
return TokenType.IFTK; return TokenType.IFTK;
case "main": case "main":
return TokenType.MAINTK; return TokenType.MAINTK;
case "else": case "else":
return TokenType.ELSETK; return TokenType.ELSETK;
case "!": case "!":
return TokenType.NOT; return TokenType.NOT;
case "&&": case "&&":
return TokenType.AND; return TokenType.AND;
case "&": case "&":
return TokenType.AND; return TokenType.AND;
case "||": case "||":
return TokenType.OR; return TokenType.OR;
case "|": case "|":
return TokenType.OR; return TokenType.OR;
case "for": case "for":
return TokenType.FORTK; return TokenType.FORTK;
case "return": case "return":
return TokenType.RETURNTK; return TokenType.RETURNTK;
case "void": case "void":
return TokenType.VOIDTK; return TokenType.VOIDTK;
case "+": case "+":
return TokenType.PLUS; return TokenType.PLUS;
case "-": case "-":
return TokenType.MINU; return TokenType.MINU;
case "printf": case "printf":
return TokenType.PRINTFTK; return TokenType.PRINTFTK;
case "*": case "*":
return TokenType.MULT; return TokenType.MULT;
case "/": case "/":
return TokenType.DIV; return TokenType.DIV;
case "%": case "%":
return TokenType.MOD; return TokenType.MOD;
case "<": case "<":
return TokenType.LSS; return TokenType.LSS;
case "<=": case "<=":
return TokenType.LEQ; return TokenType.LEQ;
case ">": case ">":
return TokenType.GRE; return TokenType.GRE;
case ">=": case ">=":
return TokenType.GEQ; return TokenType.GEQ;
case "==": case "==":
return TokenType.EQL; return TokenType.EQL;
case "!=": case "!=":
return TokenType.NEQ; return TokenType.NEQ;
case ";": case ";":
return TokenType.SEMICN; return TokenType.SEMICN;
case ",": case ",":
return TokenType.COMMA; return TokenType.COMMA;
case "(": case "(":
return TokenType.LPARENT; return TokenType.LPARENT;
case ")": case ")":
return TokenType.RPARENT; return TokenType.RPARENT;
case "[": case "[":
return TokenType.LBRACK; return TokenType.LBRACK;
case "]": case "]":
return TokenType.RBRACK; return TokenType.RBRACK;
case "{": case "{":
return TokenType.LBRACE; return TokenType.LBRACE;
case "}": case "}":
return TokenType.RBRACE; return TokenType.RBRACE;
case "=": case "=":
return TokenType.ASSIGN; return TokenType.ASSIGN;
default: default:
return TokenType.IDENFR; return TokenType.IDENFR;
} }
} }
} }

76
frontend/parser/Parser.java Normal file → Executable file
View File

@@ -1,38 +1,38 @@
package frontend.parser; package frontend.parser;
import frontend.ast.CompUnit; import frontend.ast.CompUnit;
import frontend.lexer.TokenStream; import frontend.lexer.TokenStream;
import java.nio.file.Files; import java.nio.file.Files;
import error.Errors; import error.Errors;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.io.IOException; import java.io.IOException;
public class Parser { public class Parser {
private TokenStream ts; private TokenStream ts;
private CompUnit compUnit; private CompUnit compUnit;
public Parser(TokenStream ts) { public Parser(TokenStream ts) {
this.ts = ts; this.ts = ts;
this.compUnit = new CompUnit(this.ts); this.compUnit = new CompUnit(this.ts);
} }
public void parse(Errors errors) { public void parse(Errors errors) {
compUnit.parse(errors); compUnit.parse(errors);
} }
public CompUnit getCompUnit() { public CompUnit getCompUnit() {
return compUnit; return compUnit;
} }
public void writeToFile(String fileName) { public void writeToFile(String fileName) {
try { try {
String info = this.compUnit.getInfo(); String info = this.compUnit.getInfo();
Files.write(Paths.get(fileName), info.getBytes()); Files.write(Paths.get(fileName), info.getBytes());
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
} }

67
midend/Midend.java Normal file → Executable file
View File

@@ -1,31 +1,36 @@
package midend; package midend;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
import frontend.ast.CompUnit; import frontend.ast.CompUnit;
import midend.llvm.IrBuilder; import midend.llvm.IrBuilder;
import midend.llvm.IrModule; import midend.llvm.IrModule;
import midend.visit.Visitor; import midend.visit.Visitor;
public class Midend { public class Midend {
private IrModule module; private IrModule module;
private Visitor visitor; private Visitor visitor;
public Midend(CompUnit compUnit) { public Midend(CompUnit compUnit) {
this.module = new IrModule(); this.module = new IrModule();
this.visitor = new Visitor(compUnit); this.visitor = new Visitor(compUnit);
} }
public void generateLLvmIr() { public void generateLLvmIr() {
IrBuilder.setCurrentModule(module); IrBuilder.setCurrentModule(module);
visitor.visit(); visitor.visit();
} }
public void writeToFile(String fileName) { public IrModule getModule() {
try { return module;
Files.write(Paths.get(fileName), module.toString().getBytes()); }
} catch (Exception e) {
e.printStackTrace(); public void writeToFile(String fileName) {
} try {
} Files.write(Paths.get(fileName), module.toString().getBytes());
} } catch (Exception e) {
e.printStackTrace();
}
}
}
//

64
midend/errorhandle/ErrorHandler.java Normal file → Executable file
View File

@@ -1,32 +1,32 @@
package midend.errorhandle; package midend.errorhandle;
import frontend.ast.CompUnit; import frontend.ast.CompUnit;
import midend.symbol.SymbolManager; import midend.symbol.SymbolManager;
import error.Errors; import error.Errors;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
public class ErrorHandler { public class ErrorHandler {
private CompUnit compUnit; private CompUnit compUnit;
public ErrorHandler(CompUnit compUnit) { public ErrorHandler(CompUnit compUnit) {
this.compUnit = compUnit; this.compUnit = compUnit;
SymbolManager.init(); SymbolManager.init();
} }
public void visit(Errors errors) { public void visit(Errors errors) {
compUnit.fillSymbolTable(false, false, errors); compUnit.fillSymbolTable(false, false, errors);
} }
public void writeToFile(String fileName) { public void writeToFile(String fileName) {
try { try {
String info = SymbolManager.getSymbolTableInfo(); String info = SymbolManager.getSymbolTableInfo();
Files.write(Paths.get(fileName), info.getBytes()); Files.write(Paths.get(fileName), info.getBytes());
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
} }

286
midend/llvm/IrBuilder.java Normal file → Executable file
View File

@@ -1,143 +1,143 @@
package midend.llvm; package midend.llvm;
import java.util.HashMap; import java.util.HashMap;
import java.util.Stack; import java.util.Stack;
import midend.llvm.value.IrFuncValue; import midend.llvm.value.IrFuncValue;
import midend.llvm.value.IrBasicBlock; import midend.llvm.value.IrBasicBlock;
import midend.llvm.value.IrLoop; import midend.llvm.value.IrLoop;
import midend.llvm.type.IrType; import midend.llvm.type.IrType;
import midend.llvm.constant.IrConstant; import midend.llvm.constant.IrConstant;
import midend.llvm.value.IrGlobalValue; import midend.llvm.value.IrGlobalValue;
import midend.llvm.constant.IrConstantStr; import midend.llvm.constant.IrConstantStr;
import midend.llvm.instr.IrInstr; import midend.llvm.instr.IrInstr;
public class IrBuilder { public class IrBuilder {
private static final String prebb = "b_"; private static final String prebb = "b_";
private static final String prestr = "@s_"; private static final String prestr = "@s_";
private static final String prefunc = "@f_"; private static final String prefunc = "@f_";
private static final String preglobal = "@g_"; private static final String preglobal = "@g_";
private static final String prelocal = "%v_"; private static final String prelocal = "%v_";
private static IrModule module = null; private static IrModule module = null;
private static IrFuncValue currentFunc = null; private static IrFuncValue currentFunc = null;
private static IrBasicBlock currentBB = null; private static IrBasicBlock currentBB = null;
private static int strId = 0; private static int strId = 0;
private static int globalId = 0; private static int globalId = 0;
private static int bblockId = 0; private static int bblockId = 0;
private static HashMap<IrFuncValue, Integer> funcIdMap = new HashMap<>(); // func, localId private static HashMap<IrFuncValue, Integer> funcIdMap = new HashMap<>(); // func, localId
private static Stack<IrLoop> loopStack = new Stack<>(); private static Stack<IrLoop> loopStack = new Stack<>();
public static void setCurrentModule(IrModule module) { public static void setCurrentModule(IrModule module) {
IrBuilder.module = module; IrBuilder.module = module;
} }
public static void addNewFunc(String name, IrType retType) { public static void addNewFunc(String name, IrType retType) {
IrFuncValue func = new IrFuncValue(geFuncName(name), retType); IrFuncValue func = new IrFuncValue(geFuncName(name), retType);
module.addFunc(func); module.addFunc(func);
funcIdMap.put(func, 0); funcIdMap.put(func, 0);
currentFunc = func; currentFunc = func;
IrBasicBlock entryBB = new IrBasicBlock(getBlockName(), func); IrBasicBlock entryBB = new IrBasicBlock(getBlockName(), func);
func.addBBlock(entryBB); func.addBBlock(entryBB);
currentBB = entryBB; currentBB = entryBB;
} }
public static void addNewFunc(IrFuncValue func) { public static void addNewFunc(IrFuncValue func) {
module.addFunc(func); module.addFunc(func);
funcIdMap.put(func, 0); funcIdMap.put(func, 0);
currentFunc = func; currentFunc = func;
IrBasicBlock entryBB = new IrBasicBlock(getBlockName(), func); IrBasicBlock entryBB = new IrBasicBlock(getBlockName(), func);
func.addBBlock(entryBB); func.addBBlock(entryBB);
currentBB = entryBB; currentBB = entryBB;
} }
public static void addNewBB() { public static void addNewBB() {
IrBasicBlock bb = new IrBasicBlock(getBlockName(), currentFunc); IrBasicBlock bb = new IrBasicBlock(getBlockName(), currentFunc);
currentFunc.addBBlock(bb); currentFunc.addBBlock(bb);
} }
public static void addNewBB(IrBasicBlock bb) { public static void addNewBB(IrBasicBlock bb) {
currentFunc.addBBlock(bb); currentFunc.addBBlock(bb);
} }
public static void setCurrentBBlock(IrBasicBlock bb) { public static void setCurrentBBlock(IrBasicBlock bb) {
currentBB = bb; currentBB = bb;
} }
public static void addNewGlobal(IrType type, boolean isConstant, IrConstant initVal) { public static void addNewGlobal(IrType type, boolean isConstant, IrConstant initVal) {
IrGlobalValue global = new IrGlobalValue(type, getGlobalName(), isConstant, initVal); IrGlobalValue global = new IrGlobalValue(type, getGlobalName(), isConstant, initVal);
module.addGlobalVar(global); module.addGlobalVar(global);
} }
public static void addNewGlobal(IrGlobalValue global) { public static void addNewGlobal(IrGlobalValue global) {
module.addGlobalVar(global); module.addGlobalVar(global);
} }
public static void addNewStr(String str) { public static void addNewStr(String str) {
if (module.containStr(str)) { if (module.containStr(str)) {
return; return;
} }
module.addStr(new IrConstantStr(str, getStrName())); module.addStr(new IrConstantStr(str, getStrName()));
} }
public static void addNewStr(IrConstantStr str) { public static void addNewStr(IrConstantStr str) {
module.addStr(str); module.addStr(str);
} }
public static void addInstr(IrInstr instr) { public static void addInstr(IrInstr instr) {
currentBB.addInstr(instr); currentBB.addInstr(instr);
instr.setBBlock(currentBB); instr.setBBlock(currentBB);
} }
public static String geFuncName(String name) { public static String geFuncName(String name) {
return name.equals("main") ? "@main" : prefunc + name; return name.equals("main") ? "@main" : prefunc + name;
} }
public static String getBlockName() { public static String getBlockName() {
return prebb + bblockId++; return prebb + bblockId++;
} }
public static String getStrName() { public static String getStrName() {
return prestr + strId++; return prestr + strId++;
} }
public static String getGlobalName() { public static String getGlobalName() {
return preglobal + globalId++; return preglobal + globalId++;
} }
public static String getLocalName() { public static String getLocalName() {
int id = funcIdMap.get(currentFunc); int id = funcIdMap.get(currentFunc);
funcIdMap.put(currentFunc, id + 1); funcIdMap.put(currentFunc, id + 1);
return prelocal + id; return prelocal + id;
} }
public static String getLocalName(IrFuncValue func) { public static String getLocalName(IrFuncValue func) {
int id = funcIdMap.get(func); int id = funcIdMap.get(func);
funcIdMap.put(func, id + 1); funcIdMap.put(func, id + 1);
return prelocal + id; return prelocal + id;
} }
public static IrModule getCurrentModule() { public static IrModule getCurrentModule() {
return module; return module;
} }
public static IrFuncValue getCurrentFunc() { public static IrFuncValue getCurrentFunc() {
return currentFunc; return currentFunc;
} }
public static IrBasicBlock getCurrentBB() { public static IrBasicBlock getCurrentBB() {
return currentBB; return currentBB;
} }
public static void pushLoop(IrLoop loop) { public static void pushLoop(IrLoop loop) {
loopStack.push(loop); loopStack.push(loop);
} }
public static IrLoop popLoop() { public static IrLoop popLoop() {
return loopStack.pop(); return loopStack.pop();
} }
public static IrLoop getCurrentLoop() { public static IrLoop getCurrentLoop() {
return loopStack.peek(); return loopStack.peek();
} }
} }

225
midend/llvm/IrModule.java Normal file → Executable file
View File

@@ -1,100 +1,125 @@
package midend.llvm; package midend.llvm;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import midend.llvm.constant.IrConstantStr; import backend.mips.Register;
import midend.llvm.value.IrFuncValue; import backend.mips.instr.MipsAnnotation;
import midend.llvm.value.IrGlobalValue; import backend.mips.instr.MipsJump;
import midend.llvm.instr.GetIntInstr; import backend.mips.instr.MipsLabel;
import midend.llvm.instr.PutChInstr; import backend.mips.instr.fake.MipsLi;
import midend.llvm.instr.PutIntInstr; import backend.mips.instr.MipsSyscall;
import midend.llvm.instr.PutStrInstr; import backend.mips.instr.type.MipsJumpType;
import midend.llvm.constant.IrConstantStr;
public class IrModule { import midend.llvm.value.IrFuncValue;
private ArrayList<String> decls; import midend.llvm.value.IrGlobalValue;
private HashMap<String, IrConstantStr> strs; import midend.llvm.instr.GetIntInstr;
private ArrayList<IrGlobalValue> globalVars; import midend.llvm.instr.PutChInstr;
private ArrayList<IrFuncValue> funcs; import midend.llvm.instr.PutIntInstr;
import midend.llvm.instr.PutStrInstr;
public IrModule() {
decls = new ArrayList<>(); public class IrModule {
strs = new HashMap<>(); private ArrayList<String> decls;
globalVars = new ArrayList<>(); private HashMap<String, IrConstantStr> strs;
funcs = new ArrayList<>(); private ArrayList<IrGlobalValue> globalVars;
decls.add(GetIntInstr.getIntDecl()); private ArrayList<IrFuncValue> funcs;
decls.add(PutChInstr.putChDecl());
decls.add(PutIntInstr.putIntDecl()); public IrModule() {
decls.add(PutStrInstr.putStrDecl()); decls = new ArrayList<>();
} strs = new HashMap<>();
globalVars = new ArrayList<>();
public ArrayList<String> getDecls() { funcs = new ArrayList<>();
return decls; decls.add(GetIntInstr.getIntDecl());
} decls.add(PutChInstr.putChDecl());
decls.add(PutIntInstr.putIntDecl());
public HashMap<String, IrConstantStr> getStrs() { decls.add(PutStrInstr.putStrDecl());
return strs; }
}
public ArrayList<String> getDecls() {
public ArrayList<IrGlobalValue> getGlobalVars() { return decls;
return globalVars; }
}
public HashMap<String, IrConstantStr> getStrs() {
public ArrayList<IrFuncValue> getFuncs() { return strs;
return funcs; }
}
public ArrayList<IrGlobalValue> getGlobalVars() {
public void addFunc(IrFuncValue func) { return globalVars;
funcs.add(func); }
}
public ArrayList<IrFuncValue> getFuncs() {
public void addStr(IrConstantStr str) { return funcs;
if (strs.containsKey(str.getValue())) { }
return;
} public void addFunc(IrFuncValue func) {
strs.put(str.getValue(), str); funcs.add(func);
} }
public boolean containStr(String str) { public void addStr(IrConstantStr str) {
return strs.containsKey(str); if (strs.containsKey(str.getValue())) {
} return;
}
public IrConstantStr getStr(String str) { strs.put(str.getValue(), str);
if (containStr(str)) { }
return strs.get(str);
} public boolean containStr(String str) {
return null; return strs.containsKey(str);
} }
public void addGlobalVar(IrGlobalValue globalVar) { public IrConstantStr getStr(String str) {
globalVars.add(globalVar); if (containStr(str)) {
} return strs.get(str);
}
public IrFuncValue getMainFunc() { return null;
for (IrFuncValue func : funcs) { }
if (func.isMain()) {
return func; public void addGlobalVar(IrGlobalValue globalVar) {
} globalVars.add(globalVar);
} }
return null;
} public IrFuncValue getMainFunc() {
for (IrFuncValue func : funcs) {
//TODO: toString()方法编写 if (func.isMain()) {
public String toString() { return func;
StringBuilder sb = new StringBuilder(); }
for (String decl : decls) { }
sb.append(decl).append("\n"); return null;
} }
for (IrConstantStr str : strs.values()) {
sb.append(str.toString()).append("\n"); public String toString() {
} StringBuilder sb = new StringBuilder();
for (IrGlobalValue globalVar : globalVars) { for (String decl : decls) {
sb.append(globalVar.toString()).append("\n"); sb.append(decl).append("\n");
} }
for (IrFuncValue func : funcs) { for (IrConstantStr str : strs.values()) {
sb.append(func.toString()).append("\n"); sb.append(str.toString()).append("\n");
} }
// System.out.println(funcs.size()); for (IrGlobalValue globalVar : globalVars) {
return sb.toString(); sb.append(globalVar.toString()).append("\n");
} }
} for (IrFuncValue func : funcs) {
sb.append(func.toString()).append("\n");
}
// System.out.println(funcs.size());
return sb.toString();
}
public void toMips() {
for (IrGlobalValue globalVar : this.globalVars) {
globalVar.toMips();
}
for (IrConstantStr str : this.strs.values()) {
str.toMips(str.getMipsLabel());
}
new MipsAnnotation("jump to main");
new MipsJump(MipsJumpType.JAL, "main");
new MipsJump(MipsJumpType.J, "end");
for (IrFuncValue irFunction : this.funcs) {
irFunction.toMips();
}
new MipsLabel("end");
new MipsLi(Register.V0, 10);
new MipsSyscall();
}
}

4
midend/llvm/constant/IrConstant.java Normal file → Executable file
View File

@@ -11,4 +11,8 @@ public class IrConstant extends IrValue {
public String toString() { public String toString() {
return ""; return "";
} }
public void toMips(String label) {
}
} }

17
midend/llvm/constant/IrConstantArray.java Normal file → Executable file
View File

@@ -2,6 +2,8 @@ package midend.llvm.constant;
import java.util.ArrayList; import java.util.ArrayList;
import backend.mips.instr.data.MipsSpace;
import backend.mips.instr.data.MipsWord;
import midend.llvm.type.IrInterType; import midend.llvm.type.IrInterType;
import midend.llvm.type.IrArrayType; import midend.llvm.type.IrArrayType;
@@ -44,4 +46,19 @@ public class IrConstantArray extends IrConstant {
} }
return sb.toString(); return sb.toString();
} }
public void toMips(String label) {
ArrayList<Integer> values = new ArrayList<>();
if (elements.size() == 0) {
new MipsSpace(size * 4, label);
} else {
for (IrConstant element : elements) {
values.add(((IrConstantInt) element).getValue());
}
for (int i = 0; i < size - elements.size(); i++) {
values.add(0);
}
new MipsWord(label, values);
}
}
} }

5
midend/llvm/constant/IrConstantInt.java Normal file → Executable file
View File

@@ -1,5 +1,6 @@
package midend.llvm.constant; package midend.llvm.constant;
import backend.mips.instr.data.MipsWord;
import midend.llvm.type.IrInterType; import midend.llvm.type.IrInterType;
public class IrConstantInt extends IrConstant { public class IrConstantInt extends IrConstant {
@@ -17,4 +18,8 @@ public class IrConstantInt extends IrConstant {
public String toString() { public String toString() {
return "i32 " + value; return "i32 " + value;
} }
public void toMips(String label) {
new MipsWord(label, value);
}
} }

111
midend/llvm/constant/IrConstantStr.java Normal file → Executable file
View File

@@ -1,53 +1,58 @@
package midend.llvm.constant; package midend.llvm.constant;
import midend.llvm.type.IrArrayType; import backend.mips.instr.data.MipsAsciiz;
import midend.llvm.type.IrPointerType; import midend.llvm.type.IrArrayType;
import midend.llvm.type.IrInterType; import midend.llvm.type.IrPointerType;
import midend.llvm.type.IrInterType;
public class IrConstantStr extends IrConstant {
private String value; public class IrConstantStr extends IrConstant {
private String value;
public IrConstantStr(String value, String name) {
super(new IrPointerType( public IrConstantStr(String value, String name) {
new IrArrayType(IrInterType.INT8, getLen(value) + 1)), name); super(new IrPointerType(
this.value = value; new IrArrayType(IrInterType.INT8, getLen(value) + 1)), name);
} this.value = value;
}
public String getValue() {
return value; public String getValue() {
} return value;
}
public static int getLen(String value) {
int len = 0; public static int getLen(String value) {
for (int i = 0; i < value.length(); i++) { int len = 0;
if (value.charAt(i) == '\\') { for (int i = 0; i < value.length(); i++) {
i++; if (value.charAt(i) == '\\') {
} else if (value.charAt(i) == '"') { i++;
continue; } else if (value.charAt(i) == '"') {
} continue;
len++; }
} len++;
return len; }
} return len;
}
public static String getRealStr(String str) {
boolean start = str.charAt(0) == '"'; public static String getRealStr(String str) {
boolean end = str.charAt(str.length() - 1) == '"'; boolean start = str.charAt(0) == '"';
if (start && end) { boolean end = str.charAt(str.length() - 1) == '"';
return str.substring(1, str.length() - 1); if (start && end) {
} else if (start) { return str.substring(1, str.length() - 1);
return str.substring(1); } else if (start) {
} else if (end) { return str.substring(1);
return str.substring(0, str.length() - 1); } else if (end) {
} return str.substring(0, str.length() - 1);
return str; }
} return str;
}
public String toString() {
StringBuilder sb = new StringBuilder(); public String toString() {
sb.append(getName() + " = constant " + ((IrPointerType) getType()).getPointeeType()); StringBuilder sb = new StringBuilder();
sb.append(" c\"" + getRealStr(value).replace("\\n", "\\0A")); sb.append(getName() + " = constant " + ((IrPointerType) getType()).getPointeeType());
sb.append("\\00\""); sb.append(" c\"" + getRealStr(value).replace("\\n", "\\0A"));
return sb.toString(); sb.append("\\00\"");
} return sb.toString();
} }
public void toMips(String label) {
new MipsAsciiz(label, getRealStr(value));
}
}

70
midend/llvm/instr/AllocateInstr.java Normal file → Executable file
View File

@@ -1,21 +1,49 @@
package midend.llvm.instr; package midend.llvm.instr;
import midend.llvm.type.IrPointerType; import backend.mips.MipsBuilder;
import midend.llvm.type.IrType; import midend.llvm.type.IrArrayType;
import midend.llvm.type.IrPointerType;
public class AllocateInstr extends IrInstr { import midend.llvm.type.IrType;
private IrType pointeeType; import backend.mips.Register;
import backend.mips.instr.MipsAlu;
public AllocateInstr(IrType pointeeType, String name) { // name即为局部变量的name因为要声明一个局部变量 import backend.mips.instr.MipsLs;
super(new IrPointerType(pointeeType), name, IrInstrType.ALLOCA); import backend.mips.instr.type.MipsAluType;
this.pointeeType = pointeeType; import backend.mips.instr.type.MipsLsType;
}
public class AllocateInstr extends IrInstr {
public IrType getPointeeType() { private IrType pointeeType;
return pointeeType;
} public AllocateInstr(IrType pointeeType, String name) { // name即为局部变量的name因为要声明一个局部变量
super(new IrPointerType(pointeeType), name, IrInstrType.ALLOCA);
public String toString() { this.pointeeType = pointeeType;
return getName() + " = alloca " + this.pointeeType; }
}
} public IrType getPointeeType() {
return pointeeType;
}
public String toString() {
return getName() + " = alloca " + this.pointeeType;
}
public void toMips() {
// 想法:在栈上分配数据所需要的空间,再分配四字节的指针,这就是个指针,将其当作指针就好理解了
if (pointeeType instanceof IrArrayType) {
MipsBuilder.allocaOffset(4 * ((IrArrayType) pointeeType).getSize());
} else {
MipsBuilder.allocaOffset(4);
}
Register reg = MipsBuilder.getRegister(this);
if (reg == null) { // 未分配寄存器情况
int offset = MipsBuilder.getOffset();
new MipsAlu(MipsAluType.ADDI, Register.K0, Register.SP, offset);
MipsBuilder.allocaOffset(this); // 将该变量的偏移量设置为其指针的偏移量,后续取值先取指针,再根据指针取值
offset = MipsBuilder.getOffset();
new MipsLs(MipsLsType.SW, Register.K0, Register.SP, offset);
} else {
int offset = MipsBuilder.getOffset();
new MipsAlu(MipsAluType.ADDI, reg, Register.SP, offset);
}
}
}

85
midend/llvm/instr/AluInstr.java Normal file → Executable file
View File

@@ -1,24 +1,61 @@
package midend.llvm.instr; package midend.llvm.instr;
import midend.llvm.type.IrInterType; import backend.mips.MipsBuilder;
import midend.llvm.value.IrValue; import backend.mips.instr.MipsAlu;
import backend.mips.instr.MipsMd;
public class AluInstr extends IrInstr { import backend.mips.instr.type.MipsAluType;
private AluType alutype; import backend.mips.instr.type.MipsMdType;
import backend.mips.Register;
public AluInstr(String name, String op, IrValue left, IrValue right) {
super(IrInterType.INT32, name, IrInstrType.ALU); import midend.llvm.type.IrInterType;
this.alutype = AluType.getAluType(op); import midend.llvm.value.IrValue;
addUse(left);
addUse(right); public class AluInstr extends IrInstr {
} private AluType alutype;
public AluType getAluType() { public AluInstr(String name, String op, IrValue left, IrValue right) {
return alutype; super(IrInterType.INT32, name, IrInstrType.ALU);
} this.alutype = AluType.getAluType(op);
addUse(left);
public String toString() { addUse(right);
return getName() + " = " + alutype.toString() + " " + getType() }
+ " " + getUse(0).getName() + ", " + getUse(1).getName();
} public AluType getAluType() {
} return alutype;
}
public String toString() {
return getName() + " = " + alutype.toString() + " " + getType()
+ " " + getUse(0).getName() + ", " + getUse(1).getName();
}
public void toMips() {
IrValue left = getUse(0);
IrValue right = getUse(1);
Register leftReg = MipsBuilder.getRegister(left) != null ? MipsBuilder.getRegister(left) : Register.K0;
Register rightReg = MipsBuilder.getRegister(right) != null ? MipsBuilder.getRegister(right) : Register.K1;
Register resultReg = MipsBuilder.getRegister(this) != null ? MipsBuilder.getRegister(this) : Register.K1;
loadValueToReg(left, leftReg);
loadValueToReg(right, rightReg);
if (getAluType() == AluType.ADD) {
new MipsAlu(MipsAluType.ADDU, resultReg, leftReg, rightReg);
} else if (getAluType() == AluType.SUB) {
new MipsAlu(MipsAluType.SUBU, resultReg, leftReg, rightReg);
} else if (getAluType() == AluType.AND) {
new MipsAlu(MipsAluType.AND, resultReg, leftReg, rightReg);
} else if (getAluType() == AluType.OR) {
new MipsAlu(MipsAluType.OR, resultReg, leftReg, rightReg);
} else if (getAluType() == AluType.MUL) {
new MipsMd(MipsMdType.MULT, leftReg, rightReg);
new MipsMd(MipsMdType.MFLO, resultReg);
} else if (getAluType() == AluType.SDIV) {
new MipsMd(MipsMdType.DIV, leftReg, rightReg);
new MipsMd(MipsMdType.MFLO, resultReg);
} else if (getAluType() == AluType.SREM) {
new MipsMd(MipsMdType.DIV, leftReg, rightReg);
new MipsMd(MipsMdType.MFHI, resultReg);
}
saveResult(this, resultReg);
}
}

104
midend/llvm/instr/AluType.java Normal file → Executable file
View File

@@ -1,53 +1,53 @@
package midend.llvm.instr; package midend.llvm.instr;
public enum AluType { public enum AluType {
ADD, ADD,
SUB, SUB,
MUL, MUL,
SDIV, SDIV,
SREM, SREM,
AND, AND,
OR; OR;
public static AluType getAluType(String op) { public static AluType getAluType(String op) {
switch (op) { switch (op) {
case "+": case "+":
return ADD; return ADD;
case "-": case "-":
return SUB; return SUB;
case "*": case "*":
return MUL; return MUL;
case "/": case "/":
return SDIV; return SDIV;
case "%": case "%":
return SREM; return SREM;
case "&": case "&":
return AND; return AND;
case "|": case "|":
return OR; return OR;
default: default:
return null; return null;
} }
} }
public String toString() { public String toString() {
switch (this) { switch (this) {
case ADD: case ADD:
return "add"; return "add";
case SUB: case SUB:
return "sub"; return "sub";
case MUL: case MUL:
return "mul"; return "mul";
case SDIV: case SDIV:
return "sdiv"; return "sdiv";
case SREM: case SREM:
return "srem"; return "srem";
case AND: case AND:
return "and"; return "and";
case OR: case OR:
return "or"; return "or";
default: default:
return null; return null;
} }
} }
} }

81
midend/llvm/instr/BranchInstr.java Normal file → Executable file
View File

@@ -1,33 +1,48 @@
package midend.llvm.instr; package midend.llvm.instr;
import midend.llvm.value.IrBasicBlock; import midend.llvm.value.IrBasicBlock;
import midend.llvm.value.IrValue; import midend.llvm.value.IrValue;
import midend.llvm.type.IrInterType; import backend.mips.MipsBuilder;
import backend.mips.Register;
public class BranchInstr extends IrInstr { import backend.mips.instr.MipsBranch;
public BranchInstr(String name, IrValue cond, IrBasicBlock trueBB, IrBasicBlock falseBB) { import backend.mips.instr.type.MipsBranchType;
super(IrInterType.VOID, name, IrInstrType.BR); import backend.mips.instr.type.MipsJumpType;
addUse(cond); import backend.mips.instr.MipsJump;
addUse(trueBB); import midend.llvm.type.IrInterType;
addUse(falseBB);
} public class BranchInstr extends IrInstr {
public BranchInstr(String name, IrValue cond, IrBasicBlock trueBB, IrBasicBlock falseBB) {
public IrValue getCond() { super(IrInterType.VOID, name, IrInstrType.BR);
return getUse(0); addUse(cond);
} addUse(trueBB);
addUse(falseBB);
public IrBasicBlock getTrueBB() { }
return (IrBasicBlock) getUse(1);
} public IrValue getCond() {
return getUse(0);
public IrBasicBlock getFalseBB() { }
return (IrBasicBlock) getUse(2);
} public IrBasicBlock getTrueBB() {
return (IrBasicBlock) getUse(1);
public String toString() { }
return "br i1 " + getCond().getName() +
", label %" + getTrueBB().getName() + public IrBasicBlock getFalseBB() {
", label %" + getFalseBB().getName(); return (IrBasicBlock) getUse(2);
} }
} public String toString() {
return "br i1 " + getCond().getName() +
", label %" + getTrueBB().getName() +
", label %" + getFalseBB().getName();
}
public void toMips() {
Register condReg = MipsBuilder.getRegister(getCond());
if (condReg == null) {
condReg = Register.K0;
}
loadValueToReg(getCond(), condReg);
new MipsBranch(MipsBranchType.BNE, condReg, Register.ZERO, getTrueBB().getMipsLabel());
new MipsJump(MipsJumpType.J, getFalseBB().getMipsLabel());
}
}

165
midend/llvm/instr/CallInstr.java Normal file → Executable file
View File

@@ -1,48 +1,117 @@
package midend.llvm.instr; package midend.llvm.instr;
import java.util.ArrayList; import java.util.ArrayList;
import midend.llvm.value.IrFuncValue; import backend.mips.Register;
import midend.llvm.value.IrValue; import backend.mips.instr.MipsAlu;
import backend.mips.instr.MipsJump;
public class CallInstr extends IrInstr { import backend.mips.instr.MipsLs;
public CallInstr(String name, IrFuncValue func, ArrayList<IrValue> args) { import backend.mips.instr.type.MipsAluType;
super(func.getRetType(), name, IrInstrType.CALL); import backend.mips.instr.type.MipsJumpType;
addUse(func); import backend.mips.instr.type.MipsLsType;
for (IrValue arg : args) { import backend.mips.MipsBuilder;
addUse(arg); import midend.llvm.value.IrFuncValue;
} import midend.llvm.value.IrValue;
}
public class CallInstr extends IrInstr {
public boolean callVoid() { public CallInstr(String name, IrFuncValue func, ArrayList<IrValue> args) {
return getType().isVoid(); super(func.getRetType(), name, IrInstrType.CALL);
} addUse(func);
for (IrValue arg : args) {
public IrFuncValue getCalledFunc() { addUse(arg);
return (IrFuncValue) getUse(0); }
} }
public ArrayList<IrValue> getArgs() { public boolean callVoid() {
ArrayList<IrValue> args = new ArrayList<>(); return getType().isVoid();
for (int i = 1; i < getNumUses(); i++) { }
args.add(getUse(i));
} public IrFuncValue getCalledFunc() {
return args; return (IrFuncValue) getUse(0);
} }
public String toString() { public ArrayList<IrValue> getArgs() {
StringBuilder sb = new StringBuilder(); ArrayList<IrValue> args = new ArrayList<>();
if (!callVoid()) { for (int i = 1; i < getNumUses(); i++) {
sb.append(getName() + " = "); args.add(getUse(i));
} }
sb.append("call " + getType() + " " + getCalledFunc().getName() + "("); return args;
for (int i = 1; i < getNumUses(); i++) { }
sb.append(getUse(i).getType() + " " + getUse(i).getName());
if (i < getNumUses() - 1) { public String toString() {
sb.append(", "); StringBuilder sb = new StringBuilder();
} if (!callVoid()) {
} sb.append(getName() + " = ");
sb.append(")"); }
return sb.toString(); sb.append("call " + getType() + " " + getCalledFunc().getName() + "(");
} for (int i = 1; i < getNumUses(); i++) {
} sb.append(getUse(i).getType() + " " + getUse(i).getName());
if (i < getNumUses() - 1) {
sb.append(", ");
}
}
sb.append(")");
return sb.toString();
}
public void toMips() {
ArrayList<Register> usedRegisters = MipsBuilder.getUsedRegisters();
int offset = MipsBuilder.getOffset();
save(usedRegisters, offset);
ArrayList<IrValue> args = getArgs();
saveArgs(args, offset, usedRegisters);
offset -= (usedRegisters.size() + 2) * 4;
new MipsAlu(MipsAluType.ADDI, Register.SP, Register.SP, offset);
new MipsJump(MipsJumpType.JAL, getCalledFunc().getMipsLabel());
offset += (usedRegisters.size() + 2) * 4;
recover(usedRegisters, offset);
saveResult(this, Register.V0);
}
public void save(ArrayList<Register> usedRegisters, int offset) {
int num = 0;
for (Register reg : usedRegisters) {
num++;
new MipsLs(MipsLsType.SW, reg, Register.SP, offset - num * 4);
}
new MipsLs(MipsLsType.SW, Register.SP, Register.SP, offset - (num + 1) * 4);
new MipsLs(MipsLsType.SW, Register.RA, Register.SP, offset - (num + 2) * 4);
}
public void saveArgs(ArrayList<IrValue> args, int offset, ArrayList<Register> usedRegisters) {
int num = 0;
ArrayList<Register> argRegs = new ArrayList<>();
argRegs.add(Register.A1);
argRegs.add(Register.A2);
argRegs.add(Register.A3);
for (IrValue arg : args) {
num++;
if (num <= 3) { // 分配到A1、A2、A3
if (argRegs.contains(MipsBuilder.getRegister(arg))) {
int index = usedRegisters.indexOf(MipsBuilder.getRegister(arg));
new MipsLs(MipsLsType.LW, argRegs.get(num - 1), Register.SP, offset - (index + 1) * 4);
} else {
loadValueToReg(arg, argRegs.get(num - 1));
}
} else {
if (MipsBuilder.getRegister(arg) == Register.K0 || argRegs.contains(MipsBuilder.getRegister(arg))) {
int index = usedRegisters.indexOf(MipsBuilder.getRegister(arg));
new MipsLs(MipsLsType.LW, Register.K0, Register.SP, offset - (index + 1) * 4);
} else {
loadValueToReg(arg, Register.K0);
}
new MipsLs(MipsLsType.SW, Register.K0, Register.SP, offset - (usedRegisters.size() + num + 2) * 4);
}
}
}
public void recover(ArrayList<Register> usedRegisters, int offset) {
new MipsLs(MipsLsType.LW, Register.RA, Register.SP, 0);
new MipsLs(MipsLsType.LW, Register.SP, Register.SP, 4);
int num = 0;
for (Register reg : usedRegisters) {
num++;
new MipsLs(MipsLsType.LW, reg, Register.SP, offset - num * 4);
}
}
}

90
midend/llvm/instr/CmpInstr.java Normal file → Executable file
View File

@@ -1,32 +1,58 @@
package midend.llvm.instr; package midend.llvm.instr;
import midend.llvm.value.IrValue; import midend.llvm.value.IrValue;
import midend.llvm.type.IrInterType; import backend.mips.Register;
import backend.mips.instr.MipsComp;
public class CmpInstr extends IrInstr { import backend.mips.instr.type.MipsCompareType;
private CmpType cmpType; import midend.llvm.type.IrInterType;
import backend.mips.MipsBuilder;
public CmpInstr(String name, String op, IrValue lhs, IrValue rhs) {
super(IrInterType.BOOL, name, IrInstrType.CMP); public class CmpInstr extends IrInstr {
cmpType = CmpType.getCmpType(op); private CmpType cmpType;
addUse(lhs);
addUse(rhs); public CmpInstr(String name, String op, IrValue lhs, IrValue rhs) {
} super(IrInterType.BOOL, name, IrInstrType.CMP);
cmpType = CmpType.getCmpType(op);
public CmpType getCmpType() { addUse(lhs);
return cmpType; addUse(rhs);
} }
public IrValue getLhs() { public CmpType getCmpType() {
return getUse(0); return cmpType;
} }
public IrValue getRhs() { public IrValue getLhs() {
return getUse(1); return getUse(0);
} }
public String toString() { public IrValue getRhs() {
return getName() + " = " + "icmp " + cmpType.toString() return getUse(1);
+ " i32 " + getLhs().getName() + ", " + getRhs().getName(); }
}
} public String toString() {
return getName() + " = " + "icmp " + cmpType.toString()
+ " i32 " + getLhs().getName() + ", " + getRhs().getName();
}
public void toMips() {
Register leftReg = MipsBuilder.getRegister(getLhs()) != null ? MipsBuilder.getRegister(getLhs()) : Register.K0;
Register rightReg = MipsBuilder.getRegister(getRhs()) != null ? MipsBuilder.getRegister(getRhs()) : Register.K1;
Register resultReg = MipsBuilder.getRegister(this) != null ? MipsBuilder.getRegister(this) : Register.K1;
loadValueToReg(getLhs(), leftReg);
loadValueToReg(getRhs(), rightReg);
if (getCmpType() == CmpType.EQ) {
new MipsComp(MipsCompareType.SEQ, resultReg, leftReg, rightReg);
} else if (getCmpType() == CmpType.NE) {
new MipsComp(MipsCompareType.SNE, resultReg, leftReg, rightReg);
} else if (getCmpType() == CmpType.SGE) {
new MipsComp(MipsCompareType.SGE, resultReg, leftReg, rightReg);
} else if (getCmpType() == CmpType.SLE) {
new MipsComp(MipsCompareType.SLE, resultReg, leftReg, rightReg);
} else if (getCmpType() == CmpType.SGT) {
new MipsComp(MipsCompareType.SGT, resultReg, leftReg, rightReg);
} else if (getCmpType() == CmpType.SLT) {
new MipsComp(MipsCompareType.SLT, resultReg, leftReg, rightReg);
}
saveResult(this, resultReg);
}
}

96
midend/llvm/instr/CmpType.java Normal file → Executable file
View File

@@ -1,48 +1,48 @@
package midend.llvm.instr; package midend.llvm.instr;
public enum CmpType { public enum CmpType {
EQ, EQ,
NE, NE,
SGT, SGT,
SGE, SGE,
SLT, SLT,
SLE; SLE;
public static CmpType getCmpType(String op) { public static CmpType getCmpType(String op) {
switch (op) { switch (op) {
case "==": case "==":
return EQ; return EQ;
case "!=": case "!=":
return NE; return NE;
case ">": case ">":
return SGT; return SGT;
case ">=": case ">=":
return SGE; return SGE;
case "<": case "<":
return SLT; return SLT;
case "<=": case "<=":
return SLE; return SLE;
default: default:
return null; return null;
} }
} }
public String toString() { public String toString() {
switch (this) { switch (this) {
case EQ: case EQ:
return "eq"; return "eq";
case NE: case NE:
return "ne"; return "ne";
case SGT: case SGT:
return "sgt"; return "sgt";
case SGE: case SGE:
return "sge"; return "sge";
case SLT: case SLT:
return "slt"; return "slt";
case SLE: case SLE:
return "sle"; return "sle";
default: default:
return null; return null;
} }
} }
} }

73
midend/llvm/instr/ExtendInstr.java Normal file → Executable file
View File

@@ -1,31 +1,42 @@
package midend.llvm.instr; package midend.llvm.instr;
import midend.llvm.type.IrType; import backend.mips.MipsBuilder;
import midend.llvm.value.IrValue; import backend.mips.Register;
import midend.llvm.type.IrType;
public class ExtendInstr extends IrInstr { import midend.llvm.value.IrValue;
private IrType targetType;
public class ExtendInstr extends IrInstr {
public ExtendInstr(String name, IrType targetType, IrValue src) { private IrType targetType;
super(targetType, name, IrInstrType.EXTEND);
this.targetType = targetType; public ExtendInstr(String name, IrType targetType, IrValue src) {
addUse(src); super(targetType, name, IrInstrType.EXTEND);
} this.targetType = targetType;
addUse(src);
public IrValue getSrc() { }
return getUse(0);
} public IrValue getSrc() {
return getUse(0);
public IrType getTargetType() { }
return this.targetType;
} public IrType getTargetType() {
return this.targetType;
public IrType getSrcType() { }
return getSrc().getType();
} public IrType getSrcType() {
return getSrc().getType();
public String toString() { }
return getName() + " = zext " + getSrc().getType()
+ " " + getSrc().getName() + " to " + getTargetType(); public String toString() {
} return getName() + " = zext " + getSrc().getType()
} + " " + getSrc().getName() + " to " + getTargetType();
}
public void toMips() {
Register reg = MipsBuilder.getRegister(this);
if (reg == null) {
reg = Register.K0;
}
loadValueToReg(getSrc(), reg);
saveResult(this, reg);
}
}

143
midend/llvm/instr/GepInstr.java Normal file → Executable file
View File

@@ -1,57 +1,86 @@
package midend.llvm.instr; package midend.llvm.instr;
import midend.llvm.type.IrArrayType; import backend.mips.MipsBuilder;
import midend.llvm.type.IrPointerType; import backend.mips.Register;
import midend.llvm.type.IrType; import backend.mips.instr.MipsAlu;
import midend.llvm.value.IrValue; import backend.mips.instr.type.MipsAluType;
import midend.llvm.constant.IrConstantInt;
public class GepInstr extends IrInstr { import midend.llvm.type.IrArrayType;
public GepInstr(IrValue pointer, IrValue offset, String name) { import midend.llvm.type.IrPointerType;
super(new IrPointerType(getTargetType(pointer)), name, IrInstrType.GEP); import midend.llvm.type.IrType;
addUse(pointer); import midend.llvm.value.IrValue;
addUse(offset);
} public class GepInstr extends IrInstr {
public GepInstr(IrValue pointer, IrValue offset, String name) {
public IrValue getPointer() { super(new IrPointerType(getTargetType(pointer)), name, IrInstrType.GEP);
return getUse(0); addUse(pointer);
} addUse(offset);
}
public IrValue getOffset() {
return getUse(1); public IrValue getPointer() {
} return getUse(0);
}
public String toString() {
IrValue pointer = this.getPointer(); public IrValue getOffset() {
IrValue offset = this.getOffset(); return getUse(1);
}
IrPointerType pointerType = (IrPointerType) pointer.getType();
IrType targetType = pointerType.getPointeeType(); public String toString() {
IrValue pointer = this.getPointer();
if (targetType instanceof IrArrayType arrayType) { IrValue offset = this.getOffset();
return getName() + " = getelementptr inbounds " +
arrayType + ", " + IrPointerType pointerType = (IrPointerType) pointer.getType();
pointerType + " " + IrType targetType = pointerType.getPointeeType();
pointer.getName() + ", i32 0, " +
offset.getType() + " " + if (targetType instanceof IrArrayType arrayType) {
offset.getName(); return getName() + " = getelementptr inbounds " +
} else { arrayType + ", " +
return getName() + " = getelementptr inbounds " + pointerType + " " +
targetType + ", " + pointer.getName() + ", i32 0, " +
pointerType + " " + offset.getType() + " " +
pointer.getName() + ", " + offset.getName();
offset.getType() + " " + } else {
offset.getName(); return getName() + " = getelementptr inbounds " +
} targetType + ", " +
} pointerType + " " +
pointer.getName() + ", " +
public static IrType getTargetType(IrValue pointer) { offset.getType() + " " +
IrType targetType = ((IrPointerType) pointer.getType()).getPointeeType(); offset.getName();
if (targetType instanceof IrArrayType arrayType) { }
return arrayType.getElementType(); }
} else if (targetType instanceof IrPointerType pointerType) {
return pointerType.getPointeeType(); public static IrType getTargetType(IrValue pointer) {
} else { IrType targetType = ((IrPointerType) pointer.getType()).getPointeeType();
return targetType; if (targetType instanceof IrArrayType arrayType) {
} return arrayType.getElementType();
} } else if (targetType instanceof IrPointerType pointerType) {
} return pointerType.getPointeeType();
} else {
return targetType;
}
}
public void toMips() {
Register pointerReg = MipsBuilder.getRegister(getPointer());
if (pointerReg == null) {
pointerReg = Register.K0;
}
loadValueToReg(getPointer(), pointerReg);
Register offsetReg = MipsBuilder.getRegister(getOffset());
if (offsetReg == null) {
offsetReg = Register.K1;
}
Register resultReg = MipsBuilder.getRegister(this);
if (resultReg == null) {
resultReg = Register.K1;
}
if (getOffset() instanceof IrConstantInt intOffset) {
new MipsAlu(MipsAluType.ADDI, resultReg, pointerReg, 4 * intOffset.getValue());
} else {
loadValueToReg(getOffset(), offsetReg);
new MipsAlu(MipsAluType.SLL, resultReg, offsetReg, 2);
new MipsAlu(MipsAluType.ADDU, resultReg, resultReg, pointerReg);
}
saveResult(this, resultReg);
}
}

43
midend/llvm/instr/GetIntInstr.java Normal file → Executable file
View File

@@ -1,17 +1,26 @@
package midend.llvm.instr; package midend.llvm.instr;
import midend.llvm.type.IrInterType; import backend.mips.Register;
import backend.mips.instr.MipsSyscall;
public class GetIntInstr extends IrInstr { import backend.mips.instr.fake.MipsLi;
public GetIntInstr(String name) { import midend.llvm.type.IrInterType;
super(IrInterType.INT32, name, IrInstrType.IO);
} public class GetIntInstr extends IrInstr {
public GetIntInstr(String name) {
public String toString() { super(IrInterType.INT32, name, IrInstrType.IO);
return getName() + " = call i32 @getint()"; }
}
public String toString() {
public static String getIntDecl() { return getName() + " = call i32 @getint()";
return "declare i32 @getint()"; }
}
} public static String getIntDecl() {
return "declare i32 @getint()";
}
public void toMips() {
new MipsLi(Register.V0, 5);
new MipsSyscall();
saveResult(this, Register.V0);
}
}

103
midend/llvm/instr/IrInstr.java Normal file → Executable file
View File

@@ -1,28 +1,75 @@
package midend.llvm.instr; package midend.llvm.instr;
import midend.llvm.use.IrUser; import midend.llvm.use.IrUser;
import midend.llvm.value.IrBasicBlock; import midend.llvm.value.IrBasicBlock;
import midend.llvm.type.IrType; import midend.llvm.value.IrGlobalValue;
import midend.llvm.value.IrValue;
public class IrInstr extends IrUser { import midend.llvm.constant.IrConstantInt;
private IrInstrType type; import backend.mips.MipsBuilder;
private IrBasicBlock block; import backend.mips.Register;
import backend.mips.instr.MipsLs;
public IrInstr(IrType type, String name, IrInstrType instrType) { import backend.mips.instr.fake.MipsLa;
super(type, name); import backend.mips.instr.fake.MipsLi;
this.type = instrType; import backend.mips.instr.fake.MipsMove;
this.block = null; import backend.mips.instr.type.MipsLsType;
} import midend.llvm.type.IrType;
public IrInstrType getInstrType() { public class IrInstr extends IrUser {
return type; private IrInstrType type;
} private IrBasicBlock block;
public IrBasicBlock getBBlock() { public IrInstr(IrType type, String name, IrInstrType instrType) {
return block; super(type, name);
} this.type = instrType;
this.block = null;
public void setBBlock(IrBasicBlock block) { }
this.block = block;
} public IrInstrType getInstrType() {
} return type;
}
public IrBasicBlock getBBlock() {
return block;
}
public void setBBlock(IrBasicBlock block) {
this.block = block;
}
public void saveResult(IrValue value, Register reg) {
Register valueReg = MipsBuilder.getRegister(value);
if (valueReg == null) {
Integer offset = MipsBuilder.getOffset(value);
if (offset == null) {
MipsBuilder.allocaOffset(value);
offset = MipsBuilder.getOffset(value);
}
new MipsLs(MipsLsType.SW, reg, Register.SP, offset);
} else {
new MipsMove(valueReg, reg);
}
}
public void loadValueToReg(IrValue value, Register reg) {
if (value instanceof IrGlobalValue) {
new MipsLa(reg, value.getMipsLabel());
return;
}
if (value instanceof IrConstantInt) {
new MipsLi(reg, ((IrConstantInt) value).getValue());
return;
}
Register valueReg = MipsBuilder.getRegister(value);
if (valueReg != null) {
new MipsMove(reg, valueReg);
return;
}
Integer offset = MipsBuilder.getOffset(value);
if (offset == null) {
MipsBuilder.allocaOffset(value);
offset = MipsBuilder.getOffset(value);
}
new MipsLs(MipsLsType.LW, reg, Register.SP, offset);
}
}

36
midend/llvm/instr/IrInstrType.java Normal file → Executable file
View File

@@ -1,18 +1,18 @@
package midend.llvm.instr; package midend.llvm.instr;
public enum IrInstrType { public enum IrInstrType {
ALU, ALU,
CMP, CMP,
CALL, CALL,
ALLOCA, ALLOCA,
LOAD, LOAD,
STORE, STORE,
GEP, GEP,
PHI, PHI,
EXTEND, EXTEND,
TRUNC, TRUNC,
BR, BR,
RET, RET,
JUMP, JUMP,
IO IO
} }

45
midend/llvm/instr/JumpInstr.java Normal file → Executable file
View File

@@ -1,20 +1,25 @@
package midend.llvm.instr; package midend.llvm.instr;
import midend.llvm.value.IrBasicBlock; import midend.llvm.value.IrBasicBlock;
import midend.llvm.type.IrInterType; import backend.mips.instr.MipsJump;
import backend.mips.instr.type.MipsJumpType;
public class JumpInstr extends IrInstr { import midend.llvm.type.IrInterType;
public JumpInstr(IrBasicBlock targetBlock) {
super(IrInterType.VOID, "jump", IrInstrType.JUMP); public class JumpInstr extends IrInstr {
addUse(targetBlock); public JumpInstr(IrBasicBlock targetBlock) {
} super(IrInterType.VOID, "jump", IrInstrType.JUMP);
addUse(targetBlock);
public IrBasicBlock getTargetBlock() { }
return (IrBasicBlock) getUse(0);
} public IrBasicBlock getTargetBlock() {
return (IrBasicBlock) getUse(0);
public String toString() { }
return "br label " + "%" + getTargetBlock().getName();
} public String toString() {
} return "br label " + "%" + getTargetBlock().getName();
// TODO:所有的指令的基本块设置还需完善 }
public void toMips() {
new MipsJump(MipsJumpType.J, getTargetBlock().getMipsLabel()); //TODO: 该用JAL吗
}
}

59
midend/llvm/instr/LoadInstr.java Normal file → Executable file
View File

@@ -1,20 +1,39 @@
package midend.llvm.instr; package midend.llvm.instr;
import midend.llvm.type.IrPointerType; import backend.mips.MipsBuilder;
import midend.llvm.value.IrValue; import backend.mips.Register;
import backend.mips.instr.MipsLs;
public class LoadInstr extends IrInstr { import backend.mips.instr.type.MipsLsType;
public LoadInstr(IrValue pointer, String name) { import midend.llvm.type.IrPointerType;
super(((IrPointerType) pointer.getType()).getPointeeType(), name, IrInstrType.LOAD); import midend.llvm.value.IrValue;
addUse(pointer);
} public class LoadInstr extends IrInstr {
public LoadInstr(IrValue pointer, String name) {
public IrValue getPointer() { super(((IrPointerType) pointer.getType()).getPointeeType(), name, IrInstrType.LOAD);
return getUse(0); addUse(pointer);
} }
public String toString() { public IrValue getPointer() {
return getName() + " = load " + getType() + ", " return getUse(0);
+ getPointer().getType() + " " + getPointer().getName(); }
}
} public String toString() {
return getName() + " = load " + getType() + ", "
+ getPointer().getType() + " " + getPointer().getName();
}
public void toMips() {
IrValue pointer = getPointer();
Register reg = MipsBuilder.getRegister(pointer);
if (reg == null) { // 未分配寄存器情况
reg = Register.K0;
}
loadValueToReg(pointer, reg);
Register resultReg = MipsBuilder.getRegister(this);
if (resultReg == null) {
resultReg = Register.K1;
}
new MipsLs(MipsLsType.LW, resultReg, reg, 0);
saveResult(this, resultReg);
}
}

47
midend/llvm/instr/PutChInstr.java Normal file → Executable file
View File

@@ -1,19 +1,28 @@
package midend.llvm.instr; package midend.llvm.instr;
import midend.llvm.type.IrInterType; import midend.llvm.type.IrInterType;
import midend.llvm.value.IrValue; import midend.llvm.value.IrValue;
import backend.mips.Register;
public class PutChInstr extends IrInstr { import backend.mips.instr.fake.MipsLi;
public PutChInstr(String name, IrValue putValue) { import backend.mips.instr.MipsSyscall;
super(IrInterType.VOID, name, IrInstrType.IO);
addUse(putValue); public class PutChInstr extends IrInstr {
} public PutChInstr(String name, IrValue putValue) {
super(IrInterType.VOID, name, IrInstrType.IO);
public String toString() { addUse(putValue);
return "call void @putch(i32 " + getUses().get(0).getName() + ")"; }
}
public String toString() {
public static String putChDecl() { return "call void @putch(i32 " + getUses().get(0).getName() + ")";
return "declare void @putch(i32)"; }
}
} public static String putChDecl() {
return "declare void @putch(i32)";
}
public void toMips() {
loadValueToReg(getUse(0), Register.A0);
new MipsLi(Register.V0, 11);
new MipsSyscall();
}
}

47
midend/llvm/instr/PutIntInstr.java Normal file → Executable file
View File

@@ -1,19 +1,28 @@
package midend.llvm.instr; package midend.llvm.instr;
import midend.llvm.type.IrInterType; import midend.llvm.type.IrInterType;
import midend.llvm.value.IrValue; import midend.llvm.value.IrValue;
import backend.mips.Register;
public class PutIntInstr extends IrInstr { import backend.mips.instr.fake.MipsLi;
public PutIntInstr(String name, IrValue putValue) { import backend.mips.instr.MipsSyscall;
super(IrInterType.VOID, name, IrInstrType.IO);
addUse(putValue); public class PutIntInstr extends IrInstr {
} public PutIntInstr(String name, IrValue putValue) {
super(IrInterType.VOID, name, IrInstrType.IO);
public String toString() { addUse(putValue);
return "call void @putint(i32 " + getUses().get(0).getName() + ")"; }
}
public String toString() {
public static String putIntDecl() { return "call void @putint(i32 " + getUses().get(0).getName() + ")";
return "declare void @putint(i32)"; }
}
} public static String putIntDecl() {
return "declare void @putint(i32)";
}
public void toMips() {
loadValueToReg(getUse(0), Register.A0);
new MipsLi(Register.V0, 1);
new MipsSyscall();
}
}

62
midend/llvm/instr/PutStrInstr.java Normal file → Executable file
View File

@@ -1,26 +1,36 @@
package midend.llvm.instr; package midend.llvm.instr;
import midend.llvm.type.IrInterType; import midend.llvm.type.IrInterType;
import midend.llvm.type.IrPointerType; import midend.llvm.type.IrPointerType;
import midend.llvm.constant.IrConstantStr; import backend.mips.instr.fake.MipsLa;
import midend.llvm.constant.IrConstantStr;
public class PutStrInstr extends IrInstr { import backend.mips.instr.fake.MipsLi;
private IrConstantStr strVal; import backend.mips.instr.MipsSyscall;
import backend.mips.Register;
public PutStrInstr(String name, IrConstantStr putValue) {
super(IrInterType.VOID, name, IrInstrType.IO); public class PutStrInstr extends IrInstr {
addUse(putValue); private IrConstantStr strVal;
strVal = putValue;
} public PutStrInstr(String name, IrConstantStr putValue) {
super(IrInterType.VOID, name, IrInstrType.IO);
public static String putStrDecl() { addUse(putValue);
return "declare void @putstr(i8*)"; strVal = putValue;
} }
public String toString() { public static String putStrDecl() {
IrPointerType ptrType = (IrPointerType) strVal.getType(); return "declare void @putstr(i8*)";
return "call void @putstr(i8* getelementptr inbounds (" }
+ ptrType.getPointeeType() + ", " + ptrType +
" " + strVal.getName() + ", i32 0, i32 0))"; public String toString() {
} IrPointerType ptrType = (IrPointerType) strVal.getType();
} return "call void @putstr(i8* getelementptr inbounds ("
+ ptrType.getPointeeType() + ", " + ptrType +
" " + strVal.getName() + ", i32 0, i32 0))";
}
public void toMips() {
new MipsLa(Register.A0, strVal.getMipsLabel());
new MipsLi(Register.V0, 4);
new MipsSyscall();
}
}

Some files were not shown because too many files have changed in this diff Show More