• ymhui's avatar
    submit · 1649fe46
    ymhui authored
    1649fe46
RiscBasicBlock.java 7.83 KiB
package cn.edu.nju.software.backend;
import cn.edu.nju.software.backend.regalloc.LValLiveTable;
import cn.edu.nju.software.backend.regalloc.TempVarLiveTable;
import cn.edu.nju.software.backend.riscinstruction.*;
import cn.edu.nju.software.backend.riscinstruction.floatextension.RiscFlw;
import cn.edu.nju.software.backend.riscinstruction.operand.ImmediateValue;
import cn.edu.nju.software.backend.riscinstruction.operand.IndirectRegister;
import cn.edu.nju.software.backend.riscinstruction.operand.Register;
import cn.edu.nju.software.backend.riscinstruction.pseudo.RiscLi;
import cn.edu.nju.software.backend.riscinstruction.util.RiscComment;
import cn.edu.nju.software.backend.regalloc.Allocator;
import cn.edu.nju.software.ir.basicblock.BasicBlockRef;
import cn.edu.nju.software.ir.type.*;
import cn.edu.nju.software.ir.value.FunctionValue;
import cn.edu.nju.software.ir.value.LocalVar;
import java.util.ArrayList;
import java.util.List;
public class RiscBasicBlock {
    private final BasicBlockRef basicBlockRef;
    private final Allocator allocator = Allocator.get();
    private final FunctionValue llvmFunctionValue;
    private final List<RiscInstruction> riscInstructions = new ArrayList<>() ;
    private final RiscInstrGenerator generator;
    private final TempVarLiveTable tempVarLiveTable;
    private final LValLiveTable lValLiveTable;
    public RiscBasicBlock(BasicBlockRef basicBlockRef, FunctionValue functionValue) {
        this.basicBlockRef = basicBlockRef;
        this.llvmFunctionValue = functionValue;
        this.generator = new RiscInstrGenerator(basicBlockRef.getIrs(), llvmFunctionValue);
        this.tempVarLiveTable = new TempVarLiveTable(generator, allocator);
        this.lValLiveTable = new LValLiveTable();
    public void codeGen() {
        allocator.setLValLiveTable(lValLiveTable);
        allocator.setTempVarLiveTable(tempVarLiveTable);
        allocator.setInstrGenerator(generator);
        if (basicBlockRef.isEntryBlock()) {
            functionInit();
        riscInstructions.addAll(generator.genRiscInstructions());
    private void functionInit() {
        generator.insertComment("reserve space for all local variables in function");
        int stackSize = allocator.getStackSize();
        if (stackSize > 0) {
            if(stackSize <= 2048){
                generator.addInstruction(new RiscAddi(new Register("sp"), new Register("sp"), new ImmediateValue(-stackSize)));
            } else {
                generator.addInstruction(new RiscLi(new Register("t0"), new ImmediateValue(stackSize)));
                generator.addInstruction(new RiscSub(new Register("sp"), new Register("sp"), new Register("t0")));
        if(!llvmFunctionValue.getName().equals("main")){ //main没有调用函数,也没有参数
            saveCalleeSavedRegs();
            saveParams();
    public RiscInstrGenerator getGenerator() {
        return generator;
    /**
     * 保存参数
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
* 依次检查参数的类系,如果是General,就从a0-a7中取出,如果是Float就从fa0-fa7中取出 * 如果参数个数超过8个,依次从栈中取出 * 对于每一函数的参数,都为其分配了一个LocalVar(%0,%1,...)后续对于传入的参数的值的使用都是通过这个LocalVar来引用的 * 因此需要将参数寄存器中的的值保存到这些LocalVar中 */ private void saveParams() { generator.insertComment("save the parameters value in the regs"); int preLen = getPredLen(); FunctionType functionType = (FunctionType) llvmFunctionValue.getType(); String[] fArgs = RiscSpecifications.getFArgRegs(); String[] args = RiscSpecifications.getArgRegs(); int fptr = 0; int ptr = 0; int order = 0; //order 相对于prelen的偏移量,分别对应第一个被存入栈中的参数,第二个被存入栈中的参数... for (int i = 0; i < functionType.getFParametersCount(); i++) { if (functionType.getFParameter(i) instanceof FloatType) { if(fptr >= RiscSpecifications.getFArgRegs().length){ fetchFromStack(functionType.getFParameter(i), i, preLen, order++); } else { allocator.storeLocalVarIntoMemory(new LocalVar(functionType.getFParameter(i), i +""), fArgs[fptr++]); } } else if (functionType.getFParameter(i) instanceof IntType || functionType.getFParameter(i) instanceof Pointer){ if(ptr >= RiscSpecifications.getArgRegs().length){ fetchFromStack(functionType.getFParameter(i), i, preLen, order++); } else { allocator.storeLocalVarIntoMemory(new LocalVar(functionType.getFParameter(i), i +""), args[ptr++]); } } else {assert false;} } } /** * 获取第一个参数相对于栈底的偏移量 */ public int getPredLen(){ FunctionType functionType = (FunctionType) llvmFunctionValue.getType(); int intTypeCount = functionType.getFParameters().stream() .filter(IntType.class::isInstance) .mapToInt(typeRef -> 1) .sum(); int floatTypeCount = functionType.getFParameters().stream() .filter(FloatType.class::isInstance) .mapToInt(typeRef -> 1) .sum(); int pointerTypeCount = functionType.getFParameters().stream() .filter(Pointer.class::isInstance) .mapToInt(typeRef -> 1) .sum(); int intAndPointerCount = intTypeCount + pointerTypeCount; return ( ((intAndPointerCount > RiscSpecifications.getArgRegs().length) ? (intAndPointerCount - RiscSpecifications.getArgRegs().length) : 0) + ((floatTypeCount > RiscSpecifications.getFArgRegs().length) ? (floatTypeCount - RiscSpecifications.getFArgRegs().length) : 0) ) * 8 + (RiscSpecifications.getCallerSavedRegs().length - 1) * 8; } private void fetchFromStack(TypeRef type, int i, int preLen, int order) { String destReg = "t0"; if (type instanceof IntType) { generator.addInstruction(new RiscLw(new Register("t0"), allocator.getRegWithOffset(allocator.getStackSize() + preLen - order * 8, "sp", "t4"))); destReg = "t0"; } else if (type instanceof FloatType) { generator.addInstruction(new RiscFlw(new Register("ft0"), allocator.getRegWithOffset(allocator.getStackSize() + preLen - order * 8, "sp", "t4"))); destReg = "ft0"; } else if(type instanceof Pointer){ generator.addInstruction(new RiscLd(new Register("t0"), allocator.getRegWithOffset(allocator.getStackSize() + preLen - order * 8, "sp", "t4"))); destReg = "t0"; } else {assert false;} allocator.storeLocalVarIntoMemory(new LocalVar(type, i + ""), destReg); }
141142143144145146147148149150151152153154155156157158159160161162163164165
private void saveCalleeSavedRegs() { generator.insertComment("save CallerSavedRegs"); String[] calleeSavedRegs = RiscSpecifications.getCalleeSavedRegs(); generator.addInstruction(new RiscAddi(new Register("sp"), new Register("sp"), new ImmediateValue(-8L * calleeSavedRegs.length))); for (int i = 0; i < calleeSavedRegs.length; i++) { generator.addInstruction(new RiscSd(new Register(calleeSavedRegs[i]), new IndirectRegister("sp", i * 8))); } } public void dumpToConsole() { System.out.println(basicBlockRef.getName() + ":"); for(RiscInstruction riscInstruction : riscInstructions){ if(riscInstruction instanceof RiscComment){ if(RiscSpecifications.getIsDebug()){ System.out.println(riscInstruction.emitCode()); } } else { System.out.println(riscInstruction.emitCode()); } } } }