package de.fuberlin.projecta; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import de.fuberlin.projecta.lexer.io.FileCharStream; import de.fuberlin.projecta.lexer.io.ICharStream; import de.fuberlin.projecta.utils.StringUtils; /** * Runnable class for executing the complete frontend + LLC + GCC * * Main testing tool for projecta! * * Results in a runnable binary, which is executed immediately * @note You need to have 'llc' + 'gcc' in PATH */ public class CompilerMain { static final String LLC_EXE = "llc"; static final String GCC_EXE = "gcc"; public static void main(String[] args) { // action boolean printHelp = false; boolean readFromStdin = true; // read from stdin by default // parameters boolean verbose = false; String filePath = ""; for(int i = 0; i < args.length; i++) { if (args[i].equals("-f")) { readFromStdin = false; filePath = args[++i]; } else if (args[i].equals("-v")) { verbose = true; } else if (args[i].equals("-h")) { printHelp = true; } } // run if (printHelp) { printHelp(); return; } else if (readFromStdin) { System.out .println("Reading from stdin. Exit with new line and Ctrl+D."); ICharStream stream = StringUtils.readFromStdin(); run(stream, verbose); } else if (!filePath.isEmpty()) { System.out.println("Reading from file: " + filePath); FileCharStream stream = StringUtils.readFromFile(filePath); run(stream, verbose); } else { System.out.println("Wrong parameters."); } } private static void printHelp() { System.out.println("CompilerMain:"); System.out.println(" -h Show this help"); System.out.println(" -v Turn on debugging"); System.out.println(" -f FILE Read from file FILE"); } /** * Run the compiler frontend + backend * @param stream Character stream * @param verbose If true, print out debugging output * @return Output from running the binary */ public static String execute(ICharStream stream, boolean verbose) { final String code = FrontendMain.genCode(stream, verbose); if (code == null) { System.err.println("Code generation failed."); return null; } if (verbose) { System.err.println("\nGenerated code:"); System.err.println(code); } try { // write LLVM code to file File llvmFile = File.createTempFile("code", ".ll"); BufferedWriter writer = new BufferedWriter(new FileWriter(llvmFile)); writer.write(code); writer.close(); // call "llc" File assemblyFile = File.createTempFile("code", ".s"); { String[] command = { LLC_EXE, llvmFile.getCanonicalPath(), "-o", assemblyFile.getCanonicalPath() }; Process p = Runtime.getRuntime().exec(command); BufferedReader in = new BufferedReader(new InputStreamReader( p.getErrorStream())); String text; while ((text = in.readLine()) != null) { System.out.println(text); System.out.flush(); } } // call "gcc" File executableFile = File.createTempFile("code", ".bin"); executableFile.setExecutable(true); { String[] command = { GCC_EXE, assemblyFile.getCanonicalPath(), "-o", executableFile.getCanonicalPath() }; Process p = Runtime.getRuntime().exec(command); BufferedReader in = new BufferedReader(new InputStreamReader( p.getErrorStream())); String text; while ((text = in.readLine()) != null) { System.out.println(text); System.out.flush(); } } // call generated executable { String[] command = { executableFile.getCanonicalPath() }; System.err.println("Running " + executableFile.getCanonicalPath()); Process p = Runtime.getRuntime().exec(command); BufferedReader in = new BufferedReader(new InputStreamReader( p.getInputStream())); String result = ""; String text; while ((text = in.readLine()) != null) { result += text; } return result; } } catch (IOException e) { e.printStackTrace(); } return null; } static void run(ICharStream stream, boolean verbose) { String output = execute(stream, verbose); if (output != null) { System.out.println("\nOutput:"); System.out.println(output); } } }