summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2018-02-10 12:30:45 +0800
committerJohn Hodge <tpg@mutabah.net>2018-02-10 12:30:45 +0800
commit34e5fe1f59e0c4b446cd765464d7bcdaded9433d (patch)
tree95ec031c37431f7ab54760d3e62bbd32ad170f89 /src
parentb6e4b12bdc3f55b23f71c42c8f3e34bb8c383f3a (diff)
downloadmrust-34e5fe1f59e0c4b446cd765464d7bcdaded9433d.tar.gz
Trans - Fix mismatches between mrustc's sizings and C's sizings
Diffstat (limited to 'src')
-rw-r--r--src/hir/hir.hpp1
-rw-r--r--src/mir/optimise.cpp16
-rw-r--r--src/trans/codegen_c.cpp56
-rw-r--r--src/trans/target.cpp67
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);