1*ed35a92cSVlad Serebrennikov //===------ SemaWasm.cpp ---- WebAssembly target-specific routines --------===//
2*ed35a92cSVlad Serebrennikov //
3*ed35a92cSVlad Serebrennikov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*ed35a92cSVlad Serebrennikov // See https://llvm.org/LICENSE.txt for license information.
5*ed35a92cSVlad Serebrennikov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*ed35a92cSVlad Serebrennikov //
7*ed35a92cSVlad Serebrennikov //===----------------------------------------------------------------------===//
8*ed35a92cSVlad Serebrennikov //
9*ed35a92cSVlad Serebrennikov // This file implements semantic analysis functions specific to WebAssembly.
10*ed35a92cSVlad Serebrennikov //
11*ed35a92cSVlad Serebrennikov //===----------------------------------------------------------------------===//
12*ed35a92cSVlad Serebrennikov
13*ed35a92cSVlad Serebrennikov #include "clang/Sema/SemaWasm.h"
14*ed35a92cSVlad Serebrennikov #include "clang/AST/ASTContext.h"
15*ed35a92cSVlad Serebrennikov #include "clang/AST/Decl.h"
16*ed35a92cSVlad Serebrennikov #include "clang/AST/Type.h"
17*ed35a92cSVlad Serebrennikov #include "clang/Basic/AddressSpaces.h"
18*ed35a92cSVlad Serebrennikov #include "clang/Basic/DiagnosticSema.h"
19*ed35a92cSVlad Serebrennikov #include "clang/Basic/TargetBuiltins.h"
20*ed35a92cSVlad Serebrennikov #include "clang/Sema/Attr.h"
21*ed35a92cSVlad Serebrennikov #include "clang/Sema/Sema.h"
22*ed35a92cSVlad Serebrennikov
23*ed35a92cSVlad Serebrennikov namespace clang {
24*ed35a92cSVlad Serebrennikov
SemaWasm(Sema & S)25*ed35a92cSVlad Serebrennikov SemaWasm::SemaWasm(Sema &S) : SemaBase(S) {}
26*ed35a92cSVlad Serebrennikov
27*ed35a92cSVlad Serebrennikov /// Checks the argument at the given index is a WebAssembly table and if it
28*ed35a92cSVlad Serebrennikov /// is, sets ElTy to the element type.
CheckWasmBuiltinArgIsTable(Sema & S,CallExpr * E,unsigned ArgIndex,QualType & ElTy)29*ed35a92cSVlad Serebrennikov static bool CheckWasmBuiltinArgIsTable(Sema &S, CallExpr *E, unsigned ArgIndex,
30*ed35a92cSVlad Serebrennikov QualType &ElTy) {
31*ed35a92cSVlad Serebrennikov Expr *ArgExpr = E->getArg(ArgIndex);
32*ed35a92cSVlad Serebrennikov const auto *ATy = dyn_cast<ArrayType>(ArgExpr->getType());
33*ed35a92cSVlad Serebrennikov if (!ATy || !ATy->getElementType().isWebAssemblyReferenceType()) {
34*ed35a92cSVlad Serebrennikov return S.Diag(ArgExpr->getBeginLoc(),
35*ed35a92cSVlad Serebrennikov diag::err_wasm_builtin_arg_must_be_table_type)
36*ed35a92cSVlad Serebrennikov << ArgIndex + 1 << ArgExpr->getSourceRange();
37*ed35a92cSVlad Serebrennikov }
38*ed35a92cSVlad Serebrennikov ElTy = ATy->getElementType();
39*ed35a92cSVlad Serebrennikov return false;
40*ed35a92cSVlad Serebrennikov }
41*ed35a92cSVlad Serebrennikov
42*ed35a92cSVlad Serebrennikov /// Checks the argument at the given index is an integer.
CheckWasmBuiltinArgIsInteger(Sema & S,CallExpr * E,unsigned ArgIndex)43*ed35a92cSVlad Serebrennikov static bool CheckWasmBuiltinArgIsInteger(Sema &S, CallExpr *E,
44*ed35a92cSVlad Serebrennikov unsigned ArgIndex) {
45*ed35a92cSVlad Serebrennikov Expr *ArgExpr = E->getArg(ArgIndex);
46*ed35a92cSVlad Serebrennikov if (!ArgExpr->getType()->isIntegerType()) {
47*ed35a92cSVlad Serebrennikov return S.Diag(ArgExpr->getBeginLoc(),
48*ed35a92cSVlad Serebrennikov diag::err_wasm_builtin_arg_must_be_integer_type)
49*ed35a92cSVlad Serebrennikov << ArgIndex + 1 << ArgExpr->getSourceRange();
50*ed35a92cSVlad Serebrennikov }
51*ed35a92cSVlad Serebrennikov return false;
52*ed35a92cSVlad Serebrennikov }
53*ed35a92cSVlad Serebrennikov
BuiltinWasmRefNullExtern(CallExpr * TheCall)54*ed35a92cSVlad Serebrennikov bool SemaWasm::BuiltinWasmRefNullExtern(CallExpr *TheCall) {
55*ed35a92cSVlad Serebrennikov if (TheCall->getNumArgs() != 0)
56*ed35a92cSVlad Serebrennikov return true;
57*ed35a92cSVlad Serebrennikov
58*ed35a92cSVlad Serebrennikov TheCall->setType(getASTContext().getWebAssemblyExternrefType());
59*ed35a92cSVlad Serebrennikov
60*ed35a92cSVlad Serebrennikov return false;
61*ed35a92cSVlad Serebrennikov }
62*ed35a92cSVlad Serebrennikov
BuiltinWasmRefNullFunc(CallExpr * TheCall)63*ed35a92cSVlad Serebrennikov bool SemaWasm::BuiltinWasmRefNullFunc(CallExpr *TheCall) {
64*ed35a92cSVlad Serebrennikov ASTContext &Context = getASTContext();
65*ed35a92cSVlad Serebrennikov if (TheCall->getNumArgs() != 0) {
66*ed35a92cSVlad Serebrennikov Diag(TheCall->getBeginLoc(), diag::err_typecheck_call_too_many_args)
67*ed35a92cSVlad Serebrennikov << 0 /*function call*/ << /*expected*/ 0 << TheCall->getNumArgs()
68*ed35a92cSVlad Serebrennikov << /*is non object*/ 0;
69*ed35a92cSVlad Serebrennikov return true;
70*ed35a92cSVlad Serebrennikov }
71*ed35a92cSVlad Serebrennikov
72*ed35a92cSVlad Serebrennikov // This custom type checking code ensures that the nodes are as expected
73*ed35a92cSVlad Serebrennikov // in order to later on generate the necessary builtin.
74*ed35a92cSVlad Serebrennikov QualType Pointee = Context.getFunctionType(Context.VoidTy, {}, {});
75*ed35a92cSVlad Serebrennikov QualType Type = Context.getPointerType(Pointee);
76*ed35a92cSVlad Serebrennikov Pointee = Context.getAddrSpaceQualType(Pointee, LangAS::wasm_funcref);
77*ed35a92cSVlad Serebrennikov Type = Context.getAttributedType(attr::WebAssemblyFuncref, Type,
78*ed35a92cSVlad Serebrennikov Context.getPointerType(Pointee));
79*ed35a92cSVlad Serebrennikov TheCall->setType(Type);
80*ed35a92cSVlad Serebrennikov
81*ed35a92cSVlad Serebrennikov return false;
82*ed35a92cSVlad Serebrennikov }
83*ed35a92cSVlad Serebrennikov
84*ed35a92cSVlad Serebrennikov /// Check that the first argument is a WebAssembly table, and the second
85*ed35a92cSVlad Serebrennikov /// is an index to use as index into the table.
BuiltinWasmTableGet(CallExpr * TheCall)86*ed35a92cSVlad Serebrennikov bool SemaWasm::BuiltinWasmTableGet(CallExpr *TheCall) {
87*ed35a92cSVlad Serebrennikov if (SemaRef.checkArgCount(TheCall, 2))
88*ed35a92cSVlad Serebrennikov return true;
89*ed35a92cSVlad Serebrennikov
90*ed35a92cSVlad Serebrennikov QualType ElTy;
91*ed35a92cSVlad Serebrennikov if (CheckWasmBuiltinArgIsTable(SemaRef, TheCall, 0, ElTy))
92*ed35a92cSVlad Serebrennikov return true;
93*ed35a92cSVlad Serebrennikov
94*ed35a92cSVlad Serebrennikov if (CheckWasmBuiltinArgIsInteger(SemaRef, TheCall, 1))
95*ed35a92cSVlad Serebrennikov return true;
96*ed35a92cSVlad Serebrennikov
97*ed35a92cSVlad Serebrennikov // If all is well, we set the type of TheCall to be the type of the
98*ed35a92cSVlad Serebrennikov // element of the table.
99*ed35a92cSVlad Serebrennikov // i.e. a table.get on an externref table has type externref,
100*ed35a92cSVlad Serebrennikov // or whatever the type of the table element is.
101*ed35a92cSVlad Serebrennikov TheCall->setType(ElTy);
102*ed35a92cSVlad Serebrennikov
103*ed35a92cSVlad Serebrennikov return false;
104*ed35a92cSVlad Serebrennikov }
105*ed35a92cSVlad Serebrennikov
106*ed35a92cSVlad Serebrennikov /// Check that the first argumnet is a WebAssembly table, the second is
107*ed35a92cSVlad Serebrennikov /// an index to use as index into the table and the third is the reference
108*ed35a92cSVlad Serebrennikov /// type to set into the table.
BuiltinWasmTableSet(CallExpr * TheCall)109*ed35a92cSVlad Serebrennikov bool SemaWasm::BuiltinWasmTableSet(CallExpr *TheCall) {
110*ed35a92cSVlad Serebrennikov if (SemaRef.checkArgCount(TheCall, 3))
111*ed35a92cSVlad Serebrennikov return true;
112*ed35a92cSVlad Serebrennikov
113*ed35a92cSVlad Serebrennikov QualType ElTy;
114*ed35a92cSVlad Serebrennikov if (CheckWasmBuiltinArgIsTable(SemaRef, TheCall, 0, ElTy))
115*ed35a92cSVlad Serebrennikov return true;
116*ed35a92cSVlad Serebrennikov
117*ed35a92cSVlad Serebrennikov if (CheckWasmBuiltinArgIsInteger(SemaRef, TheCall, 1))
118*ed35a92cSVlad Serebrennikov return true;
119*ed35a92cSVlad Serebrennikov
120*ed35a92cSVlad Serebrennikov if (!getASTContext().hasSameType(ElTy, TheCall->getArg(2)->getType()))
121*ed35a92cSVlad Serebrennikov return true;
122*ed35a92cSVlad Serebrennikov
123*ed35a92cSVlad Serebrennikov return false;
124*ed35a92cSVlad Serebrennikov }
125*ed35a92cSVlad Serebrennikov
126*ed35a92cSVlad Serebrennikov /// Check that the argument is a WebAssembly table.
BuiltinWasmTableSize(CallExpr * TheCall)127*ed35a92cSVlad Serebrennikov bool SemaWasm::BuiltinWasmTableSize(CallExpr *TheCall) {
128*ed35a92cSVlad Serebrennikov if (SemaRef.checkArgCount(TheCall, 1))
129*ed35a92cSVlad Serebrennikov return true;
130*ed35a92cSVlad Serebrennikov
131*ed35a92cSVlad Serebrennikov QualType ElTy;
132*ed35a92cSVlad Serebrennikov if (CheckWasmBuiltinArgIsTable(SemaRef, TheCall, 0, ElTy))
133*ed35a92cSVlad Serebrennikov return true;
134*ed35a92cSVlad Serebrennikov
135*ed35a92cSVlad Serebrennikov return false;
136*ed35a92cSVlad Serebrennikov }
137*ed35a92cSVlad Serebrennikov
138*ed35a92cSVlad Serebrennikov /// Check that the first argument is a WebAssembly table, the second is the
139*ed35a92cSVlad Serebrennikov /// value to use for new elements (of a type matching the table type), the
140*ed35a92cSVlad Serebrennikov /// third value is an integer.
BuiltinWasmTableGrow(CallExpr * TheCall)141*ed35a92cSVlad Serebrennikov bool SemaWasm::BuiltinWasmTableGrow(CallExpr *TheCall) {
142*ed35a92cSVlad Serebrennikov if (SemaRef.checkArgCount(TheCall, 3))
143*ed35a92cSVlad Serebrennikov return true;
144*ed35a92cSVlad Serebrennikov
145*ed35a92cSVlad Serebrennikov QualType ElTy;
146*ed35a92cSVlad Serebrennikov if (CheckWasmBuiltinArgIsTable(SemaRef, TheCall, 0, ElTy))
147*ed35a92cSVlad Serebrennikov return true;
148*ed35a92cSVlad Serebrennikov
149*ed35a92cSVlad Serebrennikov Expr *NewElemArg = TheCall->getArg(1);
150*ed35a92cSVlad Serebrennikov if (!getASTContext().hasSameType(ElTy, NewElemArg->getType())) {
151*ed35a92cSVlad Serebrennikov return Diag(NewElemArg->getBeginLoc(),
152*ed35a92cSVlad Serebrennikov diag::err_wasm_builtin_arg_must_match_table_element_type)
153*ed35a92cSVlad Serebrennikov << 2 << 1 << NewElemArg->getSourceRange();
154*ed35a92cSVlad Serebrennikov }
155*ed35a92cSVlad Serebrennikov
156*ed35a92cSVlad Serebrennikov if (CheckWasmBuiltinArgIsInteger(SemaRef, TheCall, 2))
157*ed35a92cSVlad Serebrennikov return true;
158*ed35a92cSVlad Serebrennikov
159*ed35a92cSVlad Serebrennikov return false;
160*ed35a92cSVlad Serebrennikov }
161*ed35a92cSVlad Serebrennikov
162*ed35a92cSVlad Serebrennikov /// Check that the first argument is a WebAssembly table, the second is an
163*ed35a92cSVlad Serebrennikov /// integer, the third is the value to use to fill the table (of a type
164*ed35a92cSVlad Serebrennikov /// matching the table type), and the fourth is an integer.
BuiltinWasmTableFill(CallExpr * TheCall)165*ed35a92cSVlad Serebrennikov bool SemaWasm::BuiltinWasmTableFill(CallExpr *TheCall) {
166*ed35a92cSVlad Serebrennikov if (SemaRef.checkArgCount(TheCall, 4))
167*ed35a92cSVlad Serebrennikov return true;
168*ed35a92cSVlad Serebrennikov
169*ed35a92cSVlad Serebrennikov QualType ElTy;
170*ed35a92cSVlad Serebrennikov if (CheckWasmBuiltinArgIsTable(SemaRef, TheCall, 0, ElTy))
171*ed35a92cSVlad Serebrennikov return true;
172*ed35a92cSVlad Serebrennikov
173*ed35a92cSVlad Serebrennikov if (CheckWasmBuiltinArgIsInteger(SemaRef, TheCall, 1))
174*ed35a92cSVlad Serebrennikov return true;
175*ed35a92cSVlad Serebrennikov
176*ed35a92cSVlad Serebrennikov Expr *NewElemArg = TheCall->getArg(2);
177*ed35a92cSVlad Serebrennikov if (!getASTContext().hasSameType(ElTy, NewElemArg->getType())) {
178*ed35a92cSVlad Serebrennikov return Diag(NewElemArg->getBeginLoc(),
179*ed35a92cSVlad Serebrennikov diag::err_wasm_builtin_arg_must_match_table_element_type)
180*ed35a92cSVlad Serebrennikov << 3 << 1 << NewElemArg->getSourceRange();
181*ed35a92cSVlad Serebrennikov }
182*ed35a92cSVlad Serebrennikov
183*ed35a92cSVlad Serebrennikov if (CheckWasmBuiltinArgIsInteger(SemaRef, TheCall, 3))
184*ed35a92cSVlad Serebrennikov return true;
185*ed35a92cSVlad Serebrennikov
186*ed35a92cSVlad Serebrennikov return false;
187*ed35a92cSVlad Serebrennikov }
188*ed35a92cSVlad Serebrennikov
189*ed35a92cSVlad Serebrennikov /// Check that the first argument is a WebAssembly table, the second is also a
190*ed35a92cSVlad Serebrennikov /// WebAssembly table (of the same element type), and the third to fifth
191*ed35a92cSVlad Serebrennikov /// arguments are integers.
BuiltinWasmTableCopy(CallExpr * TheCall)192*ed35a92cSVlad Serebrennikov bool SemaWasm::BuiltinWasmTableCopy(CallExpr *TheCall) {
193*ed35a92cSVlad Serebrennikov if (SemaRef.checkArgCount(TheCall, 5))
194*ed35a92cSVlad Serebrennikov return true;
195*ed35a92cSVlad Serebrennikov
196*ed35a92cSVlad Serebrennikov QualType XElTy;
197*ed35a92cSVlad Serebrennikov if (CheckWasmBuiltinArgIsTable(SemaRef, TheCall, 0, XElTy))
198*ed35a92cSVlad Serebrennikov return true;
199*ed35a92cSVlad Serebrennikov
200*ed35a92cSVlad Serebrennikov QualType YElTy;
201*ed35a92cSVlad Serebrennikov if (CheckWasmBuiltinArgIsTable(SemaRef, TheCall, 1, YElTy))
202*ed35a92cSVlad Serebrennikov return true;
203*ed35a92cSVlad Serebrennikov
204*ed35a92cSVlad Serebrennikov Expr *TableYArg = TheCall->getArg(1);
205*ed35a92cSVlad Serebrennikov if (!getASTContext().hasSameType(XElTy, YElTy)) {
206*ed35a92cSVlad Serebrennikov return Diag(TableYArg->getBeginLoc(),
207*ed35a92cSVlad Serebrennikov diag::err_wasm_builtin_arg_must_match_table_element_type)
208*ed35a92cSVlad Serebrennikov << 2 << 1 << TableYArg->getSourceRange();
209*ed35a92cSVlad Serebrennikov }
210*ed35a92cSVlad Serebrennikov
211*ed35a92cSVlad Serebrennikov for (int I = 2; I <= 4; I++) {
212*ed35a92cSVlad Serebrennikov if (CheckWasmBuiltinArgIsInteger(SemaRef, TheCall, I))
213*ed35a92cSVlad Serebrennikov return true;
214*ed35a92cSVlad Serebrennikov }
215*ed35a92cSVlad Serebrennikov
216*ed35a92cSVlad Serebrennikov return false;
217*ed35a92cSVlad Serebrennikov }
218*ed35a92cSVlad Serebrennikov
CheckWebAssemblyBuiltinFunctionCall(const TargetInfo & TI,unsigned BuiltinID,CallExpr * TheCall)219*ed35a92cSVlad Serebrennikov bool SemaWasm::CheckWebAssemblyBuiltinFunctionCall(const TargetInfo &TI,
220*ed35a92cSVlad Serebrennikov unsigned BuiltinID,
221*ed35a92cSVlad Serebrennikov CallExpr *TheCall) {
222*ed35a92cSVlad Serebrennikov switch (BuiltinID) {
223*ed35a92cSVlad Serebrennikov case WebAssembly::BI__builtin_wasm_ref_null_extern:
224*ed35a92cSVlad Serebrennikov return BuiltinWasmRefNullExtern(TheCall);
225*ed35a92cSVlad Serebrennikov case WebAssembly::BI__builtin_wasm_ref_null_func:
226*ed35a92cSVlad Serebrennikov return BuiltinWasmRefNullFunc(TheCall);
227*ed35a92cSVlad Serebrennikov case WebAssembly::BI__builtin_wasm_table_get:
228*ed35a92cSVlad Serebrennikov return BuiltinWasmTableGet(TheCall);
229*ed35a92cSVlad Serebrennikov case WebAssembly::BI__builtin_wasm_table_set:
230*ed35a92cSVlad Serebrennikov return BuiltinWasmTableSet(TheCall);
231*ed35a92cSVlad Serebrennikov case WebAssembly::BI__builtin_wasm_table_size:
232*ed35a92cSVlad Serebrennikov return BuiltinWasmTableSize(TheCall);
233*ed35a92cSVlad Serebrennikov case WebAssembly::BI__builtin_wasm_table_grow:
234*ed35a92cSVlad Serebrennikov return BuiltinWasmTableGrow(TheCall);
235*ed35a92cSVlad Serebrennikov case WebAssembly::BI__builtin_wasm_table_fill:
236*ed35a92cSVlad Serebrennikov return BuiltinWasmTableFill(TheCall);
237*ed35a92cSVlad Serebrennikov case WebAssembly::BI__builtin_wasm_table_copy:
238*ed35a92cSVlad Serebrennikov return BuiltinWasmTableCopy(TheCall);
239*ed35a92cSVlad Serebrennikov }
240*ed35a92cSVlad Serebrennikov
241*ed35a92cSVlad Serebrennikov return false;
242*ed35a92cSVlad Serebrennikov }
243*ed35a92cSVlad Serebrennikov
244*ed35a92cSVlad Serebrennikov WebAssemblyImportModuleAttr *
mergeImportModuleAttr(Decl * D,const WebAssemblyImportModuleAttr & AL)245*ed35a92cSVlad Serebrennikov SemaWasm::mergeImportModuleAttr(Decl *D,
246*ed35a92cSVlad Serebrennikov const WebAssemblyImportModuleAttr &AL) {
247*ed35a92cSVlad Serebrennikov auto *FD = cast<FunctionDecl>(D);
248*ed35a92cSVlad Serebrennikov
249*ed35a92cSVlad Serebrennikov if (const auto *ExistingAttr = FD->getAttr<WebAssemblyImportModuleAttr>()) {
250*ed35a92cSVlad Serebrennikov if (ExistingAttr->getImportModule() == AL.getImportModule())
251*ed35a92cSVlad Serebrennikov return nullptr;
252*ed35a92cSVlad Serebrennikov Diag(ExistingAttr->getLocation(), diag::warn_mismatched_import)
253*ed35a92cSVlad Serebrennikov << 0 << ExistingAttr->getImportModule() << AL.getImportModule();
254*ed35a92cSVlad Serebrennikov Diag(AL.getLoc(), diag::note_previous_attribute);
255*ed35a92cSVlad Serebrennikov return nullptr;
256*ed35a92cSVlad Serebrennikov }
257*ed35a92cSVlad Serebrennikov if (FD->hasBody()) {
258*ed35a92cSVlad Serebrennikov Diag(AL.getLoc(), diag::warn_import_on_definition) << 0;
259*ed35a92cSVlad Serebrennikov return nullptr;
260*ed35a92cSVlad Serebrennikov }
261*ed35a92cSVlad Serebrennikov return ::new (getASTContext())
262*ed35a92cSVlad Serebrennikov WebAssemblyImportModuleAttr(getASTContext(), AL, AL.getImportModule());
263*ed35a92cSVlad Serebrennikov }
264*ed35a92cSVlad Serebrennikov
265*ed35a92cSVlad Serebrennikov WebAssemblyImportNameAttr *
mergeImportNameAttr(Decl * D,const WebAssemblyImportNameAttr & AL)266*ed35a92cSVlad Serebrennikov SemaWasm::mergeImportNameAttr(Decl *D, const WebAssemblyImportNameAttr &AL) {
267*ed35a92cSVlad Serebrennikov auto *FD = cast<FunctionDecl>(D);
268*ed35a92cSVlad Serebrennikov
269*ed35a92cSVlad Serebrennikov if (const auto *ExistingAttr = FD->getAttr<WebAssemblyImportNameAttr>()) {
270*ed35a92cSVlad Serebrennikov if (ExistingAttr->getImportName() == AL.getImportName())
271*ed35a92cSVlad Serebrennikov return nullptr;
272*ed35a92cSVlad Serebrennikov Diag(ExistingAttr->getLocation(), diag::warn_mismatched_import)
273*ed35a92cSVlad Serebrennikov << 1 << ExistingAttr->getImportName() << AL.getImportName();
274*ed35a92cSVlad Serebrennikov Diag(AL.getLoc(), diag::note_previous_attribute);
275*ed35a92cSVlad Serebrennikov return nullptr;
276*ed35a92cSVlad Serebrennikov }
277*ed35a92cSVlad Serebrennikov if (FD->hasBody()) {
278*ed35a92cSVlad Serebrennikov Diag(AL.getLoc(), diag::warn_import_on_definition) << 1;
279*ed35a92cSVlad Serebrennikov return nullptr;
280*ed35a92cSVlad Serebrennikov }
281*ed35a92cSVlad Serebrennikov return ::new (getASTContext())
282*ed35a92cSVlad Serebrennikov WebAssemblyImportNameAttr(getASTContext(), AL, AL.getImportName());
283*ed35a92cSVlad Serebrennikov }
284*ed35a92cSVlad Serebrennikov
handleWebAssemblyImportModuleAttr(Decl * D,const ParsedAttr & AL)285*ed35a92cSVlad Serebrennikov void SemaWasm::handleWebAssemblyImportModuleAttr(Decl *D,
286*ed35a92cSVlad Serebrennikov const ParsedAttr &AL) {
287*ed35a92cSVlad Serebrennikov auto *FD = cast<FunctionDecl>(D);
288*ed35a92cSVlad Serebrennikov
289*ed35a92cSVlad Serebrennikov StringRef Str;
290*ed35a92cSVlad Serebrennikov SourceLocation ArgLoc;
291*ed35a92cSVlad Serebrennikov if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
292*ed35a92cSVlad Serebrennikov return;
293*ed35a92cSVlad Serebrennikov if (FD->hasBody()) {
294*ed35a92cSVlad Serebrennikov Diag(AL.getLoc(), diag::warn_import_on_definition) << 0;
295*ed35a92cSVlad Serebrennikov return;
296*ed35a92cSVlad Serebrennikov }
297*ed35a92cSVlad Serebrennikov
298*ed35a92cSVlad Serebrennikov FD->addAttr(::new (getASTContext())
299*ed35a92cSVlad Serebrennikov WebAssemblyImportModuleAttr(getASTContext(), AL, Str));
300*ed35a92cSVlad Serebrennikov }
301*ed35a92cSVlad Serebrennikov
handleWebAssemblyImportNameAttr(Decl * D,const ParsedAttr & AL)302*ed35a92cSVlad Serebrennikov void SemaWasm::handleWebAssemblyImportNameAttr(Decl *D, const ParsedAttr &AL) {
303*ed35a92cSVlad Serebrennikov auto *FD = cast<FunctionDecl>(D);
304*ed35a92cSVlad Serebrennikov
305*ed35a92cSVlad Serebrennikov StringRef Str;
306*ed35a92cSVlad Serebrennikov SourceLocation ArgLoc;
307*ed35a92cSVlad Serebrennikov if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
308*ed35a92cSVlad Serebrennikov return;
309*ed35a92cSVlad Serebrennikov if (FD->hasBody()) {
310*ed35a92cSVlad Serebrennikov Diag(AL.getLoc(), diag::warn_import_on_definition) << 1;
311*ed35a92cSVlad Serebrennikov return;
312*ed35a92cSVlad Serebrennikov }
313*ed35a92cSVlad Serebrennikov
314*ed35a92cSVlad Serebrennikov FD->addAttr(::new (getASTContext())
315*ed35a92cSVlad Serebrennikov WebAssemblyImportNameAttr(getASTContext(), AL, Str));
316*ed35a92cSVlad Serebrennikov }
317*ed35a92cSVlad Serebrennikov
handleWebAssemblyExportNameAttr(Decl * D,const ParsedAttr & AL)318*ed35a92cSVlad Serebrennikov void SemaWasm::handleWebAssemblyExportNameAttr(Decl *D, const ParsedAttr &AL) {
319*ed35a92cSVlad Serebrennikov ASTContext &Context = getASTContext();
320*ed35a92cSVlad Serebrennikov if (!isFuncOrMethodForAttrSubject(D)) {
321*ed35a92cSVlad Serebrennikov Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
322*ed35a92cSVlad Serebrennikov << AL << AL.isRegularKeywordAttribute() << ExpectedFunction;
323*ed35a92cSVlad Serebrennikov return;
324*ed35a92cSVlad Serebrennikov }
325*ed35a92cSVlad Serebrennikov
326*ed35a92cSVlad Serebrennikov auto *FD = cast<FunctionDecl>(D);
327*ed35a92cSVlad Serebrennikov if (FD->isThisDeclarationADefinition()) {
328*ed35a92cSVlad Serebrennikov Diag(D->getLocation(), diag::err_alias_is_definition) << FD << 0;
329*ed35a92cSVlad Serebrennikov return;
330*ed35a92cSVlad Serebrennikov }
331*ed35a92cSVlad Serebrennikov
332*ed35a92cSVlad Serebrennikov StringRef Str;
333*ed35a92cSVlad Serebrennikov SourceLocation ArgLoc;
334*ed35a92cSVlad Serebrennikov if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
335*ed35a92cSVlad Serebrennikov return;
336*ed35a92cSVlad Serebrennikov
337*ed35a92cSVlad Serebrennikov D->addAttr(::new (Context) WebAssemblyExportNameAttr(Context, AL, Str));
338*ed35a92cSVlad Serebrennikov D->addAttr(UsedAttr::CreateImplicit(Context));
339*ed35a92cSVlad Serebrennikov }
340*ed35a92cSVlad Serebrennikov
341*ed35a92cSVlad Serebrennikov } // namespace clang
342