Пример #1
0
  public FunctionContext(
      TranslationContext translationContext,
      GimpleFunction gimpleFunction,
      JimpleMethodBuilder builder) {
    this.gimpleFunction = gimpleFunction;
    this.translationContext = translationContext;
    this.builder = builder;

    VarUsageInspector varUsage = new VarUsageInspector(gimpleFunction);

    for (GimpleVarDecl decl : gimpleFunction.getVariableDeclarations()) {
      Variable localVariable =
          translationContext
              .resolveType(decl.getType())
              .createLocalVariable(this, decl.getName(), varUsage.getUsage(decl.getId()));

      symbolTable.put(decl.getId(), localVariable);
    }

    for (GimpleParameter param : gimpleFunction.getParameters()) {
      ImType type = translationContext.resolveType(param.getType());
      builder.addParameter(type.paramType(), "p_" + param.getName());
      ImExpr paramExpr =
          JvmExprs.toExpr(this, new JimpleExpr("p_" + param.getName()), type.paramType(), true);

      Variable variable =
          type.createLocalVariable(this, param.getName(), varUsage.getUsage(param.getId()));
      variable.writeAssignment(this, paramExpr);

      symbolTable.put(param.getId(), variable);
    }
  }
Пример #2
0
 static JsExpression getRTTClassId(
     TranslationContext translationContext, ClassElement classElement) {
   JsName classJsName = translationContext.getNames().getName(classElement);
   JsProgram program = translationContext.getProgram();
   JsStringLiteral clsid = program.getStringLiteral(classJsName.getShortIdent());
   return call(null, nameref(null, "$cls"), clsid);
 }
Пример #3
0
  private JsExpression generateRawInterfaceTypeComparison(
      JsExpression lhs, DartTypeNode typeNode, SourceInfo src) {
    ClassElement element = (ClassElement) typeNode.getType().getElement();
    if (element.equals(typeProvider.getObjectType().getElement())) {
      // Everything is an object, including null
      return this.translationContext.getProgram().getTrueLiteral();
    }
    String builtin = builtInTypeChecks.get(element);
    if (builtin != null) {
      return call(src, nameref(src, builtin), lhs);
    }

    // Due to implementing implied interfaces of classes, we always have to
    // use $implements$ rather than using JS instanceof for classes.

    // Inject: !!(tmp = target, tmp && tmp.$implements$type)
    JsProgram program = translationContext.getProgram();
    JsName tmp = context.createTemporary();
    String mangledClass = translationContext.getMangler().mangleClassName(element);
    return not(
        src,
        not(
            src,
            comma(
                src,
                assign(src, tmp.makeRef(), lhs),
                and(
                    src,
                    neq(src, tmp.makeRef().setSourceRef(src), program.getNullLiteral()),
                    nameref(src, tmp, "$implements$" + mangledClass)))));
  }
Пример #4
0
  public ImExpr lookupVar(GimpleExpr gimpleExpr) {
    if (gimpleExpr instanceof SymbolRef) {
      SymbolRef symbol = (SymbolRef) gimpleExpr;
      ImExpr variable = symbolTable.get(symbol.getId());

      if (variable != null) {
        return variable;
      }

      if (symbol.getName() != null) {
        variable = translationContext.findGlobal(symbol.getName());
      }

      if (variable == null) {
        throw new IllegalArgumentException(
            "No such variable '" + gimpleExpr + "' (id=" + symbol.getId() + ")");
      }
      return variable;
    } else {
      throw new UnsupportedOperationException(
          "Expected GimpleVar, got: "
              + gimpleExpr
              + " ["
              + gimpleExpr.getClass().getSimpleName()
              + "]");
    }
  }
Пример #5
0
  public ImExpr resolveExpr(GimpleExpr gimpleExpr) {
    if (gimpleExpr instanceof GimpleMemRef) {
      return resolveExpr(((GimpleMemRef) gimpleExpr).getPointer()).memref();
    } else if (gimpleExpr instanceof SymbolRef) {
      return lookupVar(gimpleExpr);

    } else if (gimpleExpr instanceof GimpleStringConstant) {
      return new ImStringConstant((GimpleStringConstant) gimpleExpr);

    } else if (gimpleExpr instanceof GimpleConstant) {
      return new ImPrimitiveConstant(this, (GimpleConstant) gimpleExpr);

    } else if (gimpleExpr instanceof GimpleAddressOf) {
      return resolveExpr(((GimpleAddressOf) gimpleExpr).getValue()).addressOf();

    } else if (gimpleExpr instanceof GimpleFunctionRef) {
      return new ImFunctionExpr(
          translationContext.resolveMethod(((GimpleFunctionRef) gimpleExpr).getName()));

    } else if (gimpleExpr instanceof GimpleArrayRef) {
      GimpleArrayRef arrayRef = (GimpleArrayRef) gimpleExpr;
      return resolveExpr(arrayRef.getArray()).elementAt(resolveExpr(arrayRef.getIndex()));

    } else if (gimpleExpr instanceof GimpleComponentRef) {
      GimpleComponentRef componentRef = (GimpleComponentRef) gimpleExpr;
      return resolveExpr(componentRef.getValue()).member(componentRef.getMember());

    } else if (gimpleExpr instanceof GimpleConstantRef) {
      return resolveExpr(((GimpleConstantRef) gimpleExpr).getValue());
    }
    throw new UnsupportedOperationException(gimpleExpr.toString());
  }
Пример #6
0
 private void injectInterfaceMarkers(ClassElement classElement, SourceInfo srcRef) {
   JsProgram program = translationContext.getProgram();
   JsName classJsName = translationContext.getNames().getName(classElement);
   for (InterfaceType iface : getAllInterfaces(classElement)) {
     JsStatement assignment =
         (JsStatement)
             newAssignment(
                     newNameRef(
                         newNameRef(new JsNameRef(classJsName), "prototype"),
                         "$implements$"
                             + translationContext
                                 .getMangler()
                                 .mangleClassName(iface.getElement())),
                     program.getNumberLiteral(1))
                 .makeStmt()
                 .setSourceRef(srcRef);
     globalBlock.getStatements().add(assignment);
   }
 }
Пример #7
0
 RuntimeTypeInjector(
     TraversalContextProvider context,
     CoreTypeProvider typeProvider,
     TranslationContext translationContext,
     boolean emitTypeChecks) {
   this.context = context;
   this.translationContext = translationContext;
   JsProgram program = translationContext.getProgram();
   this.globalBlock = program.getGlobalBlock();
   this.globalScope = program.getScope();
   this.builtInTypeChecks = makeBuiltinTypes(typeProvider);
   this.typeProvider = typeProvider;
   this.emitTypeChecks = emitTypeChecks;
 }
Пример #8
0
  /** @return a JsArrayLiteral listing the type arguments for the interface instance. */
  private JsExpression buildTypeArgsForFactory(
      FunctionType functionType,
      InterfaceType instanceType,
      List<? extends Type> listTypeVars,
      JsExpression contextTypeArgs) {
    if (functionType.getTypeVariables().size() == 0) {
      return null;
    }

    if (instanceType.hasDynamicTypeArgs()) {
      return translationContext.getProgram().getNullLiteral();
    }

    JsArrayLiteral arr = new JsArrayLiteral();
    for (Type type : instanceType.getArguments()) {
      JsExpression typeExpr = buildTypeLookupExpression(type, listTypeVars, contextTypeArgs);
      arr.getExpressions().add(typeExpr);
    }

    return arr;
  }
Пример #9
0
  /** @return a JsArrayLiteral listing the type arguments for the interface instance. */
  private JsExpression buildTypeArgs(
      InterfaceType instanceType, List<? extends Type> listTypeVars, JsExpression contextTypeArgs) {
    ClassElement classElement = instanceType.getElement();
    if (!hasTypeParameters(classElement)) {
      return null;
    }

    if (instanceType.hasDynamicTypeArgs()) {
      JsProgram program = translationContext.getProgram();
      return program.getNullLiteral();
    }

    JsArrayLiteral arr = new JsArrayLiteral();
    assert instanceType.getArguments().size() > 0;
    for (Type type : instanceType.getArguments()) {
      JsExpression typeExpr = buildTypeLookupExpression(type, listTypeVars, contextTypeArgs);
      arr.getExpressions().add(typeExpr);
    }

    return arr;
  }
Пример #10
0
  /** @return js The expression used to lookup the RTT for the given type. */
  private JsExpression buildTypeLookupExpression(
      Type type, List<? extends Type> list, JsExpression contextTypeArgs) {
    switch (TypeKind.of(type)) {
      case INTERFACE:
        InterfaceType interfaceType = (InterfaceType) type;
        JsInvocation callLookup = call(null, getRTTLookupMethodName(interfaceType.getElement()));
        if (hasTypeParameters(interfaceType.getElement()) && !interfaceType.hasDynamicTypeArgs()) {
          JsArrayLiteral typeArgs = new JsArrayLiteral();
          for (Type arg : interfaceType.getArguments()) {
            typeArgs.getExpressions().add(buildTypeLookupExpression(arg, list, contextTypeArgs));
          }
          callLookup.getArguments().add(typeArgs);
        }
        return callLookup;

      case FUNCTION_ALIAS:
        // TODO(johnlenz): implement this
        return newQualifiedNameRef("RTT.placeholderType");

      case VARIABLE:
        TypeVariable var = (TypeVariable) type;
        JsProgram program = translationContext.getProgram();
        int varIndex = 0;
        for (Type t : list) {
          if (t.equals(type)) {
            return call(
                null,
                newQualifiedNameRef("RTT.getTypeArg"),
                Cloner.clone(contextTypeArgs),
                program.getNumberLiteral(varIndex));
          }
          varIndex++;
        }
        throw new AssertionError("unresolved type variable:" + var);

      default:
        throw new AssertionError("unexpected type kind:" + type.getKind());
    }
  }
Пример #11
0
  private void generateRTTLookupMethod(DartClass x) {
    ClassElement classElement = x.getSymbol();
    boolean hasTypeParams = hasTypeParameters(classElement);

    // 1) create static type information construction function
    // function Foo$lookupOrCreateRTT(typeargs) {
    //   return $createRTT(name, Foo$RTTimplements, typeargs) ;
    // }

    // Build the function
    JsFunction lookupFn = new JsFunction(globalScope);
    lookupFn.setBody(new JsBlock());
    List<JsStatement> body = lookupFn.getBody().getStatements();
    JsScope scope = new JsScope(globalScope, "temp");

    JsProgram program = translationContext.getProgram();

    JsInvocation invokeCreate =
        call(null, newQualifiedNameRef("RTT.create"), getRTTClassId(classElement));
    List<JsExpression> callArgs = invokeCreate.getArguments();
    if (hasRTTImplements(classElement)) {
      callArgs.add(getRTTImplementsMethodName(classElement));
    } else if (hasTypeParams) {
      // need a placeholder param if the typeArgs are needed.
      callArgs.add(program.getNullLiteral());
    }

    if (hasTypeParams) {
      JsName typeArgs = scope.declareName("typeArgs");
      lookupFn.getParameters().add(new JsParameter(typeArgs));
      callArgs.add(typeArgs.makeRef());
    }

    body.add(new JsReturn(invokeCreate));

    // Finally, Add the function
    JsExpression fnDecl = assign(null, getRTTLookupMethodName(classElement), lookupFn);
    globalBlock.getStatements().add(fnDecl.makeStmt());
  }
Пример #12
0
 /** @return an expression that implements a runtime "is" operation */
 JsExpression generateInstanceOfComparison(
     ClassElement enclosingClass, JsExpression lhs, DartTypeNode typeNode, SourceInfo src) {
   ClassElement currentClass = enclosingClass;
   Type type = typeNode.getType();
   switch (TypeKind.of(type)) {
     case INTERFACE:
       InterfaceType interfaceType = (InterfaceType) type;
       if (hasTypeParameters(interfaceType.getElement()) && !interfaceType.hasDynamicTypeArgs()) {
         return generateRefiedInterfaceTypeComparison(lhs, interfaceType, currentClass, src);
       } else {
         // TODO(johnlenz): special case "is Object"?
         return generateRawInterfaceTypeComparison(lhs, typeNode, src);
       }
     case VARIABLE:
       TypeVariable typeVar = (TypeVariable) type;
       return generateRefiedTypeVariableComparison(lhs, typeVar, currentClass, src);
     case DYNAMIC:
       JsProgram program = translationContext.getProgram();
       return program.getTrueLiteral();
     default:
       throw new IllegalStateException("unexpected");
   }
 }
Пример #13
0
 public MethodRef resolveMethod(GimpleCall call) {
   return translationContext.resolveMethod(call, getCallingConvention());
 }
Пример #14
0
 private JsNameRef getRTTAddToMethodName(ClassElement classElement) {
   return nameref(null, translationContext.getNames().getName(classElement), "$addTo");
 }
Пример #15
0
 private JsNameRef getRTTImplementsMethodName(ClassElement classElement) {
   return nameref(null, translationContext.getNames().getName(classElement), "$RTTimplements");
 }
Пример #16
0
 private JsNameRef getRTTLookupMethodName(ClassElement classElement) {
   return nameref(null, translationContext.getNames().getName(classElement), "$lookupRTT");
 }