diff options
author | John Hodge <tpg@mutabah.net> | 2018-02-10 12:30:45 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2018-02-10 12:30:45 +0800 |
commit | 34e5fe1f59e0c4b446cd765464d7bcdaded9433d (patch) | |
tree | 95ec031c37431f7ab54760d3e62bbd32ad170f89 /src | |
parent | b6e4b12bdc3f55b23f71c42c8f3e34bb8c383f3a (diff) | |
download | mrust-34e5fe1f59e0c4b446cd765464d7bcdaded9433d.tar.gz |
Trans - Fix mismatches between mrustc's sizings and C's sizings
Diffstat (limited to 'src')
-rw-r--r-- | src/hir/hir.hpp | 1 | ||||
-rw-r--r-- | src/mir/optimise.cpp | 16 | ||||
-rw-r--r-- | src/trans/codegen_c.cpp | 56 | ||||
-rw-r--r-- | src/trans/target.cpp | 67 |
4 files changed, 115 insertions, 25 deletions
diff --git a/src/hir/hir.hpp b/src/hir/hir.hpp index be83b7c3..f6a1b990 100644 --- a/src/hir/hir.hpp +++ b/src/hir/hir.hpp @@ -227,6 +227,7 @@ public: struct ValueVariant { ::std::string name; ::HIR::ExprPtr expr; + // TODO: Signed. uint64_t val; }; TAGGED_UNION(Class, Data, diff --git a/src/mir/optimise.cpp b/src/mir/optimise.cpp index 873a3997..0a83332d 100644 --- a/src/mir/optimise.cpp +++ b/src/mir/optimise.cpp @@ -1983,6 +1983,8 @@ bool MIR_Optimise_ConstPropagte(::MIR::TypeResolve& state, ::MIR::Function& fcn) // - Remove calls to `size_of` and `align_of` (replace with value if known) for(auto& bb : fcn.blocks) { + state.set_cur_stmt_term(bb); + MIR_DEBUG(state, bb.terminator); if( !bb.terminator.is_Call() ) continue ; auto& te = bb.terminator.as_Call(); @@ -1994,6 +1996,19 @@ bool MIR_Optimise_ConstPropagte(::MIR::TypeResolve& state, ::MIR::Function& fcn) size_t size_val = 0; if( Target_GetSizeOf(state.sp, state.m_resolve, tef.params.m_types.at(0), size_val) ) { + DEBUG("size_of = " << size_val); + auto val = ::MIR::Constant::make_Uint({ size_val, ::HIR::CoreType::Usize }); + bb.statements.push_back(::MIR::Statement::make_Assign({ mv$(te.ret_val), mv$(val) })); + bb.terminator = ::MIR::Terminator::make_Goto(te.ret_block); + changed = true; + } + } + else if( tef.name == "size_of_val" ) + { + size_t size_val = 0, tmp; + if( Target_GetSizeAndAlignOf(state.sp, state.m_resolve, tef.params.m_types.at(0), size_val, tmp) && size_val != SIZE_MAX ) + { + DEBUG("size_of_val = " << size_val); auto val = ::MIR::Constant::make_Uint({ size_val, ::HIR::CoreType::Usize }); bb.statements.push_back(::MIR::Statement::make_Assign({ mv$(te.ret_val), mv$(val) })); bb.terminator = ::MIR::Terminator::make_Goto(te.ret_block); @@ -2005,6 +2020,7 @@ bool MIR_Optimise_ConstPropagte(::MIR::TypeResolve& state, ::MIR::Function& fcn) size_t align_val = 0; if( Target_GetAlignOf(state.sp, state.m_resolve, tef.params.m_types.at(0), align_val) ) { + DEBUG("align_of = " << align_val); auto val = ::MIR::Constant::make_Uint({ align_val, ::HIR::CoreType::Usize }); bb.statements.push_back(::MIR::Statement::make_Assign({ mv$(te.ret_val), mv$(val) })); bb.terminator = ::MIR::Terminator::make_Goto(te.ret_block); diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index d208c2ca..bcf5f20f 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -1013,7 +1013,7 @@ namespace { void emit_enum_path(const TypeRepr* repr, const TypeRepr::FieldPath& path) { - if( path.index == repr->fields.size() - 1 && !repr->variants.is_NonZero() ) + if( TU_TEST1(repr->variants, Values, .field.index == path.index) ) { m_of << ".TAG"; } @@ -1101,11 +1101,23 @@ namespace { } else if( repr->fields.size() == 1 ) { - // Tag only. - // - A value-only enum. - m_of << "\t"; - emit_ctype(repr->fields.back().ty, FMT_CB(os, os << "TAG")); - m_of << ";\n"; + if( repr->variants.is_Values() ) + { + // Tag only. + // - A value-only enum. + m_of << "\t"; + emit_ctype(repr->fields.back().ty, FMT_CB(os, os << "TAG")); + m_of << ";\n"; + } + else + { + m_of << "\tunion {\n"; + m_of << "\t\t"; + emit_ctype(repr->fields.back().ty, FMT_CB(os, os << "var_0")); + m_of << ";\n"; + m_of << "\t} DATA;\n"; + // No tag + } } else if( repr->fields.size() == 0 ) { @@ -1196,7 +1208,7 @@ namespace { auto p = path.clone(); p.m_path.m_components.pop_back(); - //const auto* repr = Target_GetTypeRepr(sp, m_resolve, ::HIR::TypeRef::new_path(p.clone(), &item)); + const auto* repr = Target_GetTypeRepr(sp, m_resolve, ::HIR::TypeRef::new_path(p.clone(), &item)); ASSERT_BUG(sp, item.m_data.is_Data(), ""); const auto& var = item.m_data.as_Data().at(var_idx); @@ -1216,13 +1228,24 @@ namespace { m_of << ") {\n"; //if( repr->variants. - m_of << "\tstruct e_" << Trans_Mangle(p) << " rv = { .TAG = " << var_idx; + m_of << "\tstruct e_" << Trans_Mangle(p) << " rv = {"; + switch(repr->variants.tag()) + { + case TypeRepr::VariantMode::TAGDEAD: throw ""; + TU_ARM(repr->variants, Values, ve) + m_of << " .TAG = " << ve.values[var_idx] << ","; + break; + TU_ARM(repr->variants, NonZero, ve) + break; + TU_ARM(repr->variants, None, ve) + break; + } if( e.empty() ) { if( m_options.disallow_empty_structs ) { - m_of << ", .DATA = { .var_" << var_idx << " = {0} }"; + m_of << " .DATA = { .var_" << var_idx << " = {0} }"; } else { @@ -1231,7 +1254,7 @@ namespace { } else { - m_of << ", .DATA = { .var_" << var_idx << " = {"; + m_of << " .DATA = { .var_" << var_idx << " = {"; for(unsigned int i = 0; i < e.size(); i ++) { if(i != 0) @@ -1464,7 +1487,8 @@ namespace { m_of << "{"; m_of << " { .var_" << e.idx << " = "; emit_literal(get_inner_type(e.idx, 0), *e.val, params); - m_of << " }, .TAG = " << e.idx; + m_of << " }"; + m_of << ", .TAG = " << repr->variants.as_Values().values[e.idx]; m_of << "}"; } ), @@ -2533,7 +2557,7 @@ namespace { if( repr->variants.is_None() ) { - emit_lvalue(e.dst); m_of << ".TAG = "; emit_param(ve.val); + emit_lvalue(e.dst); m_of << ".DATA.var_0 = "; emit_param(ve.val); } else if( const auto* re = repr->variants.opt_NonZero() ) { @@ -2555,7 +2579,7 @@ namespace { } else { - emit_lvalue(e.dst); m_of << ".TAG = " << ve.index << ";\n\t"; + emit_lvalue(e.dst); m_of << ".TAG = " << repr->variants.as_Values().values[ve.index] << ";\n\t"; emit_lvalue(e.dst); m_of << ".DATA"; m_of << ".var_" << ve.index << " = "; emit_param(ve.val); } @@ -2827,9 +2851,13 @@ namespace { m_of << indent << "default: abort();\n"; m_of << indent << "}\n"; } + else if( repr->variants.is_None() ) + { + m_of << indent; cb(0); m_of << "\n"; + } else { - BUG(sp, ""); + BUG(sp, "Unexpected variant type - " << repr->variants.tag_str()); } } void emit_term_switchvalue(const ::MIR::TypeResolve& mir_res, const ::MIR::LValue& val, const ::MIR::SwitchValues& values, unsigned indent_level, ::std::function<void(size_t)> cb) diff --git a/src/trans/target.cpp b/src/trans/target.cpp index 61789a75..08cad81a 100644 --- a/src/trans/target.cpp +++ b/src/trans/target.cpp @@ -588,6 +588,7 @@ namespace { } if( !packed && cur_ofs != SIZE_MAX ) { + // Size must be a multiple of alignment while( cur_ofs % max_align != 0 ) { cur_ofs ++; @@ -705,6 +706,14 @@ namespace { max_align = ::std::max(max_align, align); rv.fields.push_back(TypeRepr::Field { 0, mv$(t) }); } + DEBUG("max_size = " << max_size << ", max_align = " << max_align); + // HACK: This is required for the C backend, because the union that contains the enum variants is + // padded out to align. + if(max_size > 0) + { + while(max_size % max_align) + max_size ++; + } size_t tag_size = 0; // TODO: repr(C) enums if( mono_types.size() == 0 ) { @@ -716,12 +725,14 @@ namespace { else if( mono_types.size() <= 255 ) { rv.fields.push_back(TypeRepr::Field { max_size, ::HIR::CoreType::U8 }); tag_size = 1; + DEBUG("u8 data tag"); } else { ASSERT_BUG(sp, mono_types.size() <= 0xFFFF, ""); while(max_size % 2) max_size ++; rv.fields.push_back(TypeRepr::Field { max_size, ::HIR::CoreType::U16 }); tag_size = 2; + DEBUG("u16 data tag"); } max_align = ::std::max(max_align, tag_size); ::std::vector<uint64_t> vals; @@ -739,6 +750,7 @@ namespace { } if( max_align > 0 ) { + // Size must be a multiple of alignment rv.size = (max_size + tag_size); while(rv.size % max_align) rv.size ++; @@ -759,23 +771,47 @@ namespace { // No auto-sizing, just i32? rv.fields.push_back(TypeRepr::Field { 0, ::HIR::CoreType::U32 }); break; - case ::HIR::Enum::Repr::Rust: - if( e.variants.size() == 0 ) { + case ::HIR::Enum::Repr::Rust: { + int pow8 = 0; + for( const auto& v : e.variants ) + { + auto v2 = static_cast<int64_t>(v.val); + if( -0x80 <= v2 && v2 < 0x80 ) + { + pow8 = ::std::max(pow8, 1); + } + else if( -0x8000 <= v2 && v2 < 0x8000 ) + { + pow8 = ::std::max(pow8, 2); + } + else if( -0x80000000 <= v2 && v2 < 0x80000000 ) + { + pow8 = ::std::max(pow8, 3); + } + else + { + pow8 = 4; + } } - // NOTE: Even with 1 variant, we need to save the value - else if( e.variants.size() <= 128 ) { + switch(pow8) + { + case 0: break; + case 1: rv.fields.push_back(TypeRepr::Field { 0, ::HIR::CoreType::I8 }); - } - else if( e.variants.size() <= 0x7FFF ) { + break; + case 2: rv.fields.push_back(TypeRepr::Field { 0, ::HIR::CoreType::I16 }); - } - else if( e.variants.size() <= 0x7FFFFFFF ) { + break; + case 3: rv.fields.push_back(TypeRepr::Field { 0, ::HIR::CoreType::I32 }); - } - else { + break; + case 4: rv.fields.push_back(TypeRepr::Field { 0, ::HIR::CoreType::I64 }); + break; + default: + break; } - break; + } break; case ::HIR::Enum::Repr::U8: rv.fields.push_back(TypeRepr::Field { 0, ::HIR::CoreType::U8 }); break; @@ -817,6 +853,7 @@ namespace { } } break; } + DEBUG("rv.variants = " << rv.variants.tag_str()); return box$(rv); } ::std::unique_ptr<TypeRepr> make_type_repr(const Span& sp, const StaticTraitResolve& resolve, const ::HIR::TypeRef& ty) @@ -861,6 +898,14 @@ namespace { { return make_type_repr_enum(sp, resolve, ty); } + else if( ty.m_data.is_Primitive() ) + { + return nullptr; + } + else if( ty.m_data.is_Borrow() || ty.m_data.is_Pointer() ) + { + return nullptr; + } else { TODO(sp, "Type repr for " << ty); |