Example #1
0
SubstitutionMap
GenericSignature::getSubstitutionMap(SubstitutionList subs) const {
  SubstitutionMap result(const_cast<GenericSignature *>(this));

  enumeratePairedRequirements(
    [&](Type depTy, ArrayRef<Requirement> reqts) -> bool {
      auto sub = subs.front();
      subs = subs.slice(1);

      auto canTy = depTy->getCanonicalType();
      if (auto paramTy = dyn_cast<GenericTypeParamType>(canTy))
        result.addSubstitution(paramTy,
                               sub.getReplacement());

      auto conformances = sub.getConformances();
      assert(reqts.size() == conformances.size());

      for (unsigned i = 0, e = conformances.size(); i < e; i++) {
        assert(reqts[i].getSecondType()->getAnyNominal() ==
               conformances[i].getRequirement());
        result.addConformance(canTy, conformances[i]);
      }

      return false;
    });

  assert(subs.empty() && "did not use all substitutions?!");
  result.verify();
  return result;
}
Example #2
0
void cGraphMaster::do_substitutions(string& input, const SubstitutionList& subs_vec) const {
  for (SubstitutionList::const_iterator it = subs_vec.begin(); it != subs_vec.end(); ++it) {
    // from is already lowercase
    const string& from = it->from;
    const string& to = it->to;
    
    if (!it->regex) {
      for (size_t i = 0; i < input.length(); i++) {
        size_t j;
        for (j = 0; (i+j) < input.length() && j < from.length(); j++) {
          if (tolower(input[i+j]) != from[j]) break;
        }
        if (j == from.length()) {
          // even if there's a match I need that chars around the matching part be [^A-Za-z0-9']
          if (((i > 0 && !isalnum(input[i-1]) && input[i-1] != '\'') || i == 0) &&
              (((i + from.length()) < input.length() && !isalnum(input[i + from.length()]) && input[i + from.length()] != '\'') ||
                i + from.length() >= input.length()))
          {
            input.replace(i, from.length(), to);
            if (!to.empty()) i += (to.length() - 1);
          }
        }
      }
    }
    else {
#ifdef ENABLE_PCRECPP
      pcrecpp::RE(from).GlobalReplace(to, &input);
#endif
    }
  }
}
Example #3
0
SubstitutionMap GenericEnvironment::
getSubstitutionMap(SubstitutionList subs) const {
  SubstitutionMap result;

  for (auto depTy : getGenericSignature()->getAllDependentTypes()) {

    // Map the interface type to a context type.
    auto contextTy = depTy.subst(QueryInterfaceTypeSubstitutions(this),
                                 MakeAbstractConformanceForGenericType());

    auto sub = subs.front();
    subs = subs.slice(1);

    // Record the replacement type and its conformances.
    if (auto *archetype = contextTy->getAs<ArchetypeType>()) {
      result.addSubstitution(CanArchetypeType(archetype), sub.getReplacement());
      for (auto conformance : sub.getConformances())
        result.addConformance(CanType(archetype), conformance);
      continue;
    }

    // FIXME: getAllDependentTypes() includes generic type parameters that
    // have been made concrete.
    assert(contextTy->hasError() || depTy->is<GenericTypeParamType>());
  }

  assert(subs.empty() && "did not use all substitutions?!");

  populateParentMap(result);
  return result;
}
Example #4
0
static void emitTypeTraitBuiltin(IRGenFunction &IGF,
                                 Explosion &out,
                                 Explosion &args,
                                 SubstitutionList substitutions,
                                 TypeTraitResult (TypeBase::*trait)()) {
  assert(substitutions.size() == 1
         && "type trait should have gotten single type parameter");
  args.claimNext();
  
  // Lower away the trait to a tristate 0 = no, 1 = yes, 2 = maybe.
  unsigned result;
  switch ((substitutions[0].getReplacement().getPointer()->*trait)()) {
  case TypeTraitResult::IsNot:
    result = 0;
    break;
  case TypeTraitResult::Is:
    result = 1;
    break;
  case TypeTraitResult::CanBe:
    result = 2;
    break;
  }

  out.add(llvm::ConstantInt::get(IGF.IGM.Int8Ty, result));
}
Example #5
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 #6
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 #7
0
static ManagedValue emitCastFromReferenceType(SILGenFunction &gen,
                                         SILLocation loc,
                                         SubstitutionList substitutions,
                                         ArrayRef<ManagedValue> args,
                                         SGFContext C) {
  assert(args.size() == 1 && "cast should have a single argument");
  assert(substitutions.size() == 1 &&
         "cast should have a single substitution");

  // The substitution determines the destination type.
  SILType destType = gen.getLoweredType(substitutions[0].getReplacement());
  
  // Bail if the source type is not a class reference of some kind.
  if (!substitutions[0].getReplacement()->isBridgeableObjectType()
      || !destType.isObject()) {
    gen.SGM.diagnose(loc, diag::invalid_sil_builtin,
                     "castFromNativeObject dest must be an object type");
    // Recover by propagating an undef result.
    SILValue result = SILUndef::get(destType, gen.SGM.M);
    return ManagedValue::forUnmanaged(result);
  }
  
  // Save the cleanup on the argument so we can forward it onto the cast
  // result.
  auto cleanup = args[0].getCleanup();

  // Take the reference type argument and cast it.
  SILValue result = gen.B.createUncheckedRefCast(loc, args[0].getValue(),
                                                 destType);
  // Return the cast result with the original cleanup.
  return ManagedValue(result, cleanup);
}
Example #8
0
/// Specialized emitter for Builtin.castReference.
static ManagedValue
emitBuiltinCastReference(SILGenFunction &SGF,
                         SILLocation loc,
                         SubstitutionList substitutions,
                         ArrayRef<ManagedValue> args,
                         SGFContext C) {
  assert(args.size() == 1 && "castReference should be given one argument");
  assert(substitutions.size() == 2 && "castReference should have two subs");

  auto fromTy = substitutions[0].getReplacement();
  auto toTy = substitutions[1].getReplacement();
  auto &fromTL = SGF.getTypeLowering(fromTy);
  auto &toTL = SGF.getTypeLowering(toTy);
  assert(!fromTL.isTrivial() && !toTL.isTrivial() && "expected ref type");

  if (!fromTL.isAddress() || !toTL.isAddress()) { 
    if (auto refCast = SGF.B.tryCreateUncheckedRefCast(loc, args[0].getValue(),
                                                       toTL.getLoweredType())) {
      // Create a reference cast, forwarding the cleanup.
      // The cast takes the source reference.
      return ManagedValue(refCast, args[0].getCleanup());
    }
  }
  // We are either casting between address-only types, or cannot promote to a
  // cast of reference values.
  //
  // If the from/to types are invalid, then use a cast that will fail at
  // runtime. We cannot catch these errors with SIL verification because they
  // may legitimately occur during code specialization on dynamically
  // unreachable paths.
  //
  // TODO: For now, we leave invalid casts in address form so that the runtime
  // will trap. We could emit a noreturn call here instead which would provide
  // more information to the optimizer.
  SILValue srcVal = args[0].forward(SGF);
  SILValue fromAddr;
  if (!fromTL.isAddress()) {
    // Move the loadable value into a "source temp".  Since the source and
    // dest are RC identical, store the reference into the source temp without
    // a retain. The cast will load the reference from the source temp and
    // store it into a dest temp effectively forwarding the cleanup.
    fromAddr = SGF.emitTemporaryAllocation(loc, srcVal->getType());
    fromTL.emitStore(SGF.B, loc, srcVal, fromAddr,
                     StoreOwnershipQualifier::Init);
  } else {
    // The cast loads directly from the source address.
    fromAddr = srcVal;
  }
  // Create a "dest temp" to hold the reference after casting it.
  SILValue toAddr = SGF.emitTemporaryAllocation(loc, toTL.getLoweredType());
  SGF.B.createUncheckedRefCastAddr(loc, fromAddr, fromTy->getCanonicalType(),
                                   toAddr, toTy->getCanonicalType());
  // Forward it along and register a cleanup.
  if (toTL.isAddress())
    return SGF.emitManagedBufferWithCleanup(toAddr);

  // Load the destination value.
  auto result = toTL.emitLoad(SGF.B, loc, toAddr, LoadOwnershipQualifier::Take);
  return SGF.emitManagedRValueWithCleanup(result);
}
Example #9
0
/// Specialized emitter for Builtin.castReferenceFromBridgeObject.
static ManagedValue emitBuiltinCastReferenceFromBridgeObject(
                                                  SILGenFunction &gen,
                                                  SILLocation loc,
                                                  SubstitutionList subs,
                                                  ArrayRef<ManagedValue> args,
                                                  CanFunctionType formalApplyType,
                                                  SGFContext C) {
  assert(args.size() == 1 && "cast should have one argument");
  assert(subs.size() == 1 && "cast should have a type substitution");

  // The substitution determines the destination type.
  SILType destType = gen.getLoweredType(subs[0].getReplacement());
  
  // Bail if the source type is not a class reference of some kind.
  if (!subs[0].getReplacement()->isBridgeableObjectType()
      || !destType.isObject()) {
    gen.SGM.diagnose(loc, diag::invalid_sil_builtin,
                 "castReferenceFromBridgeObject dest must be an object type");
    // Recover by propagating an undef result.
    SILValue result = SILUndef::get(destType, gen.SGM.M);
    return ManagedValue::forUnmanaged(result);
  }
  
  SILValue result = gen.B.createBridgeObjectToRef(loc, args[0].forward(gen),
                                                  destType);
  return gen.emitManagedRValueWithCleanup(result);
}
Example #10
0
static ManagedValue emitBuiltinAllocWithTailElems(SILGenFunction &gen,
                                              SILLocation loc,
                                              SubstitutionList subs,
                                              ArrayRef<ManagedValue> args,
                                              CanFunctionType formalApplyType,
                                              SGFContext C) {
  unsigned NumTailTypes = subs.size() - 1;
  assert(args.size() == NumTailTypes * 2 + 1 &&
         "wrong number of substitutions for allocWithTailElems");

  // The substitution determines the element type for bound memory.
  SILType RefType = gen.getLoweredType(subs[0].getReplacement()->
                                  getCanonicalType()).getObjectType();

  SmallVector<ManagedValue, 4> Counts;
  SmallVector<SILType, 4> ElemTypes;
  for (unsigned Idx = 0; Idx < NumTailTypes; ++Idx) {
    Counts.push_back(args[Idx * 2 + 1]);
    ElemTypes.push_back(gen.getLoweredType(subs[Idx+1].getReplacement()->
                                           getCanonicalType()).getObjectType());
  }
  ManagedValue Metatype = args[0];
  if (isa<MetatypeInst>(Metatype)) {
    assert(Metatype.getType().getMetatypeInstanceType(gen.SGM.M) == RefType &&
           "substituted type does not match operand metatype");
    return gen.B.createAllocRef(loc, RefType, false, false,
                                ElemTypes, Counts);
  } else {
    return gen.B.createAllocRefDynamic(loc, Metatype, RefType, false,
                                       ElemTypes, Counts);
  }
}
Example #11
0
static ManagedValue emitCastToReferenceType(SILGenFunction &SGF,
                                            SILLocation loc,
                                            SubstitutionList substitutions,
                                            ArrayRef<ManagedValue> args,
                                            SGFContext C,
                                            SILType objPointerType) {
  assert(args.size() == 1 && "cast should have a single argument");
  assert(substitutions.size() == 1 && "cast should have a type substitution");
  
  // Bail if the source type is not a class reference of some kind.
  if (!substitutions[0].getReplacement()->mayHaveSuperclass() &&
      !substitutions[0].getReplacement()->isClassExistentialType()) {
    SGF.SGM.diagnose(loc, diag::invalid_sil_builtin,
                     "castToNativeObject source must be a class");
    SILValue undef = SILUndef::get(objPointerType, SGF.SGM.M);
    return ManagedValue::forUnmanaged(undef);
  }

  // Grab the argument.
  ManagedValue arg = args[0];

  // If the argument is existential, open it.
  if (substitutions[0].getReplacement()->isClassExistentialType()) {
    auto openedTy
      = ArchetypeType::getOpened(substitutions[0].getReplacement());
    SILType loweredOpenedTy = SGF.getLoweredLoadableType(openedTy);
    arg = SGF.B.createOpenExistentialRef(loc, arg, loweredOpenedTy);
  }

  // Return the cast result.
  return SGF.B.createUncheckedRefCast(loc, arg, objPointerType);
}
Example #12
0
/// Specialized emitter for Builtin.reinterpretCast.
static ManagedValue emitBuiltinReinterpretCast(SILGenFunction &gen,
                                         SILLocation loc,
                                         SubstitutionList substitutions,
                                         ArrayRef<ManagedValue> args,
                                         CanFunctionType formalApplyType,
                                         SGFContext C) {
  assert(args.size() == 1 && "reinterpretCast should be given one argument");
  assert(substitutions.size() == 2 && "reinterpretCast should have two subs");
  
  auto &fromTL = gen.getTypeLowering(substitutions[0].getReplacement());
  auto &toTL = gen.getTypeLowering(substitutions[1].getReplacement());
  
  // If casting between address-only types, cast the address.
  if (!fromTL.isLoadable() || !toTL.isLoadable()) {
    SILValue fromAddr;

    // If the from value is loadable, move it to a buffer.
    if (fromTL.isLoadable()) {
      fromAddr = gen.emitTemporaryAllocation(loc, args[0].getValue()->getType());
      fromTL.emitStore(gen.B, loc, args[0].getValue(), fromAddr,
                       StoreOwnershipQualifier::Init);
    } else {
      fromAddr = args[0].getValue();
    }
    auto toAddr = gen.B.createUncheckedAddrCast(loc, fromAddr,
                                      toTL.getLoweredType().getAddressType());
    
    // Load and retain the destination value if it's loadable. Leave the cleanup
    // on the original value since we don't know anything about it's type.
    if (toTL.isLoadable()) {
      return gen.emitManagedLoadCopy(loc, toAddr, toTL);
    }
    // Leave the cleanup on the original value.
    if (toTL.isTrivial())
      return ManagedValue::forUnmanaged(toAddr);

    // Initialize the +1 result buffer without taking the incoming value. The
    // source and destination cleanups will be independent.
    return gen.B.bufferForExpr(
        loc, toTL.getLoweredType(), toTL, C,
        [&](SILValue bufferAddr) {
          gen.B.createCopyAddr(loc, toAddr, bufferAddr, IsNotTake,
                               IsInitialization);
        });
  }
  // Create the appropriate bitcast based on the source and dest types.
  auto &in = args[0];
  SILValue out = gen.B.createUncheckedBitCast(loc, in.getValue(),
                                              toTL.getLoweredType());

  // If the cast reduces to unchecked_ref_cast, then the source and dest
  // have identical cleanup, so just forward the cleanup as an optimization.
  if (isa<UncheckedRefCastInst>(out))
    return ManagedValue(out, in.getCleanup());

  // Otherwise leave the original cleanup and retain the cast value.
  return gen.emitManagedRetain(loc, out, toTL);
}
Example #13
0
/// Compute substitutions for making a direct call to a SIL function with
/// @convention(witness_method) convention.
///
/// Such functions have a substituted generic signature where the
/// abstract `Self` parameter from the original type of the protocol
/// requirement is replaced by a concrete type.
///
/// Thus, the original substitutions of the apply instruction that
/// are written in terms of the requirement's generic signature need
/// to be remapped to substitutions suitable for the witness signature.
///
/// \param conformanceRef The (possibly-specialized) conformance
/// \param requirementSig The generic signature of the requirement
/// \param witnessThunkSig The generic signature of the witness method
/// \param origSubs The substitutions from the call instruction
/// \param newSubs New substitutions are stored here
static void getWitnessMethodSubstitutions(
    SILModule &M,
    ProtocolConformanceRef conformanceRef,
    GenericSignature *requirementSig,
    GenericSignature *witnessThunkSig,
    SubstitutionList origSubs,
    bool isDefaultWitness,
    SmallVectorImpl<Substitution> &newSubs) {

  if (witnessThunkSig == nullptr)
    return;

  if (isDefaultWitness) {
    newSubs.append(origSubs.begin(), origSubs.end());
    return;
  }

  assert(!conformanceRef.isAbstract());
  auto conformance = conformanceRef.getConcrete();

  // If `Self` maps to a bound generic type, this gives us the
  // substitutions for the concrete type's generic parameters.
  auto baseSubMap = getSubstitutionsForProtocolConformance(conformanceRef);

  unsigned baseDepth = 0;
  auto *rootConformance = conformance->getRootNormalConformance();
  if (auto *witnessSig = rootConformance->getGenericSignature())
    baseDepth = witnessSig->getGenericParams().back()->getDepth() + 1;

  auto origDepth = 1;
  auto origSubMap = requirementSig->getSubstitutionMap(origSubs);

  auto subMap =
    SubstitutionMap::combineSubstitutionMaps(baseSubMap,
                                             origSubMap, 
                                             CombineSubstitutionMaps::AtDepth,
                                             baseDepth,
                                             origDepth,
                                             witnessThunkSig);

  witnessThunkSig->getSubstitutions(subMap, newSubs);
}
Example #14
0
static SubstitutionMap
getSubstitutionsForProtocolConformance(ProtocolConformanceRef CRef) {
  auto C = CRef.getConcrete();

  // Walk down to the base NormalProtocolConformance.
  SubstitutionList Subs;
  const ProtocolConformance *ParentC = C;
  while (!isa<NormalProtocolConformance>(ParentC)) {
    switch (ParentC->getKind()) {
    case ProtocolConformanceKind::Normal:
      llvm_unreachable("should have exited the loop?!");
    case ProtocolConformanceKind::Inherited:
      ParentC = cast<InheritedProtocolConformance>(ParentC)
        ->getInheritedConformance();
      break;
    case ProtocolConformanceKind::Specialized: {
      auto SC = cast<SpecializedProtocolConformance>(ParentC);
      ParentC = SC->getGenericConformance();
      assert(Subs.empty() && "multiple conformance specializations?!");
      Subs = SC->getGenericSubstitutions();
      break;
    }
    }
  }
  const NormalProtocolConformance *NormalC
    = cast<NormalProtocolConformance>(ParentC);

  // If the normal conformance is for a generic type, and we didn't hit a
  // specialized conformance, collect the substitutions from the generic type.
  // FIXME: The AST should do this for us.
  if (!NormalC->getType()->isSpecialized())
    return SubstitutionMap();

  if (Subs.empty()) {
    auto *DC = NormalC->getDeclContext();
    return NormalC->getType()
      ->getContextSubstitutionMap(DC->getParentModule(), DC);
  }

  return NormalC->getGenericSignature()->getSubstitutionMap(Subs);
}
Example #15
0
shared_ptr<Predicate> PredicateEntry::substitute(SubstitutionList & substitution_list) const {
	vector<shared_ptr<SymbolTableEntry>> symbols;
	for (auto i = _symbols.begin(); i != _symbols.end(); ++i) {
		symbols.push_back(substitution_list.find_value(*i));
	}
	PredicateEntry p(string(_name), symbols);
	ostringstream s;
	s << "(" << p.text() << ")";
	Parser parser(s.str());

	return parser.parse_predicate();
}
Example #16
0
// @brief Returns true if the PredicateEnry matches with other PredicateEntry
// @return bool 		
bool PredicateEntry::matches(shared_ptr<SymbolTableEntry> other, SubstitutionList & substitution_list) const {
	if (!other->is_predicate()) {
		return false;
	}
	shared_ptr<PredicateEntry> otherp = dynamic_pointer_cast<PredicateEntry>(other);

	if (_name != otherp->_name || _symbols.size() != otherp->_symbols.size()) {
		return false;
	}

	for (unsigned int i = 0; i < _symbols.size(); ++i) {
		shared_ptr<SymbolTableEntry> ci_value = substitution_list.find_value(_symbols[i]);
		shared_ptr<SymbolTableEntry> oi_value = substitution_list.find_value(otherp->_symbols[i]);
		shared_ptr<SymbolTableEntry> ci = substitution_list.find_non_null(_symbols[i]);
		shared_ptr<SymbolTableEntry> oi = substitution_list.find_non_null(otherp->_symbols[i]);
		if (!ci_value || !oi_value) {
			//semantic error
			return false;
		}

		if (!(*ci_value == *oi_value)) {
			if (ci_value->is_constant() && oi_value->is_constant()) {
				return false;
			} 

			if (!ci_value->is_constant()) {
				substitution_list.add(ci, oi);
			} else { //!oi->is_constant()
				substitution_list.add(oi, ci);
			}
		} 
	}
	return true;
}
Example #17
0
int Specialization::substituteVariablesWithConst(SgNode* node, ConstReporter* constReporter) {
   typedef pair<SgExpression*,int> SubstitutionPair;
   typedef list<SubstitutionPair > SubstitutionList;
   SubstitutionList substitutionList;
   RoseAst ast(node);
   for(RoseAst::iterator i=ast.begin();i!=ast.end();++i) {
     if(constReporter->isConst(*i)) {
       int varIntValue=constReporter->getConstInt();
       SgVarRefExp* varRefExp=constReporter->getVarRefExp();
       SubstitutionPair p=make_pair(varRefExp,varIntValue);
       substitutionList.push_back(p);
     }
   }
   for(SubstitutionList::iterator i=substitutionList.begin(); i!=substitutionList.end(); ++i) {
     // buildSignedIntType()
     // buildFloatType()
     // buildDoubleType()
     // SgIntVal* buildIntVal(int)
     SgNodeHelper::replaceExpression((*i).first,SageBuilder::buildIntVal((*i).second),false);
   }
   return (int)substitutionList.size();
 }
Example #18
0
static ManagedValue emitBuiltinCastBitPatternFromBridgeObject(
                                                  SILGenFunction &SGF,
                                                  SILLocation loc,
                                                  SubstitutionList subs,
                                                  ArrayRef<ManagedValue> args,
                                                  SGFContext C) {
  assert(args.size() == 1 && "cast should have one argument");
  assert(subs.empty() && "cast should not have subs");

  SILType wordType = SILType::getBuiltinWordType(SGF.getASTContext());
  SILValue result = SGF.B.createBridgeObjectToWord(loc, args[0].getValue(),
                                                   wordType);
  return ManagedValue::forUnmanaged(result);
}
Example #19
0
static ManagedValue
emitBuiltinIsUniqueOrPinned(SILGenFunction &SGF,
                               SILLocation loc,
                               SubstitutionList subs,
                               ArrayRef<ManagedValue> args,
                               SGFContext C) {
  assert(subs.size() == 1 && "isUnique should have a single substitution");
  assert(args.size() == 1 && "isUnique should have a single argument");
  assert((args[0].getType().isAddress() && !args[0].hasCleanup()) &&
         "Builtin.isUnique takes an address.");

  return ManagedValue::forUnmanaged(
    SGF.B.createIsUniqueOrPinned(loc, args[0].getValue()));
}
Example #20
0
static ManagedValue
emitBuiltinIsUniqueOrPinned_native(SILGenFunction &SGF,
                                   SILLocation loc,
                                   SubstitutionList subs,
                                   ArrayRef<ManagedValue> args,
                                   SGFContext C) {

  assert(subs.size() == 1 && "isUniqueOrPinned_native should have one sub.");
  assert(args.size() == 1 && "isUniqueOrPinned_native should have one arg.");

  auto ToType =
    SILType::getNativeObjectType(SGF.getASTContext()).getAddressType();
  auto toAddr = SGF.B.createUncheckedAddrCast(loc, args[0].getValue(), ToType);
  SILValue result = SGF.B.createIsUniqueOrPinned(loc, toAddr);
  return ManagedValue::forUnmanaged(result);
}
Example #21
0
static ManagedValue emitBuiltinBindMemory(SILGenFunction &SGF,
                                          SILLocation loc,
                                          SubstitutionList subs,
                                          ArrayRef<ManagedValue> args,
                                          SGFContext C) {
  assert(subs.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[0].getReplacement()->getCanonicalType();
  SILType boundType = SGF.getLoweredType(boundFormalType);

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

  return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
}
Example #22
0
/// Specialized emitter for Builtin.gep.
static ManagedValue emitBuiltinGep(SILGenFunction &gen,
                                   SILLocation loc,
                                   SubstitutionList substitutions,
                                   ArrayRef<ManagedValue> args,
                                   CanFunctionType formalApplyType,
                                   SGFContext C) {
  assert(substitutions.size() == 1 && "gep should have two substitutions");
  assert(args.size() == 3 && "gep should be given three arguments");

  SILType ElemTy = gen.getLoweredType(substitutions[0].getReplacement());
  SILType RawPtrType = args[0].getUnmanagedValue()->getType();
  SILValue addr = gen.B.createPointerToAddress(loc, args[0].getUnmanagedValue(),
                                               ElemTy.getAddressType(), true);
  addr = gen.B.createIndexAddr(loc, addr, args[1].getUnmanagedValue());
  addr = gen.B.createAddressToPointer(loc, addr, RawPtrType);

  return ManagedValue::forUnmanaged(addr);
}
Example #23
0
static ManagedValue emitBuiltinTypeTrait(SILGenFunction &gen,
                                        SILLocation loc,
                                        SubstitutionList substitutions,
                                        ArrayRef<ManagedValue> args,
                                        CanFunctionType formalApplyType,
                                        SGFContext C) {
  assert(substitutions.size() == 1
         && "type trait should take a single type parameter");
  assert(args.size() == 1
         && "type trait should take a single argument");
  
  unsigned result;
  
  auto traitTy = substitutions[0].getReplacement()->getCanonicalType();
  
  switch ((traitTy.getPointer()->*Trait)()) {
  // If the type obviously has or lacks the trait, emit a constant result.
  case TypeTraitResult::IsNot:
    result = 0;
    break;
  case TypeTraitResult::Is:
    result = 1;
    break;
      
  // If not, emit the builtin call normally. Specialization may be able to
  // eliminate it later, or we'll lower it away at IRGen time.
  case TypeTraitResult::CanBe: {
    auto &C = gen.getASTContext();
    auto int8Ty = BuiltinIntegerType::get(8, C)->getCanonicalType();
    auto apply = gen.B.createBuiltin(loc,
                                     C.getIdentifier(getBuiltinName(Kind)),
                                     SILType::getPrimitiveObjectType(int8Ty),
                                     substitutions, args[0].getValue());
    
    return ManagedValue::forUnmanaged(apply);
  }
  }
  
  // Produce the result as an integer literal constant.
  auto val = gen.B.createIntegerLiteral(
      loc, SILType::getBuiltinIntegerType(8, gen.getASTContext()),
      (uintmax_t)result);
  return ManagedValue::forUnmanaged(val);
}
Example #24
0
static ManagedValue emitBuiltinProjectTailElems(SILGenFunction &SGF,
                                                SILLocation loc,
                                                SubstitutionList subs,
                                                ArrayRef<ManagedValue> args,
                                                SGFContext C) {
  assert(subs.size() == 2 &&
         "allocWithTailElems should have two substitutions");
  assert(args.size() == 2 &&
         "allocWithTailElems should have three arguments");

  // The substitution determines the element type for bound memory.
  SILType ElemType = SGF.getLoweredType(subs[1].getReplacement()->
                                        getCanonicalType()).getObjectType();

  SILValue result = SGF.B.createRefTailAddr(loc, args[0].getValue(),
                                            ElemType.getAddressType());
  SILType rawPointerType = SILType::getRawPointerType(SGF.F.getASTContext());
  result = SGF.B.createAddressToPointer(loc, result, rawPointerType);
  return ManagedValue::forUnmanaged(result);
}
Example #25
0
/// Specialized emitter for Builtin.bridgeFromRawPointer.
static ManagedValue emitBuiltinBridgeFromRawPointer(SILGenFunction &SGF,
                                        SILLocation loc,
                                        SubstitutionList substitutions,
                                        ArrayRef<ManagedValue> args,
                                        SGFContext C) {
  assert(substitutions.size() == 1 &&
         "bridge should have a single substitution");
  assert(args.size() == 1 && "bridge should have a single argument");
  
  // The substitution determines the destination type.
  // FIXME: Archetype destination type?
  auto &destLowering = SGF.getTypeLowering(substitutions[0].getReplacement());
  assert(destLowering.isLoadable());
  SILType destType = destLowering.getLoweredType();

  // Take the raw pointer argument and cast it to the destination type.
  SILValue result = SGF.B.createRawPointerToRef(loc, args[0].getUnmanagedValue(),
                                                destType);
  // The result has ownership semantics, so retain it with a cleanup.
  return SGF.emitManagedRetain(loc, result, destLowering);
}
Example #26
0
/// Specialized emitter for Builtin.getTailAddr.
static ManagedValue emitBuiltinGetTailAddr(SILGenFunction &SGF,
                                           SILLocation loc,
                                           SubstitutionList substitutions,
                                           ArrayRef<ManagedValue> args,
                                           SGFContext C) {
  assert(substitutions.size() == 2 && "getTailAddr should have two substitutions");
  assert(args.size() == 4 && "gep should be given four arguments");

  SILType ElemTy = SGF.getLoweredType(substitutions[0].getReplacement());
  SILType TailTy = SGF.getLoweredType(substitutions[1].getReplacement());
  SILType RawPtrType = args[0].getUnmanagedValue()->getType();
  SILValue addr = SGF.B.createPointerToAddress(loc, args[0].getUnmanagedValue(),
                                               ElemTy.getAddressType(),
                                               /*strict*/ true,
                                               /*invariant*/ false);
  addr = SGF.B.createTailAddr(loc, addr, args[1].getUnmanagedValue(),
                              TailTy.getAddressType());
  addr = SGF.B.createAddressToPointer(loc, addr, RawPtrType);

  return ManagedValue::forUnmanaged(addr);
}
Example #27
0
/// Specialized emitter for Builtin.castToBridgeObject.
static ManagedValue emitBuiltinCastToBridgeObject(SILGenFunction &gen,
                                                  SILLocation loc,
                                                  SubstitutionList subs,
                                                  ArrayRef<ManagedValue> args,
                                                  CanFunctionType formalApplyType,
                                                  SGFContext C) {
  assert(args.size() == 2 && "cast should have two arguments");
  assert(subs.size() == 1 && "cast should have a type substitution");
  
  // Take the reference type argument and cast it to BridgeObject.
  SILType objPointerType = SILType::getBridgeObjectType(gen.F.getASTContext());

  // Bail if the source type is not a class reference of some kind.
  if (!subs[0].getReplacement()->mayHaveSuperclass() &&
      !subs[0].getReplacement()->isClassExistentialType()) {
    gen.SGM.diagnose(loc, diag::invalid_sil_builtin,
                     "castToBridgeObject source must be a class");
    SILValue undef = SILUndef::get(objPointerType, gen.SGM.M);
    return ManagedValue::forUnmanaged(undef);
  }
  
  // Save the cleanup on the argument so we can forward it onto the cast
  // result.
  auto refCleanup = args[0].getCleanup();
  SILValue ref = args[0].getValue();
  SILValue bits = args[1].getUnmanagedValue();
  
  // If the argument is existential, open it.
  if (subs[0].getReplacement()->isClassExistentialType()) {
    auto openedTy
      = ArchetypeType::getOpened(subs[0].getReplacement());
    SILType loweredOpenedTy = gen.getLoweredLoadableType(openedTy);
    ref = gen.B.createOpenExistentialRef(loc, ref, loweredOpenedTy);
    gen.setArchetypeOpeningSite(openedTy, ref);
  }
  
  SILValue result = gen.B.createRefToBridgeObject(loc, ref, bits);
  return ManagedValue(result, refCleanup);
}
Example #28
0
static ManagedValue emitCastToReferenceType(SILGenFunction &gen,
                                            SILLocation loc,
                                            SubstitutionList substitutions,
                                            ArrayRef<ManagedValue> args,
                                            SGFContext C,
                                            SILType objPointerType) {
  assert(args.size() == 1 && "cast should have a single argument");
  assert(substitutions.size() == 1 && "cast should have a type substitution");
  
  // Bail if the source type is not a class reference of some kind.
  if (!substitutions[0].getReplacement()->mayHaveSuperclass() &&
      !substitutions[0].getReplacement()->isClassExistentialType()) {
    gen.SGM.diagnose(loc, diag::invalid_sil_builtin,
                     "castToNativeObject source must be a class");
    SILValue undef = SILUndef::get(objPointerType, gen.SGM.M);
    return ManagedValue::forUnmanaged(undef);
  }
  
  // Save the cleanup on the argument so we can forward it onto the cast
  // result.
  auto cleanup = args[0].getCleanup();
  
  SILValue arg = args[0].getValue();

  // If the argument is existential, open it.
  if (substitutions[0].getReplacement()->isClassExistentialType()) {
    auto openedTy
      = ArchetypeType::getOpened(substitutions[0].getReplacement());
    SILType loweredOpenedTy = gen.getLoweredLoadableType(openedTy);
    arg = gen.B.createOpenExistentialRef(loc, arg, loweredOpenedTy);
    gen.setArchetypeOpeningSite(openedTy, arg);
  }

  SILValue result = gen.B.createUncheckedRefCast(loc, arg, objPointerType);
  // Return the cast result with the original cleanup.
  return ManagedValue(result, cleanup);
}
Example #29
0
/// Specialized emitter for Builtin.load and Builtin.take.
static ManagedValue emitBuiltinLoadOrTake(SILGenFunction &gen,
                                          SILLocation loc,
                                          SubstitutionList substitutions,
                                          ArrayRef<ManagedValue> args,
                                          CanFunctionType formalApplyType,
                                          SGFContext C,
                                          IsTake_t isTake,
                                          bool isStrict) {
  assert(substitutions.size() == 1 && "load should have single substitution");
  assert(args.size() == 1 && "load should have a single argument");
  
  // The substitution gives the type of the load.  This is always a
  // first-class type; there is no way to e.g. produce a @weak load
  // with this builtin.
  auto &rvalueTL = gen.getTypeLowering(substitutions[0].getReplacement());
  SILType loadedType = rvalueTL.getLoweredType();

  // Convert the pointer argument to a SIL address.
  SILValue addr = gen.B.createPointerToAddress(loc, args[0].getUnmanagedValue(),
                                               loadedType.getAddressType(),
                                               isStrict);
  // Perform the load.
  return gen.emitLoad(loc, addr, rvalueTL, C, isTake);
}
Example #30
0
ManagedValue
SILGenFunction::emitClosureValue(SILLocation loc, SILDeclRef constant,
                                 CanType expectedType,
                                 SubstitutionList subs) {
  auto closure = *constant.getAnyFunctionRef();
  auto captureInfo = closure.getCaptureInfo();
  auto loweredCaptureInfo = SGM.Types.getLoweredLocalCaptures(closure);
  auto hasCaptures = SGM.Types.hasLoweredLocalCaptures(closure);
  assert(((constant.uncurryLevel == 1 && hasCaptures) ||
          (constant.uncurryLevel == 0 && !hasCaptures)) &&
         "curried local functions not yet supported");

  auto constantInfo = getConstantInfo(constant);
  SILValue functionRef = emitGlobalFunctionRef(loc, constant, constantInfo);
  SILType functionTy = functionRef->getType();

  // Apply substitutions.
  auto pft = constantInfo.SILFnType;

  auto *dc = closure.getAsDeclContext()->getParent();
  if (dc->isLocalContext() && !loweredCaptureInfo.hasGenericParamCaptures()) {
    // If the lowered function type is not polymorphic but we were given
    // substitutions, we have a closure in a generic context which does not
    // capture generic parameters. Just drop the substitutions.
    subs = { };
  } else if (closure.getAbstractClosureExpr()) {
    // If we have a closure expression in generic context, Sema won't give
    // us substitutions, so we just use the forwarding substitutions from
    // context.
    subs = getForwardingSubstitutions();
  }

  bool wasSpecialized = false;
  if (!subs.empty()) {
    auto specialized = pft->substGenericArgs(F.getModule(), subs);
    functionTy = SILType::getPrimitiveObjectType(specialized);
    wasSpecialized = true;
  }

  // If we're in top-level code, we don't need to physically capture script
  // globals, but we still need to mark them as escaping so that DI can flag
  // uninitialized uses.
  if (this == SGM.TopLevelSGF) {
    SGM.emitMarkFunctionEscapeForTopLevelCodeGlobals(
        loc, captureInfo);
  }

  if (!hasCaptures && !wasSpecialized) {
    auto result = ManagedValue::forUnmanaged(functionRef);
    return emitOrigToSubstValue(loc, result,
                                AbstractionPattern(expectedType),
                                expectedType);
  }

  SmallVector<ManagedValue, 4> capturedArgs;
  emitCaptures(loc, closure, CaptureEmission::PartialApplication,
               capturedArgs);

  // The partial application takes ownership of the context parameters.
  SmallVector<SILValue, 4> forwardedArgs;
  for (auto capture : capturedArgs)
    forwardedArgs.push_back(capture.forward(*this));

  SILType closureTy =
    SILGenBuilder::getPartialApplyResultType(functionRef->getType(),
                                             capturedArgs.size(), SGM.M,
                                             subs,
                                             ParameterConvention::Direct_Owned);
  auto toClosure =
    B.createPartialApply(loc, functionRef, functionTy,
                         subs, forwardedArgs, closureTy);
  auto result = emitManagedRValueWithCleanup(toClosure);

  // Get the lowered AST types:
  //  - the original type
  auto origLoweredFormalType =
      AbstractionPattern(constantInfo.LoweredInterfaceType);
  if (hasCaptures) {
    // Get the unlowered formal type of the constant, stripping off
    // the first level of function application, which applies captures.
    origLoweredFormalType =
      AbstractionPattern(constantInfo.FormalInterfaceType)
          .getFunctionResultType();

    // Lower it, being careful to use the right generic signature.
    origLoweredFormalType =
      AbstractionPattern(
          origLoweredFormalType.getGenericSignature(),
          SGM.Types.getLoweredASTFunctionType(
              cast<FunctionType>(origLoweredFormalType.getType()),
              0, constant));
  }

  // - the substituted type
  auto substFormalType = cast<FunctionType>(expectedType);
  auto substLoweredFormalType =
    SGM.Types.getLoweredASTFunctionType(substFormalType, 0, constant);

  // Generalize if necessary.
  result = emitOrigToSubstValue(loc, result, origLoweredFormalType,
                                substLoweredFormalType);

  return result;
}