Package org.renjin.gcc.translate

Source Code of org.renjin.gcc.translate.TranslationContext

package org.renjin.gcc.translate;

import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.renjin.gcc.gimple.*;
import org.renjin.gcc.gimple.expr.GimpleAddressOf;
import org.renjin.gcc.gimple.expr.GimpleExpr;
import org.renjin.gcc.gimple.expr.GimpleFunctionRef;
import org.renjin.gcc.gimple.ins.GimpleCall;
import org.renjin.gcc.gimple.type.*;
import org.renjin.gcc.jimple.JimpleClassBuilder;
import org.renjin.gcc.jimple.JimpleOutput;
import org.renjin.gcc.jimple.JimpleType;
import org.renjin.gcc.jimple.SyntheticJimpleType;
import org.renjin.gcc.translate.call.*;
import org.renjin.gcc.translate.expr.ImExpr;
import org.renjin.gcc.translate.field.PrimitiveFieldExpr;
import org.renjin.gcc.translate.type.ImPrimitiveType;
import org.renjin.gcc.translate.type.ImType;
import org.renjin.gcc.translate.type.ImVoidType;
import org.renjin.gcc.translate.type.struct.ImRecordType;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;

public class TranslationContext {
  private JimpleClassBuilder mainClass;
  private MethodTable methodTable;
  private List<GimpleFunction> functions = Lists.newArrayList();
  private FunPtrTable funPtrTable;
  private RecordTypeTable recordTypeTable;
  private Map<String, ImExpr> globalVariables = Maps.newHashMap();
 
  private List<CallTranslator> builtinCallTranslators = Lists.newArrayList();

  public TranslationContext(JimpleClassBuilder mainClass, MethodTable methodTable,
                            Map<String, ImRecordType> providedRecordTypes,
                            List<GimpleCompilationUnit> units) {
    this.mainClass = mainClass;
    this.methodTable = methodTable;
    this.funPtrTable = new FunPtrTable(this);

    this.recordTypeTable = new RecordTypeTable(units, this, providedRecordTypes);

    for(GimpleCompilationUnit unit : units) {
      functions.addAll(unit.getFunctions());
      for(GimpleVarDecl varDecl : unit.getGlobalVariables()) {
        translateGlobalVarDecl(varDecl);
      }
    }
   
    builtinCallTranslators.add(new MallocCallTranslator("malloc"));
    builtinCallTranslators.add(new MallocCallTranslator("__builtin_malloc"));
    builtinCallTranslators.add(new NullCallTranslator("__builtin_free"));
    builtinCallTranslators.add(FunPtrCallTranslator.INSTANCE);
    builtinCallTranslators.add(StaticCallTranslator.INSTANCE);

  }

  public RecordTypeTable getRecordTypeTable() {
    return recordTypeTable;
  }

  private void translateGlobalVarDecl(GimpleVarDecl varDecl) {
  
    try {
     
      ImType type = resolveType(varDecl.getType());
 
      type.defineField(mainClass, varDecl.getName(), false);

      globalVariables.put(varDecl.getName(), type.createFieldExpr(
          null, new SyntheticJimpleType(mainClass.getFqcn()),
          varDecl.getName()));
     
    } catch(Exception e) {
      throw new RuntimeException("Exception translating global variable '" + varDecl.getName() + "'", e);
    }
  }

  public JimpleClassBuilder getMainClass() {
    return mainClass;
  }

  public MethodRef resolveMethod(String name) {
    MethodRef ref = resolveInternally(name);
    if (ref != null) {
      return ref;
    }
    return methodTable.resolve(name);
  }

  public MethodRef resolveMethod(GimpleCall call, CallingConvention callingConvention) {

    return resolveMethod(callingConvention.mangleFunctionName(functionName(call)));
  }

  private String functionName(GimpleCall call) {
    if (call.getFunction() instanceof GimpleAddressOf) {
     
      GimpleExpr functionValue = ((GimpleAddressOf) call.getFunction()).getValue();
      if(functionValue instanceof GimpleFunctionRef) {
        return ((GimpleFunctionRef) functionValue).getName();
      }
    }
    throw new UnsupportedOperationException(call.toString());
  }

  private MethodRef resolveInternally(String name) {
    for (GimpleFunction function : functions) {
      if (function.getMangledName().equals(name)) {
        return asRef(function);
      }
    }
    return null;
  }

  private MethodRef asRef(GimpleFunction function) {
   
    JimpleType returnType;
    if(function.getReturnType() instanceof GimpleVoidType) {
      returnType = JimpleType.VOID;
    } else {
      returnType = resolveType(function.getReturnType()).returnType();
    }
    List<JimpleType> paramTypes = Lists.newArrayList();
    for (GimpleParameter param : function.getParameters()) {
      paramTypes.add(resolveType(param.getType()).paramType());
    }
    return new GccFunction(mainClass.getFqcn(), function.getMangledName(), returnType, paramTypes);
  }

  public ImExpr findGlobal(String name) {
    if(globalVariables.containsKey(name)) {
      return globalVariables.get(name);
    }
    Field field = methodTable.findGlobal(name);
    if(field != null) {
      return new PrimitiveFieldExpr(field);
    }
    return null;
  }

  public ImType resolveType(GimpleType type) {
    if (type instanceof GimplePrimitiveType) {
      return ImPrimitiveType.valueOf(type);

    } else if (type instanceof GimpleRecordType) {
      return resolveRecordType((GimpleRecordType) type);

    } else if(type instanceof GimpleFunctionType) {
      return funPtrTable.resolveFunctionType((GimpleFunctionType) type);

    } else if (type instanceof GimpleIndirectType) {
      return resolveType(type.getBaseType()).pointerType();

    } else if (type instanceof GimpleArrayType) {
      GimpleArrayType arrayType = (GimpleArrayType) type;
      return resolveType(arrayType.getComponentType()).arrayType(
          arrayType.getLbound(), arrayType.getUbound());

    } else if (type instanceof GimpleVoidType) {
      return ImVoidType.INSTANCE;
    }
    throw new UnsupportedOperationException(type.toString());
  }

  public JimpleOutput getJimpleOutput() {
    return mainClass.getOutput();
  }

  public String getInvokerClass(MethodRef method) {
    return funPtrTable.getInvokerClassName(method);
  }

  public List<GimpleFunction> getFunctions() {
    return functions;
  }

  public ImRecordType resolveRecordType(GimpleRecordType recordType) {
    return recordTypeTable.resolveStruct(recordType);
  }

  public JimpleType getInvokerType(MethodRef method) {
    return new SyntheticJimpleType(getInvokerClass(method));
  }

  public CallTranslator getCallTranslator(GimpleCall call) {
    for(CallTranslator translator : Iterables.concat(methodTable.getCallTranslators(), builtinCallTranslators)) {
      if(translator.accept(call)) {
        return translator;
      }
    }
    throw new UnsupportedOperationException("No matching call translator");
  }

 
}
TOP

Related Classes of org.renjin.gcc.translate.TranslationContext

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.