X-Git-Url: http://git.megacz.com/?p=nestedvm.git;a=blobdiff_plain;f=src%2Forg%2Fibex%2Fnestedvm%2FCompiler.java;h=acf1c48d689ba30b7543e33c5026b7315e0966e1;hp=ebdf29d30489739597e97acd33f4bf0edb58b482;hb=b11e7c6c29f2b5f7b0828bf93eb741c4a30ec411;hpb=98f786ce8ee1fcd9568d1c367160851d32e1c786 diff --git a/src/org/ibex/nestedvm/Compiler.java b/src/org/ibex/nestedvm/Compiler.java index ebdf29d..acf1c48 100644 --- a/src/org/ibex/nestedvm/Compiler.java +++ b/src/org/ibex/nestedvm/Compiler.java @@ -1,4 +1,6 @@ -// Copyright 2003 Adam Megacz, see the COPYING file for licensing [GPL] +// Copyright 2000-2005 the Contributors, as shown in the revision logs. +// Licensed under the Apache License 2.0 ("the License"). +// You may not use this file except in compliance with the License. package org.ibex.nestedvm; @@ -7,38 +9,36 @@ import java.io.*; import org.ibex.nestedvm.util.*; -// FEATURE: -d option for classfilecompiler (just like javac's -d) - public abstract class Compiler implements Registers { /** The ELF binary being read */ - protected ELF elf; + ELF elf; /** The name of the class beging generated */ - protected final String fullClassName; + final String fullClassName; /** The name of the binary this class is begin generated from */ - protected String source = "unknown.mips.binary"; + String source = "unknown.mips.binary"; public void setSource(String source) { this.source = source; } /** Thrown when the compilation fails for some reason */ - protected static class Exn extends Exception { public Exn(String s) { super(s); } } + static class Exn extends Exception { public Exn(String s) { super(s); } } // Set this to true to enable fast memory access // When this is enabled a Java RuntimeException will be thrown when a page fault occures. When it is disabled // a FaultException will be throw which is easier to catch and deal with, however. as the name implies, this is slower - protected boolean fastMem = true; + boolean fastMem = true; // This MUST be a power of two. If it is not horrible things will happen // NOTE: This value can be much higher without breaking the classfile // specs (around 1024) but Hotstop seems to do much better with smaller // methods. - protected int maxInsnPerMethod = 128; + int maxInsnPerMethod = 128; // non-configurable - protected int maxBytesPerMethod; - protected int methodMask; - protected int methodShift; - protected void maxInsnPerMethodInit() throws Exn { + int maxBytesPerMethod; + int methodMask; + int methodShift; + void maxInsnPerMethodInit() throws Exn { if((maxInsnPerMethod&(maxInsnPerMethod-1)) != 0) throw new Exn("maxBytesPerMethod is not a power of two"); maxBytesPerMethod = maxInsnPerMethod*4; methodMask = ~(maxBytesPerMethod-1); @@ -46,44 +46,46 @@ public abstract class Compiler implements Registers { } // True to try to determine which case statement are needed and only include them - protected boolean pruneCases = true; + boolean pruneCases = true; - protected boolean assumeTailCalls = true; + boolean assumeTailCalls = true; // True to insert some code in the output to help diagnore compiler problems - protected boolean debugCompiler = false; + boolean debugCompiler = false; // True to print various statistics about the compilation - protected boolean printStats = false; + boolean printStats = false; // True to generate runtime statistics that slow execution down significantly - protected boolean runtimeStats = false; + boolean runtimeStats = false; + + boolean supportCall = true; - protected boolean supportCall = true; + boolean nullPointerCheck = false; - protected boolean nullPointerCheck = false; + String runtimeClass = "org.ibex.nestedvm.Runtime"; - protected String runtimeClass = "org.ibex.nestedvm.Runtime"; + String hashClass = "java.util.Hashtable"; - protected String hashClass = "java.util.Hashtable"; + boolean unixRuntime; - protected boolean unixRuntime; + boolean lessConstants; - protected boolean lessConstants = false; + boolean singleFloat; - protected int pageSize = 4096; - protected int totalPages = 65536; - protected int pageShift; - protected boolean onePage; + int pageSize = 4096; + int totalPages = 65536; + int pageShift; + boolean onePage; - protected void pageSizeInit() throws Exn { + void pageSizeInit() throws Exn { if((pageSize&(pageSize-1)) != 0) throw new Exn("pageSize not a multiple of two"); if((totalPages&(totalPages-1)) != 0) throw new Exn("totalPages not a multiple of two"); while(pageSize>>>pageShift != 1) pageShift++; } /** A set of all addresses that can be jumped too (only available if pruneCases == true) */ - protected Set jumpableAddresses; + Hashtable jumpableAddresses; /** Some important symbols */ ELF.Symbol userInfo, gp; @@ -99,6 +101,7 @@ public abstract class Compiler implements Registers { public static void main(String[] args) throws IOException { String outfile = null; + String outdir = null; String o = null; String className = null; String mipsBinaryFileName = null; @@ -110,6 +113,10 @@ public abstract class Compiler implements Registers { arg++; if(arg==args.length) usage(); outfile = args[arg]; + } else if(args[arg].equals("-d")) { + arg++; + if(arg==args.length) usage(); + outdir = args[arg]; } else if(args[arg].equals("-outformat")) { arg++; if(arg==args.length) usage(); @@ -140,12 +147,20 @@ public abstract class Compiler implements Registers { OutputStream os = null; Compiler comp = null; if(outformat == null || outformat.equals("class")) { - if(outfile == null) { + if(outfile != null) { + os = new FileOutputStream(outfile); + comp = new ClassFileCompiler(mipsBinary,className,os); + } else if(outdir != null) { + File f = new File(outdir); + if(!f.isDirectory()) { + System.err.println(outdir + " doesn't exist or is not a directory"); + System.exit(1); + } + comp = new ClassFileCompiler(mipsBinary,className,f); + } else { System.err.println("Refusing to write a classfile to stdout - use -outfile foo.class"); System.exit(1); } - os = new FileOutputStream(outfile); - comp = new ClassFileCompiler(mipsBinary,className,os); } else if(outformat.equals("javasource") || outformat .equals("java")) { w = outfile == null ? new OutputStreamWriter(System.out): new FileWriter(outfile); comp = new JavaSourceCompiler(mipsBinary,className,w); @@ -179,12 +194,12 @@ public abstract class Compiler implements Registers { this.fullClassName = fullClassName; elf = new ELF(binary); - if(elf.header.type != ELF.ELFHeader.ET_EXEC) throw new IOException("Binary is not an executable"); - if(elf.header.machine != ELF.ELFHeader.EM_MIPS) throw new IOException("Binary is not for the MIPS I Architecture"); - if(elf.ident.data != ELF.ELFIdent.ELFDATA2MSB) throw new IOException("Binary is not big endian"); + if(elf.header.type != ELF.ET_EXEC) throw new IOException("Binary is not an executable"); + if(elf.header.machine != ELF.EM_MIPS) throw new IOException("Binary is not for the MIPS I Architecture"); + if(elf.ident.data != ELF.ELFDATA2MSB) throw new IOException("Binary is not big endian"); } - protected abstract void _go() throws Exn, IOException; + abstract void _go() throws Exn, IOException; private boolean used; public void go() throws Exn, IOException { @@ -211,9 +226,9 @@ public abstract class Compiler implements Registers { if(pruneCases) { // Find all possible branches - jumpableAddresses = new HashSet(); + jumpableAddresses = new Hashtable(); - jumpableAddresses.add(new Integer(elf.header.entry)); + jumpableAddresses.put(new Integer(elf.header.entry),Boolean.TRUE); ELF.SHeader text = elf.sectionWithName(".text"); if(text == null) throw new Exn("No .text segment"); @@ -236,7 +251,7 @@ public abstract class Compiler implements Registers { for(int i=0;i= base && t < base+size) { - if(jumps.add(new Integer(t))) { + if(jumps.put(new Integer(t),Boolean.TRUE) == null) { //System.err.println("Possible jump to " + toHex(t) + " (" + inter.sourceLine(t) + ") from " + toHex(pc) + " (" + inter.sourceLine(pc) + ")"); n++; } @@ -336,7 +351,7 @@ public abstract class Compiler implements Registers { case 17: // FPU Instructions switch(rs) { case 8: // BC1F, BC1T - if(jumps.add(new Integer(pc+branchTarget*4+4))) n++; + if(jumps.put(new Integer(pc+branchTarget*4+4),Boolean.TRUE) == null) n++; break; } break; @@ -346,13 +361,13 @@ public abstract class Compiler implements Registers { if(printStats) System.err.println("Found " + n + " additional possible branch targets in Text segment"); } - private void findBranchesInData(DataInputStream dis, int size, Set jumps, int textStart, int textEnd) throws IOException { + private void findBranchesInData(DataInputStream dis, int size, Hashtable jumps, int textStart, int textEnd) throws IOException { int count = size/4; int n=0; for(int i=0;i= textStart && word < textEnd) { - if(jumps.add(new Integer(word))) { + if(jumps.put(new Integer(word),Boolean.TRUE) == null) { //System.err.println("Added " + toHex(word) + " as possible branch target (fron data segment)"); n++; } @@ -363,8 +378,8 @@ public abstract class Compiler implements Registers { } // Helper functions for pretty output - protected final static String toHex(int n) { return "0x" + Long.toString(n & 0xffffffffL, 16); } - protected final static String toHex8(int n) { + final static String toHex(int n) { return "0x" + Long.toString(n & 0xffffffffL, 16); } + final static String toHex8(int n) { String s = Long.toString(n & 0xffffffffL, 16); StringBuffer sb = new StringBuffer("0x"); for(int i=8-s.length();i>0;i--) sb.append('0'); @@ -372,7 +387,7 @@ public abstract class Compiler implements Registers { return sb.toString(); } - protected final static String toOctal3(int n) { + final static String toOctal3(int n) { char[] buf = new char[3]; for(int i=2;i>=0;i--) { buf[i] = (char) ('0' + (n & 7)); @@ -388,7 +403,7 @@ public abstract class Compiler implements Registers { public void set(Object val) { if(field == null) return; try { - field.setAccessible(true); + /*field.setAccessible(true); NOT in JDK 1.1 */ field.set(Compiler.this,val); } catch(IllegalAccessException e) { System.err.println(e); @@ -397,7 +412,7 @@ public abstract class Compiler implements Registers { public Object get() { if(field == null) return null; try { - field.setAccessible(true); + /*field.setAccessible(true); NOT in JDK 1.1 */ return field.get(Compiler.this); } catch(IllegalAccessException e) { System.err.println(e); return null; @@ -423,7 +438,8 @@ public abstract class Compiler implements Registers { "pageSize", "The page size (must be a power of two)", "totalPages", "Total number of pages (total mem = pageSize*totalPages, must be a power of two)", "onePage", "One page hack (FIXME: document this better)", - "lessConstants", "Use less constants at the cost of speed (FIXME: document this better)" + "lessConstants", "Use less constants at the cost of speed (FIXME: document this better)", + "singleFloat", "Support single precision (32-bit) FP ops only" }; private Option getOption(String name) { @@ -512,7 +528,7 @@ public abstract class Compiler implements Registers { // This ugliness is to work around a gcj static linking bug (Bug 12908) // The best solution is to force gnu.java.locale.Calendar to be linked in but this'll do - protected static String dateTime() { + static String dateTime() { try { return new Date().toString(); } catch(RuntimeException e) {