Index: include/clang/Basic/Attr.td =================================================================== --- include/clang/Basic/Attr.td +++ include/clang/Basic/Attr.td @@ -1519,6 +1519,14 @@ let Subjects = SubjectList<[Function], ErrorDiag>; } +def WebAssemblyImportField : InheritableAttr, + TargetSpecificAttr { + let Spellings = [Clang<"import_field">]; + let Args = [StringArgument<"ImportFieldName">]; + let Documentation = [WebAssemblyImportFieldDocs]; + let Subjects = SubjectList<[Function], ErrorDiag>; +} + def NoSplitStack : InheritableAttr { let Spellings = [GCC<"no_split_stack">]; let Subjects = SubjectList<[Function], ErrorDiag>; Index: include/clang/Basic/AttrDocs.td =================================================================== --- include/clang/Basic/AttrDocs.td +++ include/clang/Basic/AttrDocs.td @@ -3730,6 +3730,23 @@ }]; } +def WebAssemblyImportFieldDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +Clang supports the ``__attribute__((import_field()))`` +attribute for the WebAssembly target. This attribute may be attached to a +function declaration, where it modifies how the symbol is to be imported +within the WebAssembly linking environment. + +WebAssembly imports use a two-level namespace scheme, consisting of a module +name, which typically identifies a module from which to import, and a field +name, which typically identifies a field from that module to import. By +default, field names for C/C++ symbols are the same as their C/C++ symbol +names. This attribute can be used to override the default behavior, and +reuqest a specific field name be used instead. + }]; +} + def ArtificialDocs : Documentation { let Category = DocCatFunction; let Content = [{ Index: lib/CodeGen/TargetInfo.cpp =================================================================== --- lib/CodeGen/TargetInfo.cpp +++ lib/CodeGen/TargetInfo.cpp @@ -768,6 +768,12 @@ B.addAttribute("wasm-import-module", Attr->getImportModuleName()); Fn->addAttributes(llvm::AttributeList::FunctionIndex, B); } + if (const auto *Attr = FD->getAttr()) { + llvm::Function *Fn = cast(GV); + llvm::AttrBuilder B; + B.addAttribute("wasm-import-field", Attr->getImportFieldName()); + Fn->addAttributes(llvm::AttributeList::FunctionIndex, B); + } } if (auto *FD = dyn_cast_or_null(D)) { Index: lib/Sema/SemaDeclAttr.cpp =================================================================== --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -5732,6 +5732,29 @@ AL.getAttributeSpellingListIndex())); } +static void handleWebAssemblyImportFieldAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + if (!isFunctionOrMethod(D)) { + S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type) + << "'import_field'" << ExpectedFunction; + return; + } + + auto *FD = cast(D); + if (FD->isThisDeclarationADefinition()) { + S.Diag(D->getLocation(), diag::err_alias_is_definition) << FD << 0; + return; + } + + StringRef Str; + SourceLocation ArgLoc; + if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc)) + return; + + FD->addAttr(::new (S.Context) WebAssemblyImportFieldAttr( + AL.getRange(), S.Context, Str, + AL.getAttributeSpellingListIndex())); +} + static void handleRISCVInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // Warn about repeated attributes. @@ -6489,6 +6512,9 @@ case ParsedAttr::AT_WebAssemblyImportModule: handleWebAssemblyImportModuleAttr(S, D, AL); break; + case ParsedAttr::AT_WebAssemblyImportField: + handleWebAssemblyImportFieldAttr(S, D, AL); + break; case ParsedAttr::AT_IBAction: handleSimpleAttribute(S, D, AL); break; Index: test/CodeGen/wasm-import-field.c =================================================================== --- test/CodeGen/wasm-import-field.c +++ test/CodeGen/wasm-import-field.c @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -triple wasm32-unknown-unknown-wasm -emit-llvm -o - %s | FileCheck %s -void __attribute__((import_module("bar"))) foo(void); +void __attribute__((import_field("bar"))) foo(void); void call(void) { foo(); @@ -8,4 +8,4 @@ // CHECK: declare void @foo() [[A:#[0-9]+]] -// CHECK: attributes [[A]] = {{{.*}} "wasm-import-module"="bar" {{.*}}} +// CHECK: attributes [[A]] = {{{.*}} "wasm-import-field"="bar" {{.*}}} Index: test/Misc/pragma-attribute-supported-attributes-list.test =================================================================== --- test/Misc/pragma-attribute-supported-attributes-list.test +++ test/Misc/pragma-attribute-supported-attributes-list.test @@ -138,6 +138,7 @@ // CHECK-NEXT: WarnUnusedResult (SubjectMatchRule_objc_method, SubjectMatchRule_enum, SubjectMatchRule_record, SubjectMatchRule_hasType_functionType) // CHECK-NEXT: Weak (SubjectMatchRule_variable, SubjectMatchRule_function, SubjectMatchRule_record) // CHECK-NEXT: WeakRef (SubjectMatchRule_variable, SubjectMatchRule_function) +// CHECK-NEXT: WebAssemblyImportField (SubjectMatchRule_function) // CHECK-NEXT: WebAssemblyImportModule (SubjectMatchRule_function) // CHECK-NEXT: WorkGroupSizeHint (SubjectMatchRule_function) // CHECK-NEXT: XRayInstrument (SubjectMatchRule_function, SubjectMatchRule_objc_method)