Skip to content

Commit bd898b0

Browse files
[wasm] add @_extern(wasm) attribute support
This attribute instructs the compiler that this function declaration should be "import"ed from host environment. It's equivalent of Clang's `__attribute__((import_module("module"), import_name("field")))`
1 parent 356bfd5 commit bd898b0

21 files changed

+311
-3
lines changed

docs/ReferenceGuides/UnderscoredAttributes.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,18 @@ the export name.
437437

438438
It's the equivalent of clang's `__attribute__((export_name))`.
439439

440+
## `@_extern(<language>)`
441+
442+
Indicates that a particular declaration should be imported
443+
from the external environment.
444+
445+
### `@_extern(wasm, module: <"moduleName">, name: <"fieldName">)`
446+
447+
Indicates that a particular declaration should be imported
448+
through WebAssembly's import interface.
449+
450+
It's the equivalent of clang's `__attribute__((import_module("module"), import_name("field")))`.
451+
440452
## `@_fixed_layout`
441453

442454
Same as `@frozen` but also works for classes.

include/swift/AST/Attr.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,9 @@ DECL_ATTR(_section, Section,
418418
DECL_ATTR(_rawLayout, RawLayout,
419419
OnStruct | UserInaccessible | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove,
420420
146)
421+
DECL_ATTR(_extern, Extern,
422+
OnFunc | ABIStableToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove,
423+
147)
421424
CONTEXTUAL_SIMPLE_DECL_ATTR(final, Final,
422425
OnClass | OnFunc | OnAccessor | OnVar | OnSubscript | DeclModifier | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove,
423426
2)

include/swift/AST/Attr.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2335,6 +2335,28 @@ class ExposeAttr : public DeclAttribute {
23352335
}
23362336
};
23372337

2338+
/// Define the `@_extern` attribute, used to import external declarations in
2339+
/// the specified way to interoperate with Swift.
2340+
class ExternAttr : public DeclAttribute {
2341+
public:
2342+
ExternAttr(StringRef ModuleName, StringRef Name, SourceLoc AtLoc, SourceRange Range, bool Implicit)
2343+
: DeclAttribute(DAK_Extern, AtLoc, Range, Implicit),
2344+
ModuleName(ModuleName), Name(Name) {}
2345+
2346+
ExternAttr(StringRef ModuleName, StringRef Name, bool Implicit)
2347+
: ExternAttr(ModuleName, Name, SourceLoc(), SourceRange(), Implicit) {}
2348+
2349+
/// The module name to import the named declaration in it
2350+
const StringRef ModuleName;
2351+
2352+
/// The declaration name to import
2353+
const StringRef Name;
2354+
2355+
static bool classof(const DeclAttribute *DA) {
2356+
return DA->getKind() == DAK_Extern;
2357+
}
2358+
};
2359+
23382360
/// The `@_documentation(...)` attribute, used to override a symbol's visibility
23392361
/// in symbol graphs, and/or adding arbitrary metadata to it.
23402362
class DocumentationAttr: public DeclAttribute {

include/swift/AST/DiagnosticsCommon.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ ERROR(require_const_initializer_for_const,none,
8484
ERROR(func_decl_without_brace,PointsToFirstBadToken,
8585
"expected '{' in body of function declaration", ())
8686

87+
ERROR(func_decl_no_body_expected,PointsToFirstBadToken,
88+
"unexpected body of function declaration", ())
89+
8790
NOTE(convert_let_to_var,none,
8891
"change 'let' to 'var' to make it mutable", ())
8992

include/swift/AST/DiagnosticsParse.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1867,6 +1867,8 @@ ERROR(attr_rawlayout_expected_integer_count,none,
18671867
ERROR(attr_rawlayout_expected_params,none,
18681868
"expected %1 argument after %0 argument in @_rawLayout attribute", (StringRef, StringRef))
18691869

1870+
ERROR(attr_extern_expected_label,none,
1871+
"expected %0 argument to @_extern attribute", (StringRef))
18701872
//------------------------------------------------------------------------------
18711873
// MARK: Generics parsing diagnostics
18721874
//------------------------------------------------------------------------------

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1866,6 +1866,10 @@ ERROR(section_not_at_top_level,none,
18661866
ERROR(section_empty_name,none,
18671867
"@_section section name cannot be empty", ())
18681868

1869+
// @_extern
1870+
ERROR(extern_not_at_top_level_func,none,
1871+
"@_extern attribute can only be applied to global functions", ())
1872+
18691873
ERROR(expose_wasm_not_at_top_level_func,none,
18701874
"@_expose attribute with 'wasm' can only be applied to global functions", ())
18711875

include/swift/Parse/Parser.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1095,6 +1095,10 @@ class Parser {
10951095
ParserResult<DifferentiableAttr> parseDifferentiableAttribute(SourceLoc AtLoc,
10961096
SourceLoc Loc);
10971097

1098+
/// Parse the @_extern attribute.
1099+
bool parseExternAttribute(DeclAttributes &Attributes, bool &DiscardAttribute,
1100+
StringRef AttrName, SourceLoc AtLoc, SourceLoc Loc);
1101+
10981102
/// Parse the arguments inside the @differentiable attribute.
10991103
bool parseDifferentiableAttributeArguments(
11001104
DifferentiabilityKind &diffKind,

include/swift/SIL/SILFunction.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,9 @@ class SILFunction
303303
/// empty.
304304
StringRef WasmExportName;
305305

306+
/// Name of a Wasm import module and field if @_extern(wasm) attribute
307+
llvm::Optional<std::pair<StringRef, StringRef>> WasmImportModuleAndField;
308+
306309
/// Has value if there's a profile for this function
307310
/// Contains Function Entry Count
308311
ProfileCounter EntryCount;
@@ -1278,6 +1281,24 @@ class SILFunction
12781281
StringRef wasmExportName() const { return WasmExportName; }
12791282
void setWasmExportName(StringRef value) { WasmExportName = value; }
12801283

1284+
/// Return Wasm import module name if @_extern(wasm) was used otherwise empty
1285+
StringRef wasmImportModuleName() const {
1286+
if (WasmImportModuleAndField)
1287+
return WasmImportModuleAndField->first;
1288+
return StringRef();
1289+
}
1290+
1291+
/// Return Wasm import field name if @_extern(wasm) was used otherwise empty
1292+
StringRef wasmImportFieldName() const {
1293+
if (WasmImportModuleAndField)
1294+
return WasmImportModuleAndField->second;
1295+
return StringRef();
1296+
}
1297+
1298+
void setWasmImportModuleAndField(StringRef module, StringRef field) {
1299+
WasmImportModuleAndField = std::make_pair(module, field);
1300+
}
1301+
12811302
/// Returns true if this function belongs to a declaration that returns
12821303
/// an opaque result type with one or more availability conditions that are
12831304
/// allowed to produce a different underlying type at runtime.

lib/AST/Attr.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,6 +1138,15 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
11381138
Printer << ")";
11391139
break;
11401140
}
1141+
1142+
case DAK_Extern: {
1143+
auto *Attr = cast<ExternAttr>(this);
1144+
Printer.printAttrName("@_extern");
1145+
// For now, it accepts only "wasm" as its kind.
1146+
Printer << "(wasm, module: \"" << Attr->ModuleName << "\", name: \"" << Attr->Name << "\")";
1147+
break;
1148+
}
1149+
11411150
case DAK_Section:
11421151
Printer.printAttrName("@_section");
11431152
Printer << "(\"" << cast<SectionAttr>(this)->Name << "\")";
@@ -1708,6 +1717,8 @@ StringRef DeclAttribute::getAttrName() const {
17081717
}
17091718
case DAK_RawLayout:
17101719
return "_rawLayout";
1720+
case DAK_Extern:
1721+
return "_extern";
17111722
}
17121723
llvm_unreachable("bad DeclAttrKind");
17131724
}

lib/IRGen/GenDecl.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3577,11 +3577,18 @@ llvm::Function *IRGenModule::getAddrOfSILFunction(
35773577
addUsedGlobal(fn);
35783578
if (!f->section().empty())
35793579
fn->setSection(f->section());
3580+
3581+
llvm::AttrBuilder attrBuilder(getLLVMContext());
35803582
if (!f->wasmExportName().empty()) {
3581-
llvm::AttrBuilder attrBuilder(getLLVMContext());
35823583
attrBuilder.addAttribute("wasm-export-name", f->wasmExportName());
3583-
fn->addFnAttrs(attrBuilder);
35843584
}
3585+
if (!f->wasmImportFieldName().empty()) {
3586+
attrBuilder.addAttribute("wasm-import-name", f->wasmImportFieldName());
3587+
}
3588+
if (!f->wasmImportModuleName().empty()) {
3589+
attrBuilder.addAttribute("wasm-import-module", f->wasmImportModuleName());
3590+
}
3591+
fn->addFnAttrs(attrBuilder);
35853592

35863593
// If `hasCReferences` is true, then the function is either marked with
35873594
// @_silgen_name OR @_cdecl. If it is the latter, it must have a definition

0 commit comments

Comments
 (0)