@@ -79,6 +79,8 @@ def SDT_WebAssemblyWrapperPIC : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>,
79
79
SDTCisPtrTy<0>]>;
80
80
def SDT_WebAssemblyThrow : SDTypeProfile<0, -1, []>;
81
81
def SDT_WebAssemblyCatch : SDTypeProfile<1, 1, [SDTCisPtrTy<0>]>;
82
+ def SDT_WebAssemblyGlobalGet : SDTypeProfile<1, 1, [SDTCisPtrTy<1>]>;
83
+ def SDT_WebAssemblyGlobalSet : SDTypeProfile<0, 2, [SDTCisPtrTy<1>]>;
82
84
83
85
//===----------------------------------------------------------------------===//
84
86
// WebAssembly-specific DAG Nodes.
@@ -106,6 +108,12 @@ def WebAssemblythrow : SDNode<"WebAssemblyISD::THROW", SDT_WebAssemblyThrow,
106
108
[SDNPHasChain, SDNPVariadic]>;
107
109
def WebAssemblycatch : SDNode<"WebAssemblyISD::CATCH", SDT_WebAssemblyCatch,
108
110
[SDNPHasChain, SDNPSideEffect]>;
111
+ def WebAssemblyglobal_get :
112
+ SDNode<"WebAssemblyISD::GLOBAL_GET", SDT_WebAssemblyGlobalGet,
113
+ [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>;
114
+ def WebAssemblyglobal_set :
115
+ SDNode<"WebAssemblyISD::GLOBAL_SET", SDT_WebAssemblyGlobalSet,
116
+ [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>;
109
117
110
118
//===----------------------------------------------------------------------===//
111
119
// WebAssembly-specific Operands.
@@ -241,12 +249,12 @@ include "WebAssemblyInstrFormats.td"
241
249
// Additional instructions.
242
250
//===----------------------------------------------------------------------===//
243
251
244
- multiclass ARGUMENT<WebAssemblyRegClass reg , ValueType vt> {
252
+ multiclass ARGUMENT<WebAssemblyRegClass rc , ValueType vt> {
245
253
let hasSideEffects = 1, isCodeGenOnly = 1, Defs = []<Register>,
246
254
Uses = [ARGUMENTS] in
247
255
defm ARGUMENT_#vt :
248
- I<(outs reg :$res), (ins i32imm:$argno), (outs), (ins i32imm:$argno),
249
- [(set (vt reg :$res), (WebAssemblyargument timm:$argno))]>;
256
+ I<(outs rc :$res), (ins i32imm:$argno), (outs), (ins i32imm:$argno),
257
+ [(set (vt rc :$res), (WebAssemblyargument timm:$argno))]>;
250
258
}
251
259
defm "": ARGUMENT<I32, i32>;
252
260
defm "": ARGUMENT<I64, i64>;
@@ -257,66 +265,74 @@ defm "": ARGUMENT<EXTERNREF, externref>;
257
265
258
266
// local.get and local.set are not generated by instruction selection; they
259
267
// are implied by virtual register uses and defs.
260
- multiclass LOCAL<WebAssemblyRegClass vt , Operand global_op> {
268
+ multiclass LOCAL<WebAssemblyRegClass rc , Operand global_op> {
261
269
let hasSideEffects = 0 in {
262
270
// COPY is not an actual instruction in wasm, but since we allow local.get and
263
271
// local.set to be implicit during most of codegen, we can have a COPY which
264
272
// is actually a no-op because all the work is done in the implied local.get
265
273
// and local.set. COPYs are eliminated (and replaced with
266
274
// local.get/local.set) in the ExplicitLocals pass.
267
275
let isAsCheapAsAMove = 1, isCodeGenOnly = 1 in
268
- defm COPY_#vt : I<(outs vt :$res), (ins vt :$src), (outs), (ins), [],
276
+ defm COPY_#rc : I<(outs rc :$res), (ins rc :$src), (outs), (ins), [],
269
277
"local.copy\t$res, $src", "local.copy">;
270
278
271
279
// TEE is similar to COPY, but writes two copies of its result. Typically
272
280
// this would be used to stackify one result and write the other result to a
273
281
// local.
274
282
let isAsCheapAsAMove = 1, isCodeGenOnly = 1 in
275
- defm TEE_#vt : I<(outs vt :$res, vt :$also), (ins vt :$src), (outs), (ins), [],
283
+ defm TEE_#rc : I<(outs rc :$res, rc :$also), (ins rc :$src), (outs), (ins), [],
276
284
"local.tee\t$res, $also, $src", "local.tee">;
277
285
278
286
// This is the actual local.get instruction in wasm. These are made explicit
279
287
// by the ExplicitLocals pass. It has mayLoad because it reads from a wasm
280
288
// local, which is a side effect not otherwise modeled in LLVM.
281
289
let mayLoad = 1, isAsCheapAsAMove = 1 in
282
- defm LOCAL_GET_#vt : I<(outs vt :$res), (ins local_op:$local),
290
+ defm LOCAL_GET_#rc : I<(outs rc :$res), (ins local_op:$local),
283
291
(outs), (ins local_op:$local), [],
284
292
"local.get\t$res, $local", "local.get\t$local", 0x20>;
285
293
286
294
// This is the actual local.set instruction in wasm. These are made explicit
287
295
// by the ExplicitLocals pass. It has mayStore because it writes to a wasm
288
296
// local, which is a side effect not otherwise modeled in LLVM.
289
297
let mayStore = 1, isAsCheapAsAMove = 1 in
290
- defm LOCAL_SET_#vt : I<(outs), (ins local_op:$local, vt :$src),
298
+ defm LOCAL_SET_#rc : I<(outs), (ins local_op:$local, rc :$src),
291
299
(outs), (ins local_op:$local), [],
292
300
"local.set\t$local, $src", "local.set\t$local", 0x21>;
293
301
294
302
// This is the actual local.tee instruction in wasm. TEEs are turned into
295
303
// LOCAL_TEEs by the ExplicitLocals pass. It has mayStore for the same reason
296
304
// as LOCAL_SET.
297
305
let mayStore = 1, isAsCheapAsAMove = 1 in
298
- defm LOCAL_TEE_#vt : I<(outs vt :$res), (ins local_op:$local, vt :$src),
306
+ defm LOCAL_TEE_#rc : I<(outs rc :$res), (ins local_op:$local, rc :$src),
299
307
(outs), (ins local_op:$local), [],
300
308
"local.tee\t$res, $local, $src", "local.tee\t$local",
301
309
0x22>;
302
310
303
311
// Unused values must be dropped in some contexts.
304
- defm DROP_#vt : I<(outs), (ins vt :$src), (outs), (ins), [],
312
+ defm DROP_#rc : I<(outs), (ins rc :$src), (outs), (ins), [],
305
313
"drop\t$src", "drop", 0x1a>;
306
314
307
315
let mayLoad = 1 in
308
- defm GLOBAL_GET_#vt : I<(outs vt :$res), (ins global_op:$local ),
309
- (outs), (ins global_op:$local ), [],
310
- "global.get\t$res, $local ", "global.get\t$local ",
316
+ defm GLOBAL_GET_#rc : I<(outs rc :$res), (ins global_op:$addr ),
317
+ (outs), (ins global_op:$addr ), [],
318
+ "global.get\t$res, $addr ", "global.get\t$addr ",
311
319
0x23>;
312
320
313
321
let mayStore = 1 in
314
- defm GLOBAL_SET_#vt : I<(outs), (ins global_op:$local, vt :$src),
315
- (outs), (ins global_op:$local ), [],
316
- "global.set\t$local , $src", "global.set\t$local ",
322
+ defm GLOBAL_SET_#rc : I<(outs), (ins global_op:$addr, rc :$src),
323
+ (outs), (ins global_op:$addr ), [],
324
+ "global.set\t$addr , $src", "global.set\t$addr ",
317
325
0x24>;
318
326
319
- } // hasSideEffects = 0
327
+ } // hasSideEffects = 0
328
+ foreach vt = rc.RegTypes in {
329
+ def : Pat<(vt (WebAssemblyglobal_get
330
+ (WebAssemblywrapper tglobaladdr:$addr))),
331
+ (!cast<NI>("GLOBAL_GET_" # rc) tglobaladdr:$addr)>;
332
+ def : Pat<(WebAssemblyglobal_set
333
+ vt:$src, (WebAssemblywrapper tglobaladdr:$addr)),
334
+ (!cast<NI>("GLOBAL_SET_" # rc) tglobaladdr:$addr, vt:$src)>;
335
+ }
320
336
}
321
337
defm "" : LOCAL<I32, global_op32>;
322
338
defm "" : LOCAL<I64, global_op64>; // 64-bit only needed for pointers.
0 commit comments