Ejemplo n.º 1
0
RValue ArgumentSource::getAsRValue(SILGenFunction &gen, SGFContext C) && {
  assert(!isLValue());
  if (isRValue())
    return std::move(*this).asKnownRValue();

  return gen.emitRValue(std::move(*this).asKnownExpr(), C);
}
Ejemplo n.º 2
0
/// Specialized emitter for Builtin.addressOfBorrow.
static ManagedValue emitBuiltinAddressOfBorrow(SILGenFunction &SGF,
                                               SILLocation loc,
                                               SubstitutionMap substitutions,
                                               PreparedArguments &&preparedArgs,
                                               SGFContext C) {
  SILType rawPointerType = SILType::getRawPointerType(SGF.getASTContext());

  auto argsOrError = decomposeArguments(SGF, loc, std::move(preparedArgs), 1);
  if (!argsOrError)
    return SGF.emitUndef(rawPointerType);

  auto argument = (*argsOrError)[0];

  SILValue addr;
  // Try to borrow the argument at +0. We only support if it's
  // naturally emitted borrowed in memory.
  auto borrow = SGF.emitRValue(argument, SGFContext::AllowGuaranteedPlusZero)
     .getAsSingleValue(SGF, argument);
  if (!borrow.isPlusZero() || !borrow.getType().isAddress()) {
    SGF.SGM.diagnose(argument->getLoc(), diag::non_borrowed_indirect_addressof);
    return SGF.emitUndef(rawPointerType);
  }
  
  addr = borrow.getValue();
  
  // Take the address argument and cast it to RawPointer.
  SILValue result = SGF.B.createAddressToPointer(loc, addr,
                                                 rawPointerType);
  return ManagedValue::forUnmanaged(result);
}
Ejemplo n.º 3
0
RValue ArgumentSource::getAsRValue(SILGenFunction &SGF, SGFContext C) && {
  switch (StoredKind) {
  case Kind::Invalid:
    llvm_unreachable("argument source is invalid");
  case Kind::LValue:
    llvm_unreachable("cannot get l-value as r-value");
  case Kind::RValue:
    return std::move(*this).asKnownRValue(SGF);
  case Kind::Expr:
    return SGF.emitRValue(std::move(*this).asKnownExpr(), C);
  }
  llvm_unreachable("bad kind");
}
Ejemplo n.º 4
0
static void emitImplicitValueConstructor(SILGenFunction &gen,
                                         ConstructorDecl *ctor) {
  RegularLocation Loc(ctor);
  Loc.markAutoGenerated();
  // FIXME: Handle 'self' along with the other arguments.
  auto *paramList = ctor->getParameterList(1);
  auto selfTyCan = ctor->getImplicitSelfDecl()->getType()->getInOutObjectType();
  SILType selfTy = gen.getLoweredType(selfTyCan);

  // Emit the indirect return argument, if any.
  SILValue resultSlot;
  if (selfTy.isAddressOnly(gen.SGM.M)) {
    auto &AC = gen.getASTContext();
    auto VD = new (AC) ParamDecl(/*IsLet*/ false, SourceLoc(), SourceLoc(),
                                 AC.getIdentifier("$return_value"),
                                 SourceLoc(),
                                 AC.getIdentifier("$return_value"), selfTyCan,
                                 ctor);
    resultSlot = new (gen.F.getModule()) SILArgument(gen.F.begin(), selfTy, VD);
  }

  // Emit the elementwise arguments.
  SmallVector<RValue, 4> elements;
  for (size_t i = 0, size = paramList->size(); i < size; ++i) {
    auto &param = paramList->get(i);

    elements.push_back(
      emitImplicitValueConstructorArg(gen, Loc,
                                      param->getType()->getCanonicalType(),
                                      ctor));
  }

  emitConstructorMetatypeArg(gen, ctor);

  auto *decl = selfTy.getStructOrBoundGenericStruct();
  assert(decl && "not a struct?!");

  // If we have an indirect return slot, initialize it in-place.
  if (resultSlot) {

    auto elti = elements.begin(), eltEnd = elements.end();
    for (VarDecl *field : decl->getStoredProperties()) {
      auto fieldTy = selfTy.getFieldType(field, gen.SGM.M);
      auto &fieldTL = gen.getTypeLowering(fieldTy);
      SILValue slot = gen.B.createStructElementAddr(Loc, resultSlot, field,
                                                    fieldTL.getLoweredType().getAddressType());
      InitializationPtr init(new KnownAddressInitialization(slot));

      // An initialized 'let' property has a single value specified by the
      // initializer - it doesn't come from an argument.
      if (!field->isStatic() && field->isLet() &&
          field->getParentInitializer()) {
        assert(field->getType()->isEqual(field->getParentInitializer()
                                         ->getType()) && "Checked by sema");

        // Cleanup after this initialization.
        FullExpr scope(gen.Cleanups, field->getParentPatternBinding());
        gen.emitExprInto(field->getParentInitializer(), init.get());
        continue;
      }

      assert(elti != eltEnd && "number of args does not match number of fields");
      (void)eltEnd;
      std::move(*elti).forwardInto(gen, Loc, init.get());
      ++elti;
    }
    gen.B.createReturn(ImplicitReturnLocation::getImplicitReturnLoc(Loc),
                       gen.emitEmptyTuple(Loc));
    return;
  }

  // Otherwise, build a struct value directly from the elements.
  SmallVector<SILValue, 4> eltValues;

  auto elti = elements.begin(), eltEnd = elements.end();
  for (VarDecl *field : decl->getStoredProperties()) {
    auto fieldTy = selfTy.getFieldType(field, gen.SGM.M);
    SILValue v;

    // An initialized 'let' property has a single value specified by the
    // initializer - it doesn't come from an argument.
    if (!field->isStatic() && field->isLet() && field->getParentInitializer()) {
      // Cleanup after this initialization.
      FullExpr scope(gen.Cleanups, field->getParentPatternBinding());
      v = gen.emitRValue(field->getParentInitializer())
             .forwardAsSingleStorageValue(gen, fieldTy, Loc);
    } else {
      assert(elti != eltEnd && "number of args does not match number of fields");
      (void)eltEnd;
      v = std::move(*elti).forwardAsSingleStorageValue(gen, fieldTy, Loc);
      ++elti;
    }

    eltValues.push_back(v);
  }

  SILValue selfValue = gen.B.createStruct(Loc, selfTy, eltValues);
  gen.B.createReturn(ImplicitReturnLocation::getImplicitReturnLoc(Loc),
                     selfValue);
  return;
}