package midend.llvm.instr; import backend.mips.MipsBuilder; import backend.mips.Register; import backend.mips.instr.MipsAlu; import backend.mips.instr.type.MipsAluType; import midend.llvm.constant.IrConstantInt; import midend.llvm.type.IrArrayType; import midend.llvm.type.IrPointerType; import midend.llvm.type.IrType; import midend.llvm.value.IrValue; public class GepInstr extends IrInstr { public GepInstr(IrValue pointer, IrValue offset, String name) { super(new IrPointerType(getTargetType(pointer)), name, IrInstrType.GEP); addUse(pointer); addUse(offset); } public IrValue getPointer() { return getUse(0); } public IrValue getOffset() { return getUse(1); } public String toString() { IrValue pointer = this.getPointer(); IrValue offset = this.getOffset(); IrPointerType pointerType = (IrPointerType) pointer.getType(); IrType targetType = pointerType.getPointeeType(); if (targetType instanceof IrArrayType arrayType) { return getName() + " = getelementptr inbounds " + arrayType + ", " + pointerType + " " + pointer.getName() + ", i32 0, " + offset.getType() + " " + offset.getName(); } else { return getName() + " = getelementptr inbounds " + targetType + ", " + pointerType + " " + pointer.getName() + ", " + offset.getType() + " " + offset.getName(); } } public static IrType getTargetType(IrValue pointer) { IrType targetType = ((IrPointerType) pointer.getType()).getPointeeType(); 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); } }