/**
* Fifth pass, produce Java byte code.
*/
public void byte_code(ClassGen class_gen, ConstantPoolGen cp) {
MethodGen method=null;
boolean main=false, ignore=false;
String class_name = class_gen.getClassName();
String fname = name.getName();
InstructionList il = new InstructionList();
Type[] args = { new ArrayType(Type.STRING, 1) }; // default for `main'
String[] arg_names = { "$argv" };
if(fname.equals("main")) {
method = new MethodGen(ACC_STATIC | ACC_PUBLIC,
Type.VOID, args, arg_names,
"main", class_name, il, cp);
main = true;
} else if(fname.equals("READ") || fname.equals("WRITE")) { // Do nothing
ignore = true;
} else {
int size = argv.length;
arg_names = new String[size];
args = new Type[size];
for(int i = 0; i < size; i++) {
args[i] = Type.INT;
arg_names[i] = argv[i].getName();
}
method = new MethodGen(ACC_STATIC | ACC_PRIVATE | ACC_FINAL,
Type.INT, args, arg_names,
fname, class_name, il, cp);
LocalVariableGen[] lv = method.getLocalVariables();
for(int i = 0; i < size; i++) {
Variable entry = (Variable)env.get(arg_names[i]);
entry.setLocalVariable(lv[i]);
}
method.addException("java.io.IOException");
}
if(!ignore) {
body.byte_code(il, method, cp);
if(main) {
ObjectType e_type = new ObjectType("java.lang.Exception");
InstructionHandle start = il.getStart(), end, handler, end_handler;
LocalVariableGen exc = method.addLocalVariable("$e",
e_type,
null, null);
int slot = exc.getIndex();
il.append(InstructionConstants.POP); pop(); // Remove last element on stack
end = il.append(InstructionConstants.RETURN); // Use instruction constants, if possible
// catch
handler = il.append(new ASTORE(slot)); // save exception object
il.append(new GETSTATIC(cp.addFieldref("java.lang.System", "err",
"Ljava/io/PrintStream;")));
il.append(new ALOAD(slot)); push(2);
il.append(new INVOKEVIRTUAL(cp.addMethodref("java.io.PrintStream",
"println",
"(Ljava/lang/Object;)V")));
pop(2);
end_handler = il.append(InstructionConstants.RETURN);
method.addExceptionHandler(start, end, handler, e_type);
exc.setStart(handler); exc.setEnd(end_handler);
} else {
il.append(InstructionConstants.IRETURN); // Reuse object to save memory
}
method.removeNOPs(); // First optimization pass, provided by MethodGen
optimizeIFs(il); // Second optimization pass, application-specific
method.setMaxStack(max_size);
class_gen.addMethod(method.getMethod());
}
il.dispose(); // Dispose instruction handles for better memory utilization
reset();