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