Package org.renjin.gcc.translate

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

package org.renjin.gcc.translate;

import java.util.List;
import java.util.Set;

import org.renjin.gcc.gimple.type.GimpleFunctionType;
import org.renjin.gcc.gimple.type.GimpleType;
import org.renjin.gcc.jimple.JimpleClassBuilder;
import org.renjin.gcc.jimple.JimpleInterfaceBuilder;
import org.renjin.gcc.jimple.JimpleMethodBuilder;
import org.renjin.gcc.jimple.JimpleModifiers;
import org.renjin.gcc.jimple.JimpleType;
import org.renjin.gcc.translate.call.MethodRef;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.renjin.gcc.translate.type.ImFunctionType;

public class FunPtrTable {

  public static final String PACKAGE_NAME = "org.renjin.gcc.runtime";

  private Set<ImFunctionType> interfaces = Sets.newHashSet();
  private Set<MethodRef> invokers = Sets.newHashSet();

  private TranslationContext context;

  public FunPtrTable(TranslationContext context) {
    this.context = context;
  }

  public ImFunctionType resolveFunctionType(GimpleFunctionType type) {
    JimpleType returnType = context.resolveType(type.getReturnType()).returnType();
    List<JimpleType> paramTypes = Lists.newArrayList();
    for (GimpleType paramType : type.getArgumentTypes()) {
      paramTypes.add(context.resolveType(paramType).paramType());
    }
    return new ImFunctionType(returnType, paramTypes);
  }

  private String getInterfaceName(ImFunctionType signature) {
    if (!interfaces.contains(signature)) {
      addInterface(signature);
    }
    return PACKAGE_NAME + "." + signature.interfaceName();
  }

  public String getInterfaceName(MethodRef ref) {
    return getInterfaceName(new ImFunctionType(ref));
  }

  public String getInterfaceName(GimpleFunctionType type) {
    return getInterfaceName(resolveFunctionType(type));
  }

  public ImFunctionType methodRef(GimpleFunctionType type) {
    return resolveFunctionType(type);
  }

  private void addInterface(ImFunctionType signature) {
    JimpleInterfaceBuilder iface = context.getJimpleOutput().newInterface();
    iface.setPackageName(PACKAGE_NAME);
    iface.setClassName(signature.interfaceName());
    iface.extendsInterface("org.renjin.gcc.runtime.FunPtr");

    JimpleMethodBuilder applyMethod = iface.newMethod();
    applyMethod.setName("apply");
    applyMethod.setReturnType(signature.getReturnType());

    int paramIndex = 0;
    for (JimpleType paramType : signature.getParameterTypes()) {
      applyMethod.addParameter(paramType, "p" + paramIndex);
      paramIndex++;
    }

    interfaces.add(signature);
  }

  public String getInvokerClassName(MethodRef method) {
    String invokerName = invokerName(method);

    if (!invokers.contains(method)) {

      JimpleClassBuilder invokerClass = context.getJimpleOutput().newClass();
      invokerClass.setClassName(invokerName);
      invokerClass.addInterface(getInterfaceName(method));

      JimpleMethodBuilder applyMethod = invokerClass.newMethod();
      applyMethod.setModifiers(JimpleModifiers.PUBLIC);
      applyMethod.setName("apply");
      applyMethod.setReturnType(method.getReturnType());

      int paramIndex = 0;
      for (JimpleType type : method.getParameterTypes()) {
        applyMethod.addParameter(type, "p" + paramIndex);
        paramIndex++;
      }

      StringBuilder call = new StringBuilder();
      call.append("staticinvoke ").append(method.signature()).append("(");
      for (paramIndex = 0; paramIndex != method.getParameterTypes().size(); ++paramIndex) {
        if (paramIndex > 0) {
          call.append(", ");
        }
        call.append("p").append(paramIndex);
      }
      call.append(")");

      if (method.getReturnType().toString().equals("void")) {
        applyMethod.addStatement(call.toString());
        applyMethod.addStatement("return");
      } else {
        applyMethod.addVarDecl(method.getReturnType(), "_retval");
        applyMethod.addStatement("_retval = " + call.toString());
        applyMethod.addStatement("return _retval");
      }
    }
    return invokerName;
  }

  private String invokerName(MethodRef method) {
    return method.getClassName() + "$" + method.getMethodName() + "$" + new ImFunctionType(method).interfaceName();
  }
}
TOP

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

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.