ModuleInfo* XQueryCompiler::parseInfo( std::istream& aXQuery, const zstring& aFileName) { parsenode_t lParseNode = parse(aXQuery, aFileName); if (typeid (*lParseNode) == typeid (ParseErrorNode)) { ParseErrorNode* pen = static_cast<ParseErrorNode *>(lParseNode.getp()); throw XQUERY_EXCEPTION_VAR(pen->err, ERROR_PARAMS(pen->msg), ERROR_LOC(pen->get_location())); } LibraryModule* lLibModule = dynamic_cast<LibraryModule*>(lParseNode.getp()); zstring lTargetNamespace; if (lLibModule) { ModuleDecl* lDecl = lLibModule->get_decl().getp(); lTargetNamespace = lDecl->get_target_namespace(); } return new ModuleInfoImpl(lTargetNamespace); }
SILLinkage swift::getLinkageForProtocolConformance(const NormalProtocolConformance *C, ForDefinition_t definition) { // Behavior conformances are always private. if (C->isBehaviorConformance()) return (definition ? SILLinkage::Private : SILLinkage::PrivateExternal); ModuleDecl *conformanceModule = C->getDeclContext()->getParentModule(); // If the conformance was synthesized by the ClangImporter, give it // shared linkage. auto typeDecl = C->getType()->getNominalOrBoundGenericNominal(); auto typeUnit = typeDecl->getModuleScopeContext(); if (isa<ClangModuleUnit>(typeUnit) && conformanceModule == typeUnit->getParentModule()) return SILLinkage::Shared; // If we're bulding with -sil-serialize-all, give the conformance public // linkage. if (conformanceModule->getResilienceStrategy() == ResilienceStrategy::Fragile) return (definition ? SILLinkage::Public : SILLinkage::PublicExternal); // FIXME: This should be using std::min(protocol's access, type's access). switch (C->getProtocol()->getEffectiveAccess()) { case Accessibility::Private: return (definition ? SILLinkage::Private : SILLinkage::PrivateExternal); case Accessibility::Internal: return (definition ? SILLinkage::Hidden : SILLinkage::HiddenExternal); default: return (definition ? SILLinkage::Public : SILLinkage::PublicExternal); } }
/// Returns true if the object file generated by \p IGM will be the "first" /// object file in the module. This lets us determine where to put a symbol /// that must be unique. static bool isFirstObjectFileInModule(IRGenModule &IGM) { if (IGM.getSILModule().isWholeModule()) return IGM.IRGen.getPrimaryIGM() == &IGM; const DeclContext *DC = IGM.getSILModule().getAssociatedContext(); if (!DC) return false; assert(!isa<ModuleDecl>(DC) && "that would be a whole module build"); assert(isa<FileUnit>(DC) && "compiling something smaller than a file?"); ModuleDecl *containingModule = cast<FileUnit>(DC)->getParentModule(); return containingModule->getFiles().front() == DC; }
bool CompilerInstance::loadStdlib() { SharedTimer timer("performSema-loadStdlib"); ModuleDecl *M = Context->getStdlibModule(true); if (!M) { Diagnostics.diagnose(SourceLoc(), diag::error_stdlib_not_found, Invocation.getTargetTriple()); return false; } // If we failed to load, we should have already diagnosed if (M->failedToLoad()) { assert(Diagnostics.hadAnyError() && "Module failed to load but nothing was diagnosed?"); return false; } return true; }
static void indexModule(llvm::MemoryBuffer *Input, StringRef ModuleName, StringRef Hash, IndexingConsumer &IdxConsumer, CompilerInstance &CI, ArrayRef<const char *> Args) { ASTContext &Ctx = CI.getASTContext(); std::unique_ptr<SerializedModuleLoader> Loader; ModuleDecl *Mod = nullptr; if (ModuleName == Ctx.StdlibModuleName.str()) { Mod = Ctx.getModule({ {Ctx.StdlibModuleName, SourceLoc()} }); } else { Loader = SerializedModuleLoader::create(Ctx); auto Buf = std::unique_ptr<llvm::MemoryBuffer>( llvm::MemoryBuffer::getMemBuffer(Input->getBuffer(), Input->getBufferIdentifier())); // FIXME: These APIs allocate memory on the ASTContext, meaning it may not // be freed for a long time. Mod = ModuleDecl::create(Ctx.getIdentifier(ModuleName), Ctx); // Indexing is not using documentation now, so don't open the module // documentation file. // FIXME: refactor the frontend to provide an easy way to figure out the // correct filename here. auto FUnit = Loader->loadAST(*Mod, None, std::move(Buf), nullptr); // FIXME: Not knowing what went wrong is pretty bad. loadModule() should be // more modular, rather than emitting diagnostics itself. if (!FUnit) { IdxConsumer.failed("failed to load module"); return; } Mod->setHasResolvedImports(); } // Setup a typechecker for protocol conformance resolving. (void)createTypeChecker(Ctx); SKIndexDataConsumer IdxDataConsumer(IdxConsumer); index::indexModule(Mod, Hash, IdxDataConsumer); }
void CompilerInstance::performParseOnly(bool EvaluateConditionals) { const InputFileKind Kind = Invocation.getInputKind(); ModuleDecl *MainModule = getMainModule(); Context->LoadedModules[MainModule->getName()] = MainModule; bool KeepTokens = Invocation.getLangOptions().KeepTokensInSourceFile; assert((Kind == InputFileKind::IFK_Swift || Kind == InputFileKind::IFK_Swift_Library) && "only supports parsing .swift files"); (void)Kind; auto implicitModuleImportKind = SourceFile::ImplicitModuleImportKind::None; // Make sure the main file is the first file in the module but parse it last, // to match the parsing logic used when performing Sema. if (MainBufferID != NO_SUCH_BUFFER) { assert(Kind == InputFileKind::IFK_Swift); SourceMgr.setHashbangBufferID(MainBufferID); auto *MainFile = new (*Context) SourceFile(*MainModule, Invocation.getSourceFileKind(), MainBufferID, implicitModuleImportKind, KeepTokens); MainModule->addFile(*MainFile); if (MainBufferID == PrimaryBufferID) setPrimarySourceFile(MainFile); } PersistentParserState PersistentState; PersistentState.PerformConditionEvaluation = EvaluateConditionals; // Parse all the library files. for (auto BufferID : InputSourceCodeBufferIDs) { if (BufferID == MainBufferID) continue; auto *NextInput = new (*Context) SourceFile(*MainModule, SourceFileKind::Library, BufferID, implicitModuleImportKind, KeepTokens); MainModule->addFile(*NextInput); if (BufferID == PrimaryBufferID) setPrimarySourceFile(NextInput); bool Done; do { // Parser may stop at some erroneous constructions like #else, #endif // or '}' in some cases, continue parsing until we are done parseIntoSourceFile(*NextInput, BufferID, &Done, nullptr, &PersistentState, nullptr); } while (!Done); } // Now parse the main file. if (MainBufferID != NO_SUCH_BUFFER) { SourceFile &MainFile = MainModule->getMainSourceFile(Invocation.getSourceFileKind()); bool Done; do { parseIntoSourceFile(MainFile, MainFile.getBufferID().getValue(), &Done, nullptr, &PersistentState, nullptr); } while (!Done); } assert(Context->LoadedModules.size() == 1 && "Loaded a module during parse-only"); }
void SILGenFunction::emitArtificialTopLevel(ClassDecl *mainClass) { // Load argc and argv from the entry point arguments. SILValue argc = F.begin()->getArgument(0); SILValue argv = F.begin()->getArgument(1); switch (mainClass->getArtificialMainKind()) { case ArtificialMainKind::UIApplicationMain: { // Emit a UIKit main. // return UIApplicationMain(C_ARGC, C_ARGV, nil, ClassName); CanType NSStringTy = SGM.Types.getNSStringType(); CanType OptNSStringTy = OptionalType::get(NSStringTy)->getCanonicalType(); CanType IUOptNSStringTy = ImplicitlyUnwrappedOptionalType::get(NSStringTy)->getCanonicalType(); // Look up UIApplicationMain. // FIXME: Doing an AST lookup here is gross and not entirely sound; // we're getting away with it because the types are guaranteed to already // be imported. ASTContext &ctx = getASTContext(); ModuleDecl *UIKit = ctx.getLoadedModule(ctx.getIdentifier("UIKit")); SmallVector<ValueDecl *, 1> results; UIKit->lookupQualified(UIKit->getInterfaceType(), ctx.getIdentifier("UIApplicationMain"), NL_QualifiedDefault, /*resolver*/nullptr, results); assert(!results.empty() && "couldn't find UIApplicationMain in UIKit"); assert(results.size() == 1 && "more than one UIApplicationMain?"); SILDeclRef mainRef{results.front(), ResilienceExpansion::Minimal, SILDeclRef::ConstructAtNaturalUncurryLevel, /*isForeign*/true}; auto UIApplicationMainFn = SGM.M.getOrCreateFunction(mainClass, mainRef, NotForDefinition); auto fnTy = UIApplicationMainFn->getLoweredFunctionType(); SILFunctionConventions fnConv(fnTy, SGM.M); // Get the class name as a string using NSStringFromClass. CanType mainClassTy = mainClass->getDeclaredInterfaceType() ->getCanonicalType(); CanType mainClassMetaty = CanMetatypeType::get(mainClassTy, MetatypeRepresentation::ObjC); ProtocolDecl *anyObjectProtocol = ctx.getProtocol(KnownProtocolKind::AnyObject); auto mainClassAnyObjectConformance = ProtocolConformanceRef( *SGM.M.getSwiftModule()->lookupConformance(mainClassTy, anyObjectProtocol, nullptr)); CanType anyObjectTy = anyObjectProtocol ->getDeclaredInterfaceType() ->getCanonicalType(); CanType anyObjectMetaTy = CanExistentialMetatypeType::get(anyObjectTy, MetatypeRepresentation::ObjC); auto NSStringFromClassType = SILFunctionType::get(nullptr, SILFunctionType::ExtInfo() .withRepresentation(SILFunctionType::Representation:: CFunctionPointer), ParameterConvention::Direct_Unowned, SILParameterInfo(anyObjectMetaTy, ParameterConvention::Direct_Unowned), SILResultInfo(OptNSStringTy, ResultConvention::Autoreleased), /*error result*/ None, ctx); auto NSStringFromClassFn = SGM.M.getOrCreateFunction(mainClass, "NSStringFromClass", SILLinkage::PublicExternal, NSStringFromClassType, IsBare, IsTransparent, IsNotSerialized); auto NSStringFromClass = B.createFunctionRef(mainClass, NSStringFromClassFn); SILValue metaTy = B.createMetatype(mainClass, SILType::getPrimitiveObjectType(mainClassMetaty)); metaTy = B.createInitExistentialMetatype(mainClass, metaTy, SILType::getPrimitiveObjectType(anyObjectMetaTy), ctx.AllocateCopy( llvm::makeArrayRef(mainClassAnyObjectConformance))); SILValue optName = B.createApply(mainClass, NSStringFromClass, NSStringFromClass->getType(), SILType::getPrimitiveObjectType(OptNSStringTy), {}, metaTy); // Fix up the string parameters to have the right type. SILType nameArgTy = fnConv.getSILArgumentType(3); assert(nameArgTy == fnConv.getSILArgumentType(2)); auto managedName = ManagedValue::forUnmanaged(optName); SILValue nilValue; if (optName->getType() == nameArgTy) { nilValue = getOptionalNoneValue(mainClass, getTypeLowering(OptNSStringTy)); } else { assert(nameArgTy.getSwiftRValueType() == IUOptNSStringTy); nilValue = getOptionalNoneValue(mainClass, getTypeLowering(IUOptNSStringTy)); managedName = emitOptionalToOptional( mainClass, managedName, SILType::getPrimitiveObjectType(IUOptNSStringTy), [](SILGenFunction &, SILLocation, ManagedValue input, SILType) { return input; }); } // Fix up argv to have the right type. auto argvTy = fnConv.getSILArgumentType(1); SILType unwrappedTy = argvTy; if (Type innerTy = argvTy.getSwiftRValueType()->getAnyOptionalObjectType()){ auto canInnerTy = innerTy->getCanonicalType(); unwrappedTy = SILType::getPrimitiveObjectType(canInnerTy); } auto managedArgv = ManagedValue::forUnmanaged(argv); if (unwrappedTy != argv->getType()) { auto converted = emitPointerToPointer(mainClass, managedArgv, argv->getType().getSwiftRValueType(), unwrappedTy.getSwiftRValueType()); managedArgv = std::move(converted).getAsSingleValue(*this, mainClass); } if (unwrappedTy != argvTy) { managedArgv = getOptionalSomeValue(mainClass, managedArgv, getTypeLowering(argvTy)); } auto UIApplicationMain = B.createFunctionRef(mainClass, UIApplicationMainFn); SILValue args[] = {argc, managedArgv.getValue(), nilValue, managedName.getValue()}; B.createApply(mainClass, UIApplicationMain, UIApplicationMain->getType(), argc->getType(), {}, args); SILValue r = B.createIntegerLiteral(mainClass, SILType::getBuiltinIntegerType(32, ctx), 0); auto rType = F.getConventions().getSingleSILResultType(); if (r->getType() != rType) r = B.createStruct(mainClass, rType, r); Cleanups.emitCleanupsForReturn(mainClass); B.createReturn(mainClass, r); return; } case ArtificialMainKind::NSApplicationMain: { // Emit an AppKit main. // return NSApplicationMain(C_ARGC, C_ARGV); SILParameterInfo argTypes[] = { SILParameterInfo(argc->getType().getSwiftRValueType(), ParameterConvention::Direct_Unowned), SILParameterInfo(argv->getType().getSwiftRValueType(), ParameterConvention::Direct_Unowned), }; auto NSApplicationMainType = SILFunctionType::get(nullptr, SILFunctionType::ExtInfo() // Should be C calling convention, but NSApplicationMain // has an overlay to fix the type of argv. .withRepresentation(SILFunctionType::Representation::Thin), ParameterConvention::Direct_Unowned, argTypes, SILResultInfo(argc->getType().getSwiftRValueType(), ResultConvention::Unowned), /*error result*/ None, getASTContext()); auto NSApplicationMainFn = SGM.M.getOrCreateFunction(mainClass, "NSApplicationMain", SILLinkage::PublicExternal, NSApplicationMainType, IsBare, IsTransparent, IsNotSerialized); auto NSApplicationMain = B.createFunctionRef(mainClass, NSApplicationMainFn); SILValue args[] = { argc, argv }; B.createApply(mainClass, NSApplicationMain, NSApplicationMain->getType(), argc->getType(), {}, args); SILValue r = B.createIntegerLiteral(mainClass, SILType::getBuiltinIntegerType(32, getASTContext()), 0); auto rType = F.getConventions().getSingleSILResultType(); if (r->getType() != rType) r = B.createStruct(mainClass, rType, r); B.createReturn(mainClass, r); return; } } }
// Returns the callee of an apply_inst if it is basically inlinable. SILFunction *swift::getEligibleFunction(FullApplySite AI, InlineSelection WhatToInline) { SILFunction *Callee = AI.getReferencedFunction(); if (!Callee) { return nullptr; } // Not all apply sites can be inlined, even if they're direct. if (!SILInliner::canInline(AI)) return nullptr; ModuleDecl *SwiftModule = Callee->getModule().getSwiftModule(); bool IsInStdlib = (SwiftModule->isStdlibModule() || SwiftModule->isOnoneSupportModule()); // Don't inline functions that are marked with the @_semantics or @_effects // attribute if the inliner is asked not to inline them. if (Callee->hasSemanticsAttrs() || Callee->hasEffectsKind()) { if (WhatToInline == InlineSelection::NoSemanticsAndGlobalInit) { if (shouldSkipApplyDuringEarlyInlining(AI)) return nullptr; if (Callee->hasSemanticsAttr("inline_late")) return nullptr; } // The "availability" semantics attribute is treated like global-init. if (Callee->hasSemanticsAttrs() && WhatToInline != InlineSelection::Everything && (Callee->hasSemanticsAttrThatStartsWith("availability") || (Callee->hasSemanticsAttrThatStartsWith("inline_late")))) { return nullptr; } if (Callee->hasSemanticsAttrs() && WhatToInline == InlineSelection::Everything) { if (Callee->hasSemanticsAttrThatStartsWith("inline_late") && IsInStdlib) { return nullptr; } } } else if (Callee->isGlobalInit()) { if (WhatToInline != InlineSelection::Everything) { return nullptr; } } // We can't inline external declarations. if (Callee->empty() || Callee->isExternalDeclaration()) { return nullptr; } // Explicitly disabled inlining. if (Callee->getInlineStrategy() == NoInline) { return nullptr; } if (!Callee->shouldOptimize()) { return nullptr; } SILFunction *Caller = AI.getFunction(); // We don't support inlining a function that binds dynamic self because we // have no mechanism to preserve the original function's local self metadata. if (mayBindDynamicSelf(Callee)) { // Check if passed Self is the same as the Self of the caller. // In this case, it is safe to inline because both functions // use the same Self. if (AI.hasSelfArgument() && Caller->hasSelfParam()) { auto CalleeSelf = stripCasts(AI.getSelfArgument()); auto CallerSelf = Caller->getSelfArgument(); if (CalleeSelf != SILValue(CallerSelf)) return nullptr; } else return nullptr; } // Detect self-recursive calls. if (Caller == Callee) { return nullptr; } // A non-fragile function may not be inlined into a fragile function. if (Caller->isSerialized() && !Callee->hasValidLinkageForFragileInline()) { if (!Callee->hasValidLinkageForFragileRef()) { llvm::errs() << "caller: " << Caller->getName() << "\n"; llvm::errs() << "callee: " << Callee->getName() << "\n"; llvm_unreachable("Should never be inlining a resilient function into " "a fragile function"); } return nullptr; } // Inlining self-recursive functions into other functions can result // in excessive code duplication since we run the inliner multiple // times in our pipeline if (calleeIsSelfRecursive(Callee)) { return nullptr; } if (!EnableSILInliningOfGenerics && AI.hasSubstitutions()) { // Inlining of generics is not allowed unless it is an @inline(__always) // or transparent function. if (Callee->getInlineStrategy() != AlwaysInline && !Callee->isTransparent()) return nullptr; } // We cannot inline function with layout constraints on its generic types // if the corresponding substitution type does not have the same constraints. // The reason for this restriction is that we'd need to be able to express // in SIL something like casting a value of generic type T into a value of // generic type T: _LayoutConstraint, which is impossible currently. if (EnableSILInliningOfGenerics && AI.hasSubstitutions()) { if (!isCallerAndCalleeLayoutConstraintsCompatible(AI)) return nullptr; } // IRGen cannot handle partial_applies containing opened_existentials // in its substitutions list. if (calleeHasPartialApplyWithOpenedExistentials(AI)) { return nullptr; } return Callee; }
void CompilerInstance::performSema() { const FrontendOptions &options = Invocation.getFrontendOptions(); const InputFileKind Kind = Invocation.getInputKind(); Module *MainModule = getMainModule(); Context->LoadedModules[MainModule->getName()] = MainModule; auto modImpKind = SourceFile::ImplicitModuleImportKind::Stdlib; if (Kind == InputFileKind::IFK_SIL) { assert(BufferIDs.size() == 1); assert(MainBufferID != NO_SUCH_BUFFER); // Assume WMO, if a -primary-file option was not provided. createSILModule(!options.PrimaryInput.hasValue()); modImpKind = SourceFile::ImplicitModuleImportKind::None; } else if (Invocation.getParseStdlib()) { modImpKind = SourceFile::ImplicitModuleImportKind::Builtin; } switch (modImpKind) { case SourceFile::ImplicitModuleImportKind::None: case SourceFile::ImplicitModuleImportKind::Builtin: break; case SourceFile::ImplicitModuleImportKind::Stdlib: { ModuleDecl *M = Context->getStdlibModule(true); if (!M) { Diagnostics.diagnose(SourceLoc(), diag::error_stdlib_not_found, Invocation.getTargetTriple()); return; } // If we failed to load, we should have already diagnosed if (M->failedToLoad()) { assert(Diagnostics.hadAnyError() && "Module failed to load but nothing was diagnosed?"); return; } const auto &silOptions = Invocation.getSILOptions(); if ((silOptions.Optimization <= SILOptions::SILOptMode::None && (options.RequestedAction == FrontendOptions::EmitObject || options.RequestedAction == FrontendOptions::Immediate || options.RequestedAction == FrontendOptions::EmitSIL)) || (silOptions.Optimization == SILOptions::SILOptMode::None && options.RequestedAction >= FrontendOptions::EmitSILGen)) { // Implicitly import the SwiftOnoneSupport module in non-optimized // builds. This allows for use of popular specialized functions // from the standard library, which makes the non-optimized builds // execute much faster. Invocation.getFrontendOptions() .ImplicitImportModuleNames.push_back(SWIFT_ONONE_SUPPORT); } break; } } auto clangImporter = static_cast<ClangImporter *>(Context->getClangModuleLoader()); Module *underlying = nullptr; if (options.ImportUnderlyingModule) { underlying = clangImporter->loadModule(SourceLoc(), std::make_pair(MainModule->getName(), SourceLoc())); if (!underlying) { Diagnostics.diagnose(SourceLoc(), diag::error_underlying_module_not_found, MainModule->getName()); } } Module *importedHeaderModule = nullptr; StringRef implicitHeaderPath = options.ImplicitObjCHeaderPath; if (!implicitHeaderPath.empty()) { if (!clangImporter->importBridgingHeader(implicitHeaderPath, MainModule)) { importedHeaderModule = clangImporter->getImportedHeaderModule(); assert(importedHeaderModule); } } SmallVector<Module *, 4> importModules; if (!options.ImplicitImportModuleNames.empty()) { for (auto &ImplicitImportModuleName : options.ImplicitImportModuleNames) { if (Lexer::isIdentifier(ImplicitImportModuleName)) { auto moduleID = Context->getIdentifier(ImplicitImportModuleName); Module *importModule = Context->getModule(std::make_pair(moduleID, SourceLoc())); if (importModule) { importModules.push_back(importModule); } else { Diagnostics.diagnose(SourceLoc(), diag::sema_no_import, ImplicitImportModuleName); if (Invocation.getSearchPathOptions().SDKPath.empty() && llvm::Triple(llvm::sys::getProcessTriple()).isMacOSX()) { Diagnostics.diagnose(SourceLoc(), diag::sema_no_import_no_sdk); Diagnostics.diagnose(SourceLoc(), diag::sema_no_import_no_sdk_xcrun); } } } else { Diagnostics.diagnose(SourceLoc(), diag::error_bad_module_name, ImplicitImportModuleName, false); } } } auto addAdditionalInitialImports = [&](SourceFile *SF) { if (!underlying && !importedHeaderModule && importModules.empty()) return; using ImportPair = std::pair<Module::ImportedModule, SourceFile::ImportOptions>; SmallVector<ImportPair, 4> additionalImports; if (underlying) additionalImports.push_back({ { /*accessPath=*/{}, underlying }, SourceFile::ImportFlags::Exported }); if (importedHeaderModule) additionalImports.push_back({ { /*accessPath=*/{}, importedHeaderModule }, SourceFile::ImportFlags::Exported }); if (!importModules.empty()) { for (auto &importModule : importModules) { additionalImports.push_back({ { /*accessPath=*/{}, importModule }, {} }); } } SF->addImports(additionalImports); }; if (Kind == InputFileKind::IFK_Swift_REPL) { auto *SingleInputFile = new (*Context) SourceFile(*MainModule, Invocation.getSourceFileKind(), None, modImpKind); MainModule->addFile(*SingleInputFile); addAdditionalInitialImports(SingleInputFile); return; } std::unique_ptr<DelayedParsingCallbacks> DelayedCB; if (Invocation.isCodeCompletion()) { DelayedCB.reset( new CodeCompleteDelayedCallbacks(SourceMgr.getCodeCompletionLoc())); } else if (Invocation.isDelayedFunctionBodyParsing()) { DelayedCB.reset(new AlwaysDelayedCallbacks); } PersistentParserState PersistentState; // Make sure the main file is the first file in the module. This may only be // a source file, or it may be a SIL file, which requires pumping the parser. // We parse it last, though, to make sure that it can use decls from other // files in the module. if (MainBufferID != NO_SUCH_BUFFER) { assert(Kind == InputFileKind::IFK_Swift || Kind == InputFileKind::IFK_SIL); if (Kind == InputFileKind::IFK_Swift) SourceMgr.setHashbangBufferID(MainBufferID); auto *MainFile = new (*Context) SourceFile(*MainModule, Invocation.getSourceFileKind(), MainBufferID, modImpKind); MainModule->addFile(*MainFile); addAdditionalInitialImports(MainFile); if (MainBufferID == PrimaryBufferID) setPrimarySourceFile(MainFile); } bool hadLoadError = false; // Parse all the partial modules first. for (auto &PM : PartialModules) { assert(PM.ModuleBuffer); if (!SML->loadAST(*MainModule, SourceLoc(), std::move(PM.ModuleBuffer), std::move(PM.ModuleDocBuffer))) hadLoadError = true; } // Then parse all the library files. for (auto BufferID : BufferIDs) { if (BufferID == MainBufferID) continue; auto *NextInput = new (*Context) SourceFile(*MainModule, SourceFileKind::Library, BufferID, modImpKind); MainModule->addFile(*NextInput); addAdditionalInitialImports(NextInput); if (BufferID == PrimaryBufferID) setPrimarySourceFile(NextInput); auto &Diags = NextInput->getASTContext().Diags; auto DidSuppressWarnings = Diags.getSuppressWarnings(); auto IsPrimary = PrimaryBufferID == NO_SUCH_BUFFER || BufferID == PrimaryBufferID; Diags.setSuppressWarnings(DidSuppressWarnings || !IsPrimary); bool Done; do { // Parser may stop at some erroneous constructions like #else, #endif // or '}' in some cases, continue parsing until we are done parseIntoSourceFile(*NextInput, BufferID, &Done, nullptr, &PersistentState, DelayedCB.get()); } while (!Done); Diags.setSuppressWarnings(DidSuppressWarnings); performNameBinding(*NextInput); } if (Invocation.isCodeCompletion()) { // When we are doing code completion, make sure to emit at least one // diagnostic, so that ASTContext is marked as erroneous. In this case // various parts of the compiler (for example, AST verifier) have less // strict assumptions about the AST. Diagnostics.diagnose(SourceLoc(), diag::error_doing_code_completion); } if (hadLoadError) return; // Compute the options we want to use for type checking. OptionSet<TypeCheckingFlags> TypeCheckOptions; if (PrimaryBufferID == NO_SUCH_BUFFER) { TypeCheckOptions |= TypeCheckingFlags::DelayWholeModuleChecking; } if (Invocation.getFrontendOptions().DebugTimeFunctionBodies) { TypeCheckOptions |= TypeCheckingFlags::DebugTimeFunctionBodies; } if (Invocation.getFrontendOptions().actionIsImmediate()) { TypeCheckOptions |= TypeCheckingFlags::ForImmediateMode; } // Parse the main file last. if (MainBufferID != NO_SUCH_BUFFER) { bool mainIsPrimary = (PrimaryBufferID == NO_SUCH_BUFFER || MainBufferID == PrimaryBufferID); SourceFile &MainFile = MainModule->getMainSourceFile(Invocation.getSourceFileKind()); auto &Diags = MainFile.getASTContext().Diags; auto DidSuppressWarnings = Diags.getSuppressWarnings(); Diags.setSuppressWarnings(DidSuppressWarnings || !mainIsPrimary); SILParserState SILContext(TheSILModule.get()); unsigned CurTUElem = 0; bool Done; do { // Pump the parser multiple times if necessary. It will return early // after parsing any top level code in a main module, or in SIL mode when // there are chunks of swift decls (e.g. imports and types) interspersed // with 'sil' definitions. parseIntoSourceFile(MainFile, MainFile.getBufferID().getValue(), &Done, TheSILModule ? &SILContext : nullptr, &PersistentState, DelayedCB.get()); if (mainIsPrimary) { performTypeChecking(MainFile, PersistentState.getTopLevelContext(), TypeCheckOptions, CurTUElem); } CurTUElem = MainFile.Decls.size(); } while (!Done); Diags.setSuppressWarnings(DidSuppressWarnings); if (mainIsPrimary && !Context->hadError() && Invocation.getFrontendOptions().PlaygroundTransform) performPlaygroundTransform(MainFile, Invocation.getFrontendOptions().PlaygroundHighPerformance); if (!mainIsPrimary) performNameBinding(MainFile); } // Type-check each top-level input besides the main source file. for (auto File : MainModule->getFiles()) if (auto SF = dyn_cast<SourceFile>(File)) if (PrimaryBufferID == NO_SUCH_BUFFER || SF == PrimarySourceFile) performTypeChecking(*SF, PersistentState.getTopLevelContext(), TypeCheckOptions); // Even if there were no source files, we should still record known // protocols. if (auto *stdlib = Context->getStdlibModule()) Context->recordKnownProtocols(stdlib); if (DelayedCB) { performDelayedParsing(MainModule, PersistentState, Invocation.getCodeCompletionFactory()); } // Perform whole-module type checking. if (TypeCheckOptions & TypeCheckingFlags::DelayWholeModuleChecking) { for (auto File : MainModule->getFiles()) if (auto SF = dyn_cast<SourceFile>(File)) performWholeModuleTypeChecking(*SF); } for (auto File : MainModule->getFiles()) if (auto SF = dyn_cast<SourceFile>(File)) if (PrimaryBufferID == NO_SUCH_BUFFER || SF == PrimarySourceFile) finishTypeChecking(*SF); }
bool SourceEntityWalker::walk(ModuleDecl &Mod) { SemaAnnotator Annotator(*this); return Mod.walk(Annotator); }
ProtocolConformance *ConformanceLookupTable::getConformance( NominalTypeDecl *nominal, LazyResolver *resolver, ConformanceEntry *entry) { // If we already have a conformance, we're done. if (auto conformance = entry->getConformance()) return conformance; ProtocolDecl *protocol = entry->getProtocol(); // Determine where the explicit conformance actually lives. // FIXME: This is a hack to ensure that inherited conformances are // always "single step", which is bad for resilience but is assumed // elsewhere in the compiler. DeclContext *conformingDC = getConformingContext(nominal, resolver, entry); if (!conformingDC) return nullptr; auto *conformingNominal = conformingDC->getAsNominalTypeOrNominalTypeExtensionContext(); // Form the conformance. Type type = entry->getDeclContext()->getDeclaredTypeInContext(); ProtocolConformance *conformance; ASTContext &ctx = nominal->getASTContext(); if (entry->getKind() == ConformanceEntryKind::Inherited) { // For an inherited conformance, the conforming nominal type will // be different from the nominal type. assert(conformingNominal != nominal && "Broken inherited conformance"); // Find the superclass type that matches where the conformance was // declared. Type superclassTy = type->getSuperclass(resolver); while (superclassTy->getAnyNominal() != conformingNominal) superclassTy = superclassTy->getSuperclass(resolver); // Look up the inherited conformance. ModuleDecl *module = entry->getDeclContext()->getParentModule(); auto inheritedConformance = module->lookupConformance(superclassTy, protocol, resolver) .getPointer(); // Form the inherited conformance. conformance = ctx.getInheritedConformance( type, inheritedConformance->getConcrete()); } else { // Create or find the normal conformance. Type conformingType = conformingDC->getDeclaredTypeInContext(); SourceLoc conformanceLoc = conformingNominal == conformingDC ? conformingNominal->getLoc() : cast<ExtensionDecl>(conformingDC)->getLoc(); conformance = ctx.getConformance(conformingType, protocol, conformanceLoc, conformingDC, ProtocolConformanceState::Incomplete); } // Record the conformance. entry->Conformance = conformance; return conformance; }
void SILGenFunction::emitArtificialTopLevel(ClassDecl *mainClass) { // Load argc and argv from the entry point arguments. SILValue argc = F.begin()->getArgument(0); SILValue argv = F.begin()->getArgument(1); switch (mainClass->getArtificialMainKind()) { case ArtificialMainKind::UIApplicationMain: { // Emit a UIKit main. // return UIApplicationMain(C_ARGC, C_ARGV, nil, ClassName); CanType NSStringTy = SGM.Types.getNSStringType(); CanType OptNSStringTy = OptionalType::get(NSStringTy)->getCanonicalType(); // Look up UIApplicationMain. // FIXME: Doing an AST lookup here is gross and not entirely sound; // we're getting away with it because the types are guaranteed to already // be imported. ASTContext &ctx = getASTContext(); std::pair<Identifier, SourceLoc> UIKitName = {ctx.getIdentifier("UIKit"), SourceLoc()}; ModuleDecl *UIKit = ctx .getClangModuleLoader() ->loadModule(SourceLoc(), UIKitName); assert(UIKit && "couldn't find UIKit objc module?!"); SmallVector<ValueDecl *, 1> results; UIKit->lookupQualified(UIKit, ctx.getIdentifier("UIApplicationMain"), NL_QualifiedDefault, results); assert(results.size() == 1 && "couldn't find a unique UIApplicationMain in the UIKit ObjC " "module?!"); ValueDecl *UIApplicationMainDecl = results.front(); auto mainRef = SILDeclRef(UIApplicationMainDecl).asForeign(); SILGenFunctionBuilder builder(SGM); auto UIApplicationMainFn = builder.getOrCreateFunction(mainClass, mainRef, NotForDefinition); auto fnTy = UIApplicationMainFn->getLoweredFunctionType(); SILFunctionConventions fnConv(fnTy, SGM.M); // Get the class name as a string using NSStringFromClass. CanType mainClassTy = mainClass->getDeclaredInterfaceType() ->getCanonicalType(); CanType mainClassMetaty = CanMetatypeType::get(mainClassTy, MetatypeRepresentation::ObjC); CanType anyObjectTy = ctx.getAnyObjectType(); CanType anyObjectMetaTy = CanExistentialMetatypeType::get(anyObjectTy, MetatypeRepresentation::ObjC); auto NSStringFromClassType = SILFunctionType::get(nullptr, SILFunctionType::ExtInfo() .withRepresentation(SILFunctionType::Representation:: CFunctionPointer), SILCoroutineKind::None, ParameterConvention::Direct_Unowned, SILParameterInfo(anyObjectMetaTy, ParameterConvention::Direct_Unowned), /*yields*/ {}, SILResultInfo(OptNSStringTy, ResultConvention::Autoreleased), /*error result*/ None, ctx); auto NSStringFromClassFn = builder.getOrCreateFunction( mainClass, "NSStringFromClass", SILLinkage::PublicExternal, NSStringFromClassType, IsBare, IsTransparent, IsNotSerialized); auto NSStringFromClass = B.createFunctionRef(mainClass, NSStringFromClassFn); SILValue metaTy = B.createMetatype(mainClass, SILType::getPrimitiveObjectType(mainClassMetaty)); metaTy = B.createInitExistentialMetatype(mainClass, metaTy, SILType::getPrimitiveObjectType(anyObjectMetaTy), {}); SILValue optName = B.createApply(mainClass, NSStringFromClass, NSStringFromClass->getType(), SILType::getPrimitiveObjectType(OptNSStringTy), {}, metaTy); // Fix up the string parameters to have the right type. SILType nameArgTy = fnConv.getSILArgumentType(3); assert(nameArgTy == fnConv.getSILArgumentType(2)); (void)nameArgTy; auto managedName = ManagedValue::forUnmanaged(optName); SILValue nilValue; assert(optName->getType() == nameArgTy); nilValue = getOptionalNoneValue(mainClass, getTypeLowering(OptNSStringTy)); // Fix up argv to have the right type. auto argvTy = fnConv.getSILArgumentType(1); SILType unwrappedTy = argvTy; if (Type innerTy = argvTy.getASTType()->getOptionalObjectType()) { auto canInnerTy = innerTy->getCanonicalType(); unwrappedTy = SILType::getPrimitiveObjectType(canInnerTy); } auto managedArgv = ManagedValue::forUnmanaged(argv); if (unwrappedTy != argv->getType()) { auto converted = emitPointerToPointer(mainClass, managedArgv, argv->getType().getASTType(), unwrappedTy.getASTType()); managedArgv = std::move(converted).getAsSingleValue(*this, mainClass); } if (unwrappedTy != argvTy) { managedArgv = getOptionalSomeValue(mainClass, managedArgv, getTypeLowering(argvTy)); } auto UIApplicationMain = B.createFunctionRef(mainClass, UIApplicationMainFn); SILValue args[] = {argc, managedArgv.getValue(), nilValue, managedName.getValue()}; B.createApply(mainClass, UIApplicationMain, UIApplicationMain->getType(), argc->getType(), {}, args); SILValue r = B.createIntegerLiteral(mainClass, SILType::getBuiltinIntegerType(32, ctx), 0); auto rType = F.getConventions().getSingleSILResultType(); if (r->getType() != rType) r = B.createStruct(mainClass, rType, r); Cleanups.emitCleanupsForReturn(mainClass, NotForUnwind); B.createReturn(mainClass, r); return; } case ArtificialMainKind::NSApplicationMain: { // Emit an AppKit main. // return NSApplicationMain(C_ARGC, C_ARGV); SILParameterInfo argTypes[] = { SILParameterInfo(argc->getType().getASTType(), ParameterConvention::Direct_Unowned), SILParameterInfo(argv->getType().getASTType(), ParameterConvention::Direct_Unowned), }; auto NSApplicationMainType = SILFunctionType::get(nullptr, SILFunctionType::ExtInfo() // Should be C calling convention, but NSApplicationMain // has an overlay to fix the type of argv. .withRepresentation(SILFunctionType::Representation::Thin), SILCoroutineKind::None, ParameterConvention::Direct_Unowned, argTypes, /*yields*/ {}, SILResultInfo(argc->getType().getASTType(), ResultConvention::Unowned), /*error result*/ None, getASTContext()); SILGenFunctionBuilder builder(SGM); auto NSApplicationMainFn = builder.getOrCreateFunction( mainClass, "NSApplicationMain", SILLinkage::PublicExternal, NSApplicationMainType, IsBare, IsTransparent, IsNotSerialized); auto NSApplicationMain = B.createFunctionRef(mainClass, NSApplicationMainFn); SILValue args[] = { argc, argv }; B.createApply(mainClass, NSApplicationMain, NSApplicationMain->getType(), argc->getType(), {}, args); SILValue r = B.createIntegerLiteral(mainClass, SILType::getBuiltinIntegerType(32, getASTContext()), 0); auto rType = F.getConventions().getSingleSILResultType(); if (r->getType() != rType) r = B.createStruct(mainClass, rType, r); B.createReturn(mainClass, r); return; } } }
void NameBinder::addImport( SmallVectorImpl<SourceFile::ImportedModuleDesc> &imports, ImportDecl *ID) { if (ID->getModulePath().front().first == SF.getParentModule()->getName() && ID->getModulePath().size() == 1 && !shouldImportSelfImportClang(ID, SF)) { // If the imported module name is the same as the current module, // produce a diagnostic. StringRef filename = llvm::sys::path::filename(SF.getFilename()); if (filename.empty()) Context.Diags.diagnose(ID, diag::sema_import_current_module, ID->getModulePath().front().first); else Context.Diags.diagnose(ID, diag::sema_import_current_module_with_file, filename, ID->getModulePath().front().first); ID->setModule(SF.getParentModule()); return; } ModuleDecl *M = getModule(ID->getModulePath()); if (!M) { SmallString<64> modulePathStr; interleave(ID->getModulePath(), [&](ImportDecl::AccessPathElement elem) { modulePathStr += elem.first.str(); }, [&] { modulePathStr += "."; }); auto diagKind = diag::sema_no_import; if (SF.Kind == SourceFileKind::REPL || Context.LangOpts.DebuggerSupport) diagKind = diag::sema_no_import_repl; diagnose(ID->getLoc(), diagKind, modulePathStr); if (Context.SearchPathOpts.SDKPath.empty() && llvm::Triple(llvm::sys::getProcessTriple()).isMacOSX()) { diagnose(SourceLoc(), diag::sema_no_import_no_sdk); diagnose(SourceLoc(), diag::sema_no_import_no_sdk_xcrun); } return; } ID->setModule(M); ModuleDecl *topLevelModule; if (ID->getModulePath().size() == 1) { topLevelModule = M; } else { // If we imported a submodule, import the top-level module as well. Identifier topLevelName = ID->getModulePath().front().first; topLevelModule = Context.getLoadedModule(topLevelName); if (!topLevelModule) { // Clang can sometimes import top-level modules as if they were // submodules. assert(!M->getFiles().empty() && isa<ClangModuleUnit>(M->getFiles().front())); topLevelModule = M; } } auto *testableAttr = ID->getAttrs().getAttribute<TestableAttr>(); if (testableAttr && !topLevelModule->isTestingEnabled() && Context.LangOpts.EnableTestableAttrRequiresTestableModule) { diagnose(ID->getModulePath().front().second, diag::module_not_testable, topLevelModule->getName()); testableAttr->setInvalid(); } auto *privateImportAttr = ID->getAttrs().getAttribute<PrivateImportAttr>(); StringRef privateImportFileName; if (privateImportAttr) { if (!topLevelModule->arePrivateImportsEnabled()) { diagnose(ID->getModulePath().front().second, diag::module_not_compiled_for_private_import, topLevelModule->getName()); privateImportAttr->setInvalid(); } else { privateImportFileName = privateImportAttr->getSourceFile(); } } ImportOptions options; if (ID->isExported()) options |= SourceFile::ImportFlags::Exported; if (testableAttr) options |= SourceFile::ImportFlags::Testable; if (privateImportAttr) options |= SourceFile::ImportFlags::PrivateImport; auto *implementationOnlyAttr = ID->getAttrs().getAttribute<ImplementationOnlyAttr>(); if (implementationOnlyAttr) { if (options.contains(SourceFile::ImportFlags::Exported)) { diagnose(ID, diag::import_implementation_cannot_be_exported, topLevelModule->getName()) .fixItRemove(implementationOnlyAttr->getRangeWithAt()); } else { options |= SourceFile::ImportFlags::ImplementationOnly; } } imports.push_back(SourceFile::ImportedModuleDesc( {ID->getDeclPath(), M}, options, privateImportFileName)); if (topLevelModule != M) imports.push_back(SourceFile::ImportedModuleDesc( {ID->getDeclPath(), topLevelModule}, options, privateImportFileName)); if (ID->getImportKind() != ImportKind::Module) { // If we're importing a specific decl, validate the import kind. using namespace namelookup; auto declPath = ID->getDeclPath(); // FIXME: Doesn't handle scoped testable imports correctly. assert(declPath.size() == 1 && "can't handle sub-decl imports"); SmallVector<ValueDecl *, 8> decls; lookupInModule(topLevelModule, declPath, declPath.front().first, decls, NLKind::QualifiedLookup, ResolutionKind::Overloadable, /*resolver*/nullptr, &SF); if (decls.empty()) { diagnose(ID, diag::decl_does_not_exist_in_module, static_cast<unsigned>(ID->getImportKind()), declPath.front().first, ID->getModulePath().front().first) .highlight(SourceRange(declPath.front().second, declPath.back().second)); return; } ID->setDecls(Context.AllocateCopy(decls)); Optional<ImportKind> actualKind = ImportDecl::findBestImportKind(decls); if (!actualKind.hasValue()) { // FIXME: print entire module name? diagnose(ID, diag::ambiguous_decl_in_module, declPath.front().first, M->getName()); for (auto next : decls) diagnose(next, diag::found_candidate); } else if (!isCompatibleImportKind(ID->getImportKind(), *actualKind)) { Optional<InFlightDiagnostic> emittedDiag; if (*actualKind == ImportKind::Type && isNominalImportKind(ID->getImportKind())) { assert(decls.size() == 1 && "if we start suggesting ImportKind::Type for, e.g., a mix of " "structs and classes, we'll need a different message here"); assert(isa<TypeAliasDecl>(decls.front()) && "ImportKind::Type is only the best choice for a typealias"); auto *typealias = cast<TypeAliasDecl>(decls.front()); emittedDiag.emplace(diagnose(ID, diag::imported_decl_is_wrong_kind_typealias, typealias->getDescriptiveKind(), TypeAliasType::get(typealias, Type(), SubstitutionMap(), typealias->getUnderlyingTypeLoc().getType()), getImportKindString(ID->getImportKind()))); } else { emittedDiag.emplace(diagnose(ID, diag::imported_decl_is_wrong_kind, declPath.front().first, getImportKindString(ID->getImportKind()), static_cast<unsigned>(*actualKind))); } emittedDiag->fixItReplace(SourceRange(ID->getKindLoc()), getImportKindString(*actualKind)); emittedDiag->flush(); if (decls.size() == 1) diagnose(decls.front(), diag::decl_declared_here, decls.front()->getFullName()); } } }
ImportDepth::ImportDepth(ASTContext &context, CompilerInvocation &invocation) { llvm::DenseSet<ModuleDecl *> seen; std::deque<std::pair<ModuleDecl *, uint8_t>> worklist; StringRef mainModule = invocation.getModuleName(); auto *main = context.getLoadedModule(context.getIdentifier(mainModule)); assert(main && "missing main module"); worklist.emplace_back(main, uint8_t(0)); // Imports from -import-name such as Playground auxiliary sources are treated // specially by applying import depth 0. llvm::StringSet<> auxImports; for (StringRef moduleName : invocation.getFrontendOptions().ImplicitImportModuleNames) auxImports.insert(moduleName); // Private imports from this module. // FIXME: only the private imports from the current source file. ModuleDecl::ImportFilter importFilter; importFilter |= ModuleDecl::ImportFilterKind::Private; importFilter |= ModuleDecl::ImportFilterKind::ImplementationOnly; SmallVector<ModuleDecl::ImportedModule, 16> mainImports; main->getImportedModules(mainImports, importFilter); for (auto &import : mainImports) { uint8_t depth = 1; if (auxImports.count(import.second->getName().str())) depth = 0; worklist.emplace_back(import.second, depth); } // Fill depths with BFS over module imports. while (!worklist.empty()) { ModuleDecl *module; uint8_t depth; std::tie(module, depth) = worklist.front(); worklist.pop_front(); if (!seen.insert(module).second) continue; // Insert new module:depth mapping. const clang::Module *CM = module->findUnderlyingClangModule(); if (CM) { depths[CM->getFullModuleName()] = depth; } else { depths[module->getName().str()] = depth; } // Add imports to the worklist. SmallVector<ModuleDecl::ImportedModule, 16> imports; module->getImportedModules(imports); for (auto &import : imports) { uint8_t next = std::max(depth, uint8_t(depth + 1)); // unsigned wrap // Implicitly imported sub-modules get the same depth as their parent. if (const clang::Module *CMI = import.second->findUnderlyingClangModule()) if (CM && CMI->isSubModuleOf(CM)) next = depth; worklist.emplace_back(import.second, next); } } }
static void addModuleDependencies(ArrayRef<ModuleDecl::ImportedModule> imports, StringRef indexStorePath, bool indexSystemModules, StringRef targetTriple, const clang::CompilerInstance &clangCI, DiagnosticEngine &diags, IndexUnitWriter &unitWriter, StringScratchSpace &moduleNameScratch) { auto &fileMgr = clangCI.getFileManager(); for (auto &import : imports) { ModuleDecl *mod = import.second; if (mod->isOnoneSupportModule()) continue; // ignore the Onone support library. if (mod->isSwiftShimsModule()) continue; for (auto *FU : mod->getFiles()) { switch (FU->getKind()) { case FileUnitKind::Source: case FileUnitKind::Builtin: break; case FileUnitKind::SerializedAST: case FileUnitKind::DWARFModule: case FileUnitKind::ClangModule: { auto *LFU = cast<LoadedFile>(FU); if (auto *F = fileMgr.getFile(LFU->getFilename())) { std::string moduleName = mod->getNameStr(); bool withoutUnitName = true; if (FU->getKind() == FileUnitKind::ClangModule) { withoutUnitName = false; auto clangModUnit = cast<ClangModuleUnit>(LFU); if (auto clangMod = clangModUnit->getUnderlyingClangModule()) { moduleName = clangMod->getTopLevelModuleName(); // FIXME: clang's -Rremarks do not seem to go through Swift's // diagnostic emitter. clang::index::emitIndexDataForModuleFile(clangMod, clangCI, unitWriter); } } else { // Serialized AST file. // Only index system modules (essentially stdlib and overlays). // We don't officially support binary swift modules, so normally // the index data for user modules would get generated while // building them. if (mod->isSystemModule() && indexSystemModules) { emitDataForSwiftSerializedModule(mod, indexStorePath, indexSystemModules, targetTriple, clangCI, diags, unitWriter); withoutUnitName = false; } } clang::index::writer::OpaqueModule opaqMod = moduleNameScratch.createString(moduleName); unitWriter.addASTFileDependency(F, mod->isSystemModule(), opaqMod, withoutUnitName); } break; } } } } }