2015-07-10 20:23:10 +02:00
|
|
|
//===- WebAssemblyInstrCall.td-WebAssembly Call codegen support -*- tablegen -*-
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
///
|
|
|
|
/// \file
|
|
|
|
/// \brief WebAssembly Call operand code-gen constructs.
|
|
|
|
///
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2015-12-05 21:41:36 +01:00
|
|
|
// TODO: addr64: These currently assume the callee address is 32-bit.
|
|
|
|
|
2015-11-25 20:36:19 +01:00
|
|
|
let Defs = [ARGUMENTS] in {
|
|
|
|
|
2015-12-05 20:43:19 +01:00
|
|
|
// Call sequence markers. These have an immediate which represents the amount of
|
|
|
|
// stack space to allocate or free, which is used for varargs lowering.
|
[WebAssembly] Fix ADJCALLSTACKDOWN/UP use/defs
Summary:
ADJCALLSTACK{DOWN,UP} (aka CALLSEQ_{START,END}) MIs are supposed to use
and def the stack pointer. Since they do not, all the nodes are being
eliminated by DeadMachineInstructionElim, so they aren't in the IR when
PrologEpilogInserter/eliminateCallFramePseudo needs them.
This change fixes that, but since RegStackify will not stackify across
them (and it runs early, before PEI), change LowerCall to only emit them
when the call frame size is > 0. That makes the current code work the
same way and makes code handled by D15344 also work the same way. We can
expand the condition beyond NumBytes > 0 in the future if needed.
Reviewers: sunfish, jfb
Subscribers: jfb, dschuff, llvm-commits
Differential Revision: http://reviews.llvm.org/D15459
llvm-svn: 255356
2015-12-11 19:55:34 +01:00
|
|
|
let Uses = [SP32, SP64], Defs = [SP32, SP64], isCodeGenOnly = 1 in {
|
2015-12-05 21:41:36 +01:00
|
|
|
def ADJCALLSTACKDOWN : I<(outs), (ins i32imm:$amt),
|
2015-12-04 18:19:44 +01:00
|
|
|
[(WebAssemblycallseq_start timm:$amt)]>;
|
2015-12-17 00:21:30 +01:00
|
|
|
def ADJCALLSTACKUP : I<(outs), (ins i32imm:$amt, i32imm:$amt2),
|
|
|
|
[(WebAssemblycallseq_end timm:$amt, timm:$amt2)]>;
|
2015-08-25 00:16:48 +02:00
|
|
|
} // isCodeGenOnly = 1
|
|
|
|
|
2015-12-14 23:56:51 +01:00
|
|
|
multiclass CALL<WebAssemblyRegClass vt, string prefix> {
|
2015-12-05 21:41:36 +01:00
|
|
|
def CALL_#vt : I<(outs vt:$dst), (ins i32imm:$callee, variable_ops),
|
|
|
|
[(set vt:$dst, (WebAssemblycall1 (i32 imm:$callee)))],
|
2016-10-25 01:27:49 +02:00
|
|
|
!strconcat(prefix, "call\t$dst, $callee"),
|
|
|
|
0x10>;
|
2016-10-21 18:38:07 +02:00
|
|
|
let isCodeGenOnly = 1 in {
|
|
|
|
def PCALL_INDIRECT_#vt : I<(outs vt:$dst), (ins I32:$callee, variable_ops),
|
|
|
|
[(set vt:$dst, (WebAssemblycall1 I32:$callee))],
|
|
|
|
"PSEUDO CALL INDIRECT\t$callee">;
|
|
|
|
} // isCodeGenOnly = 1
|
2016-10-25 18:55:52 +02:00
|
|
|
|
|
|
|
def CALL_INDIRECT_#vt : I<(outs vt:$dst), (ins i32imm:$flags, variable_ops),
|
2016-10-21 18:38:07 +02:00
|
|
|
[],
|
2016-10-25 01:27:49 +02:00
|
|
|
!strconcat(prefix, "call_indirect\t$dst"),
|
|
|
|
0x11>;
|
2015-08-25 00:16:48 +02:00
|
|
|
}
|
2016-08-03 01:16:09 +02:00
|
|
|
|
|
|
|
multiclass SIMD_CALL<ValueType vt, string prefix> {
|
|
|
|
def CALL_#vt : SIMD_I<(outs V128:$dst), (ins i32imm:$callee, variable_ops),
|
|
|
|
[(set (vt V128:$dst),
|
|
|
|
(WebAssemblycall1 (i32 imm:$callee)))],
|
2016-10-25 01:27:49 +02:00
|
|
|
!strconcat(prefix, "call\t$dst, $callee"),
|
|
|
|
0x10>;
|
2016-10-21 18:38:07 +02:00
|
|
|
let isCodeGenOnly = 1 in {
|
|
|
|
def PCALL_INDIRECT_#vt : SIMD_I<(outs V128:$dst),
|
|
|
|
(ins I32:$callee, variable_ops),
|
|
|
|
[(set (vt V128:$dst),
|
|
|
|
(WebAssemblycall1 I32:$callee))],
|
|
|
|
"PSEUDO CALL INDIRECT\t$callee">;
|
|
|
|
} // isCodeGenOnly = 1
|
2016-10-25 18:55:52 +02:00
|
|
|
|
2016-08-03 01:16:09 +02:00
|
|
|
def CALL_INDIRECT_#vt : SIMD_I<(outs V128:$dst),
|
2016-10-25 18:55:52 +02:00
|
|
|
(ins i32imm:$flags, variable_ops),
|
2016-10-21 18:38:07 +02:00
|
|
|
[],
|
2016-10-25 01:27:49 +02:00
|
|
|
!strconcat(prefix, "call_indirect\t$dst"),
|
|
|
|
0x11>;
|
2016-08-03 01:16:09 +02:00
|
|
|
}
|
|
|
|
|
2015-08-25 00:16:48 +02:00
|
|
|
let Uses = [SP32, SP64], isCall = 1 in {
|
2015-12-14 23:56:51 +01:00
|
|
|
defm : CALL<I32, "i32.">;
|
|
|
|
defm : CALL<I64, "i64.">;
|
|
|
|
defm : CALL<F32, "f32.">;
|
|
|
|
defm : CALL<F64, "f64.">;
|
2016-08-03 01:16:09 +02:00
|
|
|
defm : SIMD_CALL<v16i8, "i8x16.">;
|
|
|
|
defm : SIMD_CALL<v8i16, "i16x8.">;
|
|
|
|
defm : SIMD_CALL<v4i32, "i32x4.">;
|
|
|
|
defm : SIMD_CALL<v4f32, "f32x4.">;
|
2015-09-09 18:13:47 +02:00
|
|
|
|
2015-12-05 21:41:36 +01:00
|
|
|
def CALL_VOID : I<(outs), (ins i32imm:$callee, variable_ops),
|
|
|
|
[(WebAssemblycall0 (i32 imm:$callee))],
|
2016-10-25 01:27:49 +02:00
|
|
|
"call \t$callee", 0x10>;
|
2016-10-21 18:38:07 +02:00
|
|
|
let isCodeGenOnly = 1 in {
|
|
|
|
def PCALL_INDIRECT_VOID : I<(outs), (ins I32:$callee, variable_ops),
|
|
|
|
[(WebAssemblycall0 I32:$callee)],
|
|
|
|
"PSEUDO CALL INDIRECT\t$callee">;
|
|
|
|
} // isCodeGenOnly = 1
|
2016-10-25 18:55:52 +02:00
|
|
|
|
|
|
|
def CALL_INDIRECT_VOID : I<(outs), (ins i32imm:$flags, variable_ops),
|
2016-10-21 18:38:07 +02:00
|
|
|
[],
|
2016-10-25 01:27:49 +02:00
|
|
|
"call_indirect\t", 0x11>;
|
2015-08-25 00:16:48 +02:00
|
|
|
} // Uses = [SP32,SP64], isCall = 1
|
2015-11-25 20:36:19 +01:00
|
|
|
|
|
|
|
} // Defs = [ARGUMENTS]
|
2015-12-05 21:41:36 +01:00
|
|
|
|
|
|
|
// Patterns for matching a direct call to a global address.
|
|
|
|
def : Pat<(i32 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))),
|
|
|
|
(CALL_I32 tglobaladdr:$callee)>;
|
|
|
|
def : Pat<(i64 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))),
|
|
|
|
(CALL_I64 tglobaladdr:$callee)>;
|
|
|
|
def : Pat<(f32 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))),
|
|
|
|
(CALL_F32 tglobaladdr:$callee)>;
|
|
|
|
def : Pat<(f64 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))),
|
|
|
|
(CALL_F64 tglobaladdr:$callee)>;
|
2016-08-03 01:16:09 +02:00
|
|
|
def : Pat<(v16i8 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))),
|
|
|
|
(CALL_v16i8 tglobaladdr:$callee)>, Requires<[HasSIMD128]>;
|
|
|
|
def : Pat<(v8i16 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))),
|
|
|
|
(CALL_v8i16 tglobaladdr:$callee)>, Requires<[HasSIMD128]>;
|
|
|
|
def : Pat<(v4i32 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))),
|
|
|
|
(CALL_v4i32 tglobaladdr:$callee)>, Requires<[HasSIMD128]>;
|
|
|
|
def : Pat<(v4f32 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))),
|
|
|
|
(CALL_v4f32 tglobaladdr:$callee)>, Requires<[HasSIMD128]>;
|
2015-12-05 21:41:36 +01:00
|
|
|
def : Pat<(WebAssemblycall0 (WebAssemblywrapper tglobaladdr:$callee)),
|
|
|
|
(CALL_VOID tglobaladdr:$callee)>;
|
|
|
|
|
|
|
|
// Patterns for matching a direct call to an external symbol.
|
|
|
|
def : Pat<(i32 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))),
|
|
|
|
(CALL_I32 texternalsym:$callee)>;
|
|
|
|
def : Pat<(i64 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))),
|
|
|
|
(CALL_I64 texternalsym:$callee)>;
|
|
|
|
def : Pat<(f32 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))),
|
|
|
|
(CALL_F32 texternalsym:$callee)>;
|
|
|
|
def : Pat<(f64 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))),
|
|
|
|
(CALL_F64 texternalsym:$callee)>;
|
2016-08-03 01:16:09 +02:00
|
|
|
def : Pat<(v16i8 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))),
|
|
|
|
(CALL_v16i8 texternalsym:$callee)>, Requires<[HasSIMD128]>;
|
|
|
|
def : Pat<(v8i16 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))),
|
|
|
|
(CALL_v8i16 texternalsym:$callee)>, Requires<[HasSIMD128]>;
|
|
|
|
def : Pat<(v4i32 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))),
|
|
|
|
(CALL_v4i32 texternalsym:$callee)>, Requires<[HasSIMD128]>;
|
|
|
|
def : Pat<(v4f32 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))),
|
|
|
|
(CALL_v4f32 texternalsym:$callee)>, Requires<[HasSIMD128]>;
|
2015-12-05 21:41:36 +01:00
|
|
|
def : Pat<(WebAssemblycall0 (WebAssemblywrapper texternalsym:$callee)),
|
|
|
|
(CALL_VOID texternalsym:$callee)>;
|