Example #1
0
/// Emit Builtin.initialize by evaluating the operand directly into
/// the address.
static ManagedValue emitBuiltinInit(SILGenFunction &SGF,
                                    SILLocation loc,
                                    SubstitutionMap substitutions,
                                    PreparedArguments &&preparedArgs,
                                    SGFContext C) {
  auto argsOrError = decomposeArguments(SGF, loc, std::move(preparedArgs), 2);
  if (!argsOrError)
    return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));

  auto args = *argsOrError;

  CanType formalType =
    substitutions.getReplacementTypes()[0]->getCanonicalType();
  auto &formalTL = SGF.getTypeLowering(formalType);

  SILValue addr = SGF.emitRValueAsSingleValue(args[1]).getUnmanagedValue();
  addr = SGF.B.createPointerToAddress(
    loc, addr, formalTL.getLoweredType().getAddressType(),
    /*isStrict*/ true,
    /*isInvariant*/ false);

  TemporaryInitialization init(addr, CleanupHandle::invalid());
  SGF.emitExprInto(args[0], &init);

  return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
}
Example #2
0
/// Specialized emitter for Builtin.destroy.
static ManagedValue emitBuiltinDestroy(SILGenFunction &gen,
                                       SILLocation loc,
                                       SubstitutionList substitutions,
                                       ArrayRef<ManagedValue> args,
                                       CanFunctionType formalApplyType,
                                       SGFContext C) {
  assert(args.size() == 2 && "destroy should have two arguments");
  assert(substitutions.size() == 1 &&
         "destroy should have a single substitution");
  // The substitution determines the type of the thing we're destroying.
  auto &ti = gen.getTypeLowering(substitutions[0].getReplacement());
  
  // Destroy is a no-op for trivial types.
  if (ti.isTrivial())
    return ManagedValue::forUnmanaged(gen.emitEmptyTuple(loc));
  
  SILType destroyType = ti.getLoweredType();

  // Convert the pointer argument to a SIL address.
  SILValue addr =
    gen.B.createPointerToAddress(loc, args[1].getUnmanagedValue(),
                                 destroyType.getAddressType(),
                                 /*isStrict*/ true);
  
  // Destroy the value indirectly. Canonicalization will promote to loads
  // and releases if appropriate.
  gen.B.createDestroyAddr(loc, addr);
  
  return ManagedValue::forUnmanaged(gen.emitEmptyTuple(loc));
}
Example #3
0
static ManagedValue emitBuiltinAssign(SILGenFunction &gen,
                                      SILLocation loc,
                                      SubstitutionList substitutions,
                                      ArrayRef<ManagedValue> args,
                                      CanFunctionType formalApplyType,
                                      SGFContext C) {
  assert(args.size() >= 2 && "assign should have two arguments");
  assert(substitutions.size() == 1 &&
         "assign should have a single substitution");

  // The substitution determines the type of the thing we're destroying.
  CanType assignFormalType = substitutions[0].getReplacement()->getCanonicalType();
  SILType assignType = gen.getLoweredType(assignFormalType);
  
  // Convert the destination pointer argument to a SIL address.
  SILValue addr = gen.B.createPointerToAddress(loc,
                                               args.back().getUnmanagedValue(),
                                               assignType.getAddressType(),
                                               /*isStrict*/ true);
  
  // Build the value to be assigned, reconstructing tuples if needed.
  auto src = RValue::withPreExplodedElements(args.slice(0, args.size() - 1),
                                             assignFormalType);
  
  std::move(src).assignInto(gen, loc, addr);

  return ManagedValue::forUnmanaged(gen.emitEmptyTuple(loc));
}
Example #4
0
/// Specialized emitter for Builtin.beginUnpairedModifyAccess.
static ManagedValue emitBuiltinBeginUnpairedModifyAccess(SILGenFunction &SGF,
                                                    SILLocation loc,
                                           SubstitutionMap substitutions,
                                           ArrayRef<ManagedValue> args,
                                           SGFContext C) {
  assert(substitutions.getReplacementTypes().size() == 1 &&
        "Builtin.beginUnpairedModifyAccess should have one substitution");
  assert(args.size() == 3 &&
         "beginUnpairedModifyAccess should be given three arguments");

  SILType elemTy = SGF.getLoweredType(substitutions.getReplacementTypes()[0]);
  SILValue addr = SGF.B.createPointerToAddress(loc,
                                               args[0].getUnmanagedValue(),
                                               elemTy.getAddressType(),
                                               /*strict*/ true,
                                               /*invariant*/ false);

  SILType valueBufferTy =
      SGF.getLoweredType(SGF.getASTContext().TheUnsafeValueBufferType);

  SILValue buffer =
    SGF.B.createPointerToAddress(loc, args[1].getUnmanagedValue(),
                                 valueBufferTy.getAddressType(),
                                 /*strict*/ true,
                                 /*invariant*/ false);
  SGF.B.createBeginUnpairedAccess(loc, addr, buffer, SILAccessKind::Modify,
                                  SILAccessEnforcement::Dynamic,
                                  /*noNestedConflict*/ false,
                                  /*fromBuiltin*/ true);

  return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
}
Example #5
0
static ManagedValue emitBuiltinAssign(SILGenFunction &SGF,
                                      SILLocation loc,
                                      SubstitutionMap substitutions,
                                      ArrayRef<ManagedValue> args,
                                      SGFContext C) {
  assert(args.size() >= 2 && "assign should have two arguments");
  assert(substitutions.getReplacementTypes().size() == 1 &&
         "assign should have a single substitution");

  // The substitution determines the type of the thing we're destroying.
  CanType assignFormalType =
    substitutions.getReplacementTypes()[0]->getCanonicalType();
  SILType assignType = SGF.getLoweredType(assignFormalType);
  
  // Convert the destination pointer argument to a SIL address.
  SILValue addr = SGF.B.createPointerToAddress(loc,
                                               args.back().getUnmanagedValue(),
                                               assignType.getAddressType(),
                                               /*isStrict*/ true,
                                               /*isInvariant*/ false);
  
  // Build the value to be assigned, reconstructing tuples if needed.
  auto src = RValue(SGF, args.slice(0, args.size() - 1), assignFormalType);
  
  std::move(src).ensurePlusOne(SGF, loc).assignInto(SGF, loc, addr);

  return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
}
Example #6
0
static ManagedValue emitBuiltinAutorelease(SILGenFunction &gen,
                                           SILLocation loc,
                                           SubstitutionList substitutions,
                                           ArrayRef<ManagedValue> args,
                                           CanFunctionType formalApplyType,
                                           SGFContext C) {
  gen.B.createUnmanagedAutoreleaseValue(loc, args[0].getValue());
  return ManagedValue::forUnmanaged(gen.emitEmptyTuple(loc));    
}
Example #7
0
static ManagedValue emitBuiltinAutorelease(SILGenFunction &SGF,
                                           SILLocation loc,
                                           SubstitutionMap substitutions,
                                           ArrayRef<ManagedValue> args,
                                           SGFContext C) {
  SGF.B.createUnmanagedAutoreleaseValue(loc, args[0].getValue(),
                                        SGF.B.getDefaultAtomicity());
  return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));    
}
Example #8
0
/// Specialized emitter for Builtin.condfail.
static ManagedValue emitBuiltinCondFail(SILGenFunction &SGF,
                                        SILLocation loc,
                                        SubstitutionMap substitutions,
                                        ArrayRef<ManagedValue> args,
                                        SGFContext C) {
  assert(args.size() == 1 && "condfail should be given one argument");
  
  SGF.B.createCondFail(loc, args[0].getUnmanagedValue());
  return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
}
Example #9
0
/// Specialized emitter for Builtin.fixLifetime.
static ManagedValue emitBuiltinFixLifetime(SILGenFunction &SGF,
                                           SILLocation loc,
                                           SubstitutionMap substitutions,
                                           ArrayRef<ManagedValue> args,
                                           SGFContext C) {
  for (auto arg : args) {
    SGF.B.createFixLifetime(loc, arg.getValue());
  }
  return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
}
Example #10
0
/// Specialized emitter for Builtin.condfail.
static ManagedValue emitBuiltinCondFail(SILGenFunction &gen,
                                        SILLocation loc,
                                        SubstitutionList substitutions,
                                        ArrayRef<ManagedValue> args,
                                        CanFunctionType formalApplyType,
                                        SGFContext C) {
  assert(args.size() == 1 && "condfail should be given one argument");
  
  gen.B.createCondFail(loc, args[0].getUnmanagedValue());
  return ManagedValue::forUnmanaged(gen.emitEmptyTuple(loc));
}
Example #11
0
static ManagedValue emitBuiltinAutorelease(SILGenFunction &gen,
                                           SILLocation loc,
                                           ArrayRef<Substitution> substitutions,
                                           ArrayRef<ManagedValue> args,
                                           CanFunctionType formalApplyType,
                                           SGFContext C) {
  // The value was produced at +1, so to produce an unbalanced
  // autorelease we need to leave the cleanup intact.
  gen.B.createAutoreleaseValue(loc, args[0].getValue(), Atomicity::Atomic);
  return ManagedValue::forUnmanaged(gen.emitEmptyTuple(loc));    
}
Example #12
0
/// Specialized emitter for Builtin.fixLifetime.
static ManagedValue emitBuiltinFixLifetime(SILGenFunction &gen,
                                           SILLocation loc,
                                           SubstitutionList substitutions,
                                           ArrayRef<ManagedValue> args,
                                           CanFunctionType formalApplyType,
                                           SGFContext C) {
  for (auto arg : args) {
    gen.B.createFixLifetime(loc, arg.getValue());
  }
  return ManagedValue::forUnmanaged(gen.emitEmptyTuple(loc));
}
Example #13
0
static ManagedValue emitBuiltinRetain(SILGenFunction &gen,
                                       SILLocation loc,
                                       ArrayRef<Substitution> substitutions,
                                       ArrayRef<ManagedValue> args,
                                       CanFunctionType formalApplyType,
                                       SGFContext C) {
  // The value was produced at +1; we can produce an unbalanced
  // retain simply by disabling the cleanup.
  args[0].forward(gen);
  return ManagedValue::forUnmanaged(gen.emitEmptyTuple(loc));    
}
Example #14
0
static ManagedValue emitBuiltinRelease(SILGenFunction &gen,
                                       SILLocation loc,
                                       SubstitutionList substitutions,
                                       ArrayRef<ManagedValue> args,
                                       CanFunctionType formalApplyType,
                                       SGFContext C) {
  // The value was produced at +1, so to produce an unbalanced
  // release we need to leave the cleanup intact and then do a *second*
  // release.
  gen.B.createUnmanagedReleaseValue(loc, args[0].getValue());
  return ManagedValue::forUnmanaged(gen.emitEmptyTuple(loc));    
}
Example #15
0
static ManagedValue emitBuiltinRelease(SILGenFunction &SGF,
                                       SILLocation loc,
                                       SubstitutionMap substitutions,
                                       ArrayRef<ManagedValue> args,
                                       SGFContext C) {
  // The value was produced at +1, so to produce an unbalanced
  // release we need to leave the cleanup intact and then do a *second*
  // release.
  SGF.B.createUnmanagedReleaseValue(loc, args[0].getValue(),
                                    SGF.B.getDefaultAtomicity());
  return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));    
}
Example #16
0
static ManagedValue emitBuiltinRetain(SILGenFunction &gen,
                                       SILLocation loc,
                                       SubstitutionList substitutions,
                                       ArrayRef<ManagedValue> args,
                                       CanFunctionType formalApplyType,
                                       SGFContext C) {
  // The value was produced at +1; we can produce an unbalanced retain simply by
  // disabling the cleanup. But this would violate ownership semantics. Instead,
  // we must allow for the cleanup and emit a new unmanaged retain value.
  gen.B.createUnmanagedRetainValue(loc, args[0].getValue());
  return ManagedValue::forUnmanaged(gen.emitEmptyTuple(loc));    
}
Example #17
0
static ManagedValue emitBuiltinUnpin(SILGenFunction &SGF,
                                     SILLocation loc,
                                     SubstitutionList subs,
                                     ArrayRef<ManagedValue> args,
                                     SGFContext C) {
  assert(args.size() == 1);

  if (requireIsOptionalNativeObject(SGF, loc, subs[0].getReplacement())) {
    // Unpinning takes responsibility for the +1 handle.
    SGF.B.createStrongUnpin(loc, args[0].forward(SGF), SGF.B.getDefaultAtomicity());
  }

  return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
}
Example #18
0
static ManagedValue emitBuiltinUnpin(SILGenFunction &gen,
                                     SILLocation loc,
                                     SubstitutionList subs,
                                     ArrayRef<ManagedValue> args,
                                     CanFunctionType formalApplyType,
                                     SGFContext C) {
  assert(args.size() == 1);

  if (requireIsOptionalNativeObject(gen, loc, subs[0].getReplacement())) {
    // Unpinning takes responsibility for the +1 handle.
    gen.B.createStrongUnpin(loc, args[0].forward(gen), Atomicity::Atomic);
  }

  return ManagedValue::forUnmanaged(gen.emitEmptyTuple(loc));
}
Example #19
0
static ManagedValue emitBuiltinBindMemory(SILGenFunction &SGF,
                                          SILLocation loc,
                                          SubstitutionMap subs,
                                          ArrayRef<ManagedValue> args,
                                          SGFContext C) {
  assert(subs.getReplacementTypes().size() == 1 && "bindMemory should have a single substitution");
  assert(args.size() == 3 && "bindMemory should have three argument");

  // The substitution determines the element type for bound memory.
  CanType boundFormalType = subs.getReplacementTypes()[0]->getCanonicalType();
  SILType boundType = SGF.getLoweredType(boundFormalType);

  SGF.B.createBindMemory(loc, args[0].getValue(),
                         args[1].getValue(), boundType);

  return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
}
Example #20
0
static void emitAddressOnlyEnumConstructor(SILGenFunction &gen,
                                           SILType enumTy,
                                           EnumElementDecl *element) {
  RegularLocation Loc(element);
  CleanupLocation CleanupLoc(element);
  Loc.markAutoGenerated();

  // Emit the indirect return slot.
  auto &AC = gen.getASTContext();
  auto VD = new (AC) ParamDecl(/*IsLet*/ false, SourceLoc(),
                               AC.getIdentifier("$return_value"),
                               SourceLoc(),
                               AC.getIdentifier("$return_value"),
                               enumTy.getSwiftType(),
                               element->getDeclContext());
  SILValue resultSlot
    = new (gen.F.getModule()) SILArgument(gen.F.begin(), enumTy, VD);

  Scope scope(gen.Cleanups, CleanupLoc);

  // Emit the exploded constructor argument.
  ManagedValue argValue;
  if (element->hasArgumentType()) {
    RValue arg = emitImplicitValueConstructorArg
      (gen, Loc, element->getArgumentType()->getCanonicalType(),
       element->getDeclContext());
    argValue = std::move(arg).getAsSingleValue(gen, Loc);
  }
  emitConstructorMetatypeArg(gen, element);

  boxIndirectEnumPayload(gen, argValue, Loc, element);

  // Store the data, if any.
  if (argValue) {
    SILValue resultData = gen.B.createInitEnumDataAddr(element, resultSlot,
      element, argValue.getType().getAddressType());
    argValue.forwardInto(gen, element, resultData);
  }

  // Apply the tag.
  gen.B.createInjectEnumAddr(Loc, resultSlot, element);
  scope.pop();
  gen.B.createReturn(ImplicitReturnLocation::getImplicitReturnLoc(Loc),
                     gen.emitEmptyTuple(element));
}
Example #21
0
/// Emit Builtin.initialize by evaluating the operand directly into
/// the address.
static ManagedValue emitBuiltinInit(SILGenFunction &gen,
                                    SILLocation loc,
                                    ArrayRef<Substitution> substitutions,
                                    Expr *tuple,
                                    CanFunctionType formalApplyType,
                                    SGFContext C) {
  auto args = decomposeArguments(gen, tuple, 2);

  CanType formalType = substitutions[0].getReplacement()->getCanonicalType();
  auto &formalTL = gen.getTypeLowering(formalType);

  SILValue addr = gen.emitRValueAsSingleValue(args[1]).getUnmanagedValue();
  addr = gen.B.createPointerToAddress(loc, addr,
                                 formalTL.getLoweredType().getAddressType());

  TemporaryInitialization init(addr, CleanupHandle::invalid());
  gen.emitExprInto(args[0], &init);
  
  return ManagedValue::forUnmanaged(gen.emitEmptyTuple(loc));
}
Example #22
0
/// Specialized emitter for Builtin.performInstantaneousReadAccess
static ManagedValue emitBuiltinPerformInstantaneousReadAccess(
  SILGenFunction &SGF, SILLocation loc, SubstitutionMap substitutions,
  ArrayRef<ManagedValue> args, SGFContext C) {

  assert(substitutions.getReplacementTypes().size() == 1 &&
         "Builtin.performInstantaneousReadAccess should have one substitution");
  assert(args.size() == 2 &&
         "Builtin.performInstantaneousReadAccess should be given "
         "two arguments");

  SILType elemTy = SGF.getLoweredType(substitutions.getReplacementTypes()[0]);
  SILValue addr = SGF.B.createPointerToAddress(loc,
                                               args[0].getUnmanagedValue(),
                                               elemTy.getAddressType(),
                                               /*strict*/ true,
                                               /*invariant*/ false);

  SILType valueBufferTy =
    SGF.getLoweredType(SGF.getASTContext().TheUnsafeValueBufferType);
  SILValue unusedBuffer = SGF.emitTemporaryAllocation(loc, valueBufferTy);

  // Begin an "unscoped" read access. No nested conflict is possible because
  // the compiler should generate the actual read for the KeyPath expression
  // immediately after the call to this builtin, which forms the address of
  // that real access. When noNestedConflict=true, no EndUnpairedAccess should
  // be emitted.
  //
  // Unpaired access is necessary because a BeginAccess/EndAccess pair with no
  // use will be trivially optimized away.
  SGF.B.createBeginUnpairedAccess(loc, addr, unusedBuffer, SILAccessKind::Read,
                                  SILAccessEnforcement::Dynamic,
                                  /*noNestedConflict*/ true,
                                  /*fromBuiltin*/ true);

  return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
}
Example #23
0
/// Specialized emitter for Builtin.endUnpairedAccessModifyAccess.
static ManagedValue emitBuiltinEndUnpairedAccess(SILGenFunction &SGF,
                                                    SILLocation loc,
                                           SubstitutionMap substitutions,
                                           ArrayRef<ManagedValue> args,
                                           SGFContext C) {
  assert(substitutions.empty() &&
        "Builtin.endUnpairedAccess should have no substitutions");
  assert(args.size() == 1 &&
         "endUnpairedAccess should be given one argument");

  SILType valueBufferTy =
      SGF.getLoweredType(SGF.getASTContext().TheUnsafeValueBufferType);

  SILValue buffer = SGF.B.createPointerToAddress(loc,
                                                 args[0].getUnmanagedValue(),
                                                valueBufferTy.getAddressType(),
                                                 /*strict*/ true,
                                                 /*invariant*/ false);
  SGF.B.createEndUnpairedAccess(loc, buffer, SILAccessEnforcement::Dynamic,
                                /*aborted*/ false,
                                /*fromBuiltin*/ true);

  return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
}
Example #24
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;
}