10b57cec5SDimitry Andric //===--- ModuleBuilder.cpp - Emit LLVM Code from ASTs ---------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This builds an AST and converts it to LLVM Code. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "clang/CodeGen/ModuleBuilder.h" 140b57cec5SDimitry Andric #include "CGDebugInfo.h" 150b57cec5SDimitry Andric #include "CodeGenModule.h" 160b57cec5SDimitry Andric #include "clang/AST/ASTContext.h" 170b57cec5SDimitry Andric #include "clang/AST/DeclObjC.h" 180b57cec5SDimitry Andric #include "clang/AST/Expr.h" 190b57cec5SDimitry Andric #include "clang/Basic/CodeGenOptions.h" 200b57cec5SDimitry Andric #include "clang/Basic/Diagnostic.h" 210b57cec5SDimitry Andric #include "clang/Basic/TargetInfo.h" 220b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 230b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h" 240b57cec5SDimitry Andric #include "llvm/IR/LLVMContext.h" 250b57cec5SDimitry Andric #include "llvm/IR/Module.h" 260b57cec5SDimitry Andric #include <memory> 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric using namespace clang; 290b57cec5SDimitry Andric using namespace CodeGen; 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric namespace { 320b57cec5SDimitry Andric class CodeGeneratorImpl : public CodeGenerator { 330b57cec5SDimitry Andric DiagnosticsEngine &Diags; 340b57cec5SDimitry Andric ASTContext *Ctx; 350b57cec5SDimitry Andric const HeaderSearchOptions &HeaderSearchOpts; // Only used for debug info. 360b57cec5SDimitry Andric const PreprocessorOptions &PreprocessorOpts; // Only used for debug info. 370b57cec5SDimitry Andric const CodeGenOptions CodeGenOpts; // Intentionally copied in. 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric unsigned HandlingTopLevelDecls; 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric /// Use this when emitting decls to block re-entrant decl emission. It will 420b57cec5SDimitry Andric /// emit all deferred decls on scope exit. Set EmitDeferred to false if decl 430b57cec5SDimitry Andric /// emission must be deferred longer, like at the end of a tag definition. 440b57cec5SDimitry Andric struct HandlingTopLevelDeclRAII { 450b57cec5SDimitry Andric CodeGeneratorImpl &Self; 460b57cec5SDimitry Andric bool EmitDeferred; 470b57cec5SDimitry Andric HandlingTopLevelDeclRAII(CodeGeneratorImpl &Self, 480b57cec5SDimitry Andric bool EmitDeferred = true) 490b57cec5SDimitry Andric : Self(Self), EmitDeferred(EmitDeferred) { 500b57cec5SDimitry Andric ++Self.HandlingTopLevelDecls; 510b57cec5SDimitry Andric } 520b57cec5SDimitry Andric ~HandlingTopLevelDeclRAII() { 530b57cec5SDimitry Andric unsigned Level = --Self.HandlingTopLevelDecls; 540b57cec5SDimitry Andric if (Level == 0 && EmitDeferred) 550b57cec5SDimitry Andric Self.EmitDeferredDecls(); 560b57cec5SDimitry Andric } 570b57cec5SDimitry Andric }; 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric CoverageSourceInfo *CoverageInfo; 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric protected: 620b57cec5SDimitry Andric std::unique_ptr<llvm::Module> M; 630b57cec5SDimitry Andric std::unique_ptr<CodeGen::CodeGenModule> Builder; 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric private: 660b57cec5SDimitry Andric SmallVector<FunctionDecl *, 8> DeferredInlineMemberFuncDefs; 670b57cec5SDimitry Andric 68a7dea167SDimitry Andric static llvm::StringRef ExpandModuleName(llvm::StringRef ModuleName, 69a7dea167SDimitry Andric const CodeGenOptions &CGO) { 70a7dea167SDimitry Andric if (ModuleName == "-" && !CGO.MainFileName.empty()) 71a7dea167SDimitry Andric return CGO.MainFileName; 72a7dea167SDimitry Andric return ModuleName; 73a7dea167SDimitry Andric } 74a7dea167SDimitry Andric 750b57cec5SDimitry Andric public: 760b57cec5SDimitry Andric CodeGeneratorImpl(DiagnosticsEngine &diags, llvm::StringRef ModuleName, 770b57cec5SDimitry Andric const HeaderSearchOptions &HSO, 780b57cec5SDimitry Andric const PreprocessorOptions &PPO, const CodeGenOptions &CGO, 790b57cec5SDimitry Andric llvm::LLVMContext &C, 800b57cec5SDimitry Andric CoverageSourceInfo *CoverageInfo = nullptr) 810b57cec5SDimitry Andric : Diags(diags), Ctx(nullptr), HeaderSearchOpts(HSO), 820b57cec5SDimitry Andric PreprocessorOpts(PPO), CodeGenOpts(CGO), HandlingTopLevelDecls(0), 83a7dea167SDimitry Andric CoverageInfo(CoverageInfo), 84a7dea167SDimitry Andric M(new llvm::Module(ExpandModuleName(ModuleName, CGO), C)) { 850b57cec5SDimitry Andric C.setDiscardValueNames(CGO.DiscardValueNames); 860b57cec5SDimitry Andric } 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric ~CodeGeneratorImpl() override { 890b57cec5SDimitry Andric // There should normally not be any leftover inline method definitions. 900b57cec5SDimitry Andric assert(DeferredInlineMemberFuncDefs.empty() || 910b57cec5SDimitry Andric Diags.hasErrorOccurred()); 920b57cec5SDimitry Andric } 930b57cec5SDimitry Andric 940b57cec5SDimitry Andric CodeGenModule &CGM() { 950b57cec5SDimitry Andric return *Builder; 960b57cec5SDimitry Andric } 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric llvm::Module *GetModule() { 990b57cec5SDimitry Andric return M.get(); 1000b57cec5SDimitry Andric } 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric CGDebugInfo *getCGDebugInfo() { 1030b57cec5SDimitry Andric return Builder->getModuleDebugInfo(); 1040b57cec5SDimitry Andric } 1050b57cec5SDimitry Andric 1060b57cec5SDimitry Andric llvm::Module *ReleaseModule() { 1070b57cec5SDimitry Andric return M.release(); 1080b57cec5SDimitry Andric } 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric const Decl *GetDeclForMangledName(StringRef MangledName) { 1110b57cec5SDimitry Andric GlobalDecl Result; 1120b57cec5SDimitry Andric if (!Builder->lookupRepresentativeDecl(MangledName, Result)) 1130b57cec5SDimitry Andric return nullptr; 1140b57cec5SDimitry Andric const Decl *D = Result.getCanonicalDecl().getDecl(); 1150b57cec5SDimitry Andric if (auto FD = dyn_cast<FunctionDecl>(D)) { 1160b57cec5SDimitry Andric if (FD->hasBody(FD)) 1170b57cec5SDimitry Andric return FD; 1180b57cec5SDimitry Andric } else if (auto TD = dyn_cast<TagDecl>(D)) { 1190b57cec5SDimitry Andric if (auto Def = TD->getDefinition()) 1200b57cec5SDimitry Andric return Def; 1210b57cec5SDimitry Andric } 1220b57cec5SDimitry Andric return D; 1230b57cec5SDimitry Andric } 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric llvm::Constant *GetAddrOfGlobal(GlobalDecl global, bool isForDefinition) { 1260b57cec5SDimitry Andric return Builder->GetAddrOfGlobal(global, ForDefinition_t(isForDefinition)); 1270b57cec5SDimitry Andric } 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric llvm::Module *StartModule(llvm::StringRef ModuleName, 1300b57cec5SDimitry Andric llvm::LLVMContext &C) { 1310b57cec5SDimitry Andric assert(!M && "Replacing existing Module?"); 132a7dea167SDimitry Andric M.reset(new llvm::Module(ExpandModuleName(ModuleName, CodeGenOpts), C)); 1330b57cec5SDimitry Andric Initialize(*Ctx); 1340b57cec5SDimitry Andric return M.get(); 1350b57cec5SDimitry Andric } 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric void Initialize(ASTContext &Context) override { 1380b57cec5SDimitry Andric Ctx = &Context; 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric M->setTargetTriple(Ctx->getTargetInfo().getTriple().getTriple()); 1410b57cec5SDimitry Andric M->setDataLayout(Ctx->getTargetInfo().getDataLayout()); 1420b57cec5SDimitry Andric const auto &SDKVersion = Ctx->getTargetInfo().getSDKVersion(); 1430b57cec5SDimitry Andric if (!SDKVersion.empty()) 1440b57cec5SDimitry Andric M->setSDKVersion(SDKVersion); 1450b57cec5SDimitry Andric Builder.reset(new CodeGen::CodeGenModule(Context, HeaderSearchOpts, 1460b57cec5SDimitry Andric PreprocessorOpts, CodeGenOpts, 1470b57cec5SDimitry Andric *M, Diags, CoverageInfo)); 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric for (auto &&Lib : CodeGenOpts.DependentLibraries) 1500b57cec5SDimitry Andric Builder->AddDependentLib(Lib); 1510b57cec5SDimitry Andric for (auto &&Opt : CodeGenOpts.LinkerOptions) 1520b57cec5SDimitry Andric Builder->AppendLinkerOptions(Opt); 1530b57cec5SDimitry Andric } 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric void HandleCXXStaticMemberVarInstantiation(VarDecl *VD) override { 1560b57cec5SDimitry Andric if (Diags.hasErrorOccurred()) 1570b57cec5SDimitry Andric return; 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric Builder->HandleCXXStaticMemberVarInstantiation(VD); 1600b57cec5SDimitry Andric } 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric bool HandleTopLevelDecl(DeclGroupRef DG) override { 1630b57cec5SDimitry Andric if (Diags.hasErrorOccurred()) 1640b57cec5SDimitry Andric return true; 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andric HandlingTopLevelDeclRAII HandlingDecl(*this); 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric // Make sure to emit all elements of a Decl. 1690b57cec5SDimitry Andric for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) 1700b57cec5SDimitry Andric Builder->EmitTopLevelDecl(*I); 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric return true; 1730b57cec5SDimitry Andric } 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric void EmitDeferredDecls() { 1760b57cec5SDimitry Andric if (DeferredInlineMemberFuncDefs.empty()) 1770b57cec5SDimitry Andric return; 1780b57cec5SDimitry Andric 1790b57cec5SDimitry Andric // Emit any deferred inline method definitions. Note that more deferred 1800b57cec5SDimitry Andric // methods may be added during this loop, since ASTConsumer callbacks 1810b57cec5SDimitry Andric // can be invoked if AST inspection results in declarations being added. 1820b57cec5SDimitry Andric HandlingTopLevelDeclRAII HandlingDecl(*this); 1830b57cec5SDimitry Andric for (unsigned I = 0; I != DeferredInlineMemberFuncDefs.size(); ++I) 1840b57cec5SDimitry Andric Builder->EmitTopLevelDecl(DeferredInlineMemberFuncDefs[I]); 1850b57cec5SDimitry Andric DeferredInlineMemberFuncDefs.clear(); 1860b57cec5SDimitry Andric } 1870b57cec5SDimitry Andric 1880b57cec5SDimitry Andric void HandleInlineFunctionDefinition(FunctionDecl *D) override { 1890b57cec5SDimitry Andric if (Diags.hasErrorOccurred()) 1900b57cec5SDimitry Andric return; 1910b57cec5SDimitry Andric 1920b57cec5SDimitry Andric assert(D->doesThisDeclarationHaveABody()); 1930b57cec5SDimitry Andric 1940b57cec5SDimitry Andric // We may want to emit this definition. However, that decision might be 1950b57cec5SDimitry Andric // based on computing the linkage, and we have to defer that in case we 1960b57cec5SDimitry Andric // are inside of something that will change the method's final linkage, 1970b57cec5SDimitry Andric // e.g. 1980b57cec5SDimitry Andric // typedef struct { 1990b57cec5SDimitry Andric // void bar(); 2000b57cec5SDimitry Andric // void foo() { bar(); } 2010b57cec5SDimitry Andric // } A; 2020b57cec5SDimitry Andric DeferredInlineMemberFuncDefs.push_back(D); 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric // Provide some coverage mapping even for methods that aren't emitted. 2050b57cec5SDimitry Andric // Don't do this for templated classes though, as they may not be 2060b57cec5SDimitry Andric // instantiable. 2070b57cec5SDimitry Andric if (!D->getLexicalDeclContext()->isDependentContext()) 2080b57cec5SDimitry Andric Builder->AddDeferredUnusedCoverageMapping(D); 2090b57cec5SDimitry Andric } 2100b57cec5SDimitry Andric 2110b57cec5SDimitry Andric /// HandleTagDeclDefinition - This callback is invoked each time a TagDecl 2120b57cec5SDimitry Andric /// to (e.g. struct, union, enum, class) is completed. This allows the 2130b57cec5SDimitry Andric /// client hack on the type, which can occur at any point in the file 2140b57cec5SDimitry Andric /// (because these can be defined in declspecs). 2150b57cec5SDimitry Andric void HandleTagDeclDefinition(TagDecl *D) override { 2160b57cec5SDimitry Andric if (Diags.hasErrorOccurred()) 2170b57cec5SDimitry Andric return; 2180b57cec5SDimitry Andric 2190b57cec5SDimitry Andric // Don't allow re-entrant calls to CodeGen triggered by PCH 2200b57cec5SDimitry Andric // deserialization to emit deferred decls. 2210b57cec5SDimitry Andric HandlingTopLevelDeclRAII HandlingDecl(*this, /*EmitDeferred=*/false); 2220b57cec5SDimitry Andric 2230b57cec5SDimitry Andric Builder->UpdateCompletedType(D); 2240b57cec5SDimitry Andric 2250b57cec5SDimitry Andric // For MSVC compatibility, treat declarations of static data members with 2260b57cec5SDimitry Andric // inline initializers as definitions. 2270b57cec5SDimitry Andric if (Ctx->getTargetInfo().getCXXABI().isMicrosoft()) { 2280b57cec5SDimitry Andric for (Decl *Member : D->decls()) { 2290b57cec5SDimitry Andric if (VarDecl *VD = dyn_cast<VarDecl>(Member)) { 2300b57cec5SDimitry Andric if (Ctx->isMSStaticDataMemberInlineDefinition(VD) && 2310b57cec5SDimitry Andric Ctx->DeclMustBeEmitted(VD)) { 2320b57cec5SDimitry Andric Builder->EmitGlobal(VD); 2330b57cec5SDimitry Andric } 2340b57cec5SDimitry Andric } 2350b57cec5SDimitry Andric } 2360b57cec5SDimitry Andric } 2370b57cec5SDimitry Andric // For OpenMP emit declare reduction functions, if required. 2380b57cec5SDimitry Andric if (Ctx->getLangOpts().OpenMP) { 2390b57cec5SDimitry Andric for (Decl *Member : D->decls()) { 2400b57cec5SDimitry Andric if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(Member)) { 2410b57cec5SDimitry Andric if (Ctx->DeclMustBeEmitted(DRD)) 2420b57cec5SDimitry Andric Builder->EmitGlobal(DRD); 243a7dea167SDimitry Andric } else if (auto *DMD = dyn_cast<OMPDeclareMapperDecl>(Member)) { 244a7dea167SDimitry Andric if (Ctx->DeclMustBeEmitted(DMD)) 245a7dea167SDimitry Andric Builder->EmitGlobal(DMD); 2460b57cec5SDimitry Andric } 2470b57cec5SDimitry Andric } 2480b57cec5SDimitry Andric } 2490b57cec5SDimitry Andric } 2500b57cec5SDimitry Andric 2510b57cec5SDimitry Andric void HandleTagDeclRequiredDefinition(const TagDecl *D) override { 2520b57cec5SDimitry Andric if (Diags.hasErrorOccurred()) 2530b57cec5SDimitry Andric return; 2540b57cec5SDimitry Andric 2550b57cec5SDimitry Andric // Don't allow re-entrant calls to CodeGen triggered by PCH 2560b57cec5SDimitry Andric // deserialization to emit deferred decls. 2570b57cec5SDimitry Andric HandlingTopLevelDeclRAII HandlingDecl(*this, /*EmitDeferred=*/false); 2580b57cec5SDimitry Andric 2590b57cec5SDimitry Andric if (CodeGen::CGDebugInfo *DI = Builder->getModuleDebugInfo()) 2600b57cec5SDimitry Andric if (const RecordDecl *RD = dyn_cast<RecordDecl>(D)) 2610b57cec5SDimitry Andric DI->completeRequiredType(RD); 2620b57cec5SDimitry Andric } 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric void HandleTranslationUnit(ASTContext &Ctx) override { 2650b57cec5SDimitry Andric // Release the Builder when there is no error. 2660b57cec5SDimitry Andric if (!Diags.hasErrorOccurred() && Builder) 2670b57cec5SDimitry Andric Builder->Release(); 2680b57cec5SDimitry Andric 2690b57cec5SDimitry Andric // If there are errors before or when releasing the Builder, reset 2700b57cec5SDimitry Andric // the module to stop here before invoking the backend. 2710b57cec5SDimitry Andric if (Diags.hasErrorOccurred()) { 2720b57cec5SDimitry Andric if (Builder) 2730b57cec5SDimitry Andric Builder->clear(); 2740b57cec5SDimitry Andric M.reset(); 2750b57cec5SDimitry Andric return; 2760b57cec5SDimitry Andric } 2770b57cec5SDimitry Andric } 2780b57cec5SDimitry Andric 2790b57cec5SDimitry Andric void AssignInheritanceModel(CXXRecordDecl *RD) override { 2800b57cec5SDimitry Andric if (Diags.hasErrorOccurred()) 2810b57cec5SDimitry Andric return; 2820b57cec5SDimitry Andric 2830b57cec5SDimitry Andric Builder->RefreshTypeCacheForClass(RD); 2840b57cec5SDimitry Andric } 2850b57cec5SDimitry Andric 2860b57cec5SDimitry Andric void CompleteTentativeDefinition(VarDecl *D) override { 2870b57cec5SDimitry Andric if (Diags.hasErrorOccurred()) 2880b57cec5SDimitry Andric return; 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andric Builder->EmitTentativeDefinition(D); 2910b57cec5SDimitry Andric } 2920b57cec5SDimitry Andric 293*480093f4SDimitry Andric void CompleteExternalDeclaration(VarDecl *D) override { 294*480093f4SDimitry Andric Builder->EmitExternalDeclaration(D); 295*480093f4SDimitry Andric } 296*480093f4SDimitry Andric 2970b57cec5SDimitry Andric void HandleVTable(CXXRecordDecl *RD) override { 2980b57cec5SDimitry Andric if (Diags.hasErrorOccurred()) 2990b57cec5SDimitry Andric return; 3000b57cec5SDimitry Andric 3010b57cec5SDimitry Andric Builder->EmitVTable(RD); 3020b57cec5SDimitry Andric } 3030b57cec5SDimitry Andric }; 3040b57cec5SDimitry Andric } 3050b57cec5SDimitry Andric 3060b57cec5SDimitry Andric void CodeGenerator::anchor() { } 3070b57cec5SDimitry Andric 3080b57cec5SDimitry Andric CodeGenModule &CodeGenerator::CGM() { 3090b57cec5SDimitry Andric return static_cast<CodeGeneratorImpl*>(this)->CGM(); 3100b57cec5SDimitry Andric } 3110b57cec5SDimitry Andric 3120b57cec5SDimitry Andric llvm::Module *CodeGenerator::GetModule() { 3130b57cec5SDimitry Andric return static_cast<CodeGeneratorImpl*>(this)->GetModule(); 3140b57cec5SDimitry Andric } 3150b57cec5SDimitry Andric 3160b57cec5SDimitry Andric llvm::Module *CodeGenerator::ReleaseModule() { 3170b57cec5SDimitry Andric return static_cast<CodeGeneratorImpl*>(this)->ReleaseModule(); 3180b57cec5SDimitry Andric } 3190b57cec5SDimitry Andric 3200b57cec5SDimitry Andric CGDebugInfo *CodeGenerator::getCGDebugInfo() { 3210b57cec5SDimitry Andric return static_cast<CodeGeneratorImpl*>(this)->getCGDebugInfo(); 3220b57cec5SDimitry Andric } 3230b57cec5SDimitry Andric 3240b57cec5SDimitry Andric const Decl *CodeGenerator::GetDeclForMangledName(llvm::StringRef name) { 3250b57cec5SDimitry Andric return static_cast<CodeGeneratorImpl*>(this)->GetDeclForMangledName(name); 3260b57cec5SDimitry Andric } 3270b57cec5SDimitry Andric 3280b57cec5SDimitry Andric llvm::Constant *CodeGenerator::GetAddrOfGlobal(GlobalDecl global, 3290b57cec5SDimitry Andric bool isForDefinition) { 3300b57cec5SDimitry Andric return static_cast<CodeGeneratorImpl*>(this) 3310b57cec5SDimitry Andric ->GetAddrOfGlobal(global, isForDefinition); 3320b57cec5SDimitry Andric } 3330b57cec5SDimitry Andric 3340b57cec5SDimitry Andric llvm::Module *CodeGenerator::StartModule(llvm::StringRef ModuleName, 3350b57cec5SDimitry Andric llvm::LLVMContext &C) { 3360b57cec5SDimitry Andric return static_cast<CodeGeneratorImpl*>(this)->StartModule(ModuleName, C); 3370b57cec5SDimitry Andric } 3380b57cec5SDimitry Andric 3390b57cec5SDimitry Andric CodeGenerator *clang::CreateLLVMCodeGen( 3400b57cec5SDimitry Andric DiagnosticsEngine &Diags, llvm::StringRef ModuleName, 3410b57cec5SDimitry Andric const HeaderSearchOptions &HeaderSearchOpts, 3420b57cec5SDimitry Andric const PreprocessorOptions &PreprocessorOpts, const CodeGenOptions &CGO, 3430b57cec5SDimitry Andric llvm::LLVMContext &C, CoverageSourceInfo *CoverageInfo) { 3440b57cec5SDimitry Andric return new CodeGeneratorImpl(Diags, ModuleName, HeaderSearchOpts, 3450b57cec5SDimitry Andric PreprocessorOpts, CGO, C, CoverageInfo); 3460b57cec5SDimitry Andric } 347