Skip to content

Commit

Permalink
WebAssembly: emit (func (param t) (result t)) s-expressions
Browse files Browse the repository at this point in the history
Summary: Match spec format: https://github.com/WebAssembly/spec/blob/master/ml-proto/test/fac.wasm

Reviewers: sunfish

Subscribers: llvm-commits, jfb

Differential Revision: http://reviews.llvm.org/D12307

llvm-svn: 245986
  • Loading branch information
jfbastien committed Aug 25, 2015
1 parent e283c55 commit b6091df
Show file tree
Hide file tree
Showing 18 changed files with 329 additions and 148 deletions.
61 changes: 61 additions & 0 deletions llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
Expand Up @@ -27,6 +27,7 @@
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
Expand Down Expand Up @@ -66,6 +67,10 @@ class WebAssemblyAsmPrinter final : public AsmPrinter {
// AsmPrinter Implementation.
//===------------------------------------------------------------------===//

void EmitFunctionEntryLabel() override;
void EmitFunctionBodyStart() override;
void EmitFunctionBodyEnd() override;

void EmitInstruction(const MachineInstr *MI) override;
};

Expand All @@ -86,6 +91,62 @@ static SmallString<32> Name(const WebAssemblyInstrInfo *TII,

static std::string toSymbol(StringRef S) { return ("$" + S).str(); }

static const char *toType(const Type *Ty) {
switch (Ty->getTypeID()) {
default: break;
case Type::FloatTyID: return "f32";
case Type::DoubleTyID: return "f64";
case Type::IntegerTyID:
switch (Ty->getIntegerBitWidth()) {
case 32: return "i32";
case 64: return "i64";
default: break;
}
}
DEBUG(dbgs() << "Invalid type "; Ty->print(dbgs()); dbgs() << '\n');
llvm_unreachable("invalid type");
return "<invalid>";
}

void WebAssemblyAsmPrinter::EmitFunctionEntryLabel() {
SmallString<128> Str;
raw_svector_ostream OS(Str);

CurrentFnSym->redefineIfPossible();

// The function label could have already been emitted if two symbols end up
// conflicting due to asm renaming. Detect this and emit an error.
if (CurrentFnSym->isVariable())
report_fatal_error("'" + Twine(CurrentFnSym->getName()) +
"' is a protected alias");
if (CurrentFnSym->isDefined())
report_fatal_error("'" + Twine(CurrentFnSym->getName()) +
"' label emitted multiple times to assembly file");

OS << "(func " << toSymbol(CurrentFnSym->getName());
OutStreamer->EmitRawText(OS.str());
}

void WebAssemblyAsmPrinter::EmitFunctionBodyStart() {
SmallString<128> Str;
raw_svector_ostream OS(Str);
const Function *F = MF->getFunction();
for (const Argument &A : F->args())
OS << " (param " << toType(A.getType()) << ')';
const Type *Rt = F->getReturnType();
if (!Rt->isVoidTy())
OS << " (result " << toType(Rt) << ')';
OS << '\n';
OutStreamer->EmitRawText(OS.str());
}

void WebAssemblyAsmPrinter::EmitFunctionBodyEnd() {
SmallString<128> Str;
raw_svector_ostream OS(Str);
OS << ") ;; end func " << toSymbol(CurrentFnSym->getName()) << '\n';
OutStreamer->EmitRawText(OS.str());
}

void WebAssemblyAsmPrinter::EmitInstruction(const MachineInstr *MI) {
DEBUG(dbgs() << "EmitInstruction: " << *MI << '\n');
SmallString<128> Str;
Expand Down
15 changes: 10 additions & 5 deletions llvm/test/CodeGen/WebAssembly/call.ll
Expand Up @@ -11,7 +11,8 @@ declare i64 @i64_nullary()
declare float @float_nullary()
declare double @double_nullary()

; CHECK-LABEL: call_i32_nullary:
; CHECK-LABEL: (func $call_i32_nullary
; CHECK-NEXT: (result i32)
; CHECK-NEXT: (setlocal @0 (global $i32_nullary))
; CHECK-NEXT: (setlocal @1 (call @0))
; CHECK-NEXT: (return @1)
Expand All @@ -20,7 +21,8 @@ define i32 @call_i32_nullary() {
ret i32 %r
}

; CHECK-LABEL: call_i64_nullary:
; CHECK-LABEL: (func $call_i64_nullary
; CHECK-NEXT: (result i64)
; CHECK-NEXT: (setlocal @0 (global $i64_nullary))
; CHECK-NEXT: (setlocal @1 (call @0))
; CHECK-NEXT: (return @1)
Expand All @@ -29,7 +31,8 @@ define i64 @call_i64_nullary() {
ret i64 %r
}

; CHECK-LABEL: call_float_nullary:
; CHECK-LABEL: (func $call_float_nullary
; CHECK-NEXT: (result f32)
; CHECK-NEXT: (setlocal @0 (global $float_nullary))
; CHECK-NEXT: (setlocal @1 (call @0))
; CHECK-NEXT: (return @1)
Expand All @@ -38,7 +41,8 @@ define float @call_float_nullary() {
ret float %r
}

; CHECK-LABEL: call_double_nullary:
; CHECK-LABEL: (func $call_double_nullary
; CHECK-NEXT: (result f64)
; CHECK-NEXT: (setlocal @0 (global $double_nullary))
; CHECK-NEXT: (setlocal @1 (call @0))
; CHECK-NEXT: (return @1)
Expand All @@ -47,7 +51,8 @@ define double @call_double_nullary() {
ret double %r
}

; CHECK-LABEL: call_i32_unary:
; CHECK-LABEL: (func $call_i32_unary
; CHECK-NEXT: (param i32) (result i32)
; CHECK-NEXT: (setlocal @0 (argument 0))
; CHECK-NEXT: (setlocal @1 (global $i32_unary))
; CHECK-NEXT: (setlocal @2 (call @1 @0))
Expand Down
32 changes: 18 additions & 14 deletions llvm/test/CodeGen/WebAssembly/comparisons_f32.ll
Expand Up @@ -6,7 +6,8 @@
target datalayout = "e-p:32:32-i64:64-n32:64-S128"
target triple = "wasm32-unknown-unknown"

; CHECK-LABEL: ord_f32:
; CHECK-LABEL: (func $ord_f32
; CHECK-NEXT: (param f32) (param f32) (result i32)
; CHECK-NEXT: (setlocal @0 (argument 0))
; CHECK-NEXT: (setlocal @1 (argument 1))
; CHECK-NEXT: (setlocal @2 (eq @1 @1))
Expand All @@ -19,7 +20,8 @@ define i32 @ord_f32(float %x, float %y) {
ret i32 %b
}

; CHECK-LABEL: uno_f32:
; CHECK-LABEL: (func $uno_f32
; CHECK-NEXT: (param f32) (param f32) (result i32)
; CHECK-NEXT: (setlocal @0 (argument 0))
; CHECK-NEXT: (setlocal @1 (argument 1))
; CHECK-NEXT: (setlocal @2 (ne @1 @1))
Expand All @@ -32,7 +34,8 @@ define i32 @uno_f32(float %x, float %y) {
ret i32 %b
}

; CHECK-LABEL: oeq_f32:
; CHECK-LABEL: (func $oeq_f32
; CHECK-NEXT: (param f32) (param f32) (result i32)
; CHECK-NEXT: (setlocal @0 (argument 1))
; CHECK-NEXT: (setlocal @1 (argument 0))
; CHECK-NEXT: (setlocal @2 (eq @1 @0))
Expand All @@ -43,39 +46,39 @@ define i32 @oeq_f32(float %x, float %y) {
ret i32 %b
}

; CHECK-LABEL: une_f32:
; CHECK-LABEL: (func $une_f32
; CHECK: (setlocal @2 (ne @1 @0))
define i32 @une_f32(float %x, float %y) {
%a = fcmp une float %x, %y
%b = zext i1 %a to i32
ret i32 %b
}

; CHECK-LABEL: olt_f32:
; CHECK-LABEL: (func $olt_f32
; CHECK: (setlocal @2 (lt @1 @0))
define i32 @olt_f32(float %x, float %y) {
%a = fcmp olt float %x, %y
%b = zext i1 %a to i32
ret i32 %b
}

; CHECK-LABEL: ole_f32:
; CHECK-LABEL: (func $ole_f32
; CHECK: (setlocal @2 (le @1 @0))
define i32 @ole_f32(float %x, float %y) {
%a = fcmp ole float %x, %y
%b = zext i1 %a to i32
ret i32 %b
}

; CHECK-LABEL: ogt_f32:
; CHECK-LABEL: (func $ogt_f32
; CHECK: (setlocal @2 (gt @1 @0))
define i32 @ogt_f32(float %x, float %y) {
%a = fcmp ogt float %x, %y
%b = zext i1 %a to i32
ret i32 %b
}

; CHECK-LABEL: oge_f32:
; CHECK-LABEL: (func $oge_f32
; CHECK: (setlocal @2 (ge @1 @0))
define i32 @oge_f32(float %x, float %y) {
%a = fcmp oge float %x, %y
Expand All @@ -85,7 +88,8 @@ define i32 @oge_f32(float %x, float %y) {

; Expanded comparisons, which also check for NaN.

; CHECK-LABEL: ueq_f32:
; CHECK-LABEL: (func $ueq_f32
; CHECK-NEXT: (param f32) (param f32) (result i32)
; CHECK-NEXT: (setlocal @0 (argument 1))
; CHECK-NEXT: (setlocal @1 (argument 0))
; CHECK-NEXT: (setlocal @2 (eq @1 @0))
Expand All @@ -100,39 +104,39 @@ define i32 @ueq_f32(float %x, float %y) {
ret i32 %b
}

; CHECK-LABEL: one_f32:
; CHECK-LABEL: (func $one_f32
; CHECK: (setlocal @2 (ne @1 @0))
define i32 @one_f32(float %x, float %y) {
%a = fcmp one float %x, %y
%b = zext i1 %a to i32
ret i32 %b
}

; CHECK-LABEL: ult_f32:
; CHECK-LABEL: (func $ult_f32
; CHECK: (setlocal @2 (lt @1 @0))
define i32 @ult_f32(float %x, float %y) {
%a = fcmp ult float %x, %y
%b = zext i1 %a to i32
ret i32 %b
}

; CHECK-LABEL: ule_f32:
; CHECK-LABEL: (func $ule_f32
; CHECK: (setlocal @2 (le @1 @0))
define i32 @ule_f32(float %x, float %y) {
%a = fcmp ule float %x, %y
%b = zext i1 %a to i32
ret i32 %b
}

; CHECK-LABEL: ugt_f32:
; CHECK-LABEL: (func $ugt_f32
; CHECK: (setlocal @2 (gt @1 @0))
define i32 @ugt_f32(float %x, float %y) {
%a = fcmp ugt float %x, %y
%b = zext i1 %a to i32
ret i32 %b
}

; CHECK-LABEL: uge_f32:
; CHECK-LABEL: (func $uge_f32
; CHECK: (setlocal @2 (ge @1 @0))
define i32 @uge_f32(float %x, float %y) {
%a = fcmp uge float %x, %y
Expand Down
32 changes: 18 additions & 14 deletions llvm/test/CodeGen/WebAssembly/comparisons_f64.ll
Expand Up @@ -6,7 +6,8 @@
target datalayout = "e-p:32:32-i64:64-n32:64-S128"
target triple = "wasm32-unknown-unknown"

; CHECK-LABEL: ord_f64:
; CHECK-LABEL: (func $ord_f64
; CHECK-NEXT: (param f64) (param f64) (result i32)
; CHECK-NEXT: (setlocal @0 (argument 0))
; CHECK-NEXT: (setlocal @1 (argument 1))
; CHECK-NEXT: (setlocal @2 (eq @1 @1))
Expand All @@ -19,7 +20,8 @@ define i32 @ord_f64(double %x, double %y) {
ret i32 %b
}

; CHECK-LABEL: uno_f64:
; CHECK-LABEL: (func $uno_f64
; CHECK-NEXT: (param f64) (param f64) (result i32)
; CHECK-NEXT: (setlocal @0 (argument 0))
; CHECK-NEXT: (setlocal @1 (argument 1))
; CHECK-NEXT: (setlocal @2 (ne @1 @1))
Expand All @@ -32,7 +34,8 @@ define i32 @uno_f64(double %x, double %y) {
ret i32 %b
}

; CHECK-LABEL: oeq_f64:
; CHECK-LABEL: (func $oeq_f64
; CHECK-NEXT: (param f64) (param f64) (result i32)
; CHECK-NEXT: (setlocal @0 (argument 1))
; CHECK-NEXT: (setlocal @1 (argument 0))
; CHECK-NEXT: (setlocal @2 (eq @1 @0))
Expand All @@ -43,39 +46,39 @@ define i32 @oeq_f64(double %x, double %y) {
ret i32 %b
}

; CHECK-LABEL: une_f64:
; CHECK-LABEL: (func $une_f64
; CHECK: (setlocal @2 (ne @1 @0))
define i32 @une_f64(double %x, double %y) {
%a = fcmp une double %x, %y
%b = zext i1 %a to i32
ret i32 %b
}

; CHECK-LABEL: olt_f64:
; CHECK-LABEL: (func $olt_f64
; CHECK: (setlocal @2 (lt @1 @0))
define i32 @olt_f64(double %x, double %y) {
%a = fcmp olt double %x, %y
%b = zext i1 %a to i32
ret i32 %b
}

; CHECK-LABEL: ole_f64:
; CHECK-LABEL: (func $ole_f64
; CHECK: (setlocal @2 (le @1 @0))
define i32 @ole_f64(double %x, double %y) {
%a = fcmp ole double %x, %y
%b = zext i1 %a to i32
ret i32 %b
}

; CHECK-LABEL: ogt_f64:
; CHECK-LABEL: (func $ogt_f64
; CHECK: (setlocal @2 (gt @1 @0))
define i32 @ogt_f64(double %x, double %y) {
%a = fcmp ogt double %x, %y
%b = zext i1 %a to i32
ret i32 %b
}

; CHECK-LABEL: oge_f64:
; CHECK-LABEL: (func $oge_f64
; CHECK: (setlocal @2 (ge @1 @0))
define i32 @oge_f64(double %x, double %y) {
%a = fcmp oge double %x, %y
Expand All @@ -85,7 +88,8 @@ define i32 @oge_f64(double %x, double %y) {

; Expanded comparisons, which also check for NaN.

; CHECK-LABEL: ueq_f64:
; CHECK-LABEL: (func $ueq_f64
; CHECK-NEXT: (param f64) (param f64) (result i32)
; CHECK-NEXT: (setlocal @0 (argument 1))
; CHECK-NEXT: (setlocal @1 (argument 0))
; CHECK-NEXT: (setlocal @2 (eq @1 @0))
Expand All @@ -100,39 +104,39 @@ define i32 @ueq_f64(double %x, double %y) {
ret i32 %b
}

; CHECK-LABEL: one_f64:
; CHECK-LABEL: (func $one_f64
; CHECK: (setlocal @2 (ne @1 @0))
define i32 @one_f64(double %x, double %y) {
%a = fcmp one double %x, %y
%b = zext i1 %a to i32
ret i32 %b
}

; CHECK-LABEL: ult_f64:
; CHECK-LABEL: (func $ult_f64
; CHECK: (setlocal @2 (lt @1 @0))
define i32 @ult_f64(double %x, double %y) {
%a = fcmp ult double %x, %y
%b = zext i1 %a to i32
ret i32 %b
}

; CHECK-LABEL: ule_f64:
; CHECK-LABEL: (func $ule_f64
; CHECK: (setlocal @2 (le @1 @0))
define i32 @ule_f64(double %x, double %y) {
%a = fcmp ule double %x, %y
%b = zext i1 %a to i32
ret i32 %b
}

; CHECK-LABEL: ugt_f64:
; CHECK-LABEL: (func $ugt_f64
; CHECK: (setlocal @2 (gt @1 @0))
define i32 @ugt_f64(double %x, double %y) {
%a = fcmp ugt double %x, %y
%b = zext i1 %a to i32
ret i32 %b
}

; CHECK-LABEL: uge_f64:
; CHECK-LABEL: (func $uge_f64
; CHECK: (setlocal @2 (ge @1 @0))
define i32 @uge_f64(double %x, double %y) {
%a = fcmp uge double %x, %y
Expand Down

0 comments on commit b6091df

Please sign in to comment.