Archived
Switch to generic visitor pattern.
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
package Triangle.CodeGenerator;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import Triangle.ErrorReporter;
|
||||
import Triangle.AbstractMachine.Instruction;
|
||||
import Triangle.AbstractMachine.Machine;
|
||||
import Triangle.AbstractMachine.OpCode;
|
||||
import Triangle.AbstractMachine.Primitive;
|
||||
import Triangle.AbstractMachine.Register;
|
||||
|
||||
public class Emitter {
|
||||
|
||||
// OBJECT CODE
|
||||
|
||||
// Implementation notes:
|
||||
// Object code is generated directly into the TAM Code Store, starting at
|
||||
// CB.
|
||||
// The address of the next instruction is held in nextInstrAddr.
|
||||
|
||||
ErrorReporter errorReporter;
|
||||
|
||||
int nextInstrAddr;
|
||||
|
||||
public Emitter(ErrorReporter errorReporter) {
|
||||
this.errorReporter = errorReporter;
|
||||
nextInstrAddr = Machine.CB;
|
||||
}
|
||||
|
||||
public int getNextInstrAddr() {
|
||||
return nextInstrAddr;
|
||||
}
|
||||
|
||||
public int emit(OpCode op) {
|
||||
return emit(op, 0, Register.CB, 0);
|
||||
}
|
||||
|
||||
public int emit(OpCode op, int operand) {
|
||||
return emit(op, 0, Register.CB, operand);
|
||||
}
|
||||
|
||||
public int emit(OpCode op, int length, int operand) {
|
||||
return emit(op, length, Register.CB, operand);
|
||||
}
|
||||
|
||||
public int emit(OpCode op, Register staticRegister, Register register, int operand) {
|
||||
return emit(op, staticRegister.ordinal(), register, operand);
|
||||
}
|
||||
|
||||
public int emit(OpCode op, Register register, int operand) {
|
||||
return emit(op, 0, register, operand);
|
||||
}
|
||||
|
||||
public int emit(OpCode op, Register register) {
|
||||
return emit(op, 0, register, 0);
|
||||
}
|
||||
|
||||
public int emit(OpCode op, int length, Register register) {
|
||||
return emit(op, length, register, 0);
|
||||
}
|
||||
|
||||
public int emit(OpCode op, Register register, Primitive primitive) {
|
||||
return emit(op, 0, register, primitive.ordinal());
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends an instruction, with the given fields, to the object code.
|
||||
*
|
||||
* @param op the opcode
|
||||
* @param length the length field
|
||||
* @param register the register field
|
||||
* @param operand the operand field
|
||||
* @return the code address of the new instruction
|
||||
**/
|
||||
public int emit(OpCode op, int length, Register register, int operand) {
|
||||
|
||||
if (length > 255) {
|
||||
errorReporter.reportRestriction("length of operand can't exceed 255 words");
|
||||
length = 255; // to allow code generation to continue
|
||||
}
|
||||
|
||||
var nextInstr = new Instruction(op, register, length, operand);
|
||||
|
||||
var currentInstrAddr = nextInstrAddr;
|
||||
if (nextInstrAddr == Machine.PB) {
|
||||
errorReporter.reportRestriction("too many instructions for code segment");
|
||||
} else {
|
||||
Machine.code[nextInstrAddr++] = nextInstr;
|
||||
}
|
||||
return currentInstrAddr;
|
||||
|
||||
}
|
||||
|
||||
// Patches the d-field of the instruction at address addr with the next
|
||||
// instruction address.
|
||||
public void patch(int addr) {
|
||||
Machine.code[addr].setOperand(nextInstrAddr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the object program in the given object file.
|
||||
*
|
||||
* @param objectFile the object file
|
||||
*/
|
||||
public void saveObjectProgram(String objectFileName) {
|
||||
try (var objectFile = new FileOutputStream(objectFileName)) {
|
||||
var objectStream = new DataOutputStream(objectFile);
|
||||
for (var addr = Machine.CB; addr < nextInstrAddr; addr++) {
|
||||
Machine.code[addr].write(objectStream);
|
||||
}
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
System.err.println("Error opening object file: " + fnfe);
|
||||
} catch (IOException ioe) {
|
||||
System.err.println("Error writing object file: " + ioe);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user