87 lines
3.0 KiB
Java
Executable File
87 lines
3.0 KiB
Java
Executable File
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);
|
|
}
|
|
}
|