Esempio n. 1
0
void storeTV(Vout& v, Vptr dst, Vloc srcLoc, const SSATmp* src) {
  auto const type = src->type();

  if (srcLoc.isFullSIMD()) {
    // The whole TV is stored in a single SIMD reg.
    assertx(RuntimeOption::EvalHHIRAllocSIMDRegs);
    v << storeups{srcLoc.reg(), dst};
    return;
  }

  if (type.needsReg()) {
    assertx(srcLoc.hasReg(1));
    v << storeb{srcLoc.reg(1), dst + TVOFF(m_type)};
  } else {
    v << storeb{v.cns(type.toDataType()), dst + TVOFF(m_type)};
  }

  // We ignore the values of statically nullish types.
  if (src->isA(TNull) || src->isA(TNullptr)) return;

  // Store the value.
  if (src->hasConstVal()) {
    // Skip potential zero-extend if we know the value.
    v << store{v.cns(src->rawVal()), dst + TVOFF(m_data)};
  } else {
    assertx(srcLoc.hasReg(0));
    auto const extended = zeroExtendIfBool(v, src->type(), srcLoc.reg(0));
    v << store{extended, dst + TVOFF(m_data)};
  }
}
Esempio n. 2
0
void
IRTranslator::translateLtGtOp(const NormalizedInstruction& i) {
  auto const op = i.op();
  assert(op == Op::Lt || op == Op::Lte || op == Op::Gt || op == Op::Gte);

  auto leftType = m_hhbcTrans.topType(1, DataTypeGeneric);
  auto rightType = m_hhbcTrans.topType(0, DataTypeGeneric);
  bool ok = equivDataTypes(leftType.toDataType(), rightType.toDataType()) &&
    leftType.subtypeOfAny(Type::Null, Type::Bool, Type::Int);

  HHIR_UNIMPLEMENTED_WHEN(!ok, LtGtOp);
  switch (op) {
    case Op::Lt  : HHIR_EMIT(Lt);
    case Op::Lte : HHIR_EMIT(Lte);
    case Op::Gt  : HHIR_EMIT(Gt);
    case Op::Gte : HHIR_EMIT(Gte);
    default    : HHIR_UNIMPLEMENTED(LtGtOp);
  }
}
Esempio n. 3
0
RuntimeType Type::toRuntimeType() const {
  assert(!isPtr());
  auto const outer = isBoxed() ? KindOfRef : toDataType();
  auto const inner = isBoxed() ? innerType().toDataType() : KindOfNone;
  auto rtt = RuntimeType{outer, inner};

  if (isSpecialized()) {
    if (subtypeOf(Type::Arr)) {
      return rtt.setArrayKind(getArrayKind());
    } else if (subtypeOf(Type::Obj)) {
      return rtt.setKnownClass(getClass());
    }
  }

  return rtt;
}
Esempio n. 4
0
void cgCallBuiltin(IRLS& env, const IRInstruction* inst) {
  auto const extra = inst->extra<CallBuiltin>();
  auto const callee = extra->callee;
  auto const returnType = inst->typeParam();
  auto const funcReturnType = callee->returnType();
  auto const returnByValue = callee->isReturnByValue();

  auto const dstData = dstLoc(env, inst, 0).reg(0);
  auto const dstType = dstLoc(env, inst, 0).reg(1);

  auto& v = vmain(env);

  // Whether `t' is passed in/out of C++ as String&/Array&/Object&.
  auto const isReqPtrRef = [] (MaybeDataType t) {
    return isStringType(t) || isArrayLikeType(t) ||
           t == KindOfObject || t == KindOfResource;
  };

  if (FixupMap::eagerRecord(callee)) {
    auto const sp = srcLoc(env, inst, 1).reg();
    auto const spOffset = cellsToBytes(extra->spOffset.offset);
    auto const& marker = inst->marker();
    auto const pc = marker.fixupSk().unit()->entry() + marker.fixupBcOff();

    auto const synced_sp = v.makeReg();
    v << lea{sp[spOffset], synced_sp};
    emitEagerSyncPoint(v, pc, rvmtl(), srcLoc(env, inst, 0).reg(), synced_sp);
  }

  int returnOffset = rds::kVmMInstrStateOff +
                     offsetof(MInstrState, tvBuiltinReturn);
  auto args = argGroup(env, inst);

  if (!returnByValue) {
    if (isBuiltinByRef(funcReturnType)) {
      if (isReqPtrRef(funcReturnType)) {
        returnOffset += TVOFF(m_data);
      }
      // Pass the address of tvBuiltinReturn to the native function as the
      // location where it can construct the return Array, String, Object, or
      // Variant.
      args.addr(rvmtl(), returnOffset);
      args.indirect();
    }
  }

  // The srcs past the first two (sp and fp) are the arguments to the callee.
  auto srcNum = uint32_t{2};

  // Add the this_ or self_ argument for HNI builtins.
  if (callee->isMethod()) {
    if (callee->isStatic()) {
      args.ssa(srcNum);
      ++srcNum;
    } else {
      // Note that we don't support objects with vtables here (if they may need
      // a $this pointer adjustment).  This should be filtered out during irgen
      // or before.
      args.ssa(srcNum);
      ++srcNum;
    }
  }

  // Add the func_num_args() value if needed.
  if (callee->attrs() & AttrNumArgs) {
    // If `numNonDefault' is negative, this is passed as an src.
    if (extra->numNonDefault >= 0) {
      args.imm((int64_t)extra->numNonDefault);
    } else {
      args.ssa(srcNum);
      ++srcNum;
    }
  }

  // Add the positional arguments.
  for (uint32_t i = 0; i < callee->numParams(); ++i, ++srcNum) {
    auto const& pi = callee->params()[i];

    // Non-pointer and NativeArg args are passed by value.  String, Array,
    // Object, and Variant are passed by const&, i.e. a pointer to stack memory
    // holding the value, so we expect PtrToT types for these.  Pointers to
    // req::ptr types (String, Array, Object) need adjusting to point to
    // &ptr->m_data.
    if (TVOFF(m_data) && !pi.nativeArg && isReqPtrRef(pi.builtinType)) {
      assertx(inst->src(srcNum)->type() <= TPtrToGen);
      args.addr(srcLoc(env, inst, srcNum).reg(), TVOFF(m_data));
    } else if (pi.nativeArg && !pi.builtinType && !callee->byRef(i)) {
      // This condition indicates a MixedTV (i.e., TypedValue-by-value) arg.
      args.typedValue(srcNum);
    } else {
      args.ssa(srcNum, pi.builtinType == KindOfDouble);
    }
  }

  auto dest = [&] () -> CallDest {
    if (isBuiltinByRef(funcReturnType)) {
      if (!returnByValue) return kVoidDest; // indirect return
      return funcReturnType
        ? callDest(dstData) // String, Array, or Object
        : callDest(dstData, dstType); // Variant
    }
    return funcReturnType == KindOfDouble
      ? callDestDbl(env, inst)
      : callDest(env, inst);
  }();

  cgCallHelper(v, env, CallSpec::direct(callee->nativeFuncPtr()),
               dest, SyncOptions::Sync, args);

  // For primitive return types (int, bool, double) and returnByValue, the
  // return value is already in dstData/dstType.
  if (returnType.isSimpleType() || returnByValue) return;

  // For return by reference (String, Object, Array, Variant), the builtin
  // writes the return value into MInstrState::tvBuiltinReturn, from where it
  // has to be tested and copied.

  if (returnType.isReferenceType()) {
    // The return type is String, Array, or Object; fold nullptr to KindOfNull.
    assertx(isBuiltinByRef(funcReturnType) && isReqPtrRef(funcReturnType));

    v << load{rvmtl()[returnOffset], dstData};

    if (dstType.isValid()) {
      auto const sf = v.makeReg();
      auto const rtype = v.cns(returnType.toDataType());
      auto const nulltype = v.cns(KindOfNull);
      v << testq{dstData, dstData, sf};
      v << cmovb{CC_Z, sf, rtype, nulltype, dstType};
    }
    return;
  }

  if (returnType <= TCell || returnType <= TBoxedCell) {
    // The return type is Variant; fold KindOfUninit to KindOfNull.
    assertx(isBuiltinByRef(funcReturnType) && !isReqPtrRef(funcReturnType));
    static_assert(KindOfUninit == 0, "KindOfUninit must be 0 for test");

    v << load{rvmtl()[returnOffset + TVOFF(m_data)], dstData};

    if (dstType.isValid()) {
      auto const rtype = v.makeReg();
      v << loadb{rvmtl()[returnOffset + TVOFF(m_type)], rtype};

      auto const sf = v.makeReg();
      auto const nulltype = v.cns(KindOfNull);
      v << testb{rtype, rtype, sf};
      v << cmovb{CC_Z, sf, rtype, nulltype, dstType};
    }
    return;
  }

  not_reached();
}
Esempio n. 5
0
bool VOCatalogHeaderParser::startElement(const QString &namespaceURI, const QString &localName, const QString &qName, const QXmlAttributes &attributes)
{  
  if (qName == "TABLEDATA")
  {
    m_tableData++;
    m_desc = true;
  }

  if (qName == "RESOURCE")
  {
    m_resource++;

    for (int i = 0; i < attributes.count(); i++)
    { 
      if (attributes.qName(i) == "name")
      {
        m_current.m_name = attributes.value(i);
      }
      else
      if (attributes.qName(i) == "ID")
      {
        m_current.m_id = attributes.value(i);
      }
      /*
      else
      if (attributes.qName(i) == "type")
      {
        m_current.m_type = attributes.value(i);
      }
      */
    }
  }

  if (m_resource)
  {
    if (qName == "DESCRIPTION" && m_queue.last() == "RESOURCE")
    {
      m_desc = true;
    }

    if (qName == "TABLE")
    {
      m_table++;

      for (int i = 0; i < attributes.count(); i++)
      {
        if (attributes.qName(i) == "nrows")
        {
          m_current.m_count = attributes.value(i).toLongLong();
        }
      }
    }

    if (m_table)
    {
      if (qName == "COOSYS")
      {
        VOCooSys coo;

        for (int i = 0; i < attributes.count(); i++)
        {
          if (attributes.qName(i) == "ID")
          {
            coo.m_id = attributes.value(i);
          }
          else
          if (attributes.qName(i) == "system")
          {
            coo.m_system = attributes.value(i);
          }
          else
          if (attributes.qName(i) == "equinox")
          {
            coo.m_equinox = attributes.value(i);
          }
          else
          if (attributes.qName(i) == "epoch")
          {
            coo.m_epoch = attributes.value(i).toDouble();
          }
        }
        m_cooSys.append(coo);
      }

      if (qName == "FIELD")
      {
        m_field.clear();

        for (int i = 0; i < attributes.count(); i++)
        {
          if (attributes.qName(i) == "name")
          {
            m_field.m_name = attributes.value(i);                        
          }
          else
          if (attributes.qName(i) == "ucd")
          {
            m_field.m_ucd = attributes.value(i);            
          }
          else
          if (attributes.qName(i) == "ref")
          {
            m_field.m_ref = attributes.value(i);
          }
          else
          if (attributes.qName(i) == "display")
          {
            m_field.m_display = attributes.value(i).toInt();
          }
          else
          if (attributes.qName(i) == "datatype")
          {
            m_field.m_dataType = toDataType(attributes.value(i));
          }
          else
          if (attributes.qName(i) == "unit")
          {
            m_field.m_unit = attributes.value(i);
          }
          else
          if (attributes.qName(i) == "width")
          {
            m_field.m_width = attributes.value(i).toInt();
          }
          else
          if (attributes.qName(i) == "precision")
          {
            m_field.m_precision = attributes.value(i).toInt();
          }
          else
          if (attributes.qName(i) == "arraysize")
          {
            m_field.m_arraysize = attributes.value(i).toInt();
          }
        }
        m_desc = true;
      }
    }
  }

  m_queue.append(qName);

  return true;
}