//===--- GenMeta.cpp - IR generation for metadata constructs --------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// // // This file implements IR generation for type metadata constructs. // //===----------------------------------------------------------------------===// #include "swift/AST/ArchetypeBuilder.h" #include "swift/AST/ASTContext.h" #include "swift/AST/CanTypeVisitor.h" #include "swift/AST/Decl.h" #include "swift/AST/IRGenOptions.h" #include "swift/AST/Mangle.h" #include "swift/AST/Substitution.h" #include "swift/AST/Types.h" #include "swift/SIL/FormalLinkage.h" #include "swift/SIL/SILModule.h" #include "swift/SIL/TypeLowering.h" #include "swift/Runtime/Metadata.h" #include "swift/ABI/MetadataValues.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Module.h" #include "llvm/ADT/SmallString.h" #include "Address.h" #include "Callee.h" #include "ClassMetadataLayout.h" #include "ConstantBuilder.h" #include "FixedTypeInfo.h" #include "GenClass.h" #include "GenPoly.h" #include "GenValueWitness.h" #include "GenArchetype.h" #include "GenStruct.h" #include "HeapTypeInfo.h" #include "IRGenModule.h" #include "IRGenDebugInfo.h" #include "Linking.h" #include "ScalarTypeInfo.h" #include "StructMetadataLayout.h" #include "StructLayout.h" #include "EnumMetadataLayout.h" #include "GenMeta.h" using namespace swift; using namespace irgen; static llvm::Value *emitLoadOfObjCHeapMetadataRef(IRGenFunction &IGF, llvm::Value *object); static llvm::LoadInst * emitLoadFromMetadataAtIndex(IRGenFunction &IGF, llvm::Value *metadata, int index, llvm::Type *objectTy, const llvm::Twine &suffix = ""); /// Produce a constant to place in a metatype's isa field /// corresponding to the given metadata kind. static llvm::ConstantInt *getMetadataKind(IRGenModule &IGM, MetadataKind kind) { return llvm::ConstantInt::get(IGM.MetadataKindTy, uint8_t(kind)); } static Address createPointerSizedGEP(IRGenFunction &IGF, Address base, Size offset) { return IGF.Builder.CreateConstArrayGEP(base, IGF.IGM.getOffsetInWords(offset), offset); } // FIXME: willBeRelativelyAddressed is only needed to work around an ld64 bug // resolving relative references to coalesceable symbols. // It should be removed when fixed. rdar://problem/22674524 static llvm::Constant *getMangledTypeName(IRGenModule &IGM, CanType type, bool willBeRelativelyAddressed = false) { auto name = LinkEntity::forTypeMangling(type); llvm::SmallString<32> mangling; name.mangle(mangling); return IGM.getAddrOfGlobalString(mangling, willBeRelativelyAddressed); } llvm::Value *irgen::emitObjCMetadataRefForMetadata(IRGenFunction &IGF, llvm::Value *classPtr) { classPtr = IGF.Builder.CreateBitCast(classPtr, IGF.IGM.ObjCClassPtrTy); // Fetch the metadata for that class. auto call = IGF.Builder.CreateCall(IGF.IGM.getGetObjCClassMetadataFn(), classPtr); call->setDoesNotThrow(); call->setDoesNotAccessMemory(); return call; } /// Emit a reference to the Swift metadata for an Objective-C class. static llvm::Value *emitObjCMetadataRef(IRGenFunction &IGF, ClassDecl *theClass) { // Derive a pointer to the Objective-C class. auto classPtr = emitObjCHeapMetadataRef(IGF, theClass); return emitObjCMetadataRefForMetadata(IGF, classPtr); } namespace { /// A structure for collecting generic arguments for emitting a /// nominal metadata reference. The structure produced here is /// consumed by swift_getGenericMetadata() and must correspond to /// the fill operations that the compiler emits for the bound decl. /// /// FIXME: Rework to use GenericSignature instead of AllArchetypes /// FIXME: Rework for nested generics struct GenericArguments { /// The values to use to initialize the arguments structure. SmallVector Values; SmallVector Types; static unsigned getNumGenericArguments(IRGenModule &IGM, NominalTypeDecl *nominal) { GenericTypeRequirements requirements(IGM, nominal); return unsigned(requirements.hasParentType()) + requirements.getNumTypeRequirements(); } void collectTypes(IRGenModule &IGM, NominalTypeDecl *nominal) { GenericTypeRequirements requirements(IGM, nominal); collectTypes(IGM, requirements); } void collectTypes(IRGenModule &IGM, const GenericTypeRequirements &requirements) { if (requirements.hasParentType()) { Types.push_back(IGM.TypeMetadataPtrTy); } for (auto &requirement : requirements.getRequirements()) { if (requirement.Protocol) { Types.push_back(IGM.WitnessTablePtrTy); } else { Types.push_back(IGM.TypeMetadataPtrTy); } } } void collect(IRGenFunction &IGF, CanBoundGenericType type) { GenericTypeRequirements requirements(IGF.IGM, type->getDecl()); if (requirements.hasParentType()) { Values.push_back(IGF.emitTypeMetadataRef(type.getParent())); } auto subs = type->getSubstitutions(IGF.IGM.getSwiftModule(), nullptr); requirements.enumerateFulfillments(IGF.IGM, subs, [&](unsigned reqtIndex, CanType type, Optional conf) { if (conf) { Values.push_back(emitWitnessTableRef(IGF, type, *conf)); } else { Values.push_back(IGF.emitTypeMetadataRef(type)); } }); collectTypes(IGF.IGM, type->getDecl()); assert(Types.size() == Values.size()); } }; } /// Given an array of polymorphic arguments as might be set up by /// GenericArguments, bind the polymorphic parameters. static void emitPolymorphicParametersFromArray(IRGenFunction &IGF, NominalTypeDecl *typeDecl, Address array) { GenericTypeRequirements requirements(IGF.IGM, typeDecl); array = IGF.Builder.CreateElementBitCast(array, IGF.IGM.TypeMetadataPtrTy); auto getInContext = [&](CanType type) -> CanType { return ArchetypeBuilder::mapTypeIntoContext(typeDecl, type, nullptr) ->getCanonicalType(); }; // If we have a parent type, it's the first parameter. if (requirements.hasParentType()) { auto parentType = getInContext(requirements.getParentType()); llvm::Value *parentMetadata = IGF.Builder.CreateLoad(array); array = IGF.Builder.CreateConstArrayGEP(array, 1, IGF.IGM.getPointerSize()); IGF.bindLocalTypeDataFromTypeMetadata(parentType, IsExact, parentMetadata); } // Okay, bind everything else from the context. requirements.bindFromBuffer(IGF, array, getInContext); } /// Attempts to return a constant heap metadata reference for a /// nominal type. llvm::Constant *irgen::tryEmitConstantTypeMetadataRef(IRGenModule &IGM, CanType type) { auto theDecl = type->getAnyNominal(); assert(theDecl && "emitting constant metadata ref for non-nominal type?"); if (IGM.hasMetadataPattern(theDecl)) return nullptr; if (auto theClass = type->getClassOrBoundGenericClass()) if (!hasKnownSwiftMetadata(IGM, theClass)) return IGM.getAddrOfObjCClass(theClass, NotForDefinition); return IGM.getAddrOfTypeMetadata(type, false); } /// Emit a reference to an ObjC class. In general, the only things /// you're allowed to do with the address of an ObjC class symbol are /// (1) send ObjC messages to it (in which case the message will be /// forwarded to the real class, if one exists) or (2) put it in /// various data sections where the ObjC runtime will properly arrange /// things. Therefore, we must typically force the initialization of /// a class when emitting a reference to it. llvm::Value *irgen::emitObjCHeapMetadataRef(IRGenFunction &IGF, ClassDecl *theClass, bool allowUninitialized) { auto classObject = IGF.IGM.getAddrOfObjCClass(theClass, NotForDefinition); if (allowUninitialized) return classObject; // TODO: memoize this the same way that we memoize Swift type metadata? return IGF.Builder.CreateCall(IGF.IGM.getGetInitializedObjCClassFn(), classObject); } /// Emit a reference to the type metadata for a foreign type. static llvm::Value *emitForeignTypeMetadataRef(IRGenFunction &IGF, CanType type) { llvm::Value *candidate = IGF.IGM.getAddrOfForeignTypeMetadataCandidate(type); auto call = IGF.Builder.CreateCall(IGF.IGM.getGetForeignTypeMetadataFn(), candidate); call->addAttribute(llvm::AttributeSet::FunctionIndex, llvm::Attribute::NoUnwind); call->addAttribute(llvm::AttributeSet::FunctionIndex, llvm::Attribute::ReadNone); return call; } /// Returns a metadata reference for a nominal type. /// /// This is only valid in a couple of special cases: /// 1) The nominal type is generic, in which case we emit a call to the /// generic metadata accessor function, which must be defined separately. /// 2) The nominal type is a value type with a fixed size from this /// resilience domain, in which case we can reference the constant /// metadata directly. /// /// In any other case, a metadata accessor should be called instead. static llvm::Value *emitNominalMetadataRef(IRGenFunction &IGF, NominalTypeDecl *theDecl, CanType theType) { assert(!isa(theDecl)); if (!theDecl->isGenericContext()) { assert(!IGF.IGM.isResilient(theDecl, ResilienceExpansion::Maximal)); // TODO: If Obj-C interop is off, we can relax this to allow referencing // class metadata too. assert(isa(theDecl) || isa(theDecl)); return IGF.IGM.getAddrOfTypeMetadata(theType, false); } // We are applying generic parameters to a generic type. auto boundGeneric = cast(theType); assert(boundGeneric->getDecl() == theDecl); // Check to see if we've maybe got a local reference already. if (auto cache = IGF.tryGetLocalTypeData(theType, LocalTypeDataKind::forTypeMetadata())) return cache; // Grab the substitutions. GenericArguments genericArgs; genericArgs.collect(IGF, boundGeneric); assert(genericArgs.Values.size() > 0 && "no generic args?!"); // Call the generic metadata accessor function. llvm::Function *accessor = IGF.IGM.getAddrOfGenericTypeMetadataAccessFunction(theDecl, genericArgs.Types, NotForDefinition); auto result = IGF.Builder.CreateCall(accessor, genericArgs.Values); result->setDoesNotThrow(); result->addAttribute(llvm::AttributeSet::FunctionIndex, llvm::Attribute::ReadNone); IGF.setScopedLocalTypeData(theType, LocalTypeDataKind::forTypeMetadata(), result); return result; } bool irgen::hasKnownSwiftMetadata(IRGenModule &IGM, CanType type) { if (ClassDecl *theClass = type.getClassOrBoundGenericClass()) { return hasKnownSwiftMetadata(IGM, theClass); } if (auto archetype = dyn_cast(type)) { if (auto superclass = archetype->getSuperclass()) { return hasKnownSwiftMetadata(IGM, superclass->getCanonicalType()); } } // Class existentials, etc. return false; } /// Is the given class known to have Swift-compatible metadata? bool irgen::hasKnownSwiftMetadata(IRGenModule &IGM, ClassDecl *theClass) { // For now, the fact that a declaration was not implemented in Swift // is enough to conclusively force us into a slower path. // Eventually we might have an attribute here or something based on // the deployment target. return hasKnownSwiftImplementation(IGM, theClass); } /// Is the given class known to have an implementation in Swift? bool irgen::hasKnownSwiftImplementation(IRGenModule &IGM, ClassDecl *theClass) { return !theClass->hasClangNode(); } /// Is the given method known to be callable by vtable lookup? bool irgen::hasKnownVTableEntry(IRGenModule &IGM, AbstractFunctionDecl *theMethod) { auto theClass = dyn_cast(theMethod->getDeclContext()); // Extension methods don't get vtable entries. if (!theClass) { return false; } return hasKnownSwiftImplementation(IGM, theClass); } /// Is it basically trivial to access the given metadata? If so, we don't /// need a cache variable in its accessor. bool irgen::isTypeMetadataAccessTrivial(IRGenModule &IGM, CanType type) { assert(!type->hasArchetype()); assert(!type->hasUnboundGenericType()); // Value type metadata only requires dynamic initialization on first // access if it contains a resilient type. if (isa(type) || isa(type)) { assert(!type->getAnyNominal()->isGenericContext() && "shouldn't be called for a generic type"); // Imported type metadata always requires an accessor. if (type->getAnyNominal()->hasClangNode()) return false; // Resiliently-sized metadata access always requires an accessor. return (IGM.getTypeInfoForLowered(type).isFixedSize()); } // The empty tuple type has a singleton metadata. if (auto tuple = dyn_cast(type)) return tuple->getNumElements() == 0; // The builtin types generally don't require metadata, but some of them // have nodes in the runtime anyway. if (isa(type)) return true; // SIL box types are artificial, but for the purposes of dynamic layout, // we use the NativeObject metadata. if (isa(type)) return true; // DynamicSelfType is actually local. if (type->hasDynamicSelfType()) return true; return false; } /// Return the standard access strategy for getting a non-dependent /// type metadata object. MetadataAccessStrategy irgen::getTypeMetadataAccessStrategy(IRGenModule &IGM, CanType type) { // We should not be emitting accessors for partially-substituted // generic types. assert(!type->hasArchetype()); // Non-generic structs, enums, and classes are special cases. // // Note that while protocol types don't have a metadata pattern, // we still require an accessor since we actually want to get // the metadata for the existential type. auto nominal = type->getAnyNominal(); if (nominal && !isa(nominal)) { // Metadata accessors for fully-substituted generic types are // emitted with shared linkage. if (nominal->isGenericContext()) { if (isa(type)) return MetadataAccessStrategy::NonUniqueAccessor; assert(isa(type)); } // If the type doesn't guarantee that it has an access function, // we might have to use a non-unique accessor. // Everything else requires accessors. switch (getDeclLinkage(nominal)) { case FormalLinkage::PublicUnique: return MetadataAccessStrategy::PublicUniqueAccessor; case FormalLinkage::HiddenUnique: return MetadataAccessStrategy::HiddenUniqueAccessor; case FormalLinkage::Private: return MetadataAccessStrategy::PrivateAccessor; case FormalLinkage::PublicNonUnique: case FormalLinkage::HiddenNonUnique: return MetadataAccessStrategy::NonUniqueAccessor; } llvm_unreachable("bad formal linkage"); } // Everything else requires a shared accessor function. return MetadataAccessStrategy::NonUniqueAccessor; } /// Emit a string encoding the labels in the given tuple type. static llvm::Constant *getTupleLabelsString(IRGenModule &IGM, CanTupleType type) { bool hasLabels = false; llvm::SmallString<128> buffer; for (auto &elt : type->getElements()) { if (elt.hasName()) { hasLabels = true; buffer.append(elt.getName().str()); } // Each label is space-terminated. buffer += ' '; } // If there are no labels, use a null pointer. if (!hasLabels) { return llvm::ConstantPointerNull::get(IGM.Int8PtrTy); } // Otherwise, create a new string literal. // This method implicitly adds a null terminator. return IGM.getAddrOfGlobalString(buffer); } namespace { /// A visitor class for emitting a reference to a metatype object. /// This implements a "raw" access, useful for implementing cache /// functions or for implementing dependent accesses. /// /// If the access requires runtime initialization, that initialization /// must be dependency-ordered-before any load that carries a dependency /// from the resulting metadata pointer. class EmitTypeMetadataRef : public CanTypeVisitor { private: IRGenFunction &IGF; public: EmitTypeMetadataRef(IRGenFunction &IGF) : IGF(IGF) {} #define TREAT_AS_OPAQUE(KIND) \ llvm::Value *visit##KIND##Type(KIND##Type *type) { \ return visitOpaqueType(CanType(type)); \ } TREAT_AS_OPAQUE(BuiltinInteger) TREAT_AS_OPAQUE(BuiltinFloat) TREAT_AS_OPAQUE(BuiltinVector) TREAT_AS_OPAQUE(BuiltinRawPointer) #undef TREAT_AS_OPAQUE llvm::Value *emitDirectMetadataRef(CanType type) { return IGF.IGM.getAddrOfTypeMetadata(type, /*pattern*/ false); } /// The given type should use opaque type info. We assume that /// the runtime always provides an entry for such a type; right /// now, that mapping is as one of the power-of-two integer types. llvm::Value *visitOpaqueType(CanType type) { auto &opaqueTI = cast(IGF.IGM.getTypeInfoForLowered(type)); unsigned numBits = opaqueTI.getFixedSize().getValueInBits(); if (!llvm::isPowerOf2_32(numBits)) numBits = llvm::NextPowerOf2(numBits); auto intTy = BuiltinIntegerType::get(numBits, IGF.IGM.Context); return emitDirectMetadataRef(CanType(intTy)); } llvm::Value *visitBuiltinNativeObjectType(CanBuiltinNativeObjectType type) { return emitDirectMetadataRef(type); } llvm::Value *visitBuiltinBridgeObjectType(CanBuiltinBridgeObjectType type) { return emitDirectMetadataRef(type); } llvm::Value *visitBuiltinUnknownObjectType(CanBuiltinUnknownObjectType type) { return emitDirectMetadataRef(type); } llvm::Value *visitBuiltinUnsafeValueBufferType( CanBuiltinUnsafeValueBufferType type) { return emitDirectMetadataRef(type); } llvm::Value *visitNominalType(CanNominalType type) { assert(!type->isExistentialType()); return emitNominalMetadataRef(IGF, type->getDecl(), type); } llvm::Value *visitBoundGenericType(CanBoundGenericType type) { assert(!type->isExistentialType()); return emitNominalMetadataRef(IGF, type->getDecl(), type); } llvm::Value *visitTupleType(CanTupleType type) { if (auto cached = tryGetLocal(type)) return cached; // I think the sanest thing to do here is drop labels, but maybe // that's not correct. If so, that's really unfortunate in a // lot of ways. // Er, varargs bit? Should that go in? switch (type->getNumElements()) { case 0: {// Special case the empty tuple, just use the global descriptor. llvm::Constant *fullMetadata = IGF.IGM.getEmptyTupleMetadata(); llvm::Constant *indices[] = { llvm::ConstantInt::get(IGF.IGM.Int32Ty, 0), llvm::ConstantInt::get(IGF.IGM.Int32Ty, 1) }; return llvm::ConstantExpr::getInBoundsGetElementPtr( /*Ty=*/nullptr, fullMetadata, indices); } case 1: // For metadata purposes, we consider a singleton tuple to be // isomorphic to its element type. return IGF.emitTypeMetadataRef(type.getElementType(0)); case 2: { // Find the metadata pointer for this element. auto elt0Metadata = IGF.emitTypeMetadataRef(type.getElementType(0)); auto elt1Metadata = IGF.emitTypeMetadataRef(type.getElementType(1)); llvm::Value *args[] = { elt0Metadata, elt1Metadata, getTupleLabelsString(IGF.IGM, type), llvm::ConstantPointerNull::get(IGF.IGM.WitnessTablePtrTy) // proposed }; auto call = IGF.Builder.CreateCall(IGF.IGM.getGetTupleMetadata2Fn(), args); call->setDoesNotThrow(); return setLocal(CanType(type), call); } case 3: { // Find the metadata pointer for this element. auto elt0Metadata = IGF.emitTypeMetadataRef(type.getElementType(0)); auto elt1Metadata = IGF.emitTypeMetadataRef(type.getElementType(1)); auto elt2Metadata = IGF.emitTypeMetadataRef(type.getElementType(2)); llvm::Value *args[] = { elt0Metadata, elt1Metadata, elt2Metadata, getTupleLabelsString(IGF.IGM, type), llvm::ConstantPointerNull::get(IGF.IGM.WitnessTablePtrTy) // proposed }; auto call = IGF.Builder.CreateCall(IGF.IGM.getGetTupleMetadata3Fn(), args); call->setDoesNotThrow(); return setLocal(CanType(type), call); } default: // TODO: use a caching entrypoint (with all information // out-of-line) for non-dependent tuples. llvm::Value *pointerToFirst = nullptr; // appease -Wuninitialized auto elements = type.getElementTypes(); auto arrayTy = llvm::ArrayType::get(IGF.IGM.TypeMetadataPtrTy, elements.size()); Address buffer = IGF.createAlloca(arrayTy,IGF.IGM.getPointerAlignment(), "tuple-elements"); IGF.Builder.CreateLifetimeStart(buffer, IGF.IGM.getPointerSize() * elements.size()); for (unsigned i = 0, e = elements.size(); i != e; ++i) { // Find the metadata pointer for this element. llvm::Value *eltMetadata = IGF.emitTypeMetadataRef(elements[i]); // GEP to the appropriate element and store. Address eltPtr = IGF.Builder.CreateStructGEP(buffer, i, IGF.IGM.getPointerSize()); IGF.Builder.CreateStore(eltMetadata, eltPtr); // Remember the GEP to the first element. if (i == 0) pointerToFirst = eltPtr.getAddress(); } llvm::Value *args[] = { llvm::ConstantInt::get(IGF.IGM.SizeTy, elements.size()), pointerToFirst, getTupleLabelsString(IGF.IGM, type), llvm::ConstantPointerNull::get(IGF.IGM.WitnessTablePtrTy) // proposed }; auto call = IGF.Builder.CreateCall(IGF.IGM.getGetTupleMetadataFn(), args); call->setDoesNotThrow(); IGF.Builder.CreateLifetimeEnd(buffer, IGF.IGM.getPointerSize() * elements.size()); return setLocal(type, call); } } llvm::Value *visitPolymorphicFunctionType(CanPolymorphicFunctionType type) { IGF.unimplemented(SourceLoc(), "metadata ref for polymorphic function type"); return llvm::UndefValue::get(IGF.IGM.TypeMetadataPtrTy); } llvm::Value *visitGenericFunctionType(CanGenericFunctionType type) { IGF.unimplemented(SourceLoc(), "metadata ref for generic function type"); return llvm::UndefValue::get(IGF.IGM.TypeMetadataPtrTy); } llvm::Value *extractAndMarkResultType(CanFunctionType type) { // If the function type throws, set the lower bit of the return type // address, so that we can carry this information over to the function // type metadata. auto metadata = IGF.emitTypeMetadataRef(type->getResult()-> getCanonicalType()); return metadata; } llvm::Value *extractAndMarkInOut(CanType type) { // If the type is inout, get the metadata for its inner object type // instead, and then set the lowest bit to help the runtime unique // the metadata type for this function. if (auto inoutType = dyn_cast(type)) { auto metadata = IGF.emitTypeMetadataRef(inoutType.getObjectType()); auto metadataInt = IGF.Builder.CreatePtrToInt(metadata, IGF.IGM.SizeTy); auto inoutFlag = llvm::ConstantInt::get(IGF.IGM.SizeTy, 1); auto marked = IGF.Builder.CreateOr(metadataInt, inoutFlag); return IGF.Builder.CreateIntToPtr(marked, IGF.IGM.Int8PtrTy); } auto metadata = IGF.emitTypeMetadataRef(type); return IGF.Builder.CreateBitCast(metadata, IGF.IGM.Int8PtrTy); } llvm::Value *visitFunctionType(CanFunctionType type) { if (auto metatype = tryGetLocal(type)) return metatype; auto resultMetadata = extractAndMarkResultType(type); CanTupleType inputTuple = dyn_cast(type.getInput()); size_t numArguments = 1; if (inputTuple && !inputTuple->isMaterializable()) numArguments = inputTuple->getNumElements(); // Map the convention to a runtime metadata value. FunctionMetadataConvention metadataConvention; switch (type->getRepresentation()) { case FunctionTypeRepresentation::Swift: metadataConvention = FunctionMetadataConvention::Swift; break; case FunctionTypeRepresentation::Thin: metadataConvention = FunctionMetadataConvention::Thin; break; case FunctionTypeRepresentation::Block: metadataConvention = FunctionMetadataConvention::Block; break; case FunctionTypeRepresentation::CFunctionPointer: metadataConvention = FunctionMetadataConvention::CFunctionPointer; break; } auto flagsVal = FunctionTypeFlags() .withNumArguments(numArguments) .withConvention(metadataConvention) .withThrows(type->throws()); auto flags = llvm::ConstantInt::get(IGF.IGM.SizeTy, flagsVal.getIntValue()); switch (numArguments) { case 1: { auto arg0 = (inputTuple && !inputTuple->isMaterializable()) ? extractAndMarkInOut(inputTuple.getElementType(0)) : extractAndMarkInOut(type.getInput()); auto call = IGF.Builder.CreateCall( IGF.IGM.getGetFunctionMetadata1Fn(), {flags, arg0, resultMetadata}); call->setDoesNotThrow(); return setLocal(CanType(type), call); } case 2: { auto arg0 = extractAndMarkInOut(inputTuple.getElementType(0)); auto arg1 = extractAndMarkInOut(inputTuple.getElementType(1)); auto call = IGF.Builder.CreateCall( IGF.IGM.getGetFunctionMetadata2Fn(), {flags, arg0, arg1, resultMetadata}); call->setDoesNotThrow(); return setLocal(CanType(type), call); } case 3: { auto arg0 = extractAndMarkInOut(inputTuple.getElementType(0)); auto arg1 = extractAndMarkInOut(inputTuple.getElementType(1)); auto arg2 = extractAndMarkInOut(inputTuple.getElementType(2)); auto call = IGF.Builder.CreateCall( IGF.IGM.getGetFunctionMetadata3Fn(), {flags, arg0, arg1, arg2, resultMetadata}); call->setDoesNotThrow(); return setLocal(CanType(type), call); } default: auto arguments = inputTuple.getElementTypes(); auto arrayTy = llvm::ArrayType::get(IGF.IGM.Int8PtrTy, arguments.size() + 2); Address buffer = IGF.createAlloca(arrayTy, IGF.IGM.getPointerAlignment(), "function-arguments"); IGF.Builder.CreateLifetimeStart(buffer, IGF.IGM.getPointerSize() * arguments.size()); Address pointerToFirstArg = IGF.Builder.CreateStructGEP(buffer, 0, Size(0)); Address flagsPtr = IGF.Builder.CreateBitCast(pointerToFirstArg, IGF.IGM.SizeTy->getPointerTo()); IGF.Builder.CreateStore(flags, flagsPtr); for (size_t i = 0; i < arguments.size(); ++i) { auto argMetadata = extractAndMarkInOut( inputTuple.getElementType(i)); Address argPtr = IGF.Builder.CreateStructGEP(buffer, i + 1, IGF.IGM.getPointerSize()); IGF.Builder.CreateStore(argMetadata, argPtr); } Address resultPtr = IGF.Builder.CreateStructGEP(buffer, arguments.size() + 1, IGF.IGM.getPointerSize()); resultPtr = IGF.Builder.CreateBitCast(resultPtr, IGF.IGM.TypeMetadataPtrTy->getPointerTo()); IGF.Builder.CreateStore(resultMetadata, resultPtr); auto call = IGF.Builder.CreateCall(IGF.IGM.getGetFunctionMetadataFn(), pointerToFirstArg.getAddress()); call->setDoesNotThrow(); IGF.Builder.CreateLifetimeEnd(buffer, IGF.IGM.getPointerSize() * arguments.size()); return setLocal(type, call); } } llvm::Value *visitAnyMetatypeType(CanAnyMetatypeType type) { // FIXME: We shouldn't accept a lowered metatype here, but we need to // represent Optional<@objc_metatype T.Type> as an AST type for ABI // reasons. // assert(!type->hasRepresentation() // && "should not be asking for a representation-specific metatype " // "metadata"); if (auto metatype = tryGetLocal(type)) return metatype; auto instMetadata = IGF.emitTypeMetadataRef(type.getInstanceType()); auto fn = isa(type) ? IGF.IGM.getGetMetatypeMetadataFn() : IGF.IGM.getGetExistentialMetatypeMetadataFn(); auto call = IGF.Builder.CreateCall(fn, instMetadata); call->setDoesNotThrow(); return setLocal(type, call); } llvm::Value *visitModuleType(CanModuleType type) { IGF.unimplemented(SourceLoc(), "metadata ref for module type"); return llvm::UndefValue::get(IGF.IGM.TypeMetadataPtrTy); } llvm::Value *visitDynamicSelfType(CanDynamicSelfType type) { return IGF.getLocalSelfMetadata(); } llvm::Value *emitExistentialTypeMetadata(CanType type) { SmallVector protocols; type.getAnyExistentialTypeProtocols(protocols); // Collect references to the protocol descriptors. auto descriptorArrayTy = llvm::ArrayType::get(IGF.IGM.ProtocolDescriptorPtrTy, protocols.size()); Address descriptorArray = IGF.createAlloca(descriptorArrayTy, IGF.IGM.getPointerAlignment(), "protocols"); IGF.Builder.CreateLifetimeStart(descriptorArray, IGF.IGM.getPointerSize() * protocols.size()); descriptorArray = IGF.Builder.CreateBitCast(descriptorArray, IGF.IGM.ProtocolDescriptorPtrTy->getPointerTo()); unsigned index = 0; for (auto *p : protocols) { llvm::Value *ref = emitProtocolDescriptorRef(IGF, p); Address slot = IGF.Builder.CreateConstArrayGEP(descriptorArray, index, IGF.IGM.getPointerSize()); IGF.Builder.CreateStore(ref, slot); ++index; } auto call = IGF.Builder.CreateCall(IGF.IGM.getGetExistentialMetadataFn(), {IGF.IGM.getSize(Size(protocols.size())), descriptorArray.getAddress()}); call->setDoesNotThrow(); IGF.Builder.CreateLifetimeEnd(descriptorArray, IGF.IGM.getPointerSize() * protocols.size()); return setLocal(type, call); } llvm::Value *visitProtocolType(CanProtocolType type) { return emitExistentialTypeMetadata(type); } llvm::Value *visitProtocolCompositionType(CanProtocolCompositionType type) { return emitExistentialTypeMetadata(type); } llvm::Value *visitReferenceStorageType(CanReferenceStorageType type) { llvm_unreachable("reference storage type should have been converted by " "SILGen"); } llvm::Value *visitSILFunctionType(CanSILFunctionType type) { llvm_unreachable("should not be asking for metadata of a lowered SIL " "function type--SILGen should have used the AST type"); } llvm::Value *visitArchetypeType(CanArchetypeType type) { return emitArchetypeTypeMetadataRef(IGF, type); } llvm::Value *visitGenericTypeParamType(CanGenericTypeParamType type) { llvm_unreachable("dependent type should have been substituted by Sema or SILGen"); } llvm::Value *visitDependentMemberType(CanDependentMemberType type) { llvm_unreachable("dependent type should have been substituted by Sema or SILGen"); } llvm::Value *visitLValueType(CanLValueType type) { llvm_unreachable("lvalue type should have been lowered by SILGen"); } llvm::Value *visitInOutType(CanInOutType type) { llvm_unreachable("inout type should have been lowered by SILGen"); } llvm::Value *visitSILBlockStorageType(CanSILBlockStorageType type) { llvm_unreachable("cannot ask for metadata of block storage"); } llvm::Value *visitSILBoxType(CanSILBoxType type) { // The Builtin.NativeObject metadata can stand in for boxes. return emitDirectMetadataRef(type->getASTContext().TheNativeObjectType); } /// Try to find the metatype in local data. llvm::Value *tryGetLocal(CanType type) { return IGF.tryGetLocalTypeData(type, LocalTypeDataKind::forTypeMetadata()); } /// Set the metatype in local data. llvm::Value *setLocal(CanType type, llvm::Instruction *metatype) { IGF.setScopedLocalTypeData(type, LocalTypeDataKind::forTypeMetadata(), metatype); return metatype; } }; } /// Emit a type metadata reference without using an accessor function. static llvm::Value *emitDirectTypeMetadataRef(IRGenFunction &IGF, CanType type) { return EmitTypeMetadataRef(IGF).visit(type); } static Address emitAddressOfSuperclassRefInClassMetadata(IRGenFunction &IGF, llvm::Value *metadata) { // The superclass field in a class type is the first field past the isa. unsigned index = 1; Address addr(metadata, IGF.IGM.getPointerAlignment()); addr = IGF.Builder.CreateBitCast(addr, IGF.IGM.TypeMetadataPtrTy->getPointerTo()); return IGF.Builder.CreateConstArrayGEP(addr, index, IGF.IGM.getPointerSize()); } /// Emit the body of a lazy cache accessor. /// /// If cacheVariable is null, we perform the direct access every time. /// This is used for metadata accessors that come about due to resilience, /// where the direct access is completely trivial. void irgen::emitLazyCacheAccessFunction(IRGenModule &IGM, llvm::Function *accessor, llvm::GlobalVariable *cacheVariable, const llvm::function_ref &getValue) { accessor->setDoesNotThrow(); // This function is logically 'readnone': the caller does not need // to reason about any side effects or stores it might perform. accessor->setDoesNotAccessMemory(); IRGenFunction IGF(IGM, accessor); if (IGM.DebugInfo) IGM.DebugInfo->emitArtificialFunction(IGF, accessor); // If there's no cache variable, just perform the direct access. if (cacheVariable == nullptr) { IGF.Builder.CreateRet(getValue(IGF)); return; } // Set up the cache variable. llvm::Constant *null = llvm::ConstantPointerNull::get( cast(cacheVariable->getValueType())); cacheVariable->setInitializer(null); cacheVariable->setAlignment(IGM.getPointerAlignment().getValue()); Address cache(cacheVariable, IGM.getPointerAlignment()); // Okay, first thing, check the cache variable. // // Conceptually, this needs to establish memory ordering with the // store we do later in the function: if the metadata value is // non-null, we must be able to see any stores performed by the // initialization of the metadata. However, any attempt to read // from the metadata will be address-dependent on the loaded // metadata pointer, which is sufficient to provide adequate // memory ordering guarantees on all the platforms we care about: // ARM has special rules about address dependencies, and x86's // memory ordering is strong enough to guarantee the visibility // even without the address dependency. // // And we do not need to worry about the compiler because the // address dependency naturally forces an order to the memory // accesses. // // Therefore, we can perform a completely naked load here. // FIXME: Technically should be "consume", but that introduces barriers in the // current LLVM ARM backend. auto load = IGF.Builder.CreateLoad(cache); // Compare the load result against null. auto isNullBB = IGF.createBasicBlock("cacheIsNull"); auto contBB = IGF.createBasicBlock("cont"); llvm::Value *comparison = IGF.Builder.CreateICmpEQ(load, null); IGF.Builder.CreateCondBr(comparison, isNullBB, contBB); auto loadBB = IGF.Builder.GetInsertBlock(); // If the load yielded null, emit the type metadata. IGF.Builder.emitBlock(isNullBB); llvm::Value *directResult = getValue(IGF); // Store it back to the cache variable. The direct metadata lookup is // required to have already dependency-ordered any initialization // it triggered before loads from the pointer it returned. IGF.Builder.CreateStore(directResult, cache); IGF.Builder.CreateBr(contBB); auto storeBB = IGF.Builder.GetInsertBlock(); // Emit the continuation block. IGF.Builder.emitBlock(contBB); auto phi = IGF.Builder.CreatePHI(null->getType(), 2); phi->addIncoming(load, loadBB); phi->addIncoming(directResult, storeBB); IGF.Builder.CreateRet(phi); } static llvm::Value *emitGenericMetadataAccessFunction(IRGenFunction &IGF, NominalTypeDecl *nominal, GenericArguments &genericArgs) { CanType declaredType = nominal->getDeclaredType()->getCanonicalType(); llvm::Value *metadata = IGF.IGM.getAddrOfTypeMetadata(declaredType, true); // Collect input arguments to the generic metadata accessor, as laid out // by the GenericArguments class. for (auto &arg : IGF.CurFn->args()) genericArgs.Values.push_back(&arg); assert(genericArgs.Values.size() == genericArgs.Types.size()); assert(genericArgs.Values.size() > 0 && "no generic args?!"); // Slam that information directly into the generic arguments buffer. auto argsBufferTy = llvm::StructType::get(IGF.IGM.LLVMContext, genericArgs.Types); Address argsBuffer = IGF.createAlloca(argsBufferTy, IGF.IGM.getPointerAlignment(), "generic.arguments"); IGF.Builder.CreateLifetimeStart(argsBuffer, IGF.IGM.getPointerSize() * genericArgs.Values.size()); for (unsigned i = 0, e = genericArgs.Values.size(); i != e; ++i) { Address elt = IGF.Builder.CreateStructGEP(argsBuffer, i, IGF.IGM.getPointerSize() * i); IGF.Builder.CreateStore(genericArgs.Values[i], elt); } // Cast to void*. llvm::Value *arguments = IGF.Builder.CreateBitCast(argsBuffer.getAddress(), IGF.IGM.Int8PtrTy); // Make the call. auto result = IGF.Builder.CreateCall(IGF.IGM.getGetGenericMetadataFn(), {metadata, arguments}); result->setDoesNotThrow(); result->addAttribute(llvm::AttributeSet::FunctionIndex, llvm::Attribute::ReadOnly); IGF.Builder.CreateLifetimeEnd(argsBuffer, IGF.IGM.getPointerSize() * genericArgs.Values.size()); return result; } /// Emit the body of a metadata accessor function for the given type. static llvm::Value *emitMetadataAccessFunction(IRGenFunction &IGF, CanType type) { if (auto nominal = type->getAnyNominal()) { if (nominal->isGenericContext()) { // This is a metadata accessor for a fully substituted generic type. assert(!type->hasArchetype() && "partially substituted types do not have accessors"); return emitDirectTypeMetadataRef(IGF, type); } // We should not be emitting metadata accessors for types unless // we have full knowledge of their layout. assert(!IGF.IGM.isResilient(nominal, ResilienceExpansion::Maximal)); // We will still have a metadata pattern if the type is not generic, // but contains resiliently-sized fields. bool isPattern = IGF.IGM.hasMetadataPattern(nominal); // Non-native Swift classes need to be handled differently. if (auto classDecl = dyn_cast(nominal)) { // We emit a completely different pattern for foreign classes. if (classDecl->isForeign()) { return emitForeignTypeMetadataRef(IGF, type); } // Classes that might not have Swift metadata use a different // symbol name. if (!hasKnownSwiftMetadata(IGF.IGM, classDecl)) { assert(!classDecl->isGenericContext() && "ObjC class cannot be generic"); return emitObjCMetadataRef(IGF, classDecl); } // If this is a class with constant metadata, we still need to // force ObjC initialization if we're doing Objective-C interop. if (IGF.IGM.ObjCInterop && !isPattern) { llvm::Value *metadata = IGF.IGM.getAddrOfTypeMetadata(type, false); metadata = IGF.Builder.CreateBitCast(metadata, IGF.IGM.ObjCClassPtrTy); metadata = IGF.Builder.CreateCall(IGF.IGM.getGetInitializedObjCClassFn(), metadata); return IGF.Builder.CreateBitCast(metadata, IGF.IGM.TypeMetadataPtrTy); } // Imported value types require foreign metadata uniquing too. } else if (nominal->hasClangNode()) { return emitForeignTypeMetadataRef(IGF, type); } // If we have a pattern but no generic substitutions, we're just // doing resilient type layout. if (isPattern) { llvm::Constant *getter = IGF.IGM.getGetResilientMetadataFn(); llvm::Value *metadata = IGF.IGM.getAddrOfTypeMetadata(type, true); auto result = IGF.Builder.CreateCall(getter, {metadata}); result->setDoesNotThrow(); result->addAttribute(llvm::AttributeSet::FunctionIndex, llvm::Attribute::ReadNone); return result; } // Accessor is trivial, just return pointer to constant metadata. return IGF.IGM.getAddrOfTypeMetadata(type, false); } return emitDirectTypeMetadataRef(IGF, type); } /// Get or create an accessor function to the given non-dependent type. static llvm::Function *getTypeMetadataAccessFunction(IRGenModule &IGM, CanType type, ForDefinition_t shouldDefine) { assert(!type->hasArchetype()); assert(!isa(type)); llvm::Function *accessor = IGM.getAddrOfTypeMetadataAccessFunction(type, shouldDefine); // If we're not supposed to define the accessor, or if we already // have defined it, just return the pointer. if (!shouldDefine || !accessor->empty()) return accessor; // Okay, define the accessor. llvm::GlobalVariable *cacheVariable = nullptr; // If our preferred access method is to go via an accessor, it means // there is some non-trivial computation that needs to be cached. if (!isTypeMetadataAccessTrivial(IGM, type)) { cacheVariable = cast( IGM.getAddrOfTypeMetadataLazyCacheVariable(type, ForDefinition)); } emitLazyCacheAccessFunction(IGM, accessor, cacheVariable, [&](IRGenFunction &IGF) -> llvm::Value* { return emitMetadataAccessFunction(IGF, type); }); return accessor; } /// Get or create an accessor function to the given generic type. static llvm::Function *getGenericTypeMetadataAccessFunction(IRGenModule &IGM, NominalTypeDecl *nominal, ForDefinition_t shouldDefine) { assert(nominal->isGenericContext()); GenericArguments genericArgs; genericArgs.collectTypes(IGM, nominal); llvm::Function *accessor = IGM.getAddrOfGenericTypeMetadataAccessFunction( nominal, genericArgs.Types, shouldDefine); // If we're not supposed to define the accessor, or if we already // have defined it, just return the pointer. if (!shouldDefine || !accessor->empty()) return accessor; emitLazyCacheAccessFunction(IGM, accessor, /*cacheVariable=*/nullptr, [&](IRGenFunction &IGF) -> llvm::Value* { return emitGenericMetadataAccessFunction(IGF, nominal, genericArgs); }); return accessor; } /// Force a public metadata access function into existence if necessary /// for the given type. static void maybeEmitTypeMetadataAccessFunction(IRGenModule &IGM, NominalTypeDecl *theDecl) { if (theDecl->isGenericContext()) { (void) getGenericTypeMetadataAccessFunction(IGM, theDecl, ForDefinition); return; } CanType declaredType = theDecl->getDeclaredType()->getCanonicalType(); (void) getTypeMetadataAccessFunction(IGM, declaredType, ForDefinition); } /// Emit a call to the type metadata accessor for the given function. static llvm::Value *emitCallToTypeMetadataAccessFunction(IRGenFunction &IGF, CanType type, ForDefinition_t shouldDefine) { // If we already cached the metadata, use it. if (auto local = IGF.tryGetLocalTypeData(type, LocalTypeDataKind::forTypeMetadata())) return local; llvm::Constant *accessor = getTypeMetadataAccessFunction(IGF.IGM, type, shouldDefine); llvm::CallInst *call = IGF.Builder.CreateCall(accessor, {}); call->setCallingConv(IGF.IGM.DefaultCC); call->setDoesNotAccessMemory(); call->setDoesNotThrow(); // Save the metadata for future lookups. IGF.setScopedLocalTypeData(type, LocalTypeDataKind::forTypeMetadata(), call); return call; } /// Produce the type metadata pointer for the given type. llvm::Value *IRGenFunction::emitTypeMetadataRef(CanType type) { if (type->hasArchetype() || isTypeMetadataAccessTrivial(IGM, type)) { return emitDirectTypeMetadataRef(*this, type); } switch (getTypeMetadataAccessStrategy(IGM, type)) { case MetadataAccessStrategy::PublicUniqueAccessor: case MetadataAccessStrategy::HiddenUniqueAccessor: case MetadataAccessStrategy::PrivateAccessor: return emitCallToTypeMetadataAccessFunction(*this, type, NotForDefinition); case MetadataAccessStrategy::NonUniqueAccessor: return emitCallToTypeMetadataAccessFunction(*this, type, ForDefinition); } llvm_unreachable("bad type metadata access strategy"); } /// Return the address of a function that will return type metadata /// for the given non-dependent type. llvm::Function *irgen::getOrCreateTypeMetadataAccessFunction(IRGenModule &IGM, CanType type) { assert(!type->hasArchetype() && "cannot create global function to return dependent type metadata"); switch (getTypeMetadataAccessStrategy(IGM, type)) { case MetadataAccessStrategy::PublicUniqueAccessor: case MetadataAccessStrategy::HiddenUniqueAccessor: case MetadataAccessStrategy::PrivateAccessor: return getTypeMetadataAccessFunction(IGM, type, NotForDefinition); case MetadataAccessStrategy::NonUniqueAccessor: return getTypeMetadataAccessFunction(IGM, type, ForDefinition); } llvm_unreachable("bad type metadata access strategy"); } namespace { /// A visitor class for emitting a reference to a metatype object. /// This implements a "raw" access, useful for implementing cache /// functions or for implementing dependent accesses. class EmitTypeMetadataRefForLayout : public CanTypeVisitor { private: IRGenFunction &IGF; public: EmitTypeMetadataRefForLayout(IRGenFunction &IGF) : IGF(IGF) {} llvm::Value *emitDirectMetadataRef(CanType type) { return IGF.IGM.getAddrOfTypeMetadata(type, /*pattern*/ false); } /// For most types, we can just emit the usual metadata. llvm::Value *visitType(CanType t) { return IGF.emitTypeMetadataRef(t); } llvm::Value *visitTupleType(CanTupleType type) { if (auto cached = tryGetLocal(type)) return cached; switch (type->getNumElements()) { case 0: {// Special case the empty tuple, just use the global descriptor. llvm::Constant *fullMetadata = IGF.IGM.getEmptyTupleMetadata(); llvm::Constant *indices[] = { llvm::ConstantInt::get(IGF.IGM.Int32Ty, 0), llvm::ConstantInt::get(IGF.IGM.Int32Ty, 1) }; return llvm::ConstantExpr::getInBoundsGetElementPtr( /*Ty=*/nullptr, fullMetadata, indices); } case 1: // For layout purposes, we consider a singleton tuple to be // isomorphic to its element type. return visit(type.getElementType(0)); case 2: { // Find the layout metadata pointers for these elements. auto elt0Metadata = visit(type.getElementType(0)); auto elt1Metadata = visit(type.getElementType(1)); llvm::Value *args[] = { elt0Metadata, elt1Metadata, // labels don't matter for layout llvm::ConstantPointerNull::get(IGF.IGM.Int8PtrTy), llvm::ConstantPointerNull::get(IGF.IGM.WitnessTablePtrTy) // proposed }; auto call = IGF.Builder.CreateCall(IGF.IGM.getGetTupleMetadata2Fn(), args); call->setDoesNotThrow(); return setLocal(CanType(type), call); } case 3: { // Find the layout metadata pointers for these elements. auto elt0Metadata = visit(type.getElementType(0)); auto elt1Metadata = visit(type.getElementType(1)); auto elt2Metadata = visit(type.getElementType(2)); llvm::Value *args[] = { elt0Metadata, elt1Metadata, elt2Metadata, // labels don't matter for layout llvm::ConstantPointerNull::get(IGF.IGM.Int8PtrTy), llvm::ConstantPointerNull::get(IGF.IGM.WitnessTablePtrTy) // proposed }; auto call = IGF.Builder.CreateCall(IGF.IGM.getGetTupleMetadata3Fn(), args); call->setDoesNotThrow(); return setLocal(CanType(type), call); } default: // TODO: use a caching entrypoint (with all information // out-of-line) for non-dependent tuples. llvm::Value *pointerToFirst = nullptr; // appease -Wuninitialized auto elements = type.getElementTypes(); auto arrayTy = llvm::ArrayType::get(IGF.IGM.TypeMetadataPtrTy, elements.size()); Address buffer = IGF.createAlloca(arrayTy,IGF.IGM.getPointerAlignment(), "tuple-elements"); IGF.Builder.CreateLifetimeStart(buffer, IGF.IGM.getPointerSize() * elements.size()); for (unsigned i = 0, e = elements.size(); i != e; ++i) { // Find the metadata pointer for this element. llvm::Value *eltMetadata = visit(elements[i]); // GEP to the appropriate element and store. Address eltPtr = IGF.Builder.CreateStructGEP(buffer, i, IGF.IGM.getPointerSize()); IGF.Builder.CreateStore(eltMetadata, eltPtr); // Remember the GEP to the first element. if (i == 0) pointerToFirst = eltPtr.getAddress(); } llvm::Value *args[] = { llvm::ConstantInt::get(IGF.IGM.SizeTy, elements.size()), pointerToFirst, // labels don't matter for layout llvm::ConstantPointerNull::get(IGF.IGM.Int8PtrTy), llvm::ConstantPointerNull::get(IGF.IGM.WitnessTablePtrTy) // proposed }; auto call = IGF.Builder.CreateCall(IGF.IGM.getGetTupleMetadataFn(), args); call->setDoesNotThrow(); IGF.Builder.CreateLifetimeEnd(buffer, IGF.IGM.getPointerSize() * elements.size()); return setLocal(type, call); } } llvm::Value *visitAnyFunctionType(CanAnyFunctionType type) { llvm_unreachable("not a SIL type"); } llvm::Value *visitSILFunctionType(CanSILFunctionType type) { // All function types have the same layout regardless of arguments or // abstraction level. Use the metadata for () -> () for thick functions, // or Builtin.UnknownObject for block functions. auto &C = type->getASTContext(); switch (type->getRepresentation()) { case SILFunctionType::Representation::Thin: case SILFunctionType::Representation::Method: case SILFunctionType::Representation::WitnessMethod: case SILFunctionType::Representation::ObjCMethod: case SILFunctionType::Representation::CFunctionPointer: // A thin function looks like a plain pointer. // FIXME: Except for extra inhabitants? return emitDirectMetadataRef(C.TheRawPointerType); case SILFunctionType::Representation::Thick: // All function types look like () -> (). // FIXME: It'd be nice not to have to call through the runtime here. return IGF.emitTypeMetadataRef(CanFunctionType::get(C.TheEmptyTupleType, C.TheEmptyTupleType)); case SILFunctionType::Representation::Block: // All block types look like Builtin.UnknownObject. return emitDirectMetadataRef(C.TheUnknownObjectType); } } llvm::Value *visitAnyMetatypeType(CanAnyMetatypeType type) { assert(type->hasRepresentation() && "not a lowered metatype"); switch (type->getRepresentation()) { case MetatypeRepresentation::Thin: { // Thin metatypes are empty, so they look like the empty tuple type. llvm::Constant *fullMetadata = IGF.IGM.getEmptyTupleMetadata(); llvm::Constant *indices[] = { llvm::ConstantInt::get(IGF.IGM.Int32Ty, 0), llvm::ConstantInt::get(IGF.IGM.Int32Ty, 1) }; return llvm::ConstantExpr::getInBoundsGetElementPtr( /*Ty=*/nullptr, fullMetadata, indices); } case MetatypeRepresentation::Thick: case MetatypeRepresentation::ObjC: // Thick and ObjC metatypes look like pointers with extra inhabitants. // Get the metatype metadata from the runtime. // FIXME: It'd be nice not to need a runtime call here. return IGF.emitTypeMetadataRef(type); } } /// Try to find the metatype in local data. llvm::Value *tryGetLocal(CanType type) { return IGF.tryGetLocalTypeDataForLayout( SILType::getPrimitiveObjectType(type), LocalTypeDataKind::forTypeMetadata()); } /// Set the metatype in local data. llvm::Value *setLocal(CanType type, llvm::Instruction *metatype) { IGF.setScopedLocalTypeDataForLayout(SILType::getPrimitiveObjectType(type), LocalTypeDataKind::forTypeMetadata(), metatype); return metatype; } }; } llvm::Value *IRGenFunction::emitTypeMetadataRefForLayout(SILType type) { return EmitTypeMetadataRefForLayout(*this).visit(type.getSwiftRValueType()); } namespace { /// A visitor class for emitting a reference to a type layout struct. /// There are a few ways we can emit it: /// /// - If the type is fixed-layout and we have visibility of its value /// witness table (or one close enough), we can project the layout struct /// from it. /// - If the type is fixed layout, we can emit our own copy of the layout /// struct. /// - If the type is dynamic-layout, we have to instantiate its metadata /// and project out its metadata. (FIXME: This leads to deadlocks in /// recursive cases, though we can avoid many deadlocks because most /// valid recursive types bottom out in fixed-sized types like classes /// or pointers.) class EmitTypeLayoutRef : public CanTypeVisitor { private: IRGenFunction &IGF; public: EmitTypeLayoutRef(IRGenFunction &IGF) : IGF(IGF) {} llvm::Value *emitFromValueWitnessTablePointer(llvm::Value *vwtable) { llvm::Value *indexConstant = llvm::ConstantInt::get(IGF.IGM.Int32Ty, (unsigned)ValueWitness::First_TypeLayoutWitness); return IGF.Builder.CreateInBoundsGEP(IGF.IGM.Int8PtrTy, vwtable, indexConstant); } /// Emit the type layout by projecting it from a value witness table to /// which we have linkage. llvm::Value *emitFromValueWitnessTable(CanType t) { auto *vwtable = IGF.IGM.getAddrOfValueWitnessTable(t); return emitFromValueWitnessTablePointer(vwtable); } /// Emit the type layout by projecting it from dynamic type metadata. llvm::Value *emitFromTypeMetadata(CanType t) { auto *vwtable = IGF.emitValueWitnessTableRefForLayout( SILType::getPrimitiveObjectType(t)); return emitFromValueWitnessTablePointer(vwtable); } bool hasVisibleValueWitnessTable(CanType t) const { // Some builtin and structural types have value witnesses exported from // the runtime. auto &C = IGF.IGM.Context; if (t == C.TheEmptyTupleType || t == C.TheNativeObjectType || t == C.TheUnknownObjectType || t == C.TheBridgeObjectType) return true; if (auto intTy = dyn_cast(t)) { auto width = intTy->getWidth(); if (width.isPointerWidth()) return true; if (width.isFixedWidth()) { switch (width.getFixedWidth()) { case 8: case 16: case 32: case 64: case 128: case 256: return true; default: return false; } } return false; } // TODO: If a nominal type is in the same source file as we're currently // emitting, we would be able to see its value witness table. return false; } /// Fallback default implementation. llvm::Value *visitType(CanType t) { auto silTy = SILType::getPrimitiveObjectType(t); auto &ti = IGF.getTypeInfo(silTy); // If the type is in the same source file, or has a common value // witness table exported from the runtime, we can project from the // value witness table instead of emitting a new record. if (hasVisibleValueWitnessTable(t)) return emitFromValueWitnessTable(t); // If the type is a singleton aggregate, the field's layout is equivalent // to the aggregate's. if (SILType singletonFieldTy = getSingletonAggregateFieldType(IGF.IGM, silTy, ResilienceExpansion::Maximal)) return visit(singletonFieldTy.getSwiftRValueType()); // If the type is fixed-layout, emit a copy of its layout. if (auto fixed = dyn_cast(&ti)) { return IGF.IGM.emitFixedTypeLayout(t, *fixed); } return emitFromTypeMetadata(t); } llvm::Value *visitAnyFunctionType(CanAnyFunctionType type) { llvm_unreachable("not a SIL type"); } llvm::Value *visitSILFunctionType(CanSILFunctionType type) { // All function types have the same layout regardless of arguments or // abstraction level. Use the value witness table for // @convention(blah) () -> () from the runtime. auto &C = type->getASTContext(); switch (type->getRepresentation()) { case SILFunctionType::Representation::Thin: case SILFunctionType::Representation::Method: case SILFunctionType::Representation::WitnessMethod: case SILFunctionType::Representation::ObjCMethod: case SILFunctionType::Representation::CFunctionPointer: // A thin function looks like a plain pointer. // FIXME: Except for extra inhabitants? return emitFromValueWitnessTable(C.TheRawPointerType); case SILFunctionType::Representation::Thick: // All function types look like () -> (). return emitFromValueWitnessTable( CanFunctionType::get(C.TheEmptyTupleType, C.TheEmptyTupleType)); case SILFunctionType::Representation::Block: // All block types look like Builtin.UnknownObject. return emitFromValueWitnessTable(C.TheUnknownObjectType); } } llvm::Value *visitAnyMetatypeType(CanAnyMetatypeType type) { assert(type->hasRepresentation() && "not a lowered metatype"); switch (type->getRepresentation()) { case MetatypeRepresentation::Thin: { // Thin metatypes are empty, so they look like the empty tuple type. return emitFromValueWitnessTable(IGF.IGM.Context.TheEmptyTupleType); } case MetatypeRepresentation::Thick: case MetatypeRepresentation::ObjC: // Thick metatypes look like pointers with spare bits. return emitFromValueWitnessTable( CanMetatypeType::get(IGF.IGM.Context.TheNativeObjectType)); } } llvm::Value *visitAnyClassType(ClassDecl *classDecl) { // All class types have the same layout. switch (getReferenceCountingForClass(IGF.IGM, classDecl)) { case ReferenceCounting::Native: return emitFromValueWitnessTable(IGF.IGM.Context.TheNativeObjectType); case ReferenceCounting::ObjC: case ReferenceCounting::Block: case ReferenceCounting::Unknown: return emitFromValueWitnessTable(IGF.IGM.Context.TheUnknownObjectType); case ReferenceCounting::Bridge: case ReferenceCounting::Error: llvm_unreachable("classes shouldn't have this kind of refcounting"); } } llvm::Value *visitClassType(CanClassType type) { return visitAnyClassType(type->getClassOrBoundGenericClass()); } llvm::Value *visitBoundGenericClassType(CanBoundGenericClassType type) { return visitAnyClassType(type->getClassOrBoundGenericClass()); } llvm::Value *visitReferenceStorageType(CanReferenceStorageType type) { // Other reference storage types all have the same layout for their // storage qualification and the reference counting of their underlying // object. auto &C = IGF.IGM.Context; CanType referent; switch (type->getOwnership()) { case Ownership::Strong: llvm_unreachable("shouldn't be a ReferenceStorageType"); case Ownership::Weak: referent = type.getReferentType().getAnyOptionalObjectType(); break; case Ownership::Unmanaged: case Ownership::Unowned: referent = type.getReferentType(); break; } // Reference storage types with witness tables need open-coded layouts. // TODO: Maybe we could provide prefabs for 1 witness table. SmallVector protocols; if (referent.isAnyExistentialType(protocols)) for (auto *proto : protocols) if (IGF.IGM.SILMod->Types.protocolRequiresWitnessTable(proto)) return visitType(type); // Unmanaged references are plain pointers with extra inhabitants, // which look like thick metatypes. if (type->getOwnership() == Ownership::Unmanaged) { auto metatype = CanMetatypeType::get(C.TheNativeObjectType); return emitFromValueWitnessTable(metatype); } auto getReferenceCountingForReferent = [&](CanType referent) -> ReferenceCounting { // If Objective-C interop is enabled, generic types might contain // Objective-C references, so we have to use unknown reference // counting. if (isa(referent) || referent->isExistentialType()) return (IGF.IGM.ObjCInterop ? ReferenceCounting::Unknown : ReferenceCounting::Native); if (auto classDecl = referent->getClassOrBoundGenericClass()) return getReferenceCountingForClass(IGF.IGM, classDecl); llvm_unreachable("unexpected referent for ref storage type"); }; CanType valueWitnessReferent; switch (getReferenceCountingForReferent(referent)) { case ReferenceCounting::Unknown: case ReferenceCounting::Block: case ReferenceCounting::ObjC: valueWitnessReferent = C.TheUnknownObjectType; break; case ReferenceCounting::Native: valueWitnessReferent = C.TheNativeObjectType; break; case ReferenceCounting::Bridge: valueWitnessReferent = C.TheBridgeObjectType; break; case ReferenceCounting::Error: llvm_unreachable("shouldn't be possible"); } // Get the reference storage type of the builtin object whose value // witness we can borrow. if (type->getOwnership() == Ownership::Weak) valueWitnessReferent = OptionalType::get(valueWitnessReferent) ->getCanonicalType(); auto valueWitnessType = CanReferenceStorageType::get(valueWitnessReferent, type->getOwnership()); return emitFromValueWitnessTable(valueWitnessType); } }; } // end anonymous namespace llvm::Value *IRGenFunction::emitTypeLayoutRef(SILType type) { return EmitTypeLayoutRef(*this).visit(type.getSwiftRValueType()); } void IRGenModule::setTrueConstGlobal(llvm::GlobalVariable *var) { switch (TargetInfo.OutputObjectFormat) { case llvm::Triple::MachO: var->setSection("__TEXT, __const"); break; // TODO: ELF? default: break; } } /// Produce the heap metadata pointer for the given class type. For /// Swift-defined types, this is equivalent to the metatype for the /// class, but for Objective-C-defined types, this is the class /// object. llvm::Value *irgen::emitClassHeapMetadataRef(IRGenFunction &IGF, CanType type, MetadataValueType desiredType, bool allowUninitialized) { assert(type->mayHaveSuperclass()); // Archetypes may or may not be ObjC classes and need unwrapping to get at // the class object. if (auto archetype = dyn_cast(type)) { // Look up the Swift metadata from context. llvm::Value *archetypeMeta = IGF.emitTypeMetadataRef(type); // Get the class pointer. auto classPtr = emitClassHeapMetadataRefForMetatype(IGF, archetypeMeta, archetype); if (desiredType == MetadataValueType::ObjCClass) classPtr = IGF.Builder.CreateBitCast(classPtr, IGF.IGM.ObjCClassPtrTy); return classPtr; } // ObjC-defined classes will always be top-level non-generic classes. if (auto classType = dyn_cast(type)) { auto theClass = classType->getDecl(); if (!hasKnownSwiftMetadata(IGF.IGM, theClass)) { llvm::Value *result = emitObjCHeapMetadataRef(IGF, theClass, allowUninitialized); if (desiredType == MetadataValueType::TypeMetadata) result = IGF.Builder.CreateBitCast(result, IGF.IGM.TypeMetadataPtrTy); return result; } } else { auto genericType = cast(type); assert(hasKnownSwiftMetadata(IGF.IGM, genericType->getDecl())); (void) genericType; } llvm::Value *result = IGF.emitTypeMetadataRef(type); if (desiredType == MetadataValueType::ObjCClass) result = IGF.Builder.CreateBitCast(result, IGF.IGM.ObjCClassPtrTy); return result; } namespace { /// A CRTP type visitor for deciding whether the metatype for a type /// has trivial representation. struct HasTrivialMetatype : CanTypeVisitor { /// Class metatypes have non-trivial representation due to the /// possibility of subclassing. bool visitClassType(CanClassType type) { return false; } bool visitBoundGenericClassType(CanBoundGenericClassType type) { return false; } /// Archetype metatypes have non-trivial representation in case /// they instantiate to a class metatype. bool visitArchetypeType(CanArchetypeType type) { return false; } /// All levels of class metatypes support subtyping. bool visitMetatypeType(CanMetatypeType type) { return visit(type.getInstanceType()); } /// Everything else is trivial. bool visitType(CanType type) { return false; } }; } /// Emit a metatype value for a known type. void irgen::emitMetatypeRef(IRGenFunction &IGF, CanMetatypeType type, Explosion &explosion) { switch (type->getRepresentation()) { case MetatypeRepresentation::Thin: // Thin types have a trivial representation. break; case MetatypeRepresentation::Thick: explosion.add(IGF.emitTypeMetadataRef(type.getInstanceType())); break; case MetatypeRepresentation::ObjC: explosion.add(emitClassHeapMetadataRef(IGF, type.getInstanceType(), MetadataValueType::ObjCClass)); break; } } /*****************************************************************************/ /** Nominal Type Descriptor Emission *****************************************/ /*****************************************************************************/ namespace { /// Helper to produce a dummy value that can stand in for a global constant /// for us to build relative references against before the constant is /// instantiated. static std::unique_ptr createTemporaryRelativeAddressBase(IRGenModule &IGM) { return std::unique_ptr( new llvm::GlobalVariable(IGM.Int8Ty, true, llvm::GlobalValue::PrivateLinkage)); } static void replaceTemporaryRelativeAddressBase(IRGenModule &IGM, std::unique_ptr temp, llvm::Constant *real) { real = llvm::ConstantExpr::getBitCast(real, IGM.Int8PtrTy); temp->replaceAllUsesWith(real); } template class NominalTypeDescriptorBuilderBase : public ConstantBuilder<> { Impl &asImpl() { return *static_cast(this); } public: NominalTypeDescriptorBuilderBase(IRGenModule &IGM) : ConstantBuilder(IGM) {} void layout() { asImpl().addName(); asImpl().addKindDependentFields(); asImpl().addGenericMetadataPatternAndKind(); asImpl().addGenericParams(); } void addName() { NominalTypeDecl *ntd = asImpl().getTarget(); addRelativeAddress(getMangledTypeName(IGM, ntd->getDeclaredType()->getCanonicalType(), /*willBeRelativelyAddressed*/ true)); } void addGenericMetadataPatternAndKind() { NominalTypeDecl *ntd = asImpl().getTarget(); auto kind = asImpl().getKind(); if (!IGM.hasMetadataPattern(ntd)) { // There's no pattern to link. addConstantInt32(kind); return; } addRelativeAddressWithTag( IGM.getAddrOfTypeMetadata(ntd->getDeclaredType()->getCanonicalType(), /*pattern*/ true), kind); } void addGenericParams() { NominalTypeDecl *ntd = asImpl().getTarget(); // uint32_t GenericParameterVectorOffset; addConstantInt32InWords(asImpl().getGenericParamsOffset()); // The archetype order here needs to be consistent with // MetadataLayout::addGenericFields. GenericTypeRequirements requirements(IGM, ntd); // uint32_t NumGenericRequirements; addConstantInt32(requirements.getStorageSizeInWords()); // uint32_t NumPrimaryGenericParameters; addConstantInt32(requirements.getNumTypeRequirements()); // GenericParameterDescriptorFlags Flags; GenericParameterDescriptorFlags flags; if (ntd->getDeclContext()->isTypeContext()) flags = flags.withHasParent(true); if (requirements.hasParentType()) flags = flags.withHasGenericParent(true); addConstantInt32(flags.getIntValue()); // TODO: provide reflective descriptions of the type and // conformance requirements stored here. // }; } llvm::Constant *emit() { // Set up a dummy global to stand in for the constant. auto tempBase = createTemporaryRelativeAddressBase(IGM); setRelativeAddressBase(tempBase.get()); asImpl().layout(); auto init = getInit(); auto var = cast( IGM.getAddrOfNominalTypeDescriptor(asImpl().getTarget(), init->getType())); var->setConstant(true); var->setInitializer(init); IGM.setTrueConstGlobal(var); replaceTemporaryRelativeAddressBase(IGM, std::move(tempBase), var); return var; } // Derived class must provide: // NominalTypeDecl *getTarget(); // unsigned getKind(); // unsigned getGenericParamsOffset(); // void addKindDependentFields(); }; /// A CRTP helper for classes which are simply searching for a /// specific index within the metadata. /// /// The pattern is that subclasses should override an 'add' method /// from the appropriate layout class and ensure that they call /// setTargetOffset() when the appropriate location is reached. The /// subclass user then just calls getTargetOffset(), which performs /// the layout and returns the found index. /// /// \tparam Base the base class, which should generally be a CRTP /// class template applied to the most-derived class template class MetadataSearcher : public Base { Size TargetOffset = Size::invalid(); Size AddressPoint = Size::invalid(); protected: void setTargetOffset() { assert(TargetOffset.isInvalid() && "setting twice"); TargetOffset = this->NextOffset; } public: template MetadataSearcher(T &&...args) : Base(std::forward(args)...) {} void noteAddressPoint() { AddressPoint = this->NextOffset; } Size getTargetOffset() { assert(TargetOffset.isInvalid() && "computing twice"); this->layout(); assert(!TargetOffset.isInvalid() && "target not found!"); assert(!AddressPoint.isInvalid() && "address point not set"); return TargetOffset - AddressPoint; } Size::int_type getTargetIndex() { return this->IGM.getOffsetInWords(getTargetOffset()); } }; // A bunch of ugly macros to make it easy to declare certain // common kinds of searcher. #define BEGIN_METADATA_SEARCHER_0(SEARCHER, DECLKIND) \ struct SEARCHER \ : MetadataSearcher> { \ using super = MetadataSearcher; \ SEARCHER(IRGenModule &IGM, DECLKIND##Decl *target) \ : super(IGM, target) {} #define BEGIN_METADATA_SEARCHER_1(SEARCHER, DECLKIND, TYPE_1, NAME_1) \ struct SEARCHER \ : MetadataSearcher> { \ using super = MetadataSearcher; \ TYPE_1 NAME_1; \ SEARCHER(IRGenModule &IGM, DECLKIND##Decl *target, TYPE_1 NAME_1) \ : super(IGM, target), NAME_1(NAME_1) {} #define BEGIN_METADATA_SEARCHER_2(SEARCHER, DECLKIND, TYPE_1, NAME_1, \ TYPE_2, NAME_2) \ struct SEARCHER \ : MetadataSearcher> { \ using super = MetadataSearcher; \ TYPE_1 NAME_1; \ TYPE_2 NAME_2; \ SEARCHER(IRGenModule &IGM, DECLKIND##Decl *target, TYPE_1 NAME_1, \ TYPE_2 NAME_2) \ : super(IGM, target), NAME_1(NAME_1), NAME_2(NAME_2) {} #define END_METADATA_SEARCHER() \ }; #define BEGIN_GENERIC_METADATA_SEARCHER_0(SEARCHER) \ template