From 48cbe695f01df6801ba5bbf0bd591f3c3c9f9f5f Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Mon, 27 Aug 2018 00:29:40 -0300 Subject: [PATCH] Add OpConstant --- include/sirit/sirit.h | 14 +++++++- src/CMakeLists.txt | 1 + src/literal.cpp | 37 +++++++++++++++++++ src/op.cpp | 4 +-- src/opcodes/constant.cpp | 6 ++++ src/operand.cpp | 77 ++++++++++++++++++++++++++++++++++------ src/operand.h | 36 +++++++++++++++---- tests/main.cpp | 7 ++++ 8 files changed, 162 insertions(+), 20 deletions(-) create mode 100644 src/literal.cpp diff --git a/include/sirit/sirit.h b/include/sirit/sirit.h index aee03b6..b704cd6 100644 --- a/include/sirit/sirit.h +++ b/include/sirit/sirit.h @@ -19,6 +19,7 @@ static const std::uint32_t GeneratorMagicNumber = 0; static const std::uint32_t Undefined = UINT32_MAX; class Op; +class Operand; class Module { public: @@ -55,7 +56,7 @@ public: * @return Returns op. */ const Op* Emit(const Op* op); - + // Types /// Returns type void. @@ -128,6 +129,9 @@ public: /// Returns a false scalar constant. const Op* ConstantFalse(const Op* result_type); + /// Returns a numeric scalar constant. + const Op* Constant(const Op* result_type, Operand* literal); + // Function /// Emits a function. @@ -145,6 +149,14 @@ public: /// Emits a return. It ends a block. const Op* Return(); + // Literals + static Operand* Literal(std::uint32_t value); + static Operand* Literal(std::uint64_t value); + static Operand* Literal(std::int32_t value); + static Operand* Literal(std::int64_t value); + static Operand* Literal(float value); + static Operand* Literal(double value); + private: const Op* AddCode(Op* op); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e5c53ab..5610414 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -7,6 +7,7 @@ add_library(sirit stream.h operand.cpp operand.h + literal.cpp common_types.h opcodes.h opcodes/type.cpp diff --git a/src/literal.cpp b/src/literal.cpp new file mode 100644 index 0000000..79da059 --- /dev/null +++ b/src/literal.cpp @@ -0,0 +1,37 @@ +/* This file is part of the sirit project. + * Copyright (c) 2018 ReinUsesLisp + * This software may be used and distributed according to the terms of the GNU + * Lesser General Public License version 2.1 or any later version. + */ + +#include "sirit/sirit.h" +#include "common_types.h" +#include "operand.h" + +namespace Sirit { + +Operand* Module::Literal(u32 value) { + return new LiteralNumber(value); +} + +Operand* Module::Literal(u64 value) { + return new LiteralNumber(value); +} + +Operand* Module::Literal(s32 value) { + return new LiteralNumber(value); +} + +Operand* Module::Literal(s64 value) { + return new LiteralNumber(value); +} + +Operand* Module::Literal(f32 value) { + return new LiteralNumber(value); +} + +Operand* Module::Literal(f64 value) { + return new LiteralNumber(value); +} + +} // namespace Sirit diff --git a/src/op.cpp b/src/op.cpp index a197126..52f0cc4 100644 --- a/src/op.cpp +++ b/src/op.cpp @@ -13,7 +13,7 @@ namespace Sirit { Op::Op(spv::Op opcode_, u32 id_, const Op* result_type_) : opcode(opcode_), id(id_), result_type(result_type_) { - operand_type = OperandType::Ref; + operand_type = OperandType::Op; } Op::~Op() = default; @@ -69,7 +69,7 @@ void Op::Add(const Operand* operand) { } void Op::Add(u32 integer) { - Add(new LiteralInteger(integer)); + Add(new LiteralNumber(integer)); } void Op::Add(const std::string& string) { diff --git a/src/opcodes/constant.cpp b/src/opcodes/constant.cpp index 15a59d9..6df4e4b 100644 --- a/src/opcodes/constant.cpp +++ b/src/opcodes/constant.cpp @@ -18,4 +18,10 @@ const Op* Module::ConstantFalse(const Op* result_type) { return AddDeclaration(new Op(spv::Op::OpConstantFalse, bound, result_type)); } +const Op* Module::Constant(const Op* result_type, Operand* literal) { + Op* op{new Op(spv::Op::OpConstant, bound, result_type)}; + op->Add(literal); + return AddDeclaration(op); +} + } // namespace Sirit diff --git a/src/operand.cpp b/src/operand.cpp index 8c4329e..6123e9d 100644 --- a/src/operand.cpp +++ b/src/operand.cpp @@ -34,24 +34,79 @@ OperandType Operand::GetType() const { return operand_type; } -LiteralInteger::LiteralInteger(u32 integer_) - : integer(integer_) { - operand_type = OperandType::Integer; +LiteralNumber::LiteralNumber() { + operand_type = OperandType::Number; } -LiteralInteger::~LiteralInteger() = default; - -void LiteralInteger::Fetch(Stream& stream) const { - stream.Write(integer); +LiteralNumber::LiteralNumber(u32 number) + : uint32(number), type(NumberType::U32) { + LiteralNumber(); } -u16 LiteralInteger::GetWordCount() const { - return 1; +LiteralNumber::LiteralNumber(s32 number) + : int32(number), type(NumberType::S32) { + LiteralNumber(); } -bool LiteralInteger::operator==(const Operand& other) const { +LiteralNumber::LiteralNumber(f32 number) + : float32(number), type(NumberType::F32) { + LiteralNumber(); +} + +LiteralNumber::LiteralNumber(u64 number) + : uint64(number), type(NumberType::U64) { + LiteralNumber(); +} + +LiteralNumber::LiteralNumber(s64 number) + : int64(number), type(NumberType::S64) { + LiteralNumber(); +} + +LiteralNumber::LiteralNumber(f64 number) + : float64(number), type(NumberType::F64) { + LiteralNumber(); +} + +LiteralNumber::~LiteralNumber() = default; + +void LiteralNumber::Fetch(Stream& stream) const { + switch (type) { + case NumberType::S32: + case NumberType::U32: + case NumberType::F32: + stream.Write(uint32); + break; + case NumberType::S64: + case NumberType::U64: + case NumberType::F64: + stream.Write(uint64); + break; + default: + assert(0); + } +} + +u16 LiteralNumber::GetWordCount() const { + switch (type) { + case NumberType::S32: + case NumberType::U32: + case NumberType::F32: + return 1; + case NumberType::S64: + case NumberType::U64: + case NumberType::F64: + return 2; + default: + assert(0); + return 0; + } +} + +bool LiteralNumber::operator==(const Operand& other) const { if (operand_type == other.GetType()) { - return dynamic_cast(other).integer == integer; + const auto& o{dynamic_cast(other)}; + return o.type == type && o.raw == raw; } return false; } diff --git a/src/operand.h b/src/operand.h index 8bb5127..6f2765e 100644 --- a/src/operand.h +++ b/src/operand.h @@ -12,8 +12,8 @@ namespace Sirit { enum class OperandType { Invalid, - Ref, - Integer, + Op, + Number, String }; @@ -34,10 +34,15 @@ protected: OperandType operand_type{}; }; -class LiteralInteger : public Operand { +class LiteralNumber : public Operand { public: - LiteralInteger(u32 integer); - ~LiteralInteger(); + LiteralNumber(u32 number); + LiteralNumber(s32 number); + LiteralNumber(f32 number); + LiteralNumber(u64 number); + LiteralNumber(s64 number); + LiteralNumber(f64 number); + ~LiteralNumber(); virtual void Fetch(Stream& stream) const; virtual u16 GetWordCount() const; @@ -45,7 +50,26 @@ public: virtual bool operator==(const Operand& other) const; private: - u32 integer; + LiteralNumber(); + + enum class NumberType { + U32, + S32, + F32, + U64, + S64, + F64 + } type; + + union { + u64 raw{}; + u32 uint32; + s32 int32; + u64 uint64; + s64 int64; + f32 float32; + f64 float64; + }; }; class LiteralString : public Operand { diff --git a/tests/main.cpp b/tests/main.cpp index f793f01..7a3236b 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -41,6 +41,13 @@ public: ConstantTrue(TypeBool()); ConstantTrue(TypeBool()); ConstantFalse(TypeBool()); + Constant(TypeFloat(64), Literal(6342.2)); + Constant(TypeFloat(64), Literal(6342.21)); + Constant(TypeFloat(32), Literal(6342.21f)); + Constant(TypeFloat(16), Literal(30u)); + Constant(TypeInt(32, false), Literal(30u)); + Constant(TypeInt(16, false), Literal(30u)); + Constant(TypeInt(8, false), Literal(30u)); auto main_type{TypeFunction(TypeVoid())}; auto main_func{Emit(Function(TypeVoid(), spv::FunctionControlMask::MaskNone, main_type))};