blob: ae628149ec1ef560e5def490a40655450a0ba30b [file] [log] [blame]
/*
* Copyright 2017 WebAssembly Community Group participants
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef wasm_literal_h
#define wasm_literal_h
#include <iostream>
#include "support/hash.h"
#include "support/utilities.h"
#include "compiler-support.h"
#include "wasm-type.h"
namespace wasm {
class Literal {
public:
Type type;
private:
// store only integers, whose bits are deterministic. floats
// can have their signalling bit set, for example.
union {
int32_t i32;
int64_t i64;
};
public:
Literal() : type(Type::none), i64(0) {}
explicit Literal(Type type) : type(type), i64(0) {}
explicit Literal(int32_t init) : type(Type::i32), i32(init) {}
explicit Literal(uint32_t init) : type(Type::i32), i32(init) {}
explicit Literal(int64_t init) : type(Type::i64), i64(init) {}
explicit Literal(uint64_t init) : type(Type::i64), i64(init) {}
explicit Literal(float init) : type(Type::f32), i32(bit_cast<int32_t>(init)) {}
explicit Literal(double init) : type(Type::f64), i64(bit_cast<int64_t>(init)) {}
bool isConcrete() { return type != none; }
bool isNull() { return type == none; }
Literal castToF32();
Literal castToF64();
Literal castToI32();
Literal castToI64();
int32_t geti32() const { assert(type == Type::i32); return i32; }
int64_t geti64() const { assert(type == Type::i64); return i64; }
float getf32() const { assert(type == Type::f32); return bit_cast<float>(i32); }
double getf64() const { assert(type == Type::f64); return bit_cast<double>(i64); }
int32_t* geti32Ptr() { assert(type == Type::i32); return &i32; } // careful!
int32_t reinterpreti32() const { assert(type == Type::f32); return i32; }
int64_t reinterpreti64() const { assert(type == Type::f64); return i64; }
float reinterpretf32() const { assert(type == Type::i32); return bit_cast<float>(i32); }
double reinterpretf64() const { assert(type == Type::i64); return bit_cast<double>(i64); }
int64_t getInteger() const;
double getFloat() const;
int64_t getBits() const;
bool operator==(const Literal& other) const;
bool operator!=(const Literal& other) const;
bool bitwiseEqual(const Literal& other) const;
static uint32_t NaNPayload(float f);
static uint64_t NaNPayload(double f);
static float setQuietNaN(float f);
static double setQuietNaN(double f);
static void printFloat(std::ostream &o, float f);
static void printDouble(std::ostream& o, double d);
friend std::ostream& operator<<(std::ostream& o, Literal literal);
Literal countLeadingZeroes() const;
Literal countTrailingZeroes() const;
Literal popCount() const;
Literal extendToSI64() const;
Literal extendToUI64() const;
Literal extendToF64() const;
Literal extendS8() const;
Literal extendS16() const;
Literal extendS32() const;
Literal truncateToI32() const;
Literal truncateToF32() const;
Literal convertSToF32() const;
Literal convertUToF32() const;
Literal convertSToF64() const;
Literal convertUToF64() const;
Literal eqz() const;
Literal neg() const;
Literal abs() const;
Literal ceil() const;
Literal floor() const;
Literal trunc() const;
Literal nearbyint() const;
Literal sqrt() const;
Literal demote() const;
Literal add(const Literal& other) const;
Literal sub(const Literal& other) const;
Literal mul(const Literal& other) const;
Literal div(const Literal& other) const;
Literal divS(const Literal& other) const;
Literal divU(const Literal& other) const;
Literal remS(const Literal& other) const;
Literal remU(const Literal& other) const;
Literal and_(const Literal& other) const;
Literal or_(const Literal& other) const;
Literal xor_(const Literal& other) const;
Literal shl(const Literal& other) const;
Literal shrS(const Literal& other) const;
Literal shrU(const Literal& other) const;
Literal rotL(const Literal& other) const;
Literal rotR(const Literal& other) const;
Literal eq(const Literal& other) const;
Literal ne(const Literal& other) const;
Literal ltS(const Literal& other) const;
Literal ltU(const Literal& other) const;
Literal lt(const Literal& other) const;
Literal leS(const Literal& other) const;
Literal leU(const Literal& other) const;
Literal le(const Literal& other) const;
Literal gtS(const Literal& other) const;
Literal gtU(const Literal& other) const;
Literal gt(const Literal& other) const;
Literal geS(const Literal& other) const;
Literal geU(const Literal& other) const;
Literal ge(const Literal& other) const;
Literal min(const Literal& other) const;
Literal max(const Literal& other) const;
Literal copysign(const Literal& other) const;
};
} // namespace wasm
namespace std {
template<> struct hash<wasm::Literal> {
size_t operator()(const wasm::Literal& a) const {
return wasm::rehash(
uint64_t(hash<size_t>()(size_t(a.type))),
uint64_t(hash<int64_t>()(a.getBits()))
);
}
};
template<> struct less<wasm::Literal> {
bool operator()(const wasm::Literal& a, const wasm::Literal& b) const {
if (a.type < b.type) return true;
if (a.type > b.type) return false;
return a.getBits() < b.getBits();
}
};
}
#endif // wasm_literal_h