diff options
author | John Hodge <tpg@mutabah.net> | 2016-10-18 21:17:13 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-10-18 21:17:13 +0800 |
commit | 1daa57b7cfd4dc609502f28eeaecdad4cb43b3d4 (patch) | |
tree | 4a66d171abd4c41cdc1f4c585f4fe1b793d66968 /src | |
parent | ce853ffc73fc2cc743bf2b03cfd1e0d4130ffd30 (diff) | |
download | mrust-1daa57b7cfd4dc609502f28eeaecdad4cb43b3d4.tar.gz |
HIR Serialise - Compress (now requires boost, sorry)
Diffstat (limited to 'src')
-rw-r--r-- | src/hir/deserialise.cpp | 329 | ||||
-rw-r--r-- | src/hir/serialise.cpp | 368 | ||||
-rw-r--r-- | src/hir/serialise_lowlevel.cpp | 37 | ||||
-rw-r--r-- | src/hir/serialise_lowlevel.hpp | 247 |
4 files changed, 535 insertions, 446 deletions
diff --git a/src/hir/deserialise.cpp b/src/hir/deserialise.cpp index 75efdccf..e40788d3 100644 --- a/src/hir/deserialise.cpp +++ b/src/hir/deserialise.cpp @@ -10,6 +10,7 @@ #include <serialiser_texttree.hpp> #include <mir/mir.hpp> #include <macro_rules/macro_rules.hpp> +#include "serialise_lowlevel.hpp" namespace { @@ -21,132 +22,24 @@ namespace { class HirDeserialiser { const ::std::string& m_crate_name; - ::std::istream& m_is; + ::HIR::serialise::Reader& m_in; public: - HirDeserialiser(const ::std::string& crate_name, ::std::istream& is): + HirDeserialiser(const ::std::string& crate_name, ::HIR::serialise::Reader& in): m_crate_name( crate_name ), - m_is(is) + m_in(in) {} - uint8_t read_u8() { - uint8_t v; - m_is.read(reinterpret_cast<char*>(&v), 1); - if( !m_is ) { - throw ""; - } - assert( m_is ); - return v; - } - uint16_t read_u16() { - uint16_t v; - v = static_cast<uint16_t>(read_u8()); - v |= static_cast<uint16_t>(read_u8()) << 8; - return v; - } - uint32_t read_u32() { - uint32_t v; - v = static_cast<uint32_t>(read_u8()); - v |= static_cast<uint32_t>(read_u8()) << 8; - v |= static_cast<uint32_t>(read_u8()) << 16; - v |= static_cast<uint32_t>(read_u8()) << 24; - return v; - } - uint64_t read_u64() { - uint64_t v; - v = static_cast<uint64_t>(read_u8()); - v |= static_cast<uint64_t>(read_u8()) << 8; - v |= static_cast<uint64_t>(read_u8()) << 16; - v |= static_cast<uint64_t>(read_u8()) << 24; - v |= static_cast<uint64_t>(read_u8()) << 32; - v |= static_cast<uint64_t>(read_u8()) << 40; - v |= static_cast<uint64_t>(read_u8()) << 48; - v |= static_cast<uint64_t>(read_u8()) << 56; - return v; - } - // Variable-length encoded u64 (for array sizes) - uint64_t read_u64c() { - auto v = read_u8(); - if( v < (1<<7) ) { - return static_cast<uint64_t>(v); - } - else if( v < 0xC0 ) { - uint64_t rv = static_cast<uint64_t>(v & 0x3F) << 16; - rv |= static_cast<uint64_t>(read_u8()) << 8; - rv |= static_cast<uint64_t>(read_u8()); - return rv; - } - else if( v < 0xFF ) { - uint64_t rv = static_cast<uint64_t>(v & 0x3F) << 32; - rv |= static_cast<uint64_t>(read_u8()) << 24; - rv |= static_cast<uint64_t>(read_u8()) << 16; - rv |= static_cast<uint64_t>(read_u8()) << 8; - rv |= static_cast<uint64_t>(read_u8()); - return rv; - } - else { - return read_u64(); - } - } - int64_t read_i64c() { - uint64_t va = read_u64c(); - bool sign = (va & 0x1) != 0; - va >>= 1; - - if( va == 0 && sign ) { - return INT64_MIN; - } - else if( sign ) { - return -static_cast<int64_t>(va); - } - else { - return -static_cast<uint64_t>(va); - } - } - double read_double() { - double v; - m_is.read(reinterpret_cast<char*>(&v), sizeof v); - return v; - } - unsigned int read_tag() { - return static_cast<unsigned int>( read_u8() ); - } - size_t read_count() { - auto v = read_u8(); - if( v < 0xFE ) { - return v; - } - else if( v == 0xFE ) { - return read_u16( ); - } - else /*if( v == 0xFF )*/ { - return ~0u; - } - } - ::std::string read_string() { - size_t len = read_u8(); - if( len < 128 ) { - } - else { - len = (len & 0x7F) << 16; - len |= read_u16(); - } - ::std::string rv(len, '\0'); - m_is.read(const_cast<char*>(rv.data()), len); - return rv; - } - bool read_bool() { - return read_u8() != 0x00; - } + ::std::string read_string() { return m_in.read_string(); } template<typename V> ::std::map< ::std::string,V> deserialise_strmap() { - size_t n = read_count(); + size_t n = m_in.read_count(); ::std::map< ::std::string, V> rv; //rv.reserve(n); for(size_t i = 0; i < n; i ++) { - auto s = read_string(); + auto s = m_in.read_string(); rv.insert( ::std::make_pair( mv$(s), D<V>::des(*this) ) ); } return rv; @@ -154,12 +47,12 @@ namespace { template<typename V> ::std::unordered_map< ::std::string,V> deserialise_strumap() { - size_t n = read_count(); + size_t n = m_in.read_count(); ::std::unordered_map< ::std::string, V> rv; //rv.reserve(n); for(size_t i = 0; i < n; i ++) { - auto s = read_string(); + auto s = m_in.read_string(); DEBUG("- " << s); rv.insert( ::std::make_pair( mv$(s), D<V>::des(*this) ) ); } @@ -169,7 +62,7 @@ namespace { template<typename T> ::std::vector<T> deserialise_vec() { - size_t n = read_count(); + size_t n = m_in.read_count(); ::std::vector<T> rv; rv.reserve(n); for(size_t i = 0; i < n; i ++) @@ -179,7 +72,7 @@ namespace { template<typename T> ::std::vector<T> deserialise_vec_c(::std::function<T()> cb) { - size_t n = read_count(); + size_t n = m_in.read_count(); ::std::vector<T> rv; rv.reserve(n); for(size_t i = 0; i < n; i ++) @@ -189,7 +82,7 @@ namespace { template<typename T> ::HIR::VisEnt<T> deserialise_visent() { - return ::HIR::VisEnt<T> { read_bool(), D<T>::des(*this) }; + return ::HIR::VisEnt<T> { m_in.read_bool(), D<T>::des(*this) }; } template<typename T> @@ -220,20 +113,20 @@ namespace { rv.m_params = deserialise_genericparams(); rv.m_type = deserialise_type(); - size_t method_count = read_count(); + size_t method_count = m_in.read_count(); for(size_t i = 0; i < method_count; i ++) { - auto name = read_string(); + auto name = m_in.read_string(); rv.m_methods.insert( ::std::make_pair( mv$(name), ::HIR::TypeImpl::VisImplEnt< ::HIR::Function> { - read_bool(), read_bool(), deserialise_function() + m_in.read_bool(), m_in.read_bool(), deserialise_function() } ) ); } - size_t const_count = read_count(); + size_t const_count = m_in.read_count(); for(size_t i = 0; i < const_count; i ++) { - auto name = read_string(); + auto name = m_in.read_string(); rv.m_constants.insert( ::std::make_pair( mv$(name), ::HIR::TypeImpl::VisImplEnt< ::HIR::Constant> { - read_bool(), read_bool(), deserialise_constant() + m_in.read_bool(), m_in.read_bool(), deserialise_constant() } ) ); } // m_src_module doesn't matter after typeck @@ -249,28 +142,28 @@ namespace { rv.m_type = deserialise_type(); - size_t method_count = read_count(); + size_t method_count = m_in.read_count(); for(size_t i = 0; i < method_count; i ++) { - auto name = read_string(); + auto name = m_in.read_string(); rv.m_methods.insert( ::std::make_pair( mv$(name), ::HIR::TraitImpl::ImplEnt< ::HIR::Function> { - read_bool(), deserialise_function() + m_in.read_bool(), deserialise_function() } ) ); } - size_t const_count = read_count(); + size_t const_count = m_in.read_count(); for(size_t i = 0; i < const_count; i ++) { - auto name = read_string(); + auto name = m_in.read_string(); rv.m_constants.insert( ::std::make_pair( mv$(name), ::HIR::TraitImpl::ImplEnt< ::HIR::Constant> { - read_bool(), deserialise_constant() + m_in.read_bool(), deserialise_constant() } ) ); } - size_t type_count = read_count(); + size_t type_count = m_in.read_count(); for(size_t i = 0; i < type_count; i ++) { - auto name = read_string(); + auto name = m_in.read_string(); rv.m_types.insert( ::std::make_pair( mv$(name), ::HIR::TraitImpl::ImplEnt< ::HIR::TypeRef> { - read_bool(), deserialise_type() + m_in.read_bool(), deserialise_type() } ) ); } @@ -282,7 +175,7 @@ namespace { return ::HIR::MarkerImpl { deserialise_genericparams(), deserialise_pathparams(), - read_bool(), + m_in.read_bool(), deserialise_type() }; } @@ -297,16 +190,16 @@ namespace { // NOTE: This is set after loading. //rv.m_exported = true; rv.m_rules = deserialise_vec_c< ::MacroRulesArm>( [&](){ return deserialise_macrorulesarm(); }); - rv.m_source_crate = read_string(); + rv.m_source_crate = m_in.read_string(); if(rv.m_source_crate == "") rv.m_source_crate = m_crate_name; return rv; } ::MacroPatEnt deserialise_macropatent() { ::MacroPatEnt rv { - read_string(), - static_cast<unsigned int>(read_count()), - static_cast< ::MacroPatEnt::Type>(read_tag()) + m_in.read_string(), + static_cast<unsigned int>(m_in.read_count()), + static_cast< ::MacroPatEnt::Type>(m_in.read_tag()) }; switch(rv.type) { @@ -341,22 +234,22 @@ namespace { return rv; } ::MacroExpansionEnt deserialise_macroexpansionent() { - switch(read_tag()) + switch(m_in.read_tag()) { case 0: return ::MacroExpansionEnt( deserialise_token() ); case 1: { - unsigned int v = static_cast<unsigned int>(read_u8()) << 24; - return ::MacroExpansionEnt( v | read_count() ); + unsigned int v = static_cast<unsigned int>(m_in.read_u8()) << 24; + return ::MacroExpansionEnt( v | m_in.read_count() ); } case 2: { auto entries = deserialise_vec_c< ::MacroExpansionEnt>( [&](){ return deserialise_macroexpansionent(); } ); auto joiner = deserialise_token(); ::std::map<unsigned int, bool> variables; - size_t n = read_count(); + size_t n = m_in.read_count(); while(n--) { - auto idx = static_cast<unsigned int>(read_count()); - bool flag = read_bool(); + auto idx = static_cast<unsigned int>(m_in.read_count()); + bool flag = m_in.read_bool(); variables.insert( ::std::make_pair(idx, flag) ); } return ::MacroExpansionEnt::make_Loop({ @@ -371,7 +264,7 @@ namespace { ::Token deserialise_token() { ::Token tok; // HACK: Hand off to old serialiser code - auto s = read_string(); + auto s = m_in.read_string(); ::std::stringstream tmp(s); { Deserialiser_TextTree ser(tmp); @@ -385,7 +278,7 @@ namespace { ::HIR::ExprPtr deserialise_exprptr() { ::HIR::ExprPtr rv; - if( read_bool() ) + if( m_in.read_bool() ) { rv.m_mir = deserialise_mir(); } @@ -404,17 +297,17 @@ namespace { } ::MIR::LValue deserialise_mir_lvalue_() { - switch( read_tag() ) + switch( m_in.read_tag() ) { #define _(x, ...) case ::MIR::LValue::TAG_##x: return ::MIR::LValue::make_##x( __VA_ARGS__ ); - _(Variable, static_cast<unsigned int>(read_count()) ) - _(Temporary, { static_cast<unsigned int>(read_count()) } ) - _(Argument, { static_cast<unsigned int>(read_count()) } ) + _(Variable, static_cast<unsigned int>(m_in.read_count()) ) + _(Temporary, { static_cast<unsigned int>(m_in.read_count()) } ) + _(Argument, { static_cast<unsigned int>(m_in.read_count()) } ) _(Static, deserialise_path() ) _(Return, {}) _(Field, { box$( deserialise_mir_lvalue() ), - static_cast<unsigned int>(read_count()) + static_cast<unsigned int>(m_in.read_count()) } ) _(Deref, { box$( deserialise_mir_lvalue() ) }) _(Index, { @@ -423,7 +316,7 @@ namespace { } ) _(Downcast, { box$( deserialise_mir_lvalue() ), - static_cast<unsigned int>(read_count()) + static_cast<unsigned int>(m_in.read_count()) } ) #undef _ default: @@ -434,18 +327,18 @@ namespace { { TRACE_FUNCTION; - switch( read_tag() ) + switch( m_in.read_tag() ) { #define _(x, ...) case ::MIR::RValue::TAG_##x: return ::MIR::RValue::make_##x( __VA_ARGS__ ); _(Use, deserialise_mir_lvalue() ) _(Constant, deserialise_mir_constant() ) _(SizedArray, { deserialise_mir_lvalue(), - static_cast<unsigned int>(read_u64c()) + static_cast<unsigned int>(m_in.read_u64c()) }) _(Borrow, { 0, // TODO: Region? - static_cast< ::HIR::BorrowType>( read_tag() ), + static_cast< ::HIR::BorrowType>( m_in.read_tag() ), deserialise_mir_lvalue() }) _(Cast, { @@ -454,12 +347,12 @@ namespace { }) _(BinOp, { deserialise_mir_lvalue(), - static_cast< ::MIR::eBinOp>( read_tag() ), + static_cast< ::MIR::eBinOp>( m_in.read_tag() ), deserialise_mir_lvalue() }) _(UniOp, { deserialise_mir_lvalue(), - static_cast< ::MIR::eUniOp>( read_tag() ) + static_cast< ::MIR::eUniOp>( m_in.read_tag() ) }) _(DstMeta, { deserialise_mir_lvalue() @@ -487,20 +380,20 @@ namespace { { TRACE_FUNCTION; - switch( read_tag() ) + switch( m_in.read_tag() ) { #define _(x, ...) case ::MIR::Constant::TAG_##x: DEBUG("- " #x); return ::MIR::Constant::make_##x( __VA_ARGS__ ); - _(Int, read_i64c()) - _(Uint, read_u64c()) - _(Float, read_double()) - _(Bool, read_bool()) + _(Int, m_in.read_i64c()) + _(Uint, m_in.read_u64c()) + _(Float, m_in.read_double()) + _(Bool, m_in.read_bool()) case ::MIR::Constant::TAG_Bytes: { ::std::vector<unsigned char> bytes; - bytes.resize( read_count() ); - m_is.read( reinterpret_cast<char*>(bytes.data()), bytes.size() ); + bytes.resize( m_in.read_count() ); + m_in.read( bytes.data(), bytes.size() ); return ::MIR::Constant::make_Bytes( mv$(bytes) ); } - _(StaticString, read_string() ) + _(StaticString, m_in.read_string() ) _(Const, { deserialise_path() } ) _(ItemAddr, deserialise_path() ) #undef _ @@ -511,7 +404,7 @@ namespace { ::HIR::TypeItem deserialise_typeitem() { - switch( read_tag() ) + switch( m_in.read_tag() ) { case 0: return ::HIR::TypeItem( deserialise_simplepath() ); @@ -531,7 +424,7 @@ namespace { } ::HIR::ValueItem deserialise_valueitem() { - switch( read_tag() ) + switch( m_in.read_tag() ) { case 0: return ::HIR::ValueItem( deserialise_simplepath() ); @@ -556,13 +449,13 @@ namespace { TRACE_FUNCTION; ::HIR::Function rv { - static_cast< ::HIR::Function::Receiver>( read_tag() ), - read_string(), - read_bool(), - read_bool(), + static_cast< ::HIR::Function::Receiver>( m_in.read_tag() ), + m_in.read_string(), + m_in.read_bool(), + m_in.read_bool(), deserialise_genericparams(), deserialise_fcnargs(), - read_bool(), + m_in.read_bool(), deserialise_type(), deserialise_exprptr() }; @@ -570,7 +463,7 @@ namespace { } ::std::vector< ::std::pair< ::HIR::Pattern, ::HIR::TypeRef> > deserialise_fcnargs() { - size_t n = read_count(); + size_t n = m_in.read_count(); ::std::vector< ::std::pair< ::HIR::Pattern, ::HIR::TypeRef> > rv; rv.reserve(n); for(size_t i = 0; i < n; i ++) @@ -594,7 +487,7 @@ namespace { TRACE_FUNCTION; return ::HIR::Static { - read_bool(), + m_in.read_bool(), deserialise_type(), ::HIR::ExprPtr {} }; @@ -616,7 +509,7 @@ namespace { ::HIR::TraitValueItem deserialise_traitvalueitem() { - switch( read_tag() ) + switch( m_in.read_tag() ) { #define _(x, ...) case ::HIR::TraitValueItem::TAG_##x: DEBUG("- " #x); return ::HIR::TraitValueItem::make_##x( __VA_ARGS__ ); _(Constant, deserialise_constant() ) @@ -631,7 +524,7 @@ namespace { ::HIR::AssociatedType deserialise_associatedtype() { return ::HIR::AssociatedType { - read_bool(), + m_in.read_bool(), "", // TODO: Better lifetime type deserialise_vec< ::HIR::TraitPath>(), deserialise_type() @@ -687,21 +580,21 @@ namespace { ::HIR::TypeRef HirDeserialiser::deserialise_type() { TRACE_FUNCTION; - switch( read_tag() ) + switch( m_in.read_tag() ) { #define _(x, ...) case ::HIR::TypeRef::Data::TAG_##x: DEBUG("- "#x); return ::HIR::TypeRef( ::HIR::TypeRef::Data::make_##x( __VA_ARGS__ ) ); _(Infer, {}) _(Diverge, {}) _(Primitive, - static_cast< ::HIR::CoreType>( read_tag() ) + static_cast< ::HIR::CoreType>( m_in.read_tag() ) ) _(Path, { deserialise_path(), {} }) _(Generic, { - read_string(), - read_u16() + m_in.read_string(), + m_in.read_u16() }) _(TraitObject, { deserialise_traitpath(), @@ -711,7 +604,7 @@ namespace { _(Array, { deserialise_ptr< ::HIR::TypeRef>(), ::HIR::ExprPtr(), - read_u64c() + m_in.read_u64c() }) _(Slice, { deserialise_ptr< ::HIR::TypeRef>() @@ -720,16 +613,16 @@ namespace { deserialise_vec< ::HIR::TypeRef>() ) _(Borrow, { - static_cast< ::HIR::BorrowType>( read_tag() ), + static_cast< ::HIR::BorrowType>( m_in.read_tag() ), deserialise_ptr< ::HIR::TypeRef>() }) _(Pointer, { - static_cast< ::HIR::BorrowType>( read_tag() ), + static_cast< ::HIR::BorrowType>( m_in.read_tag() ), deserialise_ptr< ::HIR::TypeRef>() }) _(Function, { - read_bool(), - read_string(), + m_in.read_bool(), + m_in.read_string(), deserialise_ptr< ::HIR::TypeRef>(), deserialise_vec< ::HIR::TypeRef>() }) @@ -743,7 +636,7 @@ namespace { { TRACE_FUNCTION; // HACK! If the read crate name is empty, replace it with the name we're loaded with - auto crate_name = read_string(); + auto crate_name = m_in.read_string(); if( crate_name == "" ) crate_name = m_crate_name; return ::HIR::SimplePath { @@ -778,7 +671,7 @@ namespace { ::HIR::Path HirDeserialiser::deserialise_path() { TRACE_FUNCTION; - switch( read_tag() ) + switch( m_in.read_tag() ) { case 0: DEBUG("Generic"); @@ -787,7 +680,7 @@ namespace { DEBUG("Inherent"); return ::HIR::Path { deserialise_type(), - read_string(), + m_in.read_string(), deserialise_pathparams() }; case 2: @@ -795,7 +688,7 @@ namespace { return ::HIR::Path { deserialise_type(), deserialise_genericpath(), - read_string(), + m_in.read_string(), deserialise_pathparams() }; default: @@ -815,14 +708,14 @@ namespace { ::HIR::TypeParamDef HirDeserialiser::deserialise_typaramdef() { return ::HIR::TypeParamDef { - read_string(), + m_in.read_string(), deserialise_type(), - read_bool() + m_in.read_bool() }; } ::HIR::GenericBound HirDeserialiser::deserialise_genericbound() { - switch( read_tag() ) + switch( m_in.read_tag() ) { case 0: case 1: @@ -848,13 +741,13 @@ namespace { TRACE_FUNCTION; return ::HIR::Enum { deserialise_genericparams(), - static_cast< ::HIR::Enum::Repr>(read_tag()), + static_cast< ::HIR::Enum::Repr>(m_in.read_tag()), deserialise_vec< ::std::pair< ::std::string, ::HIR::Enum::Variant> >() }; } ::HIR::Enum::Variant HirDeserialiser::deserialise_enumvariant() { - switch( read_tag() ) + switch( m_in.read_tag() ) { case ::HIR::Enum::Variant::TAG_Unit: return ::HIR::Enum::Variant::make_Unit({}); @@ -875,10 +768,10 @@ namespace { { TRACE_FUNCTION; auto params = deserialise_genericparams(); - auto repr = static_cast< ::HIR::Struct::Repr>( read_tag() ); + auto repr = static_cast< ::HIR::Struct::Repr>( m_in.read_tag() ); DEBUG("params = " << params.fmt_args() << params.fmt_bounds()); - switch( read_tag() ) + switch( m_in.read_tag() ) { case ::HIR::Struct::Data::TAG_Unit: DEBUG("Unit"); @@ -911,7 +804,7 @@ namespace { "", // TODO: Better type for lifetime deserialise_vec< ::HIR::TraitPath>() }; - rv.m_is_marker = read_bool(); + rv.m_is_marker = m_in.read_bool(); rv.m_types = deserialise_strumap< ::HIR::AssociatedType>(); rv.m_values = deserialise_strumap< ::HIR::TraitValueItem>(); return rv; @@ -919,19 +812,19 @@ namespace { ::HIR::Literal HirDeserialiser::deserialise_literal() { - switch( read_tag() ) + switch( m_in.read_tag() ) { #define _(x, ...) case ::HIR::Literal::TAG_##x: return ::HIR::Literal::make_##x(__VA_ARGS__); _(Invalid, {}) _(List, deserialise_vec< ::HIR::Literal>() ) _(Variant, { - static_cast<unsigned int>(read_count()), + static_cast<unsigned int>(m_in.read_count()), deserialise_vec< ::HIR::Literal>() }) - _(Integer, read_u64() ) - _(Float, read_double() ) + _(Integer, m_in.read_u64() ) + _(Float, m_in.read_double() ) _(BorrowOf, deserialise_path() ) - _(String, read_string() ) + _(String, m_in.read_string() ) #undef _ default: throw ""; @@ -965,7 +858,7 @@ namespace { { TRACE_FUNCTION; - switch( read_tag() ) + switch( m_in.read_tag() ) { case 0: return ::MIR::Statement::make_Assign({ @@ -974,7 +867,7 @@ namespace { }); case 1: return ::MIR::Statement::make_Drop({ - read_bool() ? ::MIR::eDropKind::DEEP : ::MIR::eDropKind::SHALLOW, + m_in.read_bool() ? ::MIR::eDropKind::DEEP : ::MIR::eDropKind::SHALLOW, deserialise_mir_lvalue() }); default: @@ -985,26 +878,26 @@ namespace { { TRACE_FUNCTION; - switch( read_tag() ) + switch( m_in.read_tag() ) { #define _(x, ...) case ::MIR::Terminator::TAG_##x: return ::MIR::Terminator::make_##x( __VA_ARGS__ ); _(Incomplete, {}) _(Return, {}) _(Diverge, {}) - _(Goto, static_cast<unsigned int>(read_count()) ) - _(Panic, { static_cast<unsigned int>(read_count()) }) + _(Goto, static_cast<unsigned int>(m_in.read_count()) ) + _(Panic, { static_cast<unsigned int>(m_in.read_count()) }) _(If, { deserialise_mir_lvalue(), - static_cast<unsigned int>(read_count()), - static_cast<unsigned int>(read_count()) + static_cast<unsigned int>(m_in.read_count()), + static_cast<unsigned int>(m_in.read_count()) }) _(Switch, { deserialise_mir_lvalue(), - deserialise_vec_c<unsigned int>([&](){ return read_count(); }) + deserialise_vec_c<unsigned int>([&](){ return m_in.read_count(); }) }) _(Call, { - static_cast<unsigned int>(read_count()), - static_cast<unsigned int>(read_count()), + static_cast<unsigned int>(m_in.read_count()), + static_cast<unsigned int>(m_in.read_count()), deserialise_mir_lvalue(), deserialise_mir_lvalue(), deserialise_vec< ::MIR::LValue>() @@ -1036,7 +929,7 @@ namespace { rv.m_type_impls = deserialise_vec< ::HIR::TypeImpl>(); { - size_t n = read_count(); + size_t n = m_in.read_count(); for(size_t i = 0; i < n; i ++) { auto p = deserialise_simplepath(); @@ -1044,7 +937,7 @@ namespace { } } { - size_t n = read_count(); + size_t n = m_in.read_count(); for(size_t i = 0; i < n; i ++) { auto p = deserialise_simplepath(); @@ -1056,10 +949,10 @@ namespace { rv.m_lang_items = deserialise_strumap< ::HIR::SimplePath>(); { - size_t n = read_count(); + size_t n = m_in.read_count(); for(size_t i = 0; i < n; i ++) { - auto ext_crate_name = read_string(); + auto ext_crate_name = m_in.read_string(); rv.m_ext_crates.insert( ::std::make_pair(ext_crate_name, ::HIR::CratePtr{}) ); } } @@ -1070,7 +963,7 @@ namespace { ::HIR::CratePtr HIR_Deserialise(const ::std::string& filename, const ::std::string& loaded_name) { - ::std::ifstream in(filename); + ::HIR::serialise::Reader in { filename }; HirDeserialiser s { loaded_name, in }; try diff --git a/src/hir/serialise.cpp b/src/hir/serialise.cpp index 0fad2942..506245c1 100644 --- a/src/hir/serialise.cpp +++ b/src/hir/serialise.cpp @@ -10,135 +10,47 @@ #include <serialiser_texttree.hpp> #include <macro_rules/macro_rules.hpp> #include <mir/mir.hpp> +#include "serialise_lowlevel.hpp" namespace { class HirSerialiser { - ::std::ostream& m_os; + ::HIR::serialise::Writer& m_out; public: - HirSerialiser(::std::ostream& os): - m_os(os) + HirSerialiser(::HIR::serialise::Writer& out): + m_out( out ) {} - void write_u8(uint8_t v) { - m_os.write(reinterpret_cast<const char*>(&v), 1); - } - void write_u16(uint16_t v) { - write_u8(v & 0xFF); - write_u8(v >> 8); - } - void write_u32(uint32_t v) { - write_u8(v & 0xFF); - write_u8(v >> 8); - write_u8(v >> 16); - write_u8(v >> 24); - } - void write_u64(uint64_t v) { - write_u8(v & 0xFF); - write_u8(v >> 8); - write_u8(v >> 16); - write_u8(v >> 24); - write_u8(v >> 32); - write_u8(v >> 40); - write_u8(v >> 48); - write_u8(v >> 56); - } - // Variable-length encoded u64 (for array sizes) - void write_u64c(uint64_t v) { - if( v < (1<<7) ) { - write_u8(v); - } - else if( v < (1<<(6+16)) ) { - write_u8( 0x80 + (v >> 16)); // 0x80 -- 0xB0 - write_u8(v >> 8); - write_u8(v); - } - else if( v < (1ul << (5 + 32)) ) { - write_u8( 0xC0 + (v >> 32)); // 0x80 -- 0xB0 - write_u8(v >> 24); - write_u8(v >> 16); - write_u8(v >> 8); - write_u8(v); - } - else { - write_u8(0xFF); - write_u64(v); - } - } - void write_i64c(int64_t v) { - // Convert from 2's completement - bool sign = (v < 0); - uint64_t va = (v < 0 ? -v : v); - va <<= 1; - va |= (sign ? 1 : 0); - write_u64c(va); - } - void write_double(double v) { - m_os.write(reinterpret_cast<const char*>(&v), sizeof v); - } - void write_tag(unsigned int t) { - assert(t < 256); - write_u8( static_cast<uint8_t>(t) ); - } - void write_count(size_t c) { - //DEBUG("c = " << c); - if(c < 0xFE) { - write_u8( static_cast<uint8_t>(c) ); - } - else if( c == ~0u ) { - write_u8( 0xFF ); - } - else { - assert(c < (1u<<16)); - write_u8( 0xFE ); - write_u16( static_cast<uint16_t>(c) ); - } - } - void write_string(const ::std::string& v) { - if(v.size() < 128) { - write_u8( static_cast<uint8_t>(v.size()) ); - } - else { - assert(v.size() < (1u<<(16+7))); - write_u8( static_cast<uint8_t>(128 + (v.size() >> 16)) ); - write_u16( static_cast<uint16_t>(v.size() & 0xFFFF) ); - } - m_os.write(v.data(), v.size()); - } - void write_bool(bool v) { - write_u8(v ? 0xFF : 0x00); - } - template<typename V> void serialise_strmap(const ::std::map< ::std::string,V>& map) { - write_count(map.size()); + m_out.write_count(map.size()); for(const auto& v : map) { - write_string(v.first); + m_out.write_string(v.first); serialise(v.second); } } template<typename V> void serialise_strmap(const ::std::unordered_map< ::std::string,V>& map) { - write_count(map.size()); + m_out.write_count(map.size()); for(const auto& v : map) { DEBUG("- " << v.first); - write_string(v.first); + m_out.write_string(v.first); serialise(v.second); } } template<typename T> void serialise_vec(const ::std::vector<T>& vec) { - write_count(vec.size()); + m_out.write_count(vec.size()); for(const auto& i : vec) serialise(i); } template<typename T> void serialise(const ::HIR::VisEnt<T>& e) { - write_bool(e.is_public); + m_out.write_bool(e.is_public); serialise(e.ent); } template<typename T> @@ -147,13 +59,13 @@ namespace { } template<typename T> void serialise(const ::std::pair< ::std::string, T>& e) { - write_string(e.first); + m_out.write_string(e.first); serialise(e.second); } void serialise_type(const ::HIR::TypeRef& ty) { - write_tag( ty.m_data.tag() ); + m_out.write_tag( ty.m_data.tag() ); TU_MATCHA( (ty.m_data), (e), (Infer, // BAAD @@ -161,18 +73,18 @@ namespace { (Diverge, ), (Primitive, - write_tag( static_cast<int>(e) ); + m_out.write_tag( static_cast<int>(e) ); ), (Path, serialise_path(e.path); ), (Generic, - write_string(e.name); - write_u16(e.binding); + m_out.write_string(e.name); + m_out.write_u16(e.binding); ), (TraitObject, serialise_traitpath(e.m_trait); - write_count(e.m_markers.size()); + m_out.write_count(e.m_markers.size()); for(const auto& m : e.m_markers) serialise_genericpath(m); //write_string(e.lifetime); // TODO: Need a better type @@ -180,27 +92,27 @@ namespace { (Array, assert(e.size_val != ~0u); serialise_type(*e.inner); - write_u64c(e.size_val); + m_out.write_u64c(e.size_val); ), (Slice, serialise_type(*e.inner); ), (Tuple, - write_count(e.size()); + m_out.write_count(e.size()); for(const auto& st : e) serialise_type(st); ), (Borrow, - write_tag(static_cast<int>(e.type)); + m_out.write_tag(static_cast<int>(e.type)); serialise_type(*e.inner); ), (Pointer, - write_tag(static_cast<int>(e.type)); + m_out.write_tag(static_cast<int>(e.type)); serialise_type(*e.inner); ), (Function, - write_bool(e.is_unsafe); - write_string(e.m_abi); + m_out.write_bool(e.is_unsafe); + m_out.write_string(e.m_abi); serialise_type(*e.m_rettype); serialise_vec(e.m_arg_types); ), @@ -213,14 +125,14 @@ namespace { void serialise_simplepath(const ::HIR::SimplePath& path) { //TRACE_FUNCTION_F("path="<<path); - write_string(path.m_crate_name); - write_count(path.m_components.size()); + m_out.write_string(path.m_crate_name); + m_out.write_count(path.m_components.size()); for(const auto& c : path.m_components) - write_string(c); + m_out.write_string(c); } void serialise_pathparams(const ::HIR::PathParams& pp) { - write_count(pp.m_types.size()); + m_out.write_count(pp.m_types.size()); for(const auto& t : pp.m_types) serialise_type(t); } @@ -241,20 +153,20 @@ namespace { TRACE_FUNCTION_F("path="<<path); TU_MATCHA( (path.m_data), (e), (Generic, - write_tag(0); + m_out.write_tag(0); serialise_genericpath(e); ), (UfcsInherent, - write_tag(1); + m_out.write_tag(1); serialise_type(*e.type); - write_string(e.item); + m_out.write_string(e.item); serialise_pathparams(e.params); ), (UfcsKnown, - write_tag(2); + m_out.write_tag(2); serialise_type(*e.type); serialise_genericpath(e.trait); - write_string(e.item); + m_out.write_string(e.item); serialise_pathparams(e.params); ), (UfcsUnknown, @@ -272,25 +184,25 @@ namespace { serialise_vec(params.m_bounds); } void serialise(const ::HIR::TypeParamDef& pd) { - write_string(pd.m_name); + m_out.write_string(pd.m_name); serialise_type(pd.m_default); - write_bool(pd.m_is_sized); + m_out.write_bool(pd.m_is_sized); } void serialise(const ::HIR::GenericBound& b) { TU_MATCHA( (b), (e), (Lifetime, - write_tag(0); + m_out.write_tag(0); ), (TypeLifetime, - write_tag(1); + m_out.write_tag(1); ), (TraitBound, - write_tag(2); + m_out.write_tag(2); serialise_type(e.type); serialise_traitpath(e.trait); ), (TypeEquality, - write_tag(3); + m_out.write_tag(3); serialise_type(e.type); serialise_type(e.other_type); ) @@ -302,16 +214,16 @@ namespace { { serialise_module(crate.m_root_module); - write_count(crate.m_type_impls.size()); + m_out.write_count(crate.m_type_impls.size()); for(const auto& impl : crate.m_type_impls) { serialise_typeimpl(impl); } - write_count(crate.m_trait_impls.size()); + m_out.write_count(crate.m_trait_impls.size()); for(const auto& tr_impl : crate.m_trait_impls) { serialise_simplepath(tr_impl.first); serialise_traitimpl(tr_impl.second); } - write_count(crate.m_marker_impls.size()); + m_out.write_count(crate.m_marker_impls.size()); for(const auto& tr_impl : crate.m_marker_impls) { serialise_simplepath(tr_impl.first); serialise_markerimpl(tr_impl.second); @@ -320,9 +232,9 @@ namespace { serialise_strmap(crate.m_exported_macros); serialise_strmap(crate.m_lang_items); - write_count(crate.m_ext_crates.size()); + m_out.write_count(crate.m_ext_crates.size()); for(const auto& ext : crate.m_ext_crates) - write_string(ext.first); + m_out.write_string(ext.first); } void serialise_module(const ::HIR::Module& mod) { @@ -339,18 +251,18 @@ namespace { serialise_generics(impl.m_params); serialise_type(impl.m_type); - write_count(impl.m_methods.size()); + m_out.write_count(impl.m_methods.size()); for(const auto& v : impl.m_methods) { - write_string(v.first); - write_bool(v.second.is_pub); - write_bool(v.second.is_specialisable); + m_out.write_string(v.first); + m_out.write_bool(v.second.is_pub); + m_out.write_bool(v.second.is_specialisable); serialise(v.second.data); } - write_count(impl.m_constants.size()); + m_out.write_count(impl.m_constants.size()); for(const auto& v : impl.m_constants) { - write_string(v.first); - write_bool(v.second.is_pub); - write_bool(v.second.is_specialisable); + m_out.write_string(v.first); + m_out.write_bool(v.second.is_pub); + m_out.write_bool(v.second.is_specialisable); serialise(v.second.data); } // m_src_module doesn't matter after typeck @@ -362,25 +274,25 @@ namespace { serialise_pathparams(impl.m_trait_args); serialise_type(impl.m_type); - write_count(impl.m_methods.size()); + m_out.write_count(impl.m_methods.size()); for(const auto& v : impl.m_methods) { DEBUG("fn " << v.first); - write_string(v.first); - write_bool(v.second.is_specialisable); + m_out.write_string(v.first); + m_out.write_bool(v.second.is_specialisable); serialise(v.second.data); } - write_count(impl.m_constants.size()); + m_out.write_count(impl.m_constants.size()); for(const auto& v : impl.m_constants) { DEBUG("const " << v.first); - write_string(v.first); - write_bool(v.second.is_specialisable); + m_out.write_string(v.first); + m_out.write_bool(v.second.is_specialisable); serialise(v.second.data); } - write_count(impl.m_types.size()); + m_out.write_count(impl.m_types.size()); for(const auto& v : impl.m_types) { DEBUG("type " << v.first); - write_string(v.first); - write_bool(v.second.is_specialisable); + m_out.write_string(v.first); + m_out.write_bool(v.second.is_specialisable); serialise(v.second.data); } // m_src_module doesn't matter after typeck @@ -389,7 +301,7 @@ namespace { { serialise_generics(impl.m_params); serialise_pathparams(impl.m_trait_args); - write_bool(impl.is_positive); + m_out.write_bool(impl.is_positive); serialise_type(impl.m_type); } @@ -403,7 +315,7 @@ namespace { serialise_traitpath(p); } void serialise(const ::std::string& v) { - write_string(v); + m_out.write_string(v); } void serialise(const ::MacroRulesPtr& mac) @@ -414,12 +326,12 @@ namespace { { //m_exported: IGNORE, should be set serialise_vec(mac.m_rules); - write_string(mac.m_source_crate); + m_out.write_string(mac.m_source_crate); } void serialise(const ::MacroPatEnt& pe) { - write_string(pe.name); - write_count(pe.name_index); - write_tag( static_cast<int>(pe.type) ); + m_out.write_string(pe.name); + m_out.write_count(pe.name_index); + m_out.write_tag( static_cast<int>(pe.type) ); if( pe.type == ::MacroPatEnt::PAT_TOKEN ) { serialise(pe.tok); } @@ -436,23 +348,23 @@ namespace { void serialise(const ::MacroExpansionEnt& ent) { TU_MATCHA( (ent), (e), (Token, - write_tag(0); + m_out.write_tag(0); serialise(e); ), (NamedValue, - write_tag(1); - write_u8(e >> 24); - write_count(e & 0x00FFFFFF); + m_out.write_tag(1); + m_out.write_u8(e >> 24); + m_out.write_count(e & 0x00FFFFFF); ), (Loop, - write_tag(2); + m_out.write_tag(2); serialise_vec(e.entries); serialise(e.joiner); // ::std::map<unsigned int,bool> - write_count(e.variables.size()); + m_out.write_count(e.variables.size()); for(const auto& var : e.variables) { - write_count(var.first); - write_bool(var.second); + m_out.write_count(var.first); + m_out.write_bool(var.second); } ) ) @@ -465,12 +377,12 @@ namespace { tok.serialise( ser ); } - write_string(tmp.str()); + m_out.write_string(tmp.str()); } void serialise(const ::HIR::Literal& lit) { - write_tag(lit.tag()); + m_out.write_tag(lit.tag()); TU_MATCHA( (lit), (e), (Invalid, //BUG(Span(), "Literal::Invalid encountered in HIR"); @@ -479,27 +391,27 @@ namespace { serialise_vec(e); ), (Variant, - write_count(e.idx); + m_out.write_count(e.idx); serialise_vec(e.vals); ), (Integer, - write_u64(e); + m_out.write_u64(e); ), (Float, - write_double(e); + m_out.write_double(e); ), (BorrowOf, serialise_path(e); ), (String, - write_string(e); + m_out.write_string(e); ) ) } void serialise(const ::HIR::ExprPtr& exp) { - write_bool( (bool)exp.m_mir ); + m_out.write_bool( (bool)exp.m_mir ); if( exp.m_mir ) { serialise(*exp.m_mir); } @@ -520,21 +432,21 @@ namespace { { TU_MATCHA( (stmt), (e), (Assign, - write_tag(0); + m_out.write_tag(0); serialise(e.dst); serialise(e.src); ), (Drop, - write_tag(1); + m_out.write_tag(1); assert(e.kind == ::MIR::eDropKind::DEEP || e.kind == ::MIR::eDropKind::SHALLOW); - write_bool(e.kind == ::MIR::eDropKind::DEEP); + m_out.write_bool(e.kind == ::MIR::eDropKind::DEEP); serialise(e.slot); ) ) } void serialise(const ::MIR::Terminator& term) { - write_tag( static_cast<int>(term.tag()) ); + m_out.write_tag( static_cast<int>(term.tag()) ); TU_MATCHA( (term), (e), (Incomplete, // NOTE: loops that diverge (don't break) leave a dangling bb @@ -545,25 +457,25 @@ namespace { (Diverge, ), (Goto, - write_count(e); + m_out.write_count(e); ), (Panic, - write_count(e.dst); + m_out.write_count(e.dst); ), (If, serialise(e.cond); - write_count(e.bb0); - write_count(e.bb1); + m_out.write_count(e.bb0); + m_out.write_count(e.bb1); ), (Switch, serialise(e.val); - write_count(e.targets.size()); + m_out.write_count(e.targets.size()); for(auto t : e.targets) - write_count(t); + m_out.write_count(t); ), (Call, - write_count(e.ret_block); - write_count(e.panic_block); + m_out.write_count(e.ret_block); + m_out.write_count(e.panic_block); serialise(e.ret_val); serialise(e.fcn_val); serialise_vec(e.args); @@ -573,16 +485,16 @@ namespace { void serialise(const ::MIR::LValue& lv) { TRACE_FUNCTION_F("LValue = "<<lv); - write_tag( static_cast<int>(lv.tag()) ); + m_out.write_tag( static_cast<int>(lv.tag()) ); TU_MATCHA( (lv), (e), (Variable, - write_count(e); + m_out.write_count(e); ), (Temporary, - write_count(e.idx); + m_out.write_count(e.idx); ), (Argument, - write_count(e.idx); + m_out.write_count(e.idx); ), (Static, serialise_path(e); @@ -591,7 +503,7 @@ namespace { ), (Field, serialise(e.val); - write_count(e.field_index); + m_out.write_count(e.field_index); ), (Deref, serialise(e.val); @@ -602,14 +514,14 @@ namespace { ), (Downcast, serialise(e.val); - write_count(e.variant_index); + m_out.write_count(e.variant_index); ) ) } void serialise(const ::MIR::RValue& val) { TRACE_FUNCTION_F("RValue = "<<val); - write_tag( val.tag() ); + m_out.write_tag( val.tag() ); TU_MATCHA( (val), (e), (Use, serialise(e); @@ -619,11 +531,11 @@ namespace { ), (SizedArray, serialise(e.val); - write_u64c(e.count); + m_out.write_u64c(e.count); ), (Borrow, // TODO: Region? - write_tag( static_cast<int>(e.type) ); + m_out.write_tag( static_cast<int>(e.type) ); serialise(e.val); ), (Cast, @@ -632,12 +544,12 @@ namespace { ), (BinOp, serialise(e.val_l); - write_tag( static_cast<int>(e.op) ); + m_out.write_tag( static_cast<int>(e.op) ); serialise(e.val_r); ), (UniOp, serialise(e.val); - write_tag( static_cast<int>(e.op) ); + m_out.write_tag( static_cast<int>(e.op) ); ), (DstMeta, serialise(e.val); @@ -660,26 +572,26 @@ namespace { } void serialise(const ::MIR::Constant& v) { - write_tag(v.tag()); + m_out.write_tag(v.tag()); TU_MATCHA( (v), (e), (Int, - write_i64c(e); + m_out.write_i64c(e); ), (Uint, - write_u64c(e); + m_out.write_u64c(e); ), (Float, - write_double(e); + m_out.write_double(e); ), (Bool, - write_bool(e); + m_out.write_bool(e); ), (Bytes, - write_count(e.size()); - m_os.write( reinterpret_cast<const char*>(e.data()), e.size() ); + m_out.write_count(e.size()); + m_out.write( e.data(), e.size() ); ), (StaticString, - write_string(e); + m_out.write_string(e); ), (Const, serialise_path(e.p); @@ -694,27 +606,27 @@ namespace { { TU_MATCHA( (item), (e), (Import, - write_tag(0); + m_out.write_tag(0); serialise_simplepath(e); ), (Module, - write_tag(1); + m_out.write_tag(1); serialise_module(e); ), (TypeAlias, - write_tag(2); + m_out.write_tag(2); serialise(e); ), (Enum, - write_tag(3); + m_out.write_tag(3); serialise(e); ), (Struct, - write_tag(4); + m_out.write_tag(4); serialise(e); ), (Trait, - write_tag(5); + m_out.write_tag(5); serialise(e); ) ) @@ -723,27 +635,27 @@ namespace { { TU_MATCHA( (item), (e), (Import, - write_tag(0); + m_out.write_tag(0); serialise_simplepath(e); ), (Constant, - write_tag(1); + m_out.write_tag(1); serialise(e); ), (Static, - write_tag(2); + m_out.write_tag(2); serialise(e); ), (StructConstant, - write_tag(3); + m_out.write_tag(3); serialise_simplepath(e.ty); ), (Function, - write_tag(4); + m_out.write_tag(4); serialise(e); ), (StructConstructor, - write_tag(5); + m_out.write_tag(5); serialise_simplepath(e.ty); ) ) @@ -754,16 +666,16 @@ namespace { { TRACE_FUNCTION_F("_function:"); - write_tag( static_cast<int>(fcn.m_receiver) ); - write_string(fcn.m_abi); - write_bool(fcn.m_unsafe); - write_bool(fcn.m_const); + m_out.write_tag( static_cast<int>(fcn.m_receiver) ); + m_out.write_string(fcn.m_abi); + m_out.write_bool(fcn.m_unsafe); + m_out.write_bool(fcn.m_const); serialise_generics(fcn.m_params); - write_count(fcn.m_args.size()); + m_out.write_count(fcn.m_args.size()); for(const auto& a : fcn.m_args) serialise(a.second); - write_bool(fcn.m_variadic); + m_out.write_bool(fcn.m_variadic); serialise(fcn.m_return); DEBUG("m_args = " << fcn.m_args); @@ -782,7 +694,7 @@ namespace { { TRACE_FUNCTION_F("_static:"); - write_bool(item.m_is_mut); + m_out.write_bool(item.m_is_mut); serialise(item.m_type); // NOTE: Omit the rest, not generic and emitted as part of the image. } @@ -796,12 +708,12 @@ namespace { void serialise(const ::HIR::Enum& ta) { serialise_generics(ta.m_params); - write_tag( static_cast<int>(ta.m_repr) ); + m_out.write_tag( static_cast<int>(ta.m_repr) ); serialise_vec( ta.m_variants ); } void serialise(const ::HIR::Enum::Variant& v) { - write_tag( v.tag() ); + m_out.write_tag( v.tag() ); TU_MATCHA( (v), (e), (Unit, ), @@ -823,9 +735,9 @@ namespace { TRACE_FUNCTION; serialise_generics(item.m_params); - write_tag( static_cast<int>(item.m_repr) ); + m_out.write_tag( static_cast<int>(item.m_repr) ); - write_tag( item.m_data.tag() ); + m_out.write_tag( item.m_data.tag() ); TU_MATCHA( (item.m_data), (e), (Unit, ), @@ -841,15 +753,15 @@ namespace { { TRACE_FUNCTION_F("_trait:"); serialise_generics(item.m_params); - //write_string(item.m_lifetime); // TODO: Better type for lifetime + //m_out.write_string(item.m_lifetime); // TODO: Better type for lifetime serialise_vec( item.m_parent_traits ); - write_bool( item.m_is_marker ); + m_out.write_bool( item.m_is_marker ); serialise_strmap( item.m_types ); serialise_strmap( item.m_values ); } void serialise(const ::HIR::TraitValueItem& tvi) { - write_tag( tvi.tag() ); + m_out.write_tag( tvi.tag() ); TU_MATCHA( (tvi), (e), (Constant, DEBUG("Constant"); @@ -867,8 +779,8 @@ namespace { } void serialise(const ::HIR::AssociatedType& at) { - write_bool(at.is_sized); - //write_string(at.m_lifetime_bound); // TODO: better type for lifetime + m_out.write_bool(at.is_sized); + //m_out.write_string(at.m_lifetime_bound); // TODO: better type for lifetime serialise_vec(at.m_trait_bounds); serialise_type(at.m_default); } @@ -877,7 +789,7 @@ namespace { void HIR_Serialise(const ::std::string& filename, const ::HIR::Crate& crate) { - ::std::ofstream out(filename); + ::HIR::serialise::Writer out { filename }; HirSerialiser s { out }; s.serialise_crate(crate); } diff --git a/src/hir/serialise_lowlevel.cpp b/src/hir/serialise_lowlevel.cpp new file mode 100644 index 00000000..a8f69eb2 --- /dev/null +++ b/src/hir/serialise_lowlevel.cpp @@ -0,0 +1,37 @@ +/* + * MRustC - Rust Compiler + * - By John Hodge (Mutabah/thePowersGang) + * + * hir/serialise_lowlevel.cpp + * - HIR (De)Serialisation low-level "protocol" + */ +#include "serialise_lowlevel.hpp" +#include <boost/iostreams/filter/zlib.hpp> + +::HIR::serialise::Writer::Writer(const ::std::string& filename): + m_backing( filename ) +{ + m_os.push( ::boost::iostreams::zlib_compressor() ); + m_os.push( m_backing ); +} + +void ::HIR::serialise::Writer::write(const void* buf, size_t len) +{ + m_os.write(reinterpret_cast<const char*>(buf), len); +} + + +::HIR::serialise::Reader::Reader(const ::std::string& filename): + m_backing( filename ) +{ + m_is.push( ::boost::iostreams::zlib_decompressor() ); + m_is.push( m_backing ); +} + +void ::HIR::serialise::Reader::read(void* buf, size_t len) +{ + m_is.read(reinterpret_cast<char*>(buf), len); + if( !m_is ) { + throw ""; + } +} diff --git a/src/hir/serialise_lowlevel.hpp b/src/hir/serialise_lowlevel.hpp new file mode 100644 index 00000000..34464683 --- /dev/null +++ b/src/hir/serialise_lowlevel.hpp @@ -0,0 +1,247 @@ +/* + * MRustC - Rust Compiler + * - By John Hodge (Mutabah/thePowersGang) + * + * hir/serialise_lowlevel.hpp + * - HIR (De)Serialisation low-level "protocol" + */ +#pragma once + +#include <boost/iostreams/filtering_stream.hpp> +#include <fstream> + +namespace HIR { +namespace serialise { + +class Writer +{ + ::std::ofstream m_backing; + ::boost::iostreams::filtering_ostream m_os; +public: + Writer(const ::std::string& path); + Writer(const Writer&) = delete; + Writer(Writer&&) = delete; + + void write(const void* data, size_t count); + + void write_u8(uint8_t v) { + write(reinterpret_cast<const char*>(&v), 1); + } + void write_u16(uint16_t v) { + uint8_t buf[] = { static_cast<uint8_t>(v & 0xFF), static_cast<uint8_t>(v >> 8) }; + this->write(buf, 2); + } + void write_u32(uint32_t v) { + uint8_t buf[] = { + static_cast<uint8_t>(v & 0xFF), static_cast<uint8_t>(v >> 8), + static_cast<uint8_t>(v >> 16), static_cast<uint8_t>(v >> 24) }; + this->write(buf, 4); + } + void write_u64(uint64_t v) { + uint8_t buf[] = { + static_cast<uint8_t>(v & 0xFF), static_cast<uint8_t>(v >> 8), static_cast<uint8_t>(v >> 16), static_cast<uint8_t>(v >> 24), + static_cast<uint8_t>(v >> 32), static_cast<uint8_t>(v >> 40), static_cast<uint8_t>(v >> 48), static_cast<uint8_t>(v >> 56) + }; + this->write(buf, 8); + } + // Variable-length encoded u64 (for array sizes) + void write_u64c(uint64_t v) { + if( v < (1<<7) ) { + write_u8(v); + } + else if( v < (1<<(6+16)) ) { + uint8_t buf[] = { + static_cast<uint8_t>(0x80 + (v >> 16)), // 0x80 -- 0xBF + static_cast<uint8_t>(v >> 8), + static_cast<uint8_t>(v & 0xFF) + }; + this->write(buf, sizeof buf); + } + else if( v < (1ul << (5 + 32)) ) { + uint8_t buf[] = { + static_cast<uint8_t>(0xC0 + (v >> 32)), // 0xC0 -- 0xDF + static_cast<uint8_t>(v >> 24), + static_cast<uint8_t>(v >> 16), + static_cast<uint8_t>(v >> 8), + static_cast<uint8_t>(v) + }; + this->write(buf, sizeof buf); + } + else { + uint8_t buf[] = { + 0xFF, + static_cast<uint8_t>(v & 0xFF), static_cast<uint8_t>(v >> 8), static_cast<uint8_t>(v >> 16), static_cast<uint8_t>(v >> 24), + static_cast<uint8_t>(v >> 32), static_cast<uint8_t>(v >> 40), static_cast<uint8_t>(v >> 48), static_cast<uint8_t>(v >> 56) + }; + this->write(buf, sizeof buf); + } + } + void write_i64c(int64_t v) { + // Convert from 2's completement + bool sign = (v < 0); + uint64_t va = (v < 0 ? -v : v); + va <<= 1; + va |= (sign ? 1 : 0); + write_u64c(va); + } + void write_double(double v) { + // - Just raw-writes the double + this->write(&v, sizeof v); + } + void write_tag(unsigned int t) { + assert(t < 256); + write_u8( static_cast<uint8_t>(t) ); + } + void write_count(size_t c) { + //DEBUG("c = " << c); + if(c < 0xFE) { + write_u8( static_cast<uint8_t>(c) ); + } + else if( c == ~0u ) { + write_u8( 0xFF ); + } + else { + assert(c < (1u<<16)); + write_u8( 0xFE ); + write_u16( static_cast<uint16_t>(c) ); + } + } + void write_string(const ::std::string& v) { + if(v.size() < 128) { + write_u8( static_cast<uint8_t>(v.size()) ); + } + else { + assert(v.size() < (1u<<(16+7))); + write_u8( static_cast<uint8_t>(128 + (v.size() >> 16)) ); + write_u16( static_cast<uint16_t>(v.size() & 0xFFFF) ); + } + this->write(v.data(), v.size()); + } + void write_bool(bool v) { + write_u8(v ? 0xFF : 0x00); + } +}; + + +class Reader +{ + ::std::ifstream m_backing; + ::boost::iostreams::filtering_istream m_is; +public: + Reader(const ::std::string& path); + Reader(const Writer&) = delete; + Reader(Writer&&) = delete; + + void read(void* dst, size_t count); + + uint8_t read_u8() { + uint8_t v; + read(&v, sizeof v); + return v; + } + uint16_t read_u16() { + uint8_t buf[2]; + read(buf, sizeof buf); + return static_cast<uint16_t>(buf[0]) | (static_cast<uint16_t>(buf[1]) << 8); + } + uint32_t read_u32() { + uint8_t buf[4]; + read(buf, sizeof buf); + return static_cast<uint32_t>(buf[0]) + | (static_cast<uint32_t>(buf[1]) << 8) + | (static_cast<uint32_t>(buf[2]) << 16) + | (static_cast<uint32_t>(buf[3]) << 24) + ; + } + uint64_t read_u64() { + uint8_t buf[8]; + read(buf, sizeof buf); + return static_cast<uint64_t>(buf[0]) + | (static_cast<uint64_t>(buf[1]) << 8) + | (static_cast<uint64_t>(buf[2]) << 16) + | (static_cast<uint64_t>(buf[3]) << 24) + | (static_cast<uint64_t>(buf[4]) << 32) + | (static_cast<uint64_t>(buf[5]) << 40) + | (static_cast<uint64_t>(buf[6]) << 48) + | (static_cast<uint64_t>(buf[7]) << 56) + ; + } + // Variable-length encoded u64 (for array sizes) + uint64_t read_u64c() { + auto v = read_u8(); + if( v < (1<<7) ) { + return static_cast<uint64_t>(v); + } + else if( v < 0xC0 ) { + uint64_t rv = static_cast<uint64_t>(v & 0x3F) << 16; + rv |= static_cast<uint64_t>(read_u8()) << 8; + rv |= static_cast<uint64_t>(read_u8()); + return rv; + } + else if( v < 0xFF ) { + uint64_t rv = static_cast<uint64_t>(v & 0x3F) << 32; + rv |= static_cast<uint64_t>(read_u8()) << 24; + rv |= static_cast<uint64_t>(read_u8()) << 16; + rv |= static_cast<uint64_t>(read_u8()) << 8; + rv |= static_cast<uint64_t>(read_u8()); + return rv; + } + else { + return read_u64(); + } + } + int64_t read_i64c() { + uint64_t va = read_u64c(); + bool sign = (va & 0x1) != 0; + va >>= 1; + + if( va == 0 && sign ) { + return INT64_MIN; + } + else if( sign ) { + return -static_cast<int64_t>(va); + } + else { + return -static_cast<uint64_t>(va); + } + } + double read_double() { + double v; + read(reinterpret_cast<char*>(&v), sizeof v); + return v; + } + unsigned int read_tag() { + return static_cast<unsigned int>( read_u8() ); + } + size_t read_count() { + auto v = read_u8(); + if( v < 0xFE ) { + return v; + } + else if( v == 0xFE ) { + return read_u16( ); + } + else /*if( v == 0xFF )*/ { + return ~0u; + } + } + ::std::string read_string() { + size_t len = read_u8(); + if( len < 128 ) { + } + else { + len = (len & 0x7F) << 16; + len |= read_u16(); + } + ::std::string rv(len, '\0'); + read( const_cast<char*>(rv.data()), len); + return rv; + } + bool read_bool() { + return read_u8() != 0x00; + } +}; + +} // namespace serialise +} // namespace HIR + |