/** * This is the starting point of the compiler. * * @param args Command line arguments to control the compiler */ public static void main(String[] args) { try { run(args); } catch (FileNotFoundException e) { System.err.println("FILE NOT FOUND: " + e.getLocalizedMessage()); System.exit(FILE_NOT_FOUND_ERROR); } catch (ParseException e) { System.err.println("PARSE ERROR: " + e.getLocalizedMessage()); System.exit(PARSE_ERROR); } catch (ShadowException e) { System.err.println("ERROR IN FILE: " + e.getLocalizedMessage()); e.printStackTrace(); System.exit(TYPE_CHECK_ERROR); } catch (IOException e) { System.err.println("FILE DEPENDENCY ERROR: " + e.getLocalizedMessage()); e.printStackTrace(); System.exit(TYPE_CHECK_ERROR); } catch (org.apache.commons.cli.ParseException e) { System.err.println("COMMAND LINE ERROR: " + e.getLocalizedMessage()); Arguments.printHelp(); System.exit(COMMAND_LINE_ERROR); } catch (ConfigurationException e) { System.err.println("CONFIGURATION ERROR: " + e.getLocalizedMessage()); Arguments.printHelp(); System.exit(CONFIGURATION_ERROR); } catch (TypeCheckException e) { System.err.println("TYPE CHECK ERROR: " + e.getLocalizedMessage()); System.exit(TYPE_CHECK_ERROR); } catch (CompileException e) { System.err.println("COMPILATION ERROR: " + e.getLocalizedMessage()); System.exit(COMPILE_ERROR); } }
/** * Ensures that LLVM code exists for all dependencies of a main-method- containing class/file.This * involves either finding an existing .ll file (which has been updated more recently than the * corresponding source file or building a new one * * @throws CompileException */ private static void generateLLVM( List<String> linkCommand, Set<String> generics, Set<String> arrays) throws IOException, ShadowException, ParseException, ConfigurationException, TypeCheckException, CompileException { Type.clearTypes(); Path mainFile = currentJob.getMainFile(); String mainFileName = stripExt(mainFile.toString()); List<Node> nodes; try { nodes = TypeChecker.typeCheck(mainFile.toFile(), currentJob.isForceRecompile()); } catch (TypeCheckException e) { logger.error(mainFile + " FAILED TO TYPE CHECK"); throw e; } if (!currentJob.isCheckOnly()) { for (Node node : nodes) { File file = node.getFile(); String name = stripExt(file.getName()); String path = stripExt(file.getCanonicalPath()); File llvmFile = new File(path + ".ll"); Type type = node.getType(); // set data for main class if (path.equals(mainFileName)) { mainClass = type.toString(Type.MANGLE); SequenceType arguments = new SequenceType(new ArrayType(Type.STRING)); if (type.getMatchingMethod("main", arguments) != null) mainArguments = true; else if (type.getMatchingMethod("main", new SequenceType()) != null) mainArguments = false; else throw new ShadowException( "File " + file.getPath() + " does not contain an appropriate main() method"); } // if the LLVM didn't exist, the full .shadow file would have been used if (file.getPath().endsWith(".meta")) { logger.info("Using pre-existing LLVM code for " + name); addToLink(node.getType(), file, linkCommand); LLVMOutput.readGenericAndArrayClasses(llvmFile, generics, arrays); } else { logger.info("Generating LLVM code for " + name); // gets top level class TACModule module = new TACBuilder().build(node); logger.debug(module.toString()); // Write to file String className = typeToFileName(type); llvmFile = new File(file.getParentFile(), className + ".ll"); File nativeFile = new File(file.getParentFile(), className + ".native.ll"); LLVMOutput output = new LLVMOutput(llvmFile); try { output.build(module); } catch (ShadowException e) { logger.error(file + " FAILED TO COMPILE"); output.close(); if (llvmFile.exists()) llvmFile.delete(); throw new CompileException(e.getMessage()); } if (llvmFile.exists()) linkCommand.add(llvmFile.getCanonicalPath()); else throw new ShadowException("Failed to generate " + llvmFile.getPath()); if (nativeFile.exists()) linkCommand.add(nativeFile.getCanonicalPath()); // it's important to add generics after generating the LLVM, since more are made generics.addAll(output.getGenericClasses()); arrays.addAll(output.getArrayClasses()); } } } }