From: Dan Gohman Date: Sat, 5 Dec 2015 20:41:36 +0000 (+0000) Subject: [WebAssembly] Implement direct calls to external symbols. X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=76e67ade5a49d8ba1285a249117d8242cf3476e3 [WebAssembly] Implement direct calls to external symbols. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@254863 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/WebAssembly/WebAssemblyInstrCall.td b/lib/Target/WebAssembly/WebAssemblyInstrCall.td index 84f70400f8a..0587c0b6613 100644 --- a/lib/Target/WebAssembly/WebAssemblyInstrCall.td +++ b/lib/Target/WebAssembly/WebAssemblyInstrCall.td @@ -12,20 +12,22 @@ /// //===----------------------------------------------------------------------===// +// TODO: addr64: These currently assume the callee address is 32-bit. + let Defs = [ARGUMENTS] in { // Call sequence markers. These have an immediate which represents the amount of // stack space to allocate or free, which is used for varargs lowering. let isCodeGenOnly = 1 in { -def ADJCALLSTACKDOWN : I<(outs), (ins i64imm:$amt), +def ADJCALLSTACKDOWN : I<(outs), (ins i32imm:$amt), [(WebAssemblycallseq_start timm:$amt)]>; -def ADJCALLSTACKUP : I<(outs), (ins i64imm:$amt), +def ADJCALLSTACKUP : I<(outs), (ins i32imm:$amt), [(WebAssemblycallseq_end timm:$amt, undef)]>; } // isCodeGenOnly = 1 multiclass CALL { - def CALL_#vt : I<(outs vt:$dst), (ins global:$callee, variable_ops), - [(set vt:$dst, (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee)))], + def CALL_#vt : I<(outs vt:$dst), (ins i32imm:$callee, variable_ops), + [(set vt:$dst, (WebAssemblycall1 (i32 imm:$callee)))], "call \t$dst, $callee">; def CALL_INDIRECT_#vt : I<(outs vt:$dst), (ins I32:$callee, variable_ops), [(set vt:$dst, (WebAssemblycall1 I32:$callee))], @@ -37,8 +39,8 @@ let Uses = [SP32, SP64], isCall = 1 in { defm : CALL; defm : CALL; - def CALL_VOID : I<(outs), (ins global:$callee, variable_ops), - [(WebAssemblycall0 (WebAssemblywrapper tglobaladdr:$callee))], + def CALL_VOID : I<(outs), (ins i32imm:$callee, variable_ops), + [(WebAssemblycall0 (i32 imm:$callee))], "call \t$callee">; def CALL_INDIRECT_VOID : I<(outs), (ins I32:$callee, variable_ops), [(WebAssemblycall0 I32:$callee)], @@ -46,3 +48,27 @@ let Uses = [SP32, SP64], isCall = 1 in { } // Uses = [SP32,SP64], isCall = 1 } // Defs = [ARGUMENTS] + +// 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)>; +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)>; +def : Pat<(WebAssemblycall0 (WebAssemblywrapper texternalsym:$callee)), + (CALL_VOID texternalsym:$callee)>; diff --git a/lib/Target/WebAssembly/WebAssemblyInstrInfo.td b/lib/Target/WebAssembly/WebAssemblyInstrInfo.td index caffac1bc52..c36a45fe91d 100644 --- a/lib/Target/WebAssembly/WebAssemblyInstrInfo.td +++ b/lib/Target/WebAssembly/WebAssemblyInstrInfo.td @@ -68,7 +68,6 @@ def WebAssemblywrapper : SDNode<"WebAssemblyISD::Wrapper", def bb_op : Operand; def tjumptable_op : Operand; -def global : Operand; //===----------------------------------------------------------------------===// // WebAssembly Instruction Format Definitions. diff --git a/test/CodeGen/WebAssembly/frem.ll b/test/CodeGen/WebAssembly/frem.ll new file mode 100644 index 00000000000..43552a9bdf3 --- /dev/null +++ b/test/CodeGen/WebAssembly/frem.ll @@ -0,0 +1,26 @@ +; RUN: llc < %s -asm-verbose=false | FileCheck %s + +; Test that the frem instruction works. + +target datalayout = "e-p:32:32-i64:64-n32:64-S128" +target triple = "wasm32-unknown-unknown" + +; CHECK-LABEL: frem32: +; CHECK-NEXT: .param f32, f32{{$}} +; CHECK-NEXT: .result f32{{$}} +; CHECK-NEXT: call $push0=, fmodf, $0, $1{{$}} +; CHECK-NEXT: return $pop0{{$}} +define float @frem32(float %x, float %y) { + %a = frem float %x, %y + ret float %a +} + +; CHECK-LABEL: frem64: +; CHECK-NEXT: .param f64, f64{{$}} +; CHECK-NEXT: .result f64{{$}} +; CHECK-NEXT: call $push0=, fmod, $0, $1{{$}} +; CHECK-NEXT: return $pop0{{$}} +define double @frem64(double %x, double %y) { + %a = frem double %x, %y + ret double %a +} diff --git a/test/CodeGen/WebAssembly/global.ll b/test/CodeGen/WebAssembly/global.ll index ffc73e3c1e3..e00d32b972e 100644 --- a/test/CodeGen/WebAssembly/global.ll +++ b/test/CodeGen/WebAssembly/global.ll @@ -21,8 +21,7 @@ define i32 @foo() { ; CHECK-LABEL: call_memcpy: ; CHECK-NEXT: .param i32, i32, i32{{$}} ; CHECK-NEXT: .result i32{{$}} -; CHECK-NEXT: i32.const $push0=, memcpy{{$}} -; CHECK-NEXT: call_indirect $pop0, $0, $1, $2{{$}} +; CHECK-NEXT: call memcpy, $0, $1, $2{{$}} ; CHECK-NEXT: return $0{{$}} declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i32, i1) define i8* @call_memcpy(i8* %p, i8* nocapture readonly %q, i32 %n) {