https://github.com/Changqing-JING created 
https://github.com/llvm/llvm-project/pull/200720

This adds a source-level way to override the import module for imported
WebAssembly globals without introducing new global-specific attributes.

Clang lowers annotate("wasm-import-module", "...") on globals to
!wasm.import.module metadata, and the WebAssembly backend uses that metadata
when emitting the import. Invalid uses are ignored with a warning.

>From 11de35e8378eff10fc32c3e8e45b29491ae41cb1 Mon Sep 17 00:00:00 2001
From: Changqing Jing <[email protected]>
Date: Mon, 1 Jun 2026 13:36:37 +0800
Subject: [PATCH] [clang][WebAssembly] support custom module name of import
 globals

---
 clang/lib/CodeGen/CodeGenModule.cpp           | 475 +++++++++---------
 clang/lib/CodeGen/Targets/WebAssembly.cpp     |  45 ++
 .../WebAssembly/wasm-global-import-module.cpp |  19 +
 .../WebAssembly/WebAssemblyAsmPrinter.cpp     |  28 +-
 .../import-module-global-metadata.ll          |  24 +
 5 files changed, 355 insertions(+), 236 deletions(-)
 create mode 100644 clang/test/CodeGen/WebAssembly/wasm-global-import-module.cpp
 create mode 100644 
llvm/test/CodeGen/WebAssembly/import-module-global-metadata.ll

diff --git a/clang/lib/CodeGen/CodeGenModule.cpp 
b/clang/lib/CodeGen/CodeGenModule.cpp
index 236738e9975d3..f6dbb30300a57 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -463,14 +463,15 @@ CodeGenModule::CodeGenModule(ASTContext &C,
       C.toCharUnitsFromBits(C.getTargetInfo().getPointerAlign(LangAS::Default))
           .getQuantity();
   SizeSizeInBytes =
-    
C.toCharUnitsFromBits(C.getTargetInfo().getMaxPointerWidth()).getQuantity();
+      C.toCharUnitsFromBits(C.getTargetInfo().getMaxPointerWidth())
+          .getQuantity();
   IntAlignInBytes =
-    C.toCharUnitsFromBits(C.getTargetInfo().getIntAlign()).getQuantity();
+      C.toCharUnitsFromBits(C.getTargetInfo().getIntAlign()).getQuantity();
   CharTy =
-    llvm::IntegerType::get(LLVMContext, C.getTargetInfo().getCharWidth());
+      llvm::IntegerType::get(LLVMContext, C.getTargetInfo().getCharWidth());
   IntTy = llvm::IntegerType::get(LLVMContext, C.getTargetInfo().getIntWidth());
   IntPtrTy = llvm::IntegerType::get(LLVMContext,
-    C.getTargetInfo().getMaxPointerWidth());
+                                    C.getTargetInfo().getMaxPointerWidth());
   Int8PtrTy = llvm::PointerType::get(LLVMContext,
                                      C.getTargetAddressSpace(LangAS::Default));
   const llvm::DataLayout &DL = M.getDataLayout();
@@ -687,7 +688,8 @@ void CodeGenModule::applyReplacements() {
   }
 }
 
-void CodeGenModule::addGlobalValReplacement(llvm::GlobalValue *GV, 
llvm::Constant *C) {
+void CodeGenModule::addGlobalValReplacement(llvm::GlobalValue *GV,
+                                            llvm::Constant *C) {
   GlobalValReplacements.push_back(std::make_pair(GV, C));
 }
 
@@ -724,8 +726,9 @@ static const llvm::GlobalValue *getAliasedGlobal(const 
llvm::GlobalValue *GV) {
 }
 
 static bool checkAliasedGlobal(
-    const ASTContext &Context, DiagnosticsEngine &Diags, SourceLocation 
Location,
-    bool IsIFunc, const llvm::GlobalValue *Alias, const llvm::GlobalValue *&GV,
+    const ASTContext &Context, DiagnosticsEngine &Diags,
+    SourceLocation Location, bool IsIFunc, const llvm::GlobalValue *Alias,
+    const llvm::GlobalValue *&GV,
     const llvm::MapVector<GlobalDecl, StringRef> &MangledDeclNames,
     SourceRange AliasRange) {
   GV = getAliasedGlobal(Alias);
@@ -971,7 +974,8 @@ void InstrProfStats::reportDiagnostics(DiagnosticsEngine 
&Diags,
     Diags.Report(diag::warn_profile_data_unprofiled) << MainFile;
   } else {
     if (Mismatched > 0)
-      Diags.Report(diag::warn_profile_data_out_of_date) << Visited << 
Mismatched;
+      Diags.Report(diag::warn_profile_data_out_of_date)
+          << Visited << Mismatched;
 
     if (Missing > 0)
       Diags.Report(diag::warn_profile_data_missing) << Visited << Missing;
@@ -1220,7 +1224,8 @@ void CodeGenModule::Release() {
   // usage of #pragma comment(lib, *) is intended for host libraries on
   // Windows. Therefore emit llvm.dependent-libraries only for host.
   if (!ELFDependentLibraries.empty() && !Context.getLangOpts().CUDAIsDevice) {
-    auto *NMD = 
getModule().getOrInsertNamedMetadata("llvm.dependent-libraries");
+    auto *NMD =
+        getModule().getOrInsertNamedMetadata("llvm.dependent-libraries");
     for (auto *MD : ELFDependentLibraries)
       NMD->addOperand(MD);
   }
@@ -1275,12 +1280,12 @@ void CodeGenModule::Release() {
     // FIXME: we could support it by stripping all the information introduced
     // by StrictVTablePointers.
 
-    getModule().addModuleFlag(llvm::Module::Error, "StrictVTablePointers",1);
+    getModule().addModuleFlag(llvm::Module::Error, "StrictVTablePointers", 1);
 
     llvm::Metadata *Ops[2] = {
-              llvm::MDString::get(VMContext, "StrictVTablePointers"),
-              llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
-                  llvm::Type::getInt32Ty(VMContext), 1))};
+        llvm::MDString::get(VMContext, "StrictVTablePointers"),
+        llvm::ConstantAsMetadata::get(
+            llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 1))};
 
     getModule().addModuleFlag(llvm::Module::Require,
                               "StrictVTablePointersRequirement",
@@ -1411,15 +1416,13 @@ void CodeGenModule::Release() {
   if (CodeGenOpts.CFProtectionReturn &&
       Target.checkCFProtectionReturnSupported(getDiags())) {
     // Indicate that we want to instrument return control flow protection.
-    getModule().addModuleFlag(llvm::Module::Min, "cf-protection-return",
-                              1);
+    getModule().addModuleFlag(llvm::Module::Min, "cf-protection-return", 1);
   }
 
   if (CodeGenOpts.CFProtectionBranch &&
       Target.checkCFProtectionBranchSupported(getDiags())) {
     // Indicate that we want to instrument branch control flow protection.
-    getModule().addModuleFlag(llvm::Module::Min, "cf-protection-branch",
-                              1);
+    getModule().addModuleFlag(llvm::Module::Min, "cf-protection-branch", 1);
 
     auto Scheme = CodeGenOpts.getCFBranchLabelScheme();
     if (Target.checkCFBranchLabelSchemeSupported(Scheme, getDiags())) {
@@ -1433,10 +1436,12 @@ void CodeGenModule::Release() {
   }
 
   if (CodeGenOpts.FunctionReturnThunks)
-    getModule().addModuleFlag(llvm::Module::Override, 
"function_return_thunk_extern", 1);
+    getModule().addModuleFlag(llvm::Module::Override,
+                              "function_return_thunk_extern", 1);
 
   if (CodeGenOpts.IndirectBranchCSPrefix)
-    getModule().addModuleFlag(llvm::Module::Override, 
"indirect_branch_cs_prefix", 1);
+    getModule().addModuleFlag(llvm::Module::Override,
+                              "indirect_branch_cs_prefix", 1);
 
   // Add module metadata for return address signing (ignoring
   // non-leaf/all) and stack tagging. These are actually turned on by function
@@ -1616,10 +1621,10 @@ void CodeGenModule::Release() {
       // OpenCL.
       auto Version = LangOpts.getOpenCLCompatibleVersion();
       llvm::Metadata *SPIRVerElts[] = {
-          llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
-              Int32Ty, Version / 100)),
-          llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
-              Int32Ty, (Version / 100 > 1) ? 0 : 2))};
+          llvm::ConstantAsMetadata::get(
+              llvm::ConstantInt::get(Int32Ty, Version / 100)),
+          llvm::ConstantAsMetadata::get(
+              llvm::ConstantInt::get(Int32Ty, (Version / 100 > 1) ? 0 : 2))};
       llvm::NamedMDNode *SPIRVerMD =
           TheModule.getOrInsertNamedMetadata("opencl.spir.version");
       llvm::LLVMContext &Ctx = TheModule.getContext();
@@ -1640,14 +1645,15 @@ void CodeGenModule::Release() {
 
   if (getCodeGenOpts().CodeModel.size() > 0) {
     unsigned CM = llvm::StringSwitch<unsigned>(getCodeGenOpts().CodeModel)
-                  .Case("tiny", llvm::CodeModel::Tiny)
-                  .Case("small", llvm::CodeModel::Small)
-                  .Case("kernel", llvm::CodeModel::Kernel)
-                  .Case("medium", llvm::CodeModel::Medium)
-                  .Case("large", llvm::CodeModel::Large)
-                  .Default(~0u);
+                      .Case("tiny", llvm::CodeModel::Tiny)
+                      .Case("small", llvm::CodeModel::Small)
+                      .Case("kernel", llvm::CodeModel::Kernel)
+                      .Case("medium", llvm::CodeModel::Medium)
+                      .Case("large", llvm::CodeModel::Large)
+                      .Default(~0u);
     if (CM != ~0u) {
-      llvm::CodeModel::Model codeModel = 
static_cast<llvm::CodeModel::Model>(CM);
+      llvm::CodeModel::Model codeModel =
+          static_cast<llvm::CodeModel::Model>(CM);
       getModule().setCodeModel(codeModel);
 
       if ((CM == llvm::CodeModel::Medium || CM == llvm::CodeModel::Large) &&
@@ -2254,8 +2260,7 @@ static void AppendCPUSpecificCPUDispatchMangling(const 
CodeGenModule &CGM,
 
 // Returns true if GD is a function decl with internal linkage and
 // needs a unique suffix after the mangled name.
-static bool isUniqueInternalLinkageDecl(GlobalDecl GD,
-                                        CodeGenModule &CGM) {
+static bool isUniqueInternalLinkageDecl(GlobalDecl GD, CodeGenModule &CGM) {
   const Decl *D = GD.getDecl();
   return !CGM.getModuleNameHash().empty() && isa<FunctionDecl>(D) &&
          (CGM.getFunctionLinkage(GD) == llvm::GlobalValue::InternalLinkage);
@@ -2394,7 +2399,8 @@ void CodeGenModule::UpdateMultiVersionNames(GlobalDecl GD,
       auto Result = Manglings.insert(std::make_pair(OtherName, OtherGD));
       StringRef OtherNameRef = MangledDeclNames[OtherGD.getCanonicalDecl()] =
           Result.first->first();
-      // If this is the current decl is being created, make sure we update the 
name.
+      // If this is the current decl is being created, make sure we update the
+      // name.
       if (GD.getCanonicalDecl() == OtherGD.getCanonicalDecl())
         CurName = OtherNameRef;
       if (llvm::GlobalValue *Entry = GetGlobalValue(NonTargetName))
@@ -2473,8 +2479,8 @@ StringRef CodeGenModule::getBlockMangledName(GlobalDecl 
GD,
   SmallString<256> Buffer;
   llvm::raw_svector_ostream Out(Buffer);
   if (!D)
-    MangleCtx.mangleGlobalBlock(BD,
-      dyn_cast_or_null<VarDecl>(initializedGlobalDecl.getDecl()), Out);
+    MangleCtx.mangleGlobalBlock(
+        BD, dyn_cast_or_null<VarDecl>(initializedGlobalDecl.getDecl()), Out);
   else if (const auto *CD = dyn_cast<CXXConstructorDecl>(D))
     MangleCtx.mangleCtorBlock(CD, GD.getCtorType(), BD, Out);
   else if (const auto *DD = dyn_cast<CXXDestructorDecl>(D))
@@ -2524,7 +2530,8 @@ void CodeGenModule::AddGlobalDtor(llvm::Function *Dtor, 
int Priority,
 }
 
 void CodeGenModule::EmitCtorList(CtorList &Fns, const char *GlobalName) {
-  if (Fns.empty()) return;
+  if (Fns.empty())
+    return;
 
   const PointerAuthSchema &InitFiniAuthSchema =
       getCodeGenOpts().PointerAuth.InitFiniPointers;
@@ -2591,7 +2598,8 @@ CodeGenModule::getFunctionLinkage(GlobalDecl GD) {
 
 llvm::ConstantInt *CodeGenModule::CreateCrossDsoCfiTypeId(llvm::Metadata *MD) {
   llvm::MDString *MDS = dyn_cast<llvm::MDString>(MD);
-  if (!MDS) return nullptr;
+  if (!MDS)
+    return nullptr;
 
   return llvm::ConstantInt::get(Int64Ty, llvm::MD5Hash(MDS->getString()));
 }
@@ -2689,7 +2697,7 @@ void CodeGenModule::SetLLVMFunctionAttributes(GlobalDecl 
GD,
   F->setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv));
 }
 
-static void removeImageAccessQualifier(std::string& TyName) {
+static void removeImageAccessQualifier(std::string &TyName) {
   std::string ReadOnlyQual("__read_only");
   std::string::size_type ReadOnlyPos = TyName.find(ReadOnlyQual);
   if (ReadOnlyPos != std::string::npos)
@@ -2875,8 +2883,7 @@ void CodeGenModule::GenKernelArgMetadata(llvm::Function 
*Fn,
   }
   if (getCodeGenOpts().EmitOpenCLArgMetadata ||
       getCodeGenOpts().HIPSaveKernelArgName)
-    Fn->setMetadata("kernel_arg_name",
-                    llvm::MDNode::get(VMContext, argNames));
+    Fn->setMetadata("kernel_arg_name", llvm::MDNode::get(VMContext, argNames));
 }
 
 /// Determines whether the language options require us to model
@@ -2886,10 +2893,12 @@ void CodeGenModule::GenKernelArgMetadata(llvm::Function 
*Fn,
 /// enables this.
 static bool hasUnwindExceptions(const LangOptions &LangOpts) {
   // If exceptions are completely disabled, obviously this is false.
-  if (!LangOpts.Exceptions) return false;
+  if (!LangOpts.Exceptions)
+    return false;
 
   // If C++ exceptions are enabled, this is true.
-  if (LangOpts.CXXExceptions) return true;
+  if (LangOpts.CXXExceptions)
+    return true;
 
   // If ObjC exceptions are enabled, this depends on the ABI.
   if (LangOpts.ObjCExceptions) {
@@ -2916,7 +2925,7 @@ SmallVector<const CXXRecordDecl *, 0>
 CodeGenModule::getMostBaseClasses(const CXXRecordDecl *RD) {
   llvm::SetVector<const CXXRecordDecl *> MostBases;
 
-  std::function<void (const CXXRecordDecl *)> CollectMostBases;
+  std::function<void(const CXXRecordDecl *)> CollectMostBases;
   CollectMostBases = [&](const CXXRecordDecl *RD) {
     if (RD->getNumBases() == 0)
       MostBases.insert(RD);
@@ -3259,8 +3268,8 @@ bool 
CodeGenModule::GetCPUAndFeaturesAttributes(GlobalDecl GD,
     AddedAttr = true;
   }
   if (!Features.empty() && SetTargetFeatures) {
-    llvm::erase_if(Features, [&](const std::string& F) {
-       return getTarget().isReadOnlyFeature(F.substr(1));
+    llvm::erase_if(Features, [&](const std::string &F) {
+      return getTarget().isReadOnlyFeature(F.substr(1));
     });
     llvm::sort(Features);
     Attrs.addAttribute("target-features", llvm::join(Features, ","));
@@ -3509,10 +3518,10 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl 
GD, llvm::Function *F,
   // GCC and does not actually return "this".
   if (!IsThunk && getCXXABI().HasThisReturn(GD) &&
       !(getTriple().isiOS() && getTriple().isOSVersionLT(6))) {
-    assert(!F->arg_empty() &&
-           F->arg_begin()->getType()
-             ->canLosslesslyBitCastTo(F->getReturnType()) &&
-           "unexpected this return");
+    assert(
+        !F->arg_empty() &&
+        F->arg_begin()->getType()->canLosslesslyBitCastTo(F->getReturnType()) 
&&
+        "unexpected this return");
     F->addParamAttr(0, llvm::Attribute::Returned);
   }
 
@@ -3529,7 +3538,7 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, 
llvm::Function *F,
   if (const auto *CSA = FD->getAttr<CodeSegAttr>())
     F->setSection(CSA->getName());
   else if (const auto *SA = FD->getAttr<SectionAttr>())
-     F->setSection(SA->getName());
+    F->setSection(SA->getName());
 
   if (const auto *EA = FD->getAttr<ErrorAttr>()) {
     if (EA->isError())
@@ -3579,7 +3588,8 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, 
llvm::Function *F,
     getOpenMPRuntime().emitDeclareSimdFunction(FD, F);
 
   if (CodeGenOpts.InlineMaxStackSize != UINT_MAX)
-    F->addFnAttr("inline-max-stacksize", 
llvm::utostr(CodeGenOpts.InlineMaxStackSize));
+    F->addFnAttr("inline-max-stacksize",
+                 llvm::utostr(CodeGenOpts.InlineMaxStackSize));
 
   if (const auto *CB = FD->getAttr<CallbackAttr>()) {
     // Annotate the callback behavior as metadata:
@@ -3627,12 +3637,11 @@ static void emitUsed(CodeGenModule &CGM, StringRef Name,
     return;
 
   // Convert List to what ConstantArray needs.
-  SmallVector<llvm::Constant*, 8> UsedArray;
+  SmallVector<llvm::Constant *, 8> UsedArray;
   UsedArray.resize(List.size());
   for (unsigned i = 0, e = List.size(); i != e; ++i) {
-    UsedArray[i] =
-        llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(
-            cast<llvm::Constant>(&*List[i]), CGM.Int8PtrTy);
+    UsedArray[i] = llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(
+        cast<llvm::Constant>(&*List[i]), CGM.Int8PtrTy);
   }
 
   if (UsedArray.empty())
@@ -3668,7 +3677,7 @@ void CodeGenModule::AddDetectMismatch(StringRef Name, 
StringRef Value) {
 void CodeGenModule::AddDependentLib(StringRef Lib) {
   auto &C = getLLVMContext();
   if (getTarget().getTriple().isOSBinFormatELF()) {
-      ELFDependentLibraries.push_back(
+    ELFDependentLibraries.push_back(
         llvm::MDNode::get(C, llvm::MDString::get(C, Lib)));
     return;
   }
@@ -3890,8 +3899,8 @@ void CodeGenModule::EmitDeferred() {
     // to get GlobalValue with exactly the type we need, not something that
     // might had been created for another decl with the same mangled name but
     // different type.
-    llvm::GlobalValue *GV = dyn_cast<llvm::GlobalValue>(
-        GetAddrOfGlobal(D, ForDefinition));
+    llvm::GlobalValue *GV =
+        dyn_cast<llvm::GlobalValue>(GetAddrOfGlobal(D, ForDefinition));
 
     // In case of different address spaces, we may still get a cast, even with
     // IsForDefinition equal to true. Query mangled names table to get
@@ -3934,8 +3943,9 @@ void CodeGenModule::EmitVTablesOpportunistically() {
   // is not allowed to create new references to things that need to be emitted
   // lazily. Note that it also uses fact that we eagerly emitting RTTI.
 
-  assert((OpportunisticVTables.empty() || shouldOpportunisticallyEmitVTables())
-         && "Only emit opportunistic vtables with optimizations");
+  assert(
+      (OpportunisticVTables.empty() || shouldOpportunisticallyEmitVTables()) &&
+      "Only emit opportunistic vtables with optimizations");
 
   for (const CXXRecordDecl *RD : OpportunisticVTables) {
     assert(getVTables().isVTableExternal(RD) &&
@@ -3947,7 +3957,7 @@ void CodeGenModule::EmitVTablesOpportunistically() {
 }
 
 void CodeGenModule::EmitGlobalAnnotations() {
-  for (const auto& [MangledName, VD] : DeferredAnnotations) {
+  for (const auto &[MangledName, VD] : DeferredAnnotations) {
     llvm::GlobalValue *GV = GetGlobalValue(MangledName);
     if (GV)
       AddGlobalAnnotations(VD, GV);
@@ -3958,8 +3968,9 @@ void CodeGenModule::EmitGlobalAnnotations() {
     return;
 
   // Create a new global variable for the ConstantStruct in the Module.
-  llvm::Constant *Array = llvm::ConstantArray::get(llvm::ArrayType::get(
-    Annotations[0]->getType(), Annotations.size()), Annotations);
+  llvm::Constant *Array = llvm::ConstantArray::get(
+      llvm::ArrayType::get(Annotations[0]->getType(), Annotations.size()),
+      Annotations);
   auto *gv = new llvm::GlobalVariable(getModule(), Array->getType(), false,
                                       llvm::GlobalValue::AppendingLinkage,
                                       Array, "llvm.global.annotations");
@@ -3994,8 +4005,8 @@ llvm::Constant 
*CodeGenModule::EmitAnnotationUnit(SourceLocation Loc) {
 llvm::Constant *CodeGenModule::EmitAnnotationLineNo(SourceLocation L) {
   SourceManager &SM = getContext().getSourceManager();
   PresumedLoc PLoc = SM.getPresumedLoc(L);
-  unsigned LineNo = PLoc.isValid() ? PLoc.getLine() :
-    SM.getExpansionLineNumber(L);
+  unsigned LineNo =
+      PLoc.isValid() ? PLoc.getLine() : SM.getExpansionLineNumber(L);
   return llvm::ConstantInt::get(Int32Ty, LineNo);
 }
 
@@ -4343,7 +4354,7 @@ ConstantAddress 
CodeGenModule::GetAddrOfTemplateParamObject(
 
   ConstantEmitter Emitter(*this);
   llvm::Constant *Init = Emitter.emitForInitializer(
-        TPO->getValue(), TPO->getType().getAddressSpace(), TPO->getType());
+      TPO->getValue(), TPO->getType().getAddressSpace(), TPO->getType());
 
   if (!Init) {
     ErrorUnsupported(TPO, "template parameter object");
@@ -4361,7 +4372,7 @@ ConstantAddress 
CodeGenModule::GetAddrOfTemplateParamObject(
     GV->setComdat(TheModule.getOrInsertComdat(GV->getName()));
   Emitter.finalize(GV);
 
-    return ConstantAddress(GV, GV->getValueType(), Alignment);
+  return ConstantAddress(GV, GV->getValueType(), Alignment);
 }
 
 ConstantAddress CodeGenModule::GetWeakRefReference(const ValueDecl *VD) {
@@ -4644,105 +4655,104 @@ static bool HasNonDllImportDtor(QualType T) {
 }
 
 namespace {
-  struct FunctionIsDirectlyRecursive
-      : public ConstStmtVisitor<FunctionIsDirectlyRecursive, bool> {
-    const StringRef Name;
-    const Builtin::Context &BI;
-    FunctionIsDirectlyRecursive(StringRef N, const Builtin::Context &C)
-        : Name(N), BI(C) {}
-
-    bool VisitCallExpr(const CallExpr *E) {
-      const FunctionDecl *FD = E->getDirectCallee();
-      if (!FD)
-        return false;
-      AsmLabelAttr *Attr = FD->getAttr<AsmLabelAttr>();
-      if (Attr && Name == Attr->getLabel())
-        return true;
-      unsigned BuiltinID = FD->getBuiltinID();
-      if (!BuiltinID || !BI.isLibFunction(BuiltinID))
-        return false;
-      std::string BuiltinNameStr = BI.getName(BuiltinID);
-      StringRef BuiltinName = BuiltinNameStr;
-      return BuiltinName.consume_front("__builtin_") && Name == BuiltinName;
-    }
-
-    bool VisitStmt(const Stmt *S) {
-      for (const Stmt *Child : S->children())
-        if (Child && this->Visit(Child))
-          return true;
+struct FunctionIsDirectlyRecursive
+    : public ConstStmtVisitor<FunctionIsDirectlyRecursive, bool> {
+  const StringRef Name;
+  const Builtin::Context &BI;
+  FunctionIsDirectlyRecursive(StringRef N, const Builtin::Context &C)
+      : Name(N), BI(C) {}
+
+  bool VisitCallExpr(const CallExpr *E) {
+    const FunctionDecl *FD = E->getDirectCallee();
+    if (!FD)
       return false;
-    }
-  };
+    AsmLabelAttr *Attr = FD->getAttr<AsmLabelAttr>();
+    if (Attr && Name == Attr->getLabel())
+      return true;
+    unsigned BuiltinID = FD->getBuiltinID();
+    if (!BuiltinID || !BI.isLibFunction(BuiltinID))
+      return false;
+    std::string BuiltinNameStr = BI.getName(BuiltinID);
+    StringRef BuiltinName = BuiltinNameStr;
+    return BuiltinName.consume_front("__builtin_") && Name == BuiltinName;
+  }
 
-  // Make sure we're not referencing non-imported vars or functions.
-  struct DLLImportFunctionVisitor
-      : public RecursiveASTVisitor<DLLImportFunctionVisitor> {
-    bool SafeToInline = true;
+  bool VisitStmt(const Stmt *S) {
+    for (const Stmt *Child : S->children())
+      if (Child && this->Visit(Child))
+        return true;
+    return false;
+  }
+};
 
-    bool shouldVisitImplicitCode() const { return true; }
+// Make sure we're not referencing non-imported vars or functions.
+struct DLLImportFunctionVisitor
+    : public RecursiveASTVisitor<DLLImportFunctionVisitor> {
+  bool SafeToInline = true;
 
-    bool VisitVarDecl(VarDecl *VD) {
-      if (VD->getTLSKind()) {
-        // A thread-local variable cannot be imported.
-        SafeToInline = false;
-        return SafeToInline;
-      }
-
-      // A variable definition might imply a destructor call.
-      if (VD->isThisDeclarationADefinition())
-        SafeToInline = !HasNonDllImportDtor(VD->getType());
+  bool shouldVisitImplicitCode() const { return true; }
 
+  bool VisitVarDecl(VarDecl *VD) {
+    if (VD->getTLSKind()) {
+      // A thread-local variable cannot be imported.
+      SafeToInline = false;
       return SafeToInline;
     }
 
-    bool VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
-      if (const auto *D = E->getTemporary()->getDestructor())
-        SafeToInline = D->hasAttr<DLLImportAttr>();
-      return SafeToInline;
-    }
+    // A variable definition might imply a destructor call.
+    if (VD->isThisDeclarationADefinition())
+      SafeToInline = !HasNonDllImportDtor(VD->getType());
 
-    bool VisitDeclRefExpr(DeclRefExpr *E) {
-      ValueDecl *VD = E->getDecl();
-      if (isa<FunctionDecl>(VD))
-        SafeToInline = VD->hasAttr<DLLImportAttr>();
-      else if (VarDecl *V = dyn_cast<VarDecl>(VD))
-        SafeToInline = !V->hasGlobalStorage() || V->hasAttr<DLLImportAttr>();
-      return SafeToInline;
-    }
+    return SafeToInline;
+  }
 
-    bool VisitCXXConstructExpr(CXXConstructExpr *E) {
-      SafeToInline = E->getConstructor()->hasAttr<DLLImportAttr>();
-      return SafeToInline;
-    }
+  bool VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
+    if (const auto *D = E->getTemporary()->getDestructor())
+      SafeToInline = D->hasAttr<DLLImportAttr>();
+    return SafeToInline;
+  }
 
-    bool VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
-      CXXMethodDecl *M = E->getMethodDecl();
-      if (!M) {
-        // Call through a pointer to member function. This is safe to inline.
-        SafeToInline = true;
-      } else {
-        SafeToInline = M->hasAttr<DLLImportAttr>();
-      }
-      return SafeToInline;
-    }
+  bool VisitDeclRefExpr(DeclRefExpr *E) {
+    ValueDecl *VD = E->getDecl();
+    if (isa<FunctionDecl>(VD))
+      SafeToInline = VD->hasAttr<DLLImportAttr>();
+    else if (VarDecl *V = dyn_cast<VarDecl>(VD))
+      SafeToInline = !V->hasGlobalStorage() || V->hasAttr<DLLImportAttr>();
+    return SafeToInline;
+  }
 
-    bool VisitCXXDeleteExpr(CXXDeleteExpr *E) {
-      SafeToInline = E->getOperatorDelete()->hasAttr<DLLImportAttr>();
-      return SafeToInline;
-    }
+  bool VisitCXXConstructExpr(CXXConstructExpr *E) {
+    SafeToInline = E->getConstructor()->hasAttr<DLLImportAttr>();
+    return SafeToInline;
+  }
 
-    bool VisitCXXNewExpr(CXXNewExpr *E) {
-      SafeToInline = E->getOperatorNew()->hasAttr<DLLImportAttr>();
-      return SafeToInline;
+  bool VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
+    CXXMethodDecl *M = E->getMethodDecl();
+    if (!M) {
+      // Call through a pointer to member function. This is safe to inline.
+      SafeToInline = true;
+    } else {
+      SafeToInline = M->hasAttr<DLLImportAttr>();
     }
-  };
-}
+    return SafeToInline;
+  }
+
+  bool VisitCXXDeleteExpr(CXXDeleteExpr *E) {
+    SafeToInline = E->getOperatorDelete()->hasAttr<DLLImportAttr>();
+    return SafeToInline;
+  }
+
+  bool VisitCXXNewExpr(CXXNewExpr *E) {
+    SafeToInline = E->getOperatorNew()->hasAttr<DLLImportAttr>();
+    return SafeToInline;
+  }
+};
+} // namespace
 
 // isTriviallyRecursive - Check if this function calls another
 // decl that, because of the asm attribute or the other decl being a builtin,
 // ends up pointing to itself.
-bool
-CodeGenModule::isTriviallyRecursive(const FunctionDecl *FD) {
+bool CodeGenModule::isTriviallyRecursive(const FunctionDecl *FD) {
   StringRef Name;
   if (getCXXABI().getMangleContext().shouldMangleDeclName(FD)) {
     // asm labels are a special kind of mangling we have to support.
@@ -4797,7 +4807,7 @@ bool CodeGenModule::shouldEmitFunction(GlobalDecl GD) {
   if (F->hasAttr<DLLImportAttr>() && !F->hasAttr<AlwaysInlineAttr>()) {
     // Check whether it would be safe to inline this dllimport function.
     DLLImportFunctionVisitor Visitor;
-    Visitor.TraverseFunctionDecl(const_cast<FunctionDecl*>(F));
+    Visitor.TraverseFunctionDecl(const_cast<FunctionDecl *>(F));
     if (!Visitor.SafeToInline)
       return false;
 
@@ -5131,8 +5141,7 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl 
GD) {
         llvm::PointerType::get(getLLVMContext(),
                                
getTypes().getTargetAddressSpace(FD->getType())),
         false);
-  }
-  else {
+  } else {
     ResolverType = DeclTy;
     ResolverGD = GD;
   }
@@ -5164,10 +5173,10 @@ void 
CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
         if (!ExistingDecl.getDecl())
           ExistingDecl = GD.getWithMultiVersionIndex(Index);
 
-      Func = GetOrCreateLLVMFunction(
-          MangledName, DeclTy, ExistingDecl,
-          /*ForVTable=*/false, /*DontDefer=*/true,
-          /*IsThunk=*/false, llvm::AttributeList(), ForDefinition);
+        Func = GetOrCreateLLVMFunction(MangledName, DeclTy, ExistingDecl,
+                                       /*ForVTable=*/false, /*DontDefer=*/true,
+                                       /*IsThunk=*/false, 
llvm::AttributeList(),
+                                       ForDefinition);
       }
     }
 
@@ -5221,8 +5230,8 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl 
GD) {
       IFunc = GI;
     }
 
-    std::string AliasName = getMangledNameImpl(
-        *this, GD, FD, /*OmitMultiVersionMangling=*/true);
+    std::string AliasName =
+        getMangledNameImpl(*this, GD, FD, /*OmitMultiVersionMangling=*/true);
     llvm::Constant *AliasFunc = GetGlobalValue(AliasName);
     if (!AliasFunc) {
       auto *GA = llvm::GlobalAlias::create(DeclTy, AS, Linkage, AliasName,
@@ -5468,8 +5477,8 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
     }
 
     // Make sure the result is of the correct type.
-    // (If function is requested for a definition, we always need to create a 
new
-    // function, not just return a bitcast.)
+    // (If function is requested for a definition, we always need to create a
+    // new function, not just return a bitcast.)
     if (!IsForDefinition)
       return Entry;
   }
@@ -5632,8 +5641,8 @@ llvm::Constant *CodeGenModule::GetFunctionStart(const 
ValueDecl *Decl) {
   return llvm::NoCFIValue::get(F);
 }
 
-static const FunctionDecl *
-GetRuntimeFunctionDecl(ASTContext &C, StringRef Name) {
+static const FunctionDecl *GetRuntimeFunctionDecl(ASTContext &C,
+                                                  StringRef Name) {
   TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
   DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl);
 
@@ -5727,10 +5736,9 @@ CodeGenModule::CreateRuntimeFunction(llvm::FunctionType 
*FTy, StringRef Name,
         ExtraAttrs.addFnAttribute(VMContext, llvm::Attribute::Convergent);
   }
 
-  llvm::Constant *C =
-      GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(), /*ForVTable=*/false,
-                              /*DontDefer=*/false, /*IsThunk=*/false,
-                              ExtraAttrs);
+  llvm::Constant *C = GetOrCreateLLVMFunction(
+      Name, FTy, GlobalDecl(), /*ForVTable=*/false,
+      /*DontDefer=*/false, /*IsThunk=*/false, ExtraAttrs);
 
   if (auto *F = dyn_cast<llvm::Function>(C)) {
     if (F->empty()) {
@@ -5999,8 +6007,8 @@ llvm::GlobalVariable 
*CodeGenModule::CreateOrReplaceCXXRuntimeVariable(
   }
 
   // Create a new variable.
-  GV = new llvm::GlobalVariable(getModule(), Ty, /*isConstant=*/true,
-                                Linkage, nullptr, Name);
+  GV = new llvm::GlobalVariable(getModule(), Ty, /*isConstant=*/true, Linkage,
+                                nullptr, Name);
 
   if (OldGV) {
     // Replace occurrences of the old variable if needed.
@@ -6028,9 +6036,9 @@ llvm::GlobalVariable 
*CodeGenModule::CreateOrReplaceCXXRuntimeVariable(
 /// normal requested type would be. If IsForDefinition is true, it is 
guaranteed
 /// that an actual global with type Ty will be returned, not conversion of a
 /// variable with the same mangled name but some other type.
-llvm::Constant *CodeGenModule::GetAddrOfGlobalVar(const VarDecl *D,
-                                                  llvm::Type *Ty,
-                                           ForDefinition_t IsForDefinition) {
+llvm::Constant *
+CodeGenModule::GetAddrOfGlobalVar(const VarDecl *D, llvm::Type *Ty,
+                                  ForDefinition_t IsForDefinition) {
   assert(D->hasGlobalStorage() && "Not a global variable");
   QualType ASTTy = D->getType();
   if (!Ty)
@@ -6043,9 +6051,8 @@ llvm::Constant *CodeGenModule::GetAddrOfGlobalVar(const 
VarDecl *D,
 
 /// CreateRuntimeVariable - Create a new runtime global variable with the
 /// specified type and name.
-llvm::Constant *
-CodeGenModule::CreateRuntimeVariable(llvm::Type *Ty,
-                                     StringRef Name) {
+llvm::Constant *CodeGenModule::CreateRuntimeVariable(llvm::Type *Ty,
+                                                     StringRef Name) {
   LangAS AddrSpace = getContext().getLangOpts().OpenCL ? LangAS::opencl_global
                                                        : LangAS::Default;
   auto *Ret = GetOrCreateLLVMGlobal(Name, Ty, AddrSpace, nullptr);
@@ -6068,8 +6075,8 @@ void CodeGenModule::EmitTentativeDefinition(const VarDecl 
*D) {
   // If we have not seen a reference to this variable yet, place it into the
   // deferred declarations table to be emitted if needed later.
   if (!MustBeEmitted(D) && !GV) {
-      DeferredDecls[MangledName] = D;
-      return;
+    DeferredDecls[MangledName] = D;
+    return;
   }
 
   // The tentative definition is the only definition.
@@ -6117,12 +6124,9 @@ CharUnits 
CodeGenModule::GetTargetTypeStoreSize(llvm::Type *Ty) const {
 LangAS CodeGenModule::GetGlobalVarAddressSpace(const VarDecl *D) {
   if (LangOpts.OpenCL) {
     LangAS AS = D ? D->getType().getAddressSpace() : LangAS::opencl_global;
-    assert(AS == LangAS::opencl_global ||
-           AS == LangAS::opencl_global_device ||
-           AS == LangAS::opencl_global_host ||
-           AS == LangAS::opencl_constant ||
-           AS == LangAS::opencl_local ||
-           AS >= LangAS::FirstTargetAddressSpace);
+    assert(AS == LangAS::opencl_global || AS == LangAS::opencl_global_device ||
+           AS == LangAS::opencl_global_host || AS == LangAS::opencl_constant ||
+           AS == LangAS::opencl_local || AS >= 
LangAS::FirstTargetAddressSpace);
     return AS;
   }
 
@@ -6194,7 +6198,7 @@ castStringLiteralToDefaultAddressSpace(CodeGenModule &CGM,
   return Cast;
 }
 
-template<typename SomeDecl>
+template <typename SomeDecl>
 void CodeGenModule::MaybeHandleStaticInExternC(const SomeDecl *D,
                                                llvm::GlobalValue *GV) {
   if (!getLangOpts().CPlusPlus)
@@ -6394,7 +6398,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl 
*D,
     }
   }
 
-  llvm::Type* InitType = Init->getType();
+  llvm::Type *InitType = Init->getType();
   llvm::Constant *Entry =
       GetAddrOfGlobalVar(D, InitType, ForDefinition_t(!IsTentative));
 
@@ -6838,7 +6842,8 @@ static void replaceUsesOfNonProtoConstant(llvm::Constant 
*old,
 static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old,
                                                       llvm::Function *NewFn) {
   // If we're redefining a global as a function, don't transform it.
-  if (!isa<llvm::Function>(Old)) return;
+  if (!isa<llvm::Function>(Old))
+    return;
 
   replaceUsesOfNonProtoConstant(Old, NewFn);
 }
@@ -7014,7 +7019,8 @@ void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) {
   // Emit global alias debug information.
   if (isa<VarDecl>(D))
     if (CGDebugInfo *DI = getModuleDebugInfo())
-      
DI->EmitGlobalAlias(cast<llvm::GlobalValue>(GA->getAliasee()->stripPointerCasts()),
 GD);
+      DI->EmitGlobalAlias(
+          cast<llvm::GlobalValue>(GA->getAliasee()->stripPointerCasts()), GD);
 }
 
 void CodeGenModule::emitIFuncDefinition(GlobalDecl GD) {
@@ -7080,7 +7086,7 @@ void CodeGenModule::emitIFuncDefinition(GlobalDecl GD) {
 }
 
 llvm::Function *CodeGenModule::getIntrinsic(unsigned IID,
-                                            ArrayRef<llvm::Type*> Tys) {
+                                            ArrayRef<llvm::Type *> Tys) {
   return llvm::Intrinsic::getOrInsertDeclaration(&getModule(),
                                                  (llvm::Intrinsic::ID)IID, 
Tys);
 }
@@ -7116,7 +7122,8 @@ 
GetConstantCFStringEntry(llvm::StringMap<llvm::GlobalVariable *> &Map,
   return *Map.insert(std::make_pair(
                          StringRef(reinterpret_cast<const char 
*>(ToBuf.data()),
                                    (StringLength + 1) * 2),
-                         nullptr)).first;
+                         nullptr))
+              .first;
 }
 
 ConstantAddress
@@ -7129,8 +7136,8 @@ CodeGenModule::GetAddrOfConstantCFString(const 
StringLiteral *Literal) {
                                StringLength);
 
   if (auto *C = Entry.second)
-    return ConstantAddress(
-        C, C->getValueType(), CharUnits::fromQuantity(C->getAlignment()));
+    return ConstantAddress(C, C->getValueType(),
+                           CharUnits::fromQuantity(C->getAlignment()));
 
   const ASTContext &Context = getContext();
   const llvm::Triple &Triple = getTriple();
@@ -7148,8 +7155,10 @@ CodeGenModule::GetAddrOfConstantCFString(const 
StringLiteral *Literal) {
     Ty = llvm::ArrayType::get(Ty, 0);
 
     switch (CFRuntime) {
-    default: break;
-    case LangOptions::CoreFoundationABI::Swift: [[fallthrough]];
+    default:
+      break;
+    case LangOptions::CoreFoundationABI::Swift:
+      [[fallthrough]];
     case LangOptions::CoreFoundationABI::Swift5_0:
       CFConstantStringClassName =
           Triple.isOSDarwin() ? "$s15SwiftFoundation19_NSCFConstantStringCN"
@@ -7263,9 +7272,8 @@ CodeGenModule::GetAddrOfConstantCFString(const 
StringLiteral *Literal) {
   Fields.add(GV);
 
   // String length.
-  llvm::IntegerType *LengthTy =
-      llvm::IntegerType::get(getModule().getContext(),
-                             Context.getTargetInfo().getLongWidth());
+  llvm::IntegerType *LengthTy = llvm::IntegerType::get(
+      getModule().getContext(), Context.getTargetInfo().getLongWidth());
   if (IsSwiftABI) {
     if (CFRuntime == LangOptions::CoreFoundationABI::Swift4_1 ||
         CFRuntime == LangOptions::CoreFoundationABI::Swift4_2)
@@ -7323,14 +7331,11 @@ QualType 
CodeGenModule::getObjCFastEnumerationStateType() {
                                      nullptr, ArraySizeModifier::Normal, 0)};
 
     for (size_t i = 0; i < 4; ++i) {
-      FieldDecl *Field = FieldDecl::Create(Context,
-                                           D,
-                                           SourceLocation(),
-                                           SourceLocation(), nullptr,
-                                           FieldTypes[i], /*TInfo=*/nullptr,
-                                           /*BitWidth=*/nullptr,
-                                           /*Mutable=*/false,
-                                           ICIS_NoInit);
+      FieldDecl *Field =
+          FieldDecl::Create(Context, D, SourceLocation(), SourceLocation(),
+                            nullptr, FieldTypes[i], /*TInfo=*/nullptr,
+                            /*BitWidth=*/nullptr,
+                            /*Mutable=*/false, ICIS_NoInit);
       Field->setAccess(AS_public);
       D->addDecl(Field);
     }
@@ -7367,7 +7372,7 @@ CodeGenModule::GetConstantArrayFromStringLiteral(const 
StringLiteral *E) {
     SmallVector<uint16_t, 32> Elements;
     Elements.reserve(NumElements);
 
-    for(unsigned i = 0, e = E->getLength(); i != e; ++i)
+    for (unsigned i = 0, e = E->getLength(); i != e; ++i)
       Elements.push_back(E->getCodeUnit(i));
     Elements.resize(NumElements);
     return llvm::ConstantDataArray::get(VMContext, Elements);
@@ -7377,7 +7382,7 @@ CodeGenModule::GetConstantArrayFromStringLiteral(const 
StringLiteral *E) {
   SmallVector<uint32_t, 32> Elements;
   Elements.reserve(NumElements);
 
-  for(unsigned i = 0, e = E->getLength(); i != e; ++i)
+  for (unsigned i = 0, e = E->getLength(); i != e; ++i)
     Elements.push_back(E->getCodeUnit(i));
   Elements.resize(NumElements);
   return llvm::ConstantDataArray::get(VMContext, Elements);
@@ -7503,10 +7508,12 @@ ConstantAddress 
CodeGenModule::GetAddrOfConstantCString(const std::string &Str,
                          GV->getValueType(), Alignment);
 }
 
-ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary(
-    const MaterializeTemporaryExpr *E, const Expr *Init) {
+ConstantAddress
+CodeGenModule::GetAddrOfGlobalTemporary(const MaterializeTemporaryExpr *E,
+                                        const Expr *Init) {
   assert((E->getStorageDuration() == SD_Static ||
-          E->getStorageDuration() == SD_Thread) && "not a global temporary");
+          E->getStorageDuration() == SD_Thread) &&
+         "not a global temporary");
   const auto *VD = cast<VarDecl>(E->getExtendingDecl());
 
   // Use the MaterializeTemporaryExpr's type if it has the same unqualified
@@ -7575,8 +7582,8 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary(
   if (Value) {
     // The temporary has a constant initializer, use it.
     emitter.emplace(*this);
-    InitialValue = emitter->emitForInitializer(*Value, AddrSpace,
-                                               MaterializedType);
+    InitialValue =
+        emitter->emitForInitializer(*Value, AddrSpace, MaterializedType);
     Constant =
         MaterializedType.isConstantStorage(getContext(), /*ExcludeCtor*/ Value,
                                            /*ExcludeDtor*/ false);
@@ -7606,7 +7613,8 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary(
   auto *GV = new llvm::GlobalVariable(
       getModule(), Type, Constant, Linkage, InitialValue, Name.c_str(),
       /*InsertBefore=*/nullptr, llvm::GlobalVariable::NotThreadLocal, 
TargetAS);
-  if (emitter) emitter->finalize(GV);
+  if (emitter)
+    emitter->finalize(GV);
   // Don't assign dllimport or dllexport to local linkage globals.
   if (!llvm::GlobalValue::isLocalLinkage(Linkage)) {
     setGVProperties(GV, VD);
@@ -7640,8 +7648,8 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary(
 
 /// EmitObjCPropertyImplementations - Emit information for synthesized
 /// properties for an implementation.
-void CodeGenModule::EmitObjCPropertyImplementations(const
-                                                    ObjCImplementationDecl *D) 
{
+void CodeGenModule::EmitObjCPropertyImplementations(
+    const ObjCImplementationDecl *D) {
   for (const auto *PID : D->property_impls()) {
     // Dynamic is just for type-checking.
     if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
@@ -7659,15 +7667,15 @@ void 
CodeGenModule::EmitObjCPropertyImplementations(const
       auto *Setter = PID->getSetterMethodDecl();
       if (!PD->isReadOnly() && (!Setter || 
Setter->isSynthesizedAccessorStub()))
         CodeGenFunction(*this).GenerateObjCSetter(
-                                 const_cast<ObjCImplementationDecl *>(D), PID);
+            const_cast<ObjCImplementationDecl *>(D), PID);
     }
   }
 }
 
 static bool needsDestructMethod(ObjCImplementationDecl *impl) {
   const ObjCInterfaceDecl *iface = impl->getClassInterface();
-  for (const ObjCIvarDecl *ivar = iface->all_declared_ivar_begin();
-       ivar; ivar = ivar->getNextIvar())
+  for (const ObjCIvarDecl *ivar = iface->all_declared_ivar_begin(); ivar;
+       ivar = ivar->getNextIvar())
     if (ivar->getType().isDestructedType())
       return true;
 
@@ -7678,7 +7686,8 @@ static bool AllTrivialInitializers(CodeGenModule &CGM,
                                    ObjCImplementationDecl *D) {
   CodeGenFunction CGF(CGM);
   for (ObjCImplementationDecl::init_iterator B = D->init_begin(),
-       E = D->init_end(); B != E; ++B) {
+                                             E = D->init_end();
+       B != E; ++B) {
     CXXCtorInitializer *CtorInitExp = *B;
     Expr *Init = CtorInitExp->getInit();
     if (!CGF.isTrivialInitializer(Init))
@@ -7708,8 +7717,7 @@ void 
CodeGenModule::EmitObjCIvarInitializations(ObjCImplementationDecl *D) {
 
   // If the implementation doesn't have any ivar initializers, we don't need
   // a .cxx_construct.
-  if (D->getNumIvarInitializers() == 0 ||
-      AllTrivialInitializers(*this, D))
+  if (D->getNumIvarInitializers() == 0 || AllTrivialInitializers(*this, D))
     return;
 
   const IdentifierInfo *II = &getContext().Idents.get(".cxx_construct");
@@ -7842,7 +7850,8 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
               TSK_ExplicitInstantiationDefinition &&
           Spec->hasDefinition())
         DI->completeTemplateDefinition(*Spec);
-  } [[fallthrough]];
+  }
+    [[fallthrough]];
   case Decl::CXXRecord: {
     CXXRecordDecl *CRD = cast<CXXRecordDecl>(D);
     if (CGDebugInfo *DI = getModuleDebugInfo()) {
@@ -7871,9 +7880,9 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
   case Decl::Empty:
   case Decl::Binding:
     break;
-  case Decl::Using:          // using X; [C++]
+  case Decl::Using: // using X; [C++]
     if (CGDebugInfo *DI = getModuleDebugInfo())
-        DI->EmitUsingDecl(cast<UsingDecl>(*D));
+      DI->EmitUsingDecl(cast<UsingDecl>(*D));
     break;
   case Decl::UsingEnum: // using enum X; [C++]
     if (CGDebugInfo *DI = getModuleDebugInfo())
@@ -7881,7 +7890,7 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
     break;
   case Decl::NamespaceAlias:
     if (CGDebugInfo *DI = getModuleDebugInfo())
-        DI->EmitNamespaceAlias(cast<NamespaceAliasDecl>(*D));
+      DI->EmitNamespaceAlias(cast<NamespaceAliasDecl>(*D));
     break;
   case Decl::UsingDirective: // using namespace X; [C++]
     if (CGDebugInfo *DI = getModuleDebugInfo())
@@ -7927,8 +7936,9 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
     // Emit global variable debug information.
     if (CGDebugInfo *DI = getModuleDebugInfo())
       if (getCodeGenOpts().hasReducedDebugInfo())
-        DI->getOrCreateInterfaceType(getContext().getObjCInterfaceType(
-            OMD->getClassInterface()), OMD->getLocation());
+        DI->getOrCreateInterfaceType(
+            getContext().getObjCInterfaceType(OMD->getClassInterface()),
+            OMD->getLocation());
     break;
   }
   case Decl::ObjCMethod: {
@@ -7951,7 +7961,7 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
       AppendLinkerOptions(PCD->getArg());
       break;
     case PCK_Lib:
-        AddDependentLib(PCD->getArg());
+      AddDependentLib(PCD->getArg());
       break;
     case PCK_Compiler:
     case PCK_ExeStr:
@@ -8194,7 +8204,8 @@ void CodeGenModule::EmitMainVoidAlias() {
   // new-style no-argument main is in used.
   if (llvm::Function *F = getModule().getFunction("main")) {
     if (!F->isDeclaration() && F->arg_size() == 0 && !F->isVarArg() &&
-        
F->getReturnType()->isIntegerTy(Context.getTargetInfo().getIntWidth())) {
+        F->getReturnType()->isIntegerTy(
+            Context.getTargetInfo().getIntWidth())) {
       auto *GA = llvm::GlobalAlias::create("__main_void", F);
       GA->setVisibility(llvm::GlobalValue::HiddenVisibility);
     }
@@ -8211,11 +8222,10 @@ static llvm::Constant 
*GetPointerConstant(llvm::LLVMContext &Context,
 
 static void EmitGlobalDeclMetadata(CodeGenModule &CGM,
                                    llvm::NamedMDNode *&GlobalMetadata,
-                                   GlobalDecl D,
-                                   llvm::GlobalValue *Addr) {
+                                   GlobalDecl D, llvm::GlobalValue *Addr) {
   if (!GlobalMetadata)
     GlobalMetadata =
-      CGM.getModule().getOrInsertNamedMetadata("clang.global.decl.ptrs");
+        CGM.getModule().getOrInsertNamedMetadata("clang.global.decl.ptrs");
 
   // TODO: should we report variant information for ctors/dtors?
   llvm::Metadata *Ops[] = {llvm::ConstantAsMetadata::get(Addr),
@@ -8349,7 +8359,8 @@ void CodeGenModule::EmitDeclMetadata() {
 /// Emits metadata nodes for all the local variables in the current
 /// function.
 void CodeGenFunction::EmitDeclMetadata() {
-  if (LocalDeclMap.empty()) return;
+  if (LocalDeclMap.empty())
+    return;
 
   llvm::LLVMContext &Context = getLLVMContext();
 
@@ -8375,7 +8386,7 @@ void CodeGenFunction::EmitDeclMetadata() {
 
 void CodeGenModule::EmitVersionIdentMetadata() {
   llvm::NamedMDNode *IdentMetadata =
-    TheModule.getOrInsertNamedMetadata("llvm.ident");
+      TheModule.getOrInsertNamedMetadata("llvm.ident");
   std::string Version = getClangFullVersion();
   llvm::LLVMContext &Ctx = TheModule.getContext();
 
@@ -8385,7 +8396,7 @@ void CodeGenModule::EmitVersionIdentMetadata() {
 
 void CodeGenModule::EmitCommandLineMetadata() {
   llvm::NamedMDNode *CommandLineMetadata =
-    TheModule.getOrInsertNamedMetadata("llvm.commandline");
+      TheModule.getOrInsertNamedMetadata("llvm.commandline");
   std::string CommandLine = getCodeGenOpts().RecordCommandLine;
   llvm::LLVMContext &Ctx = TheModule.getContext();
 
diff --git a/clang/lib/CodeGen/Targets/WebAssembly.cpp 
b/clang/lib/CodeGen/Targets/WebAssembly.cpp
index ebe996a4edd8d..6ba23eff096c1 100644
--- a/clang/lib/CodeGen/Targets/WebAssembly.cpp
+++ b/clang/lib/CodeGen/Targets/WebAssembly.cpp
@@ -8,10 +8,49 @@
 
 #include "ABIInfoImpl.h"
 #include "TargetInfo.h"
+#include "clang/AST/Expr.h"
+#include "clang/Basic/DiagnosticFrontend.h"
 
 using namespace clang;
 using namespace clang::CodeGen;
 
+namespace {
+
+void warnInvalidWebAssemblyImportModuleAnnotation(const AnnotateAttr *AA,
+                                                  CodeGenModule &CGM) {
+  CGM.getDiags().Report(AA->getLocation(), diag::warn_fe_backend_unsupported)
+      << "ignoring 'annotate(\"wasm-import-module\", ...)' because it "
+         "requires exactly one string literal argument";
+}
+
+void maybeSetWebAssemblyImportModuleMetadata(const VarDecl *VD,
+                                             llvm::GlobalVariable *GV,
+                                             CodeGen::CodeGenModule &CGM) {
+  for (const auto *AA : VD->specific_attrs<AnnotateAttr>()) {
+    if (AA->getAnnotation() != "wasm-import-module")
+      continue;
+
+    if (AA->args_size() != 1) {
+      warnInvalidWebAssemblyImportModuleAnnotation(AA, CGM);
+      continue;
+    }
+
+    const auto *Module = dyn_cast<StringLiteral>(
+        (*AA->args_begin())->IgnoreUnlessSpelledInSource());
+    if (!Module) {
+      warnInvalidWebAssemblyImportModuleAnnotation(AA, CGM);
+      continue;
+    }
+
+    llvm::LLVMContext &Ctx = CGM.getLLVMContext();
+    GV->setMetadata(
+        "wasm.import.module",
+        llvm::MDNode::get(Ctx, llvm::MDString::get(Ctx, Module->getString())));
+  }
+}
+
+} // namespace
+
 
//===----------------------------------------------------------------------===//
 // WebAssembly ABI Implementation
 //
@@ -57,6 +96,12 @@ class WebAssemblyTargetCodeGenInfo final : public 
TargetCodeGenInfo {
   void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
                            CodeGen::CodeGenModule &CGM) const override {
     TargetCodeGenInfo::setTargetAttributes(D, GV, CGM);
+    if (const auto *VD = dyn_cast_or_null<VarDecl>(D)) {
+      if (auto *Global = dyn_cast<llvm::GlobalVariable>(GV))
+        maybeSetWebAssemblyImportModuleMetadata(VD, Global, CGM);
+      return;
+    }
+
     if (const auto *FD = dyn_cast_or_null<FunctionDecl>(D)) {
       if (const auto *Attr = FD->getAttr<WebAssemblyImportModuleAttr>()) {
         llvm::Function *Fn = cast<llvm::Function>(GV);
diff --git a/clang/test/CodeGen/WebAssembly/wasm-global-import-module.cpp 
b/clang/test/CodeGen/WebAssembly/wasm-global-import-module.cpp
new file mode 100644
index 0000000000000..62fe13af9e27a
--- /dev/null
+++ b/clang/test/CodeGen/WebAssembly/wasm-global-import-module.cpp
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -triple wasm32-unknown-unknown-wasm -emit-llvm -verify -o - 
%s | FileCheck %s
+
+extern "C" {
+extern const int [[clang::address_space(1)]] imported_g
+    __attribute__((annotate("wasm-import-module", "js")));
+extern const int [[clang::address_space(1)]] bad_arity
+    __attribute__((annotate("wasm-import-module"))); // expected-warning 
{{ignoring 'annotate("wasm-import-module", ...)' because it requires exactly 
one string literal argument}}
+extern const int [[clang::address_space(1)]] bad_type
+    __attribute__((annotate("wasm-import-module", 42))); // expected-warning 
{{ignoring 'annotate("wasm-import-module", ...)' because it requires exactly 
one string literal argument}}
+extern const int [[clang::address_space(1)]] default_g;
+
+int get() { return imported_g + bad_arity + bad_type + default_g; }
+}
+
+// CHECK: @imported_g = external addrspace(1) constant i32, align 4, 
!wasm.import.module ![[MD:[0-9]+]]
+// CHECK: @bad_arity = external addrspace(1) constant i32, align 4
+// CHECK: @bad_type = external addrspace(1) constant i32, align 4
+// CHECK: @default_g = external addrspace(1) constant i32, align 4
+// CHECK: ![[MD]] = !{!"js"}
\ No newline at end of file
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp 
b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
index edea99e629407..f7942fb15bc19 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
@@ -55,6 +55,18 @@ using namespace llvm;
 
 #define DEBUG_TYPE "asm-printer"
 
+static StringRef getWasmImportModuleMetadata(const GlobalVariable &GV) {
+  MDNode *MD = GV.getMetadata("wasm.import.module");
+  if (!MD || MD->getNumOperands() == 0)
+    return {};
+
+  auto *Name = dyn_cast<MDString>(MD->getOperand(0));
+  if (!Name)
+    return {};
+
+  return Name->getString();
+}
+
 extern cl::opt<bool> WasmKeepRegisters;
 
 
//===----------------------------------------------------------------------===//
@@ -211,6 +223,14 @@ void WebAssemblyAsmPrinter::emitGlobalVariable(const 
GlobalVariable *GV) {
 
   emitVisibility(Sym, GV->getVisibility(), !GV->isDeclaration());
   emitSymbolType(Sym);
+  if (GV->isDeclaration()) {
+    StringRef ImportModule = getWasmImportModuleMetadata(*GV);
+    if (!ImportModule.empty()) {
+      Sym->setImportModule(OutContext.allocateString(ImportModule));
+      getTargetStreamer()->emitImportModule(Sym, ImportModule);
+    }
+  }
+
   if (GV->hasInitializer()) {
     assert(getSymbolPreferLocal(*GV) == Sym);
     emitLinkage(GV, Sym);
@@ -236,8 +256,7 @@ MCSymbol 
*WebAssemblyAsmPrinter::getOrCreateWasmSymbol(StringRef Name) {
   if (Name == "__stack_pointer" || Name == "__tls_base" ||
       Name == "__memory_base" || Name == "__table_base" ||
       Name == "__tls_size" || Name == "__tls_align") {
-    bool Mutable =
-        Name == "__stack_pointer" || Name == "__tls_base";
+    bool Mutable = Name == "__stack_pointer" || Name == "__tls_base";
     WasmSym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL);
     WasmSym->setGlobalType(wasm::WasmGlobalType{
         uint8_t(Subtarget.hasAddr64() ? wasm::WASM_TYPE_I64
@@ -477,7 +496,7 @@ void WebAssemblyAsmPrinter::EmitProducerInfo(Module &M) {
     OutStreamer->switchSection(Producers);
     OutStreamer->emitULEB128IntValue(FieldCount);
     for (auto &Producers : {std::make_pair("language", &Languages),
-            std::make_pair("processed-by", &Tools)}) {
+                            std::make_pair("processed-by", &Tools)}) {
       if (Producers.second->empty())
         continue;
       OutStreamer->emitULEB128IntValue(strlen(Producers.first));
@@ -586,7 +605,8 @@ void WebAssemblyAsmPrinter::EmitFunctionAttributes(Module 
&M) {
   // Emit a custom section for each unique attribute.
   for (const auto &[Name, Symbols] : CustomSections) {
     MCSectionWasm *CustomSection = OutContext.getWasmSection(
-        ".custom_section.llvm.func_attr.annotate." + Name, 
SectionKind::getMetadata());
+        ".custom_section.llvm.func_attr.annotate." + Name,
+        SectionKind::getMetadata());
     OutStreamer->pushSection();
     OutStreamer->switchSection(CustomSection);
 
diff --git a/llvm/test/CodeGen/WebAssembly/import-module-global-metadata.ll 
b/llvm/test/CodeGen/WebAssembly/import-module-global-metadata.ll
new file mode 100644
index 0000000000000..35691585a7960
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/import-module-global-metadata.ll
@@ -0,0 +1,24 @@
+; RUN: llc < %s -asm-verbose=false | FileCheck --check-prefix=ASM %s
+; RUN: llc < %s --filetype=obj | obj2yaml | FileCheck --check-prefix=OBJ %s
+
+target triple = "wasm32-unknown-unknown"
+
+@imported_g = external addrspace(1) global i32, !wasm.import.module !0
+
+define i32 @get() {
+  %v = load i32, ptr addrspace(1) @imported_g
+  ret i32 %v
+}
+
+; ASM: .globaltype imported_g, i32
+; ASM-NEXT: .import_module imported_g, "js"
+
+; OBJ:      - Type:            IMPORT
+; OBJ:        Imports:
+; OBJ:          - Module:          js
+; OBJ-NEXT:       Field:           imported_g
+; OBJ-NEXT:       Kind:            GLOBAL
+; OBJ-NEXT:       GlobalType:      I32
+; OBJ-NEXT:       GlobalMutable:   true
+
+!0 = !{!"js"}
\ No newline at end of file

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to