Package org.renjin.gcc

Source Code of org.renjin.gcc.GimpleCompiler

package org.renjin.gcc;

import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.renjin.gcc.gimple.CallingConvention;
import org.renjin.gcc.gimple.CallingConventions;
import org.renjin.gcc.gimple.GimpleCompilationUnit;
import org.renjin.gcc.gimple.GimpleFunction;
import org.renjin.gcc.jimple.JimpleClassBuilder;
import org.renjin.gcc.jimple.JimpleOutput;
import org.renjin.gcc.translate.FunctionTranslator;
import org.renjin.gcc.translate.MethodTable;
import org.renjin.gcc.translate.TranslationContext;
import org.renjin.gcc.translate.type.struct.ImRecordType;
import org.renjin.gcc.translate.xform.FunctionBodyTransformer;
import org.renjin.gcc.translate.xform.VoidPointerTypeDeducer;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;

/**
* Compiles a set of Gimple functions to jvm class file
*
*/
public class GimpleCompiler  {

  private File jimpleOutputDirectory;

  private File outputDirectory;
 
  private String packageName;

  private String className;

  private boolean verbose;

  private List<File> classPaths = Lists.newArrayList();

  private static Logger LOGGER = Logger.getLogger(GimpleCompiler.class.getName());

  private MethodTable methodTable = new MethodTable();

  private Map<String, ImRecordType> providedTypes = Maps.newHashMap();

  private List<FunctionBodyTransformer> functionBodyTransformers = Lists.newArrayList();
 

  public GimpleCompiler() {
    functionBodyTransformers.add(VoidPointerTypeDeducer.INSTANCE);
  }

  public void setPackageName(String name) {
    this.packageName = name;
  }

  public void setJimpleOutputDirectory(File directory) {
    this.jimpleOutputDirectory = directory;
  }

  public void setOutputDirectory(File directory) {
    this.outputDirectory = directory;
  }

  public void setClassName(String className) {
    this.className = className;
  }

  public MethodTable getMethodTable() {
    return methodTable;
  }

  public void compile(List<GimpleCompilationUnit> units) throws Exception {

    File packageFolder = getPackageFolder();
    packageFolder.mkdirs();

    JimpleOutput output = translate(units);

    output.write(jimpleOutputDirectory);

    compileJimple(output.getClassNames());
  }

  public boolean isVerbose() {
    return verbose;
  }

  public void setVerbose(boolean verbose) {
    this.verbose = verbose;
  }

  public void addSootClassPaths(List<File> classPaths) {
    this.classPaths.addAll(classPaths);
  }

  private void compileJimple(Set<String> classNames) throws IOException, InterruptedException {
    List<String> options = Lists.newArrayList();
    if (verbose) {
      options.add("-v");
    }
    options.add("-pp");
    options.add("-cp");
    options.add(sootClassPath());
    options.add("-src-prec");
    options.add("jimple");
    options.add("-keep-line-number");
    options.add("-output-dir");
    options.add(outputDirectory.getAbsolutePath());
    options.addAll(classNames);

    LOGGER.info("Running Soot " + Joiner.on(" ").join(options));

    soot.G.reset();
    soot.Main.main(options.toArray(new String[0]));
  }
 
  public void provideType(String typeName, ImRecordType type) {
    providedTypes.put(typeName, type);
  }

  private String sootClassPath() {
    StringBuilder paths = new StringBuilder();
    paths.append(jimpleOutputDirectory.getAbsolutePath());
    for (File path : classPaths) {
      paths.append(File.pathSeparatorChar);
      paths.append(path.getAbsolutePath());
    }
    return paths.toString();
  }

  protected JimpleOutput translate(List<GimpleCompilationUnit> units) throws IOException {

    JimpleOutput jimple = new JimpleOutput();

    JimpleClassBuilder mainClass = jimple.newClass();
    mainClass.setClassName(className);
    mainClass.setPackageName(packageName);

    TranslationContext context = new TranslationContext(mainClass, methodTable, providedTypes, units);
    for(GimpleCompilationUnit unit : units) {
      for (GimpleFunction function : unit.getFunctions()) {
       
        transformFunctionBody(unit, function);
       
        FunctionTranslator translator = new FunctionTranslator(context);
        translator.translate(function);
      }
    }

    return jimple;
  }

  private void transformFunctionBody(GimpleCompilationUnit unit, GimpleFunction function) {
    boolean updated;
    do {
      updated = false;
      for(FunctionBodyTransformer transformer : functionBodyTransformers) {
        if(transformer.transform(unit, function)) {
          updated = true;
        }
      }
    } while(updated);
  }

  private File getPackageFolder() {
    return new File(outputDirectory, packageName.replace('.', File.separatorChar));
  }

}
TOP

Related Classes of org.renjin.gcc.GimpleCompiler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.