/* * MRustC - Rust Compiler * - By John Hodge (Mutabah/thePowersGang) * * hir/serialise.cpp * - HIR (De)Serialisation for crate metadata */ #include "hir.hpp" #include "main_bindings.hpp" namespace { class HirSerialiser { ::std::ostream& m_os; public: HirSerialiser(::std::ostream& os): m_os(os) {} void write_u8(uint8_t v) { m_os.write(reinterpret_cast(&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_tag(unsigned int t) { assert(t < 256); write_u8( static_cast(t) ); } void write_count(size_t c) { DEBUG("c = " << c); if(c < 0xFE) { write_u8( static_cast(c) ); } else if( c == ~0u ) { write_u8( 0xFF ); } else { assert(c < (1u<<16)); write_u8( 0xFE ); write_u16( static_cast(c) ); } } void write_string(const ::std::string& v) { if(v.size() < 128) { write_u8( static_cast(v.size()) ); } else { assert(v.size() < (1u<<(16+7))); write_u16( static_cast(128 + (v.size() >> 16)) ); write_u16( static_cast(v.size() & 0xFFFF) ); } m_os.write(v.data(), v.size()); } void write_bool(bool v) { write_u8(v ? 0xFF : 0x00); } template void serialise_strmap(const ::std::map< ::std::string,V>& map) { write_count(map.size()); for(const auto& v : map) { write_string(v.first); serialise(v.second); } } template void serialise_strmap(const ::std::unordered_map< ::std::string,V>& map) { write_count(map.size()); for(const auto& v : map) { write_string(v.first); serialise(v.second); } } template void serialise_vec(const ::std::vector& vec) { write_count(vec.size()); for(const auto& i : vec) serialise(i); } template void serialise(const ::HIR::VisEnt& e) { write_bool(e.is_public); serialise(e.ent); } template void serialise(const ::std::unique_ptr& e) { serialise(*e); } void serialise_type(const ::HIR::TypeRef& ty) { write_tag( ty.m_data.tag() ); TU_MATCHA( (ty.m_data), (e), (Infer, // BAAD ), (Diverge, ), (Primitive, write_tag( static_cast(e) ); ), (Path, serialise_path(e.path); ), (Generic, write_string(e.name); write_u16(e.binding); ), (TraitObject, serialise_traitpath(e.m_trait); 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 ), (Array, assert(e.size_val != ~0u); serialise_type(*e.inner); write_u64c(e.size_val); ), (Slice, serialise_type(*e.inner); ), (Tuple, write_count(e.size()); for(const auto& st : e) serialise_type(st); ), (Borrow, write_tag(static_cast(e.type)); serialise_type(*e.inner); ), (Pointer, write_tag(static_cast(e.type)); serialise_type(*e.inner); ), (Function, write_bool(e.is_unsafe); write_string(e.m_abi); serialise_type(*e.m_rettype); serialise_vec(e.m_arg_types); ), (Closure, throw ""; ) ) } void serialise_simplepath(const ::HIR::SimplePath& path) { TRACE_FUNCTION_F("path="<(pe.type) ); } void serialise(const ::MacroRulesArm& arm) { serialise_vec(arm.m_param_names); serialise_vec(arm.m_contents); } void serialise(const ::MacroExpansionEnt& ent) { TU_MATCHA( (ent), (e), (Token, write_tag(0); serialise(e); ), (NamedValue, DEBUG("NamedValue " << e); write_tag(1); write_u8(e >> 24); write_count(e & 0x00FFFFFF); ), (Loop, write_tag(2); serialise_vec(e.entries); serialise(e.joiner); // ::std::set write_count(e.variables.size()); for(const auto& var : e.variables) write_count(var); ) ) } void serialise(const ::Token& tok) { // TODO write_tag(tok.type()); } void serialise(const ::HIR::ExprPtr& exp) { // Write out MIR. // TODO } void serialise(const ::HIR::TypeItem& item) { TU_MATCHA( (item), (e), (Import, write_tag(0); serialise_simplepath(e); ), (Module, write_tag(1); serialise_module(e); ), (TypeAlias, write_tag(2); serialise(e); ), (Enum, write_tag(2); serialise(e); ), (Struct, write_tag(3); serialise(e); ), (Trait, write_tag(4); serialise(e); ) ) } void serialise(const ::HIR::ValueItem& item) { TU_MATCHA( (item), (e), (Import, write_tag(0); serialise_simplepath(e); ), (Constant, write_tag(1); serialise(e); ), (Static, write_tag(2); serialise(e); ), (StructConstant, write_tag(3); serialise_simplepath(e.ty); ), (Function, write_tag(4); serialise(e); ), (StructConstructor, write_tag(5); serialise_simplepath(e.ty); ) ) } // - Value items void serialise(const ::HIR::Function& fcn) { // TODO } void serialise(const ::HIR::Constant& con) { // TODO } void serialise(const ::HIR::Static& con) { // TODO } // - Type items void serialise(const ::HIR::TypeAlias& ta) { // TODO } void serialise(const ::HIR::Enum& ta) { // TODO } void serialise(const ::HIR::Struct& ta) { // TODO } void serialise(const ::HIR::Trait& ta) { // TODO } }; } void HIR_Serialise(const ::std::string& filename, const ::HIR::Crate& crate) { ::std::ofstream out(filename); HirSerialiser s { out }; s.serialise_crate(crate); }