Ejemplo n.º 1
0
 /**
  * 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);
   }
 }
Ejemplo n.º 2
0
  /**
   * 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());
        }
      }
    }
  }