From 6a56c4c2fb5be1fc6dae05da6bff936ce75553de Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 12 May 2018 19:03:55 +0800 Subject: Codegen MMIR - Emit vtables (only partially complete) --- src/trans/codegen_mmir.cpp | 142 +++++++++++++++++++++++++++++++++------------ 1 file changed, 104 insertions(+), 38 deletions(-) (limited to 'src/trans/codegen_mmir.cpp') diff --git a/src/trans/codegen_mmir.cpp b/src/trans/codegen_mmir.cpp index faa3598d..db538842 100644 --- a/src/trans/codegen_mmir.cpp +++ b/src/trans/codegen_mmir.cpp @@ -605,47 +605,50 @@ namespace const ::HIR::Path* p; ::std::string bytes; }; + void emit_str_byte(uint8_t b) { + if( b == 0 ) { + m_of << "\\0"; + } + else if( b == '\\' ) { + m_of << "\\\\"; + } + else if( b == '"' ) { + m_of << "\\\""; + } + else if( ' ' <= b && b <= 'z' && b != '\\' ) { + m_of << b; + } + else if( b < 16 ) { + m_of << "\\x0" << ::std::hex << int(b) << ::std::dec; + } + else { + m_of << "\\x" << ::std::hex << int(b) << ::std::dec; + } + } + void emit_str_u32(uint32_t v) { + emit_str_byte(v & 0xFF); + emit_str_byte(v >> 8); + emit_str_byte(v >> 16); + emit_str_byte(v >> 24); + } + void emit_str_usize(uint64_t v) { + if( Target_GetCurSpec().m_arch.m_pointer_bits == 64 ) { + emit_str_u32(v ); + emit_str_u32(v >> 32); + } + else if( Target_GetCurSpec().m_arch.m_pointer_bits == 64 ) { + emit_str_u32(v ); + } + else { + emit_str_u32(v ); + } + } void emit_literal_as_bytes(const ::HIR::Literal& lit, const ::HIR::TypeRef& ty, ::std::vector& out_relocations, size_t base_ofs) { TRACE_FUNCTION_F(lit << ", " << ty); - auto putb = [&](uint8_t b) { - if( b == 0 ) { - m_of << "\\0"; - } - else if( b == '\\' ) { - m_of << "\\\\"; - } - else if( b == '"' ) { - m_of << "\\\""; - } - else if( ' ' <= b && b <= 'z' && b != '\\' ) { - m_of << b; - } - else if( b < 16 ) { - m_of << "\\x0" << ::std::hex << int(b) << ::std::dec; - } - else { - m_of << "\\x" << ::std::hex << int(b) << ::std::dec; - } - }; - auto putu32 = [&](uint32_t v) { - putb(v & 0xFF); - putb(v >> 8); - putb(v >> 16); - putb(v >> 24); - }; - auto putsize = [&](uint64_t v) { - if( Target_GetCurSpec().m_arch.m_pointer_bits == 64 ) { - putu32(v ); - putu32(v >> 32); - } - else if( Target_GetCurSpec().m_arch.m_pointer_bits == 64 ) { - putu32(v ); - } - else { - putu32(v ); - } - }; + auto putb = [&](uint8_t b) { emit_str_byte(b); }; + auto putu32 = [&](uint32_t v) { emit_str_u32(v); }; + auto putsize = [&](uint64_t v) { emit_str_usize(v); }; switch(ty.m_data.tag()) { case ::HIR::TypeRef::Data::TAGDEAD: throw ""; @@ -877,6 +880,69 @@ namespace m_mir_res = nullptr; } + void emit_vtable(const ::HIR::Path& p, const ::HIR::Trait& trait) override + { + ::MIR::Function empty_fcn; + ::MIR::TypeResolve top_mir_res { sp, m_resolve, FMT_CB(ss, ss << "vtable " << p;), ::HIR::TypeRef(), {}, empty_fcn }; + + const size_t ptr_size = Target_GetCurSpec().m_arch.m_pointer_bits / 8; + const auto& trait_path = p.m_data.as_UfcsKnown().trait; + const auto& type = *p.m_data.as_UfcsKnown().type; + + ::HIR::TypeRef vtable_ty; + { + auto vtable_sp = trait_path.m_path; + vtable_sp.m_components.back() += "#vtable"; + auto vtable_params = trait_path.m_params.clone(); + for(const auto& ty : trait.m_type_indexes) { + auto aty = ::HIR::TypeRef( ::HIR::Path( type.clone(), trait_path.clone(), ty.first ) ); + m_resolve.expand_associated_types(sp, aty); + vtable_params.m_types.push_back( mv$(aty) ); + } + const auto& vtable_ref = m_crate.get_struct_by_path(sp, vtable_sp); + vtable_ty = ::HIR::TypeRef( ::HIR::GenericPath(mv$(vtable_sp), mv$(vtable_params)), &vtable_ref ); + } + + size_t size, align; + MIR_ASSERT(*m_mir_res, Target_GetSizeAndAlignOf(sp, m_resolve, type, size, align), "Unexpected generic? " << type); + m_of << "static " << p << ": " << vtable_ty << " = \""; + // - Data + // Drop + emit_str_usize(0); + // Align + emit_str_usize(align); + // Size + emit_str_usize(size); + // Methods + for(unsigned int i = 0; i < trait.m_value_indexes.size(); i ++ ) + { + emit_str_usize(0); + } + m_of << "\" {"; + + // - Relocations + auto monomorph_cb_trait = monomorphise_type_get_cb(sp, &type, &trait_path.m_params, nullptr); + // Drop + // - TODO: Some types don't have drop glue + m_of << "@0+" << ptr_size << " = " << ::HIR::Path(type.clone(), "drop_glue#") << ", "; + // Methods + for(unsigned int i = 0; i < trait.m_value_indexes.size(); i ++ ) + { + // Find the corresponding vtable entry + for(const auto& m : trait.m_value_indexes) + { + if( m.second.first != 3+i ) + continue ; + + //MIR_ASSERT(*m_mir_res, tr.m_values.at(m.first).is_Function(), "TODO: Handle generating vtables with non-function items"); + DEBUG("- " << m.second.first << " = " << m.second.second << " :: " << m.first); + + auto gpath = monomorphise_genericpath_with(sp, m.second.second, monomorph_cb_trait, false); + m_of << "@" << (3 + i) * ptr_size << "+" << ptr_size << " = " << ::HIR::Path(type.clone(), mv$(gpath), m.first) << ", "; + } + } + m_of << "};\n"; + } void emit_function_ext(const ::HIR::Path& p, const ::HIR::Function& item, const Trans_Params& params) override { ::MIR::Function empty_fcn; -- cgit v1.2.3 From d14ab6eae9abd88ab4e26d7c7fd2f91d48d1a10f Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 12 May 2018 21:06:49 +0800 Subject: Standalone MIRI - TLS and some other messing about --- src/trans/codegen_mmir.cpp | 2 +- tools/standalone_miri/main.cpp | 144 +++++++++++++++++++++++++++++++++------- tools/standalone_miri/value.cpp | 53 ++++++++++++++- tools/standalone_miri/value.hpp | 86 +++++++++++++++--------- 4 files changed, 228 insertions(+), 57 deletions(-) (limited to 'src/trans/codegen_mmir.cpp') diff --git a/src/trans/codegen_mmir.cpp b/src/trans/codegen_mmir.cpp index db538842..19574814 100644 --- a/src/trans/codegen_mmir.cpp +++ b/src/trans/codegen_mmir.cpp @@ -157,7 +157,7 @@ namespace { if( is_executable ) { - m_of << "fn ::main#(i32, *const *const i8): i32 {\n"; + m_of << "fn ::main#(isize, *const *const i8): i32 {\n"; auto c_start_path = m_resolve.m_crate.get_lang_item_path_opt("mrustc-start"); if( c_start_path == ::HIR::SimplePath() ) { diff --git a/tools/standalone_miri/main.cpp b/tools/standalone_miri/main.cpp index b7f62252..1b33087a 100644 --- a/tools/standalone_miri/main.cpp +++ b/tools/standalone_miri/main.cpp @@ -19,9 +19,31 @@ struct ProgramOptions int parse(int argc, const char* argv[]); }; -Value MIRI_Invoke(ModuleTree& modtree, ::HIR::Path path, ::std::vector args); -Value MIRI_Invoke_Extern(const ::std::string& link_name, const ::std::string& abi, ::std::vector args); -Value MIRI_Invoke_Intrinsic(ModuleTree& modtree, const ::std::string& name, const ::HIR::PathParams& ty_params, ::std::vector args); +struct ThreadState +{ + static unsigned s_next_tls_key; + unsigned call_stack_depth; + ::std::vector tls_values; + + ThreadState(): + call_stack_depth(0) + { + } + + struct DecOnDrop { + unsigned* p; + ~DecOnDrop() { (*p) --; } + }; + DecOnDrop enter_function() { + this->call_stack_depth ++; + return DecOnDrop { &this->call_stack_depth }; + } +}; +unsigned ThreadState::s_next_tls_key = 1; + +Value MIRI_Invoke(ModuleTree& modtree, ThreadState& thread, ::HIR::Path path, ::std::vector args); +Value MIRI_Invoke_Extern(ThreadState& thread, const ::std::string& link_name, const ::std::string& abi, ::std::vector args); +Value MIRI_Invoke_Intrinsic(ModuleTree& modtree, ThreadState& thread, const ::std::string& name, const ::HIR::PathParams& ty_params, ::std::vector args); int main(int argc, const char* argv[]) { @@ -36,20 +58,21 @@ int main(int argc, const char* argv[]) tree.load_file(opts.infile); - auto val_argc = Value( ::HIR::TypeRef{RawType::I32} ); + auto val_argc = Value( ::HIR::TypeRef{RawType::ISize} ); ::HIR::TypeRef argv_ty { RawType::I8 }; argv_ty.wrappers.push_back(TypeWrapper { TypeWrapper::Ty::Pointer, 0 }); argv_ty.wrappers.push_back(TypeWrapper { TypeWrapper::Ty::Pointer, 0 }); auto val_argv = Value(argv_ty); - val_argc.write_bytes(0, "\0\0\0", 4); + val_argc.write_bytes(0, "\0\0\0\0\0\0\0", 8); val_argv.write_bytes(0, "\0\0\0\0\0\0\0", argv_ty.get_size()); try { + ThreadState ts; ::std::vector args; args.push_back(::std::move(val_argc)); args.push_back(::std::move(val_argv)); - auto rv = MIRI_Invoke( tree, tree.find_lang_item("start"), ::std::move(args) ); + auto rv = MIRI_Invoke( tree, ts, tree.find_lang_item("start"), ::std::move(args) ); ::std::cout << rv << ::std::endl; } catch(const DebugExceptionTodo& /*e*/) @@ -291,7 +314,7 @@ struct Ops { namespace { - void drop_value(ModuleTree& modtree, Value ptr, const ::HIR::TypeRef& ty) + void drop_value(ModuleTree& modtree, ThreadState& thread, Value ptr, const ::HIR::TypeRef& ty) { if( ty.wrappers.empty() ) { @@ -301,7 +324,7 @@ namespace { LOG_DEBUG("Drop - " << ty); - MIRI_Invoke(modtree, ty.composite_type->drop_glue, { ptr }); + MIRI_Invoke(modtree, thread, ty.composite_type->drop_glue, { ptr }); } else { @@ -338,7 +361,7 @@ namespace } -Value MIRI_Invoke(ModuleTree& modtree, ::HIR::Path path, ::std::vector args) +Value MIRI_Invoke(ModuleTree& modtree, ThreadState& thread, ::HIR::Path path, ::std::vector args) { Value ret; @@ -373,17 +396,22 @@ Value MIRI_Invoke(ModuleTree& modtree, ::HIR::Path path, ::std::vector ar if( fcn.external.link_name != "" ) { // External function! - ret = MIRI_Invoke_Extern(fcn.external.link_name, fcn.external.link_abi, ::std::move(args)); + ret = MIRI_Invoke_Extern(thread, fcn.external.link_name, fcn.external.link_abi, ::std::move(args)); LOG_DEBUG(path << " = " << ret); return ret; } - // TODO: Recursion limit. + // Recursion limit. + if( thread.call_stack_depth > 40 ) { + LOG_ERROR("Recursion limit exceeded"); + } + auto _ = thread.enter_function(); TRACE_FUNCTION_R(path, path << " = " << ret); for(size_t i = 0; i < args.size(); i ++) { LOG_DEBUG("- Argument(" << i << ") = " << args[i]); + // TODO: Check argument sizes against prototype? } ret = Value(fcn.ret_ty == RawType::Unreachable ? ::HIR::TypeRef() : fcn.ret_ty); @@ -489,7 +517,7 @@ Value MIRI_Invoke(ModuleTree& modtree, ::HIR::Path path, ::std::vector ar ::HIR::TypeRef ptr_ty; auto val = get_value_and_type(*e.val, ptr_ty); ty = ptr_ty.get_inner(); - LOG_DEBUG("val = " << val); + LOG_DEBUG("val = " << val << ", (inner) ty=" << ty); LOG_ASSERT(val.m_size >= POINTER_SIZE, "Deref of a value that doesn't fit a pointer - " << ty); size_t ofs = val.read_usize(0); @@ -500,7 +528,7 @@ Value MIRI_Invoke(ModuleTree& modtree, ::HIR::Path path, ::std::vector ar LOG_ASSERT(val_alloc.is_alloc(), "Deref of a value with a non-data allocation"); LOG_TRACE("Deref " << val_alloc.alloc() << " + " << ofs << " to give value of type " << ty); auto alloc = val_alloc.alloc().get_relocation(val.m_offset); - LOG_ASSERT(alloc, "Deref of a value with no relocation"); + // NOTE: No alloc can happen when dereferencing a zero-sized pointer if( alloc.is_alloc() ) { LOG_DEBUG("> " << lv << " alloc=" << alloc.alloc()); @@ -517,15 +545,26 @@ Value MIRI_Invoke(ModuleTree& modtree, ::HIR::Path path, ::std::vector ar meta_val = ::std::make_shared( val.read_value(POINTER_SIZE, meta_size) ); // TODO: Get a more sane size from the metadata - LOG_DEBUG("> Meta " << *meta_val << ", size = " << alloc.get_size() << " - " << ofs); - size = alloc.get_size() - ofs; + if( alloc ) + { + LOG_DEBUG("> Meta " << *meta_val << ", size = " << alloc.get_size() << " - " << ofs); + size = alloc.get_size() - ofs; + } + else + { + size = 0; + } } else { LOG_ASSERT(val.m_size == POINTER_SIZE, "Deref of a value that isn't a pointer-sized value (size=" << val.m_size << ") - " << val << ": " << ptr_ty); size = ty.get_size(); + if( !alloc ) { + LOG_ERROR("Deref of a value with no relocation - " << val); + } } + LOG_DEBUG("alloc=" << alloc << ", ofs=" << ofs << ", size=" << size); auto rv = ValueRef(::std::move(alloc), ofs, size); rv.m_metadata = ::std::move(meta_val); return rv; @@ -709,7 +748,7 @@ Value MIRI_Invoke(ModuleTree& modtree, ::HIR::Path path, ::std::vector ar ::HIR::TypeRef src_ty; ValueRef src_base_value = state.get_value_and_type(re.val, src_ty); auto alloc = src_base_value.m_alloc; - if( !alloc ) + if( !alloc && src_base_value.m_value ) { if( !src_base_value.m_value->allocation ) { @@ -1422,7 +1461,7 @@ Value MIRI_Invoke(ModuleTree& modtree, ::HIR::Path path, ::std::vector ar ptr_val.write_usize(0, ofs); ptr_val.allocation.alloc().relocations.push_back(Relocation { 0, ::std::move(alloc) }); - drop_value(modtree, ptr_val, ty); + drop_value(modtree, thread, ptr_val, ty); // TODO: Clear validity on the entire inner value. //alloc.mark_as_freed(); } @@ -1515,11 +1554,12 @@ Value MIRI_Invoke(ModuleTree& modtree, ::HIR::Path path, ::std::vector ar for(const auto& a : te.args) { sub_args.push_back( state.param_to_value(a) ); + LOG_DEBUG("#" << (sub_args.size() - 1) << " " << sub_args.back()); } if( te.fcn.is_Intrinsic() ) { const auto& fe = te.fcn.as_Intrinsic(); - state.write_lvalue(te.ret_val, MIRI_Invoke_Intrinsic(modtree, fe.name, fe.params, ::std::move(sub_args))); + state.write_lvalue(te.ret_val, MIRI_Invoke_Intrinsic(modtree, thread, fe.name, fe.params, ::std::move(sub_args))); } else { @@ -1534,7 +1574,7 @@ Value MIRI_Invoke(ModuleTree& modtree, ::HIR::Path path, ::std::vector ar LOG_DEBUG("> Indirect call " << v); // TODO: Assert type // TODO: Assert offset/content. - assert(v.read_usize(v.m_offset) == 0); + assert(v.read_usize(0) == 0); auto& alloc_ptr = v.m_alloc ? v.m_alloc : v.m_value->allocation; LOG_ASSERT(alloc_ptr, "Calling value that can't be a pointer (no allocation)"); fcn_alloc_ptr = alloc_ptr.alloc().get_relocation(v.m_offset); @@ -1545,7 +1585,7 @@ Value MIRI_Invoke(ModuleTree& modtree, ::HIR::Path path, ::std::vector ar } LOG_DEBUG("Call " << *fcn_p); - auto v = MIRI_Invoke(modtree, *fcn_p, ::std::move(sub_args)); + auto v = MIRI_Invoke(modtree, thread, *fcn_p, ::std::move(sub_args)); LOG_DEBUG(te.ret_val << " = " << v << " (resume " << path << ")"); state.write_lvalue(te.ret_val, ::std::move(v)); } @@ -1562,7 +1602,7 @@ extern "C" { long sysconf(int); } -Value MIRI_Invoke_Extern(const ::std::string& link_name, const ::std::string& abi, ::std::vector args) +Value MIRI_Invoke_Extern(ThreadState& thread, const ::std::string& link_name, const ::std::string& abi, ::std::vector args) { if( link_name == "__rust_allocate" ) { @@ -1712,7 +1752,45 @@ Value MIRI_Invoke_Extern(const ::std::string& link_name, const ::std::string& ab rv.write_i32(0, 0); return rv; } - else if( link_name == "pthread_key_create" || link_name == "pthread_key_delete" ) + else if( link_name == "pthread_key_create" ) + { + size_t size; + auto key_ref = args.at(0).read_pointer_valref_mut(0, 4); + + auto key = ThreadState::s_next_tls_key ++; + key_ref.m_alloc.alloc().write_u32( key_ref.m_offset, key ); + + auto rv = Value(::HIR::TypeRef(RawType::I32)); + rv.write_i32(0, 0); + return rv; + } + else if( link_name == "pthread_getspecific" ) + { + auto key = args.at(0).read_u32(0); + + // Get a pointer-sized value from storage + uint64_t v = key < thread.tls_values.size() ? thread.tls_values[key] : 0; + + auto rv = Value(::HIR::TypeRef(RawType::USize)); + rv.write_usize(0, v); + return rv; + } + else if( link_name == "pthread_setspecific" ) + { + auto key = args.at(0).read_u32(0); + auto v = args.at(1).read_u64(0); + + // Get a pointer-sized value from storage + if( key >= thread.tls_values.size() ) { + thread.tls_values.resize(key+1); + } + thread.tls_values[key] = v; + + auto rv = Value(::HIR::TypeRef(RawType::I32)); + rv.write_i32(0, 0); + return rv; + } + else if( link_name == "pthread_key_delete" ) { auto rv = Value(::HIR::TypeRef(RawType::I32)); rv.write_i32(0, 0); @@ -1758,7 +1836,7 @@ Value MIRI_Invoke_Extern(const ::std::string& link_name, const ::std::string& ab } throw ""; } -Value MIRI_Invoke_Intrinsic(ModuleTree& modtree, const ::std::string& name, const ::HIR::PathParams& ty_params, ::std::vector args) +Value MIRI_Invoke_Intrinsic(ModuleTree& modtree, ThreadState& thread, const ::std::string& name, const ::HIR::PathParams& ty_params, ::std::vector args) { Value rv; TRACE_FUNCTION_R(name, rv); @@ -1798,6 +1876,24 @@ Value MIRI_Invoke_Intrinsic(ModuleTree& modtree, const ::std::string& name, cons const auto& ty = ty_params.tys.at(0); rv = alloc.alloc().read_value(ofs, ty.get_size()); } + else if( name == "atomic_cxchg" ) + { + const auto& ty_T = ty_params.tys.at(0); + // TODO: Get a ValueRef to the target location + auto data_ref = args.at(0).read_pointer_valref_mut(0, ty_T.get_size()); + const auto& old_v = args.at(1); + const auto& new_v = args.at(1); + rv = Value::with_size( ty_T.get_size() + 1, false ); + rv.write_value(0, data_ref.read_value(0, old_v.size())); + if( data_ref.compare(old_v.data_ptr(), old_v.size()) == 0 ) { + data_ref.m_alloc.alloc().write_value( data_ref.m_offset, new_v ); + rv.write_u8( old_v.size(), 1 ); + } + else { + rv.write_u8( old_v.size(), 0 ); + } + return rv; + } else if( name == "transmute" ) { // Transmute requires the same size, so just copying the value works @@ -1919,7 +2015,7 @@ Value MIRI_Invoke_Intrinsic(ModuleTree& modtree, const ::std::string& name, cons auto ptr = val.read_value(0, POINTER_SIZE);; for(size_t i = 0; i < item_count; i ++) { - drop_value(modtree, ptr, ity); + drop_value(modtree, thread, ptr, ity); ptr.write_usize(0, ptr.read_usize(0) + item_size); } } diff --git a/tools/standalone_miri/value.cpp b/tools/standalone_miri/value.cpp index af462e40..468425e9 100644 --- a/tools/standalone_miri/value.cpp +++ b/tools/standalone_miri/value.cpp @@ -211,6 +211,20 @@ void* ValueCommon::read_pointer_unsafe(size_t rd_ofs, size_t req_valid, size_t& throw ""; } } +ValueRef ValueCommon::read_pointer_valref_mut(size_t rd_ofs, size_t size) +{ + auto ofs = read_usize(rd_ofs); + auto reloc = get_relocation(rd_ofs); + if( !reloc ) + { + LOG_ERROR("Getting ValRef to null pointer (no relocation)"); + } + else + { + // TODO: Validate size + return ValueRef(reloc, ofs, size); + } +} void Allocation::resize(size_t new_size) @@ -231,7 +245,7 @@ void Allocation::check_bytes_valid(size_t ofs, size_t size) const { if( !(this->mask[i/8] & (1 << i%8)) ) { - ::std::cerr << "ERROR: Invalid bytes in value" << ::std::endl; + LOG_ERROR("Invalid bytes in value"); throw "ERROR"; } } @@ -749,7 +763,7 @@ extern ::std::ostream& operator<<(::std::ostream& os, const ValueRef& v) { case AllocationPtr::Ty::Allocation: { const auto& alloc = alloc_ptr.alloc(); - + auto flags = os.flags(); os << ::std::hex; for(size_t i = v.m_offset; i < ::std::min(alloc.size(), v.m_offset + v.m_size); i++) @@ -823,6 +837,41 @@ extern ::std::ostream& operator<<(::std::ostream& os, const ValueRef& v) return os; } +Value ValueRef::read_value(size_t ofs, size_t size) const +{ + if( size == 0 ) + return Value(); + if( !(ofs < m_size && size <= m_size && ofs + size <= m_size) ) { + LOG_ERROR("Read exceeds bounds, " << ofs << " + " << size << " > " << m_size << " - from " << *this); + } + if( m_alloc ) { + switch(m_alloc.get_ty()) + { + case AllocationPtr::Ty::Allocation: + return m_alloc.alloc().read_value(m_offset + ofs, size); + case AllocationPtr::Ty::StdString: { + auto rv = Value::with_size(size, false); + //ASSERT_BUG(ofs <= m_alloc.str().size(), ""); + //ASSERT_BUG(size <= m_alloc.str().size(), ""); + //ASSERT_BUG(ofs+size <= m_alloc.str().size(), ""); + assert(m_offset+ofs <= m_alloc.str().size() && size <= m_alloc.str().size() && m_offset+ofs+size <= m_alloc.str().size()); + rv.write_bytes(0, m_alloc.str().data() + m_offset + ofs, size); + return rv; + } + default: + //ASSERT_BUG(m_alloc.is_alloc(), "read_value on non-data backed Value - " << ); + throw "TODO"; + } + } + else { + return m_value->read_value(m_offset + ofs, size); + } +} +bool ValueRef::compare(const void* other, size_t other_len) const +{ + check_bytes_valid(0, other_len); + return ::std::memcmp(data_ptr(), other, other_len) == 0; +} uint64_t ValueRef::read_usize(size_t ofs) const { uint64_t v = 0; diff --git a/tools/standalone_miri/value.hpp b/tools/standalone_miri/value.hpp index 95f8b508..2b3bd4e6 100644 --- a/tools/standalone_miri/value.hpp +++ b/tools/standalone_miri/value.hpp @@ -15,6 +15,7 @@ namespace HIR { } class Allocation; struct Value; +struct ValueRef; struct FFIPointer { @@ -160,6 +161,8 @@ struct ValueCommon //LOG_FATAL("Attempting to get an uninit pointer to immutable data"); return rv; } + /// Read a pointer and return a ValueRef to it (mutable data) + ValueRef read_pointer_valref_mut(size_t rd_ofs, size_t size); }; class Allocation: @@ -223,6 +226,8 @@ struct Value: void create_allocation(); size_t size() const { return allocation ? allocation.alloc().size() : direct_data.size; } + const uint8_t* data_ptr() const { return allocation ? allocation.alloc().data_ptr() : direct_data.data; } + uint8_t* data_ptr() { return allocation ? allocation.alloc().data_ptr() : direct_data.data; } AllocationPtr get_relocation(size_t ofs) const override { if( this->allocation && this->allocation.is_alloc() ) @@ -259,20 +264,23 @@ struct ValueRef m_offset(ofs), m_size(size) { - switch(m_alloc.get_ty()) + if( m_alloc ) { - case AllocationPtr::Ty::Allocation: - assert(ofs < m_alloc.alloc().size()); - assert(size <= m_alloc.alloc().size()); - assert(ofs+size <= m_alloc.alloc().size()); - break; - case AllocationPtr::Ty::StdString: - assert(ofs < m_alloc.str().size()); - assert(size <= m_alloc.str().size()); - assert(ofs+size <= m_alloc.str().size()); - break; - default: - throw "TODO"; + switch(m_alloc.get_ty()) + { + case AllocationPtr::Ty::Allocation: + assert(ofs < m_alloc.alloc().size()); + assert(size <= m_alloc.alloc().size()); + assert(ofs+size <= m_alloc.alloc().size()); + break; + case AllocationPtr::Ty::StdString: + assert(ofs < m_alloc.str().size()); + assert(size <= m_alloc.str().size()); + assert(ofs+size <= m_alloc.str().size()); + break; + default: + throw "TODO"; + } } } ValueRef(Value& val): @@ -294,7 +302,7 @@ struct ValueRef else return AllocationPtr(); } - else if( m_value->allocation ) + else if( m_value && m_value->allocation ) { if( m_value->allocation.is_alloc() ) return m_value->allocation.alloc().get_relocation(ofs); @@ -306,9 +314,30 @@ struct ValueRef return AllocationPtr(); } } - Value read_value(size_t ofs, size_t size) const { + Value read_value(size_t ofs, size_t size) const; + const uint8_t* data_ptr() const { + if( m_alloc ) { + switch(m_alloc.get_ty()) + { + case AllocationPtr::Ty::Allocation: + return m_alloc.alloc().data_ptr() + m_offset; + break; + case AllocationPtr::Ty::StdString: + return reinterpret_cast(m_alloc.str().data() + m_offset); + default: + throw "TODO"; + } + } + else if( m_value ) { + return m_value->data_ptr() + m_offset; + } + else { + return nullptr; + } + } + void read_bytes(size_t ofs, void* dst, size_t size) const { if( size == 0 ) - return Value(); + return ; assert(ofs < m_size); assert(size <= m_size); assert(ofs+size <= m_size); @@ -316,26 +345,22 @@ struct ValueRef switch(m_alloc.get_ty()) { case AllocationPtr::Ty::Allocation: - return m_alloc.alloc().read_value(m_offset + ofs, size); - case AllocationPtr::Ty::StdString: { - auto rv = Value::with_size(size, false); - //ASSERT_BUG(ofs <= m_alloc.str().size(), ""); - //ASSERT_BUG(size <= m_alloc.str().size(), ""); - //ASSERT_BUG(ofs+size <= m_alloc.str().size(), ""); + m_alloc.alloc().read_bytes(m_offset + ofs, dst, size); + break; + case AllocationPtr::Ty::StdString: assert(m_offset+ofs <= m_alloc.str().size() && size <= m_alloc.str().size() && m_offset+ofs+size <= m_alloc.str().size()); - rv.write_bytes(0, m_alloc.str().data() + m_offset + ofs, size); - return rv; - } + ::std::memcpy(dst, m_alloc.str().data() + m_offset + ofs, size); + break; default: //ASSERT_BUG(m_alloc.is_alloc(), "read_value on non-data backed Value - " << ); throw "TODO"; } } else { - return m_value->read_value(m_offset + ofs, size); + m_value->read_bytes(m_offset + ofs, dst, size); } } - void read_bytes(size_t ofs, void* dst, size_t size) const { + void check_bytes_valid(size_t ofs, size_t size) const { if( size == 0 ) return ; assert(ofs < m_size); @@ -345,11 +370,10 @@ struct ValueRef switch(m_alloc.get_ty()) { case AllocationPtr::Ty::Allocation: - m_alloc.alloc().read_bytes(m_offset + ofs, dst, size); + m_alloc.alloc().check_bytes_valid(m_offset + ofs, size); break; case AllocationPtr::Ty::StdString: assert(m_offset+ofs <= m_alloc.str().size() && size <= m_alloc.str().size() && m_offset+ofs+size <= m_alloc.str().size()); - ::std::memcpy(dst, m_alloc.str().data() + m_offset + ofs, size); break; default: //ASSERT_BUG(m_alloc.is_alloc(), "read_value on non-data backed Value - " << ); @@ -357,10 +381,12 @@ struct ValueRef } } else { - m_value->read_bytes(m_offset + ofs, dst, size); + m_value->check_bytes_valid(m_offset + ofs, size); } } + bool compare(const void* other, size_t other_len) const; + // TODO: Figure out how to make this use `ValueCommon` when it can't write. uint8_t read_u8(size_t ofs) const { uint8_t rv; read_bytes(ofs, &rv, 1); return rv; } uint16_t read_u16(size_t ofs) const { uint16_t rv; read_bytes(ofs, &rv, 2); return rv; } -- cgit v1.2.3 From 9aae4d5af2da15c8ff40966bed6faeef7126f7a4 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 13 May 2018 08:25:04 +0800 Subject: Codegen MMIR - Struct constructors --- src/trans/codegen_mmir.cpp | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) (limited to 'src/trans/codegen_mmir.cpp') diff --git a/src/trans/codegen_mmir.cpp b/src/trans/codegen_mmir.cpp index 19574814..dd6f1468 100644 --- a/src/trans/codegen_mmir.cpp +++ b/src/trans/codegen_mmir.cpp @@ -433,6 +433,43 @@ namespace } m_mir_res = nullptr; } + void emit_constructor_struct(const Span& sp, const ::HIR::GenericPath& p, const ::HIR::Struct& item) override + { + TRACE_FUNCTION_F(p); + ::HIR::TypeRef tmp; + auto monomorph = [&](const auto& x)->const auto& { + if( monomorphise_type_needed(x) ) { + tmp = monomorphise_type(sp, item.m_params, p.m_params, x); + m_resolve.expand_associated_types(sp, tmp); + return tmp; + } + else { + return x; + } + }; + // Crate constructor function + const auto& e = item.m_data.as_Tuple(); + m_of << "fn " << p << "("; + for(unsigned int i = 0; i < e.size(); i ++) + { + if(i != 0) + m_of << ", "; + m_of << monomorph(e[i].ent); + } + m_of << "): " << p << " {\n"; + m_of << "\t0: {\n"; + m_of << "\t\tASSIGN RETURN = { "; + for(unsigned int i = 0; i < e.size(); i ++) + { + if(i != 0) + m_of << ", "; + m_of << "arg" << i; + } + m_of << " }: " << p << ";\n"; + m_of << "\t\tRETURN\n"; + m_of << "\t}\n"; + m_of << "}\n"; + } void emit_union(const Span& sp, const ::HIR::GenericPath& p, const ::HIR::Union& item) override { ::MIR::Function empty_fcn; @@ -452,7 +489,7 @@ namespace } for(const auto& e : repr->fields) { - m_of << "\t" << "#" << (&e - repr->fields.data()) << ";\n"; + m_of << "\t" << "#" << (&e - repr->fields.data()) << " =" << (&e - repr->fields.data()) << ";\n"; } m_of << "}\n"; -- cgit v1.2.3 From d526acefc4a2ac90f56b9369615250ba293e959e Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 13 May 2018 17:10:20 +0800 Subject: Codegen MMIR - Fix main return type --- src/trans/codegen_mmir.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src/trans/codegen_mmir.cpp') diff --git a/src/trans/codegen_mmir.cpp b/src/trans/codegen_mmir.cpp index dd6f1468..9755bb8b 100644 --- a/src/trans/codegen_mmir.cpp +++ b/src/trans/codegen_mmir.cpp @@ -157,7 +157,7 @@ namespace { if( is_executable ) { - m_of << "fn ::main#(isize, *const *const i8): i32 {\n"; + m_of << "fn ::main#(isize, *const *const i8): isize {\n"; auto c_start_path = m_resolve.m_crate.get_lang_item_path_opt("mrustc-start"); if( c_start_path == ::HIR::SimplePath() ) { @@ -1018,6 +1018,12 @@ namespace ::MIR::TypeResolve mir_res { sp, m_resolve, FMT_CB(ss, ss << p;), ret_type, arg_types, *code }; m_mir_res = &mir_res; + if( item.m_linkage.name != "" ) + { + // TODO: Save the linkage name. + } + + // - Signature m_of << "fn " << p << "("; for(unsigned int i = 0; i < item.m_args.size(); i ++) { @@ -1025,6 +1031,7 @@ namespace m_of << params.monomorph(m_resolve, item.m_args[i].second); } m_of << "): " << ret_type << " {\n"; + // - Locals for(unsigned int i = 0; i < code->locals.size(); i ++) { DEBUG("var" << i << " : " << code->locals[i]); m_of << "\tlet var" << i << ": " << code->locals[i] << ";\n"; @@ -1033,7 +1040,7 @@ namespace m_of << "\tlet df" << i << " = " << code->drop_flags[i] << ";\n"; } - + for(unsigned int i = 0; i < code->blocks.size(); i ++) { TRACE_FUNCTION_F(p << " bb" << i); -- cgit v1.2.3 From 50ef0034194c2dc1d2fb5730231c8566f405f1f6 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 2 Jun 2018 14:47:19 +0800 Subject: All - Warning cleanup when built with clang --- src/hir_conv/bind.cpp | 4 ++-- src/hir_conv/expand_type.cpp | 4 ++-- src/hir_expand/closures.cpp | 2 +- src/hir_typeck/helpers.hpp | 2 +- src/mir/from_hir.cpp | 4 ++-- src/mir/main_bindings.hpp | 2 +- src/trans/codegen_mmir.cpp | 1 + src/trans/mangling.hpp | 2 +- 8 files changed, 11 insertions(+), 10 deletions(-) (limited to 'src/trans/codegen_mmir.cpp') diff --git a/src/hir_conv/bind.cpp b/src/hir_conv/bind.cpp index f8a06013..5418da85 100644 --- a/src/hir_conv/bind.cpp +++ b/src/hir_conv/bind.cpp @@ -319,7 +319,7 @@ namespace { } } } - void visit_params(::HIR::GenericParams& params) + void visit_params(::HIR::GenericParams& params) override { static Span sp; for(auto& bound : params.m_bounds) @@ -422,7 +422,7 @@ namespace { upper_visitor(uv) {} - void visit_generic_path(::HIR::Visitor::PathContext pc, ::HIR::GenericPath& p) + void visit_generic_path(::HIR::Visitor::PathContext pc, ::HIR::GenericPath& p) override { upper_visitor.visit_generic_path(p, pc); } diff --git a/src/hir_conv/expand_type.cpp b/src/hir_conv/expand_type.cpp index 6802cf22..dcdf79bd 100644 --- a/src/hir_conv/expand_type.cpp +++ b/src/hir_conv/expand_type.cpp @@ -208,11 +208,11 @@ public: {} // TODO: Use the other visitors. - void visit_path(::HIR::Visitor::PathContext pc, ::HIR::Path& p) + void visit_path(::HIR::Visitor::PathContext pc, ::HIR::Path& p) override { upper_visitor.visit_path(p, pc); } - void visit_generic_path(::HIR::Visitor::PathContext pc, ::HIR::GenericPath& p) + void visit_generic_path(::HIR::Visitor::PathContext pc, ::HIR::GenericPath& p) override { upper_visitor.visit_generic_path(p, pc); } diff --git a/src/hir_expand/closures.cpp b/src/hir_expand/closures.cpp index 8a90c037..a0814e49 100644 --- a/src/hir_expand/closures.cpp +++ b/src/hir_expand/closures.cpp @@ -647,7 +647,7 @@ namespace { //node.m_res_type = ::HIR::TypeRef( node.m_obj_path.clone() ); DEBUG("-- Object name: " << node.m_obj_path); ::HIR::TypeRef closure_type = ::HIR::TypeRef( ::HIR::GenericPath(node.m_obj_path.m_path.clone(), mv$(impl_path_params)) ); - closure_type.m_data.as_Path().binding = ::HIR::TypeRef::TypePathBinding::make_Struct({ &closure_struct_ref }); + closure_type.m_data.as_Path().binding = ::HIR::TypeRef::TypePathBinding::make_Struct(&closure_struct_ref); // - Args ::std::vector< ::HIR::Pattern> args_pat_inner; diff --git a/src/hir_typeck/helpers.hpp b/src/hir_typeck/helpers.hpp index 335875a5..58688d6e 100644 --- a/src/hir_typeck/helpers.hpp +++ b/src/hir_typeck/helpers.hpp @@ -187,7 +187,7 @@ public: /// Expand any located associated types in the input, operating in-place and returning the result ::HIR::TypeRef expand_associated_types(const Span& sp, ::HIR::TypeRef input) const { expand_associated_types_inplace(sp, input, LList()); - return mv$(input); + return input; } const ::HIR::TypeRef& expand_associated_types(const Span& sp, const ::HIR::TypeRef& input, ::HIR::TypeRef& tmp) const { diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index c2b80202..dc3b78a7 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -786,10 +786,10 @@ namespace { { DEBUG("- constant condition"); if( cond_lit->m_data.as_Boolean() ) { - m_builder.end_block( ::MIR::Terminator::make_Goto({ true_branch }) ); + m_builder.end_block( ::MIR::Terminator::make_Goto( true_branch ) ); } else { - m_builder.end_block( ::MIR::Terminator::make_Goto({ false_branch }) ); + m_builder.end_block( ::MIR::Terminator::make_Goto( false_branch ) ); } return ; } diff --git a/src/mir/main_bindings.hpp b/src/mir/main_bindings.hpp index 9f160b12..cb4f3232 100644 --- a/src/mir/main_bindings.hpp +++ b/src/mir/main_bindings.hpp @@ -11,7 +11,7 @@ namespace HIR { class Crate; } -struct TransList; +class TransList; extern void HIR_GenerateMIR(::HIR::Crate& crate); extern void MIR_Dump(::std::ostream& sink, const ::HIR::Crate& crate); diff --git a/src/trans/codegen_mmir.cpp b/src/trans/codegen_mmir.cpp index 9755bb8b..3347606c 100644 --- a/src/trans/codegen_mmir.cpp +++ b/src/trans/codegen_mmir.cpp @@ -281,6 +281,7 @@ namespace case ::HIR::StructMarkings::DstType::TraitObject: return MetadataType::TraitObject; } + throw ""; } break; TU_ARM(te.binding, Union, tpb) return MetadataType::None; diff --git a/src/trans/mangling.hpp b/src/trans/mangling.hpp index e1b6e35e..0d13d906 100644 --- a/src/trans/mangling.hpp +++ b/src/trans/mangling.hpp @@ -10,7 +10,7 @@ #include namespace HIR { - class SimplePath; + struct SimplePath; class GenericPath; class Path; class TypeRef; -- cgit v1.2.3