summaryrefslogtreecommitdiff
path: root/src/trans
diff options
context:
space:
mode:
Diffstat (limited to 'src/trans')
-rw-r--r--src/trans/codegen_c.cpp313
-rw-r--r--src/trans/target.cpp14
2 files changed, 256 insertions, 71 deletions
diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp
index 3947de9b..86bbdddc 100644
--- a/src/trans/codegen_c.cpp
+++ b/src/trans/codegen_c.cpp
@@ -239,6 +239,7 @@ namespace {
<< "#include <stdlib.h>\n" // abort
<< "#include <string.h>\n" // mem*
<< "#include <math.h>\n" // round, ...
+ << "#include <setjmp.h>\n" // setjmp/jmp_buf
;
break;
case Compiler::Msvc:
@@ -294,6 +295,10 @@ namespace {
switch (m_compiler)
{
case Compiler::Gcc:
+ m_of
+ << "extern __thread jmp_buf* mrustc_panic_target;\n"
+ << "extern __thread void* mrustc_panic_value;\n"
+ ;
// 64-bit bit ops (gcc intrinsics)
m_of
<< "static inline uint64_t __builtin_clz64(uint64_t v) {\n"
@@ -427,23 +432,46 @@ namespace {
<< "static inline float cast128_float(uint128_t v) { if(v.hi == 0) return v.lo; int exp = 0; uint32_t mant = 0; return make_float(0, exp, mant); }\n"
<< "static inline double cast128_double(uint128_t v) { if(v.hi == 0) return v.lo; int exp = 0; uint64_t mant = 0; return make_double(0, exp, mant); }\n"
<< "static inline int cmp128(uint128_t a, uint128_t b) { if(a.hi != b.hi) return a.hi < b.hi ? -1 : 1; if(a.lo != b.lo) return a.lo < b.lo ? -1 : 1; return 0; }\n"
- << "static inline bool add128_o(uint128_t a, uint128_t b, uint128_t* o) { o->lo = a.lo + b.lo; o->hi = a.hi + b.hi + (o->lo < a.lo ? 1 : 0); return (o->hi >= a.hi); }\n"
- << "static inline bool sub128_o(uint128_t a, uint128_t b, uint128_t* o) { o->lo = a.lo - b.lo; o->hi = a.hi - b.hi - (o->lo < a.lo ? 1 : 0); return (o->hi <= a.hi); }\n"
+ // Returns true if overflow happens (res < a)
+ << "static inline bool add128_o(uint128_t a, uint128_t b, uint128_t* o) { o->lo = a.lo + b.lo; o->hi = a.hi + b.hi + (o->lo < a.lo ? 1 : 0); return (o->hi < a.hi); }\n"
+ // Returns true if overflow happens (res > a)
+ << "static inline bool sub128_o(uint128_t a, uint128_t b, uint128_t* o) { o->lo = a.lo - b.lo; o->hi = a.hi - b.hi - (a.lo < b.lo ? 1 : 0); return (o->hi > a.hi); }\n"
// Serial shift+add
<< "static inline bool mul128_o(uint128_t a, uint128_t b, uint128_t* o) {"
- << "bool of = false;"
- << "o->hi = 0; o->lo = 0;"
- << "for(int i=0;i<128;i++){"
- << "if((1ull<<(i&63))&(i>64?a.hi:a.lo)) of |= add128_o(*o, b, o);"
- << "b.hi = (b.hi << 1) | (b.lo >> 63);"
- << "b.lo = (b.lo << 1);"
- << "}"
- << "return of;"
- << "}\n"
- // TODO: Long division
+ << " bool of = false;"
+ << " o->hi = 0; o->lo = 0;"
+ << " for(int i=0;i<128;i++){"
+ << " uint64_t m = (1ull << (i % 64));"
+ << " if(a.hi==0&&a.lo<m) break;"
+ << " if(i>=64&&a.hi<m) break;"
+ << " if( m & (i >= 64 ? a.hi : a.lo) ) of |= add128_o(*o, b, o);"
+ << " b.hi = (b.hi << 1) | (b.lo >> 63);"
+ << " b.lo = (b.lo << 1);"
+ << " }"
+ << " return of;"
+ << "}\n"
+ // Long division
<< "static inline bool div128_o(uint128_t a, uint128_t b, uint128_t* q, uint128_t* r) {"
- << "abort();"
- << "}\n"
+ << " if(a.hi == 0 && b.hi == 0) { if(q) { q->hi=0; q->lo = a.lo / b.lo; } if(r) { r->hi=0; r->lo = a.lo % b.lo; } return false; }"
+ << " if(cmp128(a, b) < 0) { if(q) { q->hi=0; q->lo=0; } if(r) *r = a; return false; }"
+ << " uint128_t a_div_2 = {(a.lo>>1)|(a.hi << 63), a.hi>>1};"
+ << " int shift = 0;"
+ << " while( cmp128(a_div_2, b) >= 0 && shift < 128 ) {"
+ << " shift += 1;"
+ << " b.hi = (b.hi<<1)|(b.lo>>63); b.lo <<= 1;"
+ << " }"
+ << " if(shift == 128) return true;" // true = overflowed
+ << " uint128_t mask = { /*lo=*/(shift >= 64 ? 0 : (1ull << shift)), /*hi=*/(shift < 64 ? 0 : 1ull << (shift-64)) };"
+ << " shift ++;"
+ << " if(q) { q->hi = 0; q->lo = 0; }"
+ << " while(shift--) {"
+ << " if( cmp128(a, b) >= 0 ) { if(q) add128_o(*q, mask, q); sub128_o(a, b, &a); }"
+ << " mask.lo = (mask.lo >> 1) | (mask.hi << 63); mask.hi >>= 1;"
+ << " b.lo = (b.lo >> 1) | (b.hi << 63); b.hi >>= 1;"
+ << " }"
+ << " if(r) *r = a;"
+ << " return false;"
+ << "}\n"
<< "static inline uint128_t add128(uint128_t a, uint128_t b) { uint128_t v; add128_o(a, b, &v); return v; }\n"
<< "static inline uint128_t sub128(uint128_t a, uint128_t b) { uint128_t v; sub128_o(a, b, &v); return v; }\n"
<< "static inline uint128_t mul128(uint128_t a, uint128_t b) { uint128_t v; mul128_o(a, b, &v); return v; }\n"
@@ -465,18 +493,21 @@ namespace {
<< "\treturn rv;\n"
<< "}\n"
<< "static inline int128_t make128s(int64_t v) { int128_t rv = { v, (v < 0 ? -1 : 0) }; return rv; }\n"
+ << "static inline int128_t neg128s(int128_t v) { int128_t rv = { ~v.lo+1, ~v.hi + (v.lo == 0) }; return rv; }\n"
<< "static inline float cast128s_float(int128_t v) { if(v.hi == 0) return v.lo; int exp = 0; uint32_t mant = 0; return make_float(0, exp, mant); }\n"
<< "static inline double cast128s_double(int128_t v) { if(v.hi == 0) return v.lo; int exp = 0; uint64_t mant = 0; return make_double(0, exp, mant); }\n"
<< "static inline int cmp128s(int128_t a, int128_t b) { if(a.hi != b.hi) return (int64_t)a.hi < (int64_t)b.hi ? -1 : 1; if(a.lo != b.lo) return a.lo < b.lo ? -1 : 1; return 0; }\n"
- << "static inline bool add128s_o(int128_t a, int128_t b, int128_t* o) { o->lo = a.lo + b.lo; o->hi = a.hi + b.hi + (o->lo < a.lo ? 1 : 0); return (o->hi >= a.hi); }\n"
- << "static inline bool sub128s_o(int128_t a, int128_t b, int128_t* o) { o->lo = a.lo - b.lo; o->hi = a.hi - b.hi - (o->lo < a.lo ? 1 : 0); return (o->hi <= a.hi); }\n"
+ // Returns true if overflow happens (if negative with pos,pos or positive with neg,neg)
+ << "static inline bool add128s_o(int128_t a, int128_t b, int128_t* o) { bool sgna=a.hi>>63; bool sgnb=b.hi>>63; add128_o(*(uint128_t*)&a, *(uint128_t*)&b, (uint128_t*)o); bool sgno = o->hi>>63; return (sgna==sgnb && sgno != sgna); }\n"
+ // Returns true if overflow happens (if neg with pos,neg or pos with neg,pos)
+ << "static inline bool sub128s_o(int128_t a, int128_t b, int128_t* o) { bool sgna=a.hi>>63; bool sgnb=b.hi>>63; sub128_o(*(uint128_t*)&a, *(uint128_t*)&b, (uint128_t*)o); bool sgno = o->hi>>63; return (sgna!=sgnb && sgno != sgna); }\n"
<< "static inline bool mul128s_o(int128_t a, int128_t b, int128_t* o) {"
- << " bool sgna = a.hi & (1ull<<63);"
- << " bool sgnb = b.hi & (1ull<<63);"
- << " if(sgna) { a.hi = ~a.hi; a.lo = ~a.lo; a.lo += 1; if(a.lo == 0) a.hi += 1; }"
- << " if(sgnb) { b.hi = ~b.hi; b.lo = ~b.lo; b.lo += 1; if(b.lo == 0) b.hi += 1; }"
+ << " bool sgna = (a.hi >> 63);"
+ << " bool sgnb = (b.hi >> 63);"
+ << " if(sgna) a = neg128s(a);"
+ << " if(sgnb) b = neg128s(b);"
<< " bool rv = mul128_o(*(uint128_t*)&a, *(uint128_t*)&b, (uint128_t*)o);"
- << " if(sgnb != sgnb) { o->hi = ~o->hi; o->lo = ~o->lo; o->lo += 1; if(o->lo == 0) o->hi += 1; }"
+ << " if(sgnb != sgnb) *o = neg128s(*o);"
<< " return rv;"
<< " }\n"
<< "static inline bool div128s_o(int128_t a, int128_t b, int128_t* q, int128_t* r) {"
@@ -599,6 +630,14 @@ namespace {
m_of << "\treturn " << Trans_Mangle(::HIR::GenericPath(c_start_path)) << "(argc, argv);\n";
}
m_of << "}\n";
+
+ if( m_compiler == Compiler::Gcc )
+ {
+ m_of
+ << "__thread jmp_buf* mrustc_panic_target;\n"
+ << "__thread void* mrustc_panic_value;\n"
+ ;
+ }
}
m_of.flush();
@@ -953,6 +992,7 @@ namespace {
if( te.size() > 0 )
{
m_of << "typedef struct "; emit_ctype(ty); m_of << " {\n";
+ unsigned n_fields = 0;
for(unsigned int i = 0; i < te.size(); i++)
{
m_of << "\t";
@@ -965,8 +1005,13 @@ namespace {
else {
emit_ctype(te[i], FMT_CB(ss, ss << "_" << i;));
m_of << ";\n";
+ n_fields += 1;
}
}
+ if( n_fields == 0 && m_options.disallow_empty_structs )
+ {
+ m_of << "\tchar _d;\n";
+ }
m_of << "} "; emit_ctype(ty); m_of << ";\n";
}
@@ -1027,8 +1072,27 @@ namespace {
TRACE_FUNCTION_F(p);
auto item_ty = ::HIR::TypeRef::new_path(p.clone(), &item);
const auto* repr = Target_GetTypeRepr(sp, m_resolve, item_ty);
- bool has_unsized = false;
+
+ ::std::vector<unsigned> fields;
+ for(const auto& ent : repr->fields)
+ {
+ (void)ent;
+ fields.push_back(fields.size());
+ }
+ ::std::sort(fields.begin(), fields.end(), [&](auto a, auto b){ return repr->fields[a].offset < repr->fields[b].offset; });
+
m_of << "// struct " << p << "\n";
+
+ // Determine if the type has an alignment hack
+ bool has_manual_align = false;
+ for(unsigned fld : fields )
+ {
+ const auto& ty = repr->fields[fld].ty;
+ if( ty.m_data.is_Array() && ty.m_data.as_Array().size_val == 0 ) {
+ has_manual_align = true;
+ }
+ }
+
// For repr(packed), mark as packed
if(is_packed)
{
@@ -1041,15 +1105,20 @@ namespace {
break;
}
}
- m_of << "struct s_" << Trans_Mangle(p) << " {\n";
-
- ::std::vector<unsigned> fields;
- for(const auto& ent : repr->fields)
+ if(has_manual_align)
{
- (void)ent;
- fields.push_back(fields.size());
+ switch(m_compiler)
+ {
+ case Compiler::Msvc:
+ m_of << "#pragma align(push, " << repr->align << ")\n";
+ break;
+ case Compiler::Gcc:
+ break;
+ }
}
- ::std::sort(fields.begin(), fields.end(), [&](auto a, auto b){ return repr->fields[a].offset < repr->fields[b].offset; });
+ m_of << "struct s_" << Trans_Mangle(p) << " {\n";
+
+ bool has_unsized = false;
size_t sized_fields = 0;
for(unsigned fld : fields)
{
@@ -1076,9 +1145,12 @@ namespace {
continue ;
}
else {
+
// TODO: Nested unsized?
emit_ctype( ty, FMT_CB(ss, ss << "_" << fld) );
sized_fields ++;
+
+ has_unsized |= (s == SIZE_MAX);
}
}
m_of << ";\n";
@@ -1088,15 +1160,23 @@ namespace {
m_of << "\tchar _d;\n";
}
m_of << "}";
- if(is_packed)
+ if(is_packed || has_manual_align)
{
switch(m_compiler)
{
case Compiler::Msvc:
- m_of << ";\n#pragma pack(pop)\n";
+ if( is_packed )
+ m_of << ";\n#pragma pack(pop)\n";
+ if( has_manual_align )
+ m_of << ";\n#pragma align(pop)\n";
break;
case Compiler::Gcc:
- m_of << " __attribute__((packed));\n";
+ m_of << " __attribute__((";
+ if( is_packed )
+ m_of << "packed,";
+ if( has_manual_align )
+ m_of << "__aligned__(" << repr->align << "),";
+ m_of << "));\n";
break;
}
}
@@ -1105,6 +1185,12 @@ namespace {
m_of << ";\n";
}
(void)has_unsized;
+ if( true && repr->size > 0 && !has_unsized )
+ {
+ // TODO: Handle unsized (should check the size of the fixed-size region)
+ m_of << "typedef char sizeof_assert_" << Trans_Mangle(p) << "[ (sizeof(struct s_" << Trans_Mangle(p) << ") == " << repr->size << ") ? 1 : -1 ];\n";
+ //m_of << "typedef char alignof_assert_" << Trans_Mangle(p) << "[ (ALIGNOF(struct s_" << Trans_Mangle(p) << ") == " << repr->align << ") ? 1 : -1 ];\n";
+ }
auto struct_ty = ::HIR::TypeRef(p.clone(), &item);
auto drop_glue_path = ::HIR::Path(struct_ty.clone(), "#drop_glue");
@@ -1172,6 +1258,10 @@ namespace {
m_of << "\t"; emit_ctype( repr->fields[i].ty, FMT_CB(ss, ss << "var_" << i;) ); m_of << ";\n";
}
m_of << "};\n";
+ if( true && repr->size > 0 )
+ {
+ m_of << "typedef char sizeof_assert_" << Trans_Mangle(p) << "[ (sizeof(union u_" << Trans_Mangle(p) << ") == " << repr->size << ") ? 1 : -1 ];\n";
+ }
// Drop glue (calls destructor if there is one)
auto drop_glue_path = ::HIR::Path(item_ty.clone(), "#drop_glue");
@@ -1182,7 +1272,7 @@ namespace {
if( item.m_markings.has_drop_impl )
{
- m_of << "tUNIT " << Trans_Mangle(drop_impl_path) << "(union u_" << Trans_Mangle(p) << "*rv);\n";
+ m_of << "void " << Trans_Mangle(drop_impl_path) << "(union u_" << Trans_Mangle(p) << "*rv);\n";
}
m_of << "static void " << Trans_Mangle(drop_glue_path) << "(union u_" << Trans_Mangle(p) << "* rv) {\n";
@@ -1268,20 +1358,40 @@ namespace {
assert(1 + union_fields.size() + 1 >= repr->fields.size());
// Make the union!
// NOTE: The way the structure generation works is that enum variants are always first, so the field index = the variant index
- m_of << "\tunion {\n";
- // > First field
- m_of << "\t\t";
- emit_ctype(repr->fields[0].ty, FMT_CB(os, os << "var_0"));
- m_of << ";\n";
- // > All others
- for(auto idx : union_fields)
+ // TODO:
+ if( !this->type_is_bad_zst(repr->fields[0].ty) || ::std::any_of(union_fields.begin(), union_fields.end(), [this,repr](auto x){ return !this->type_is_bad_zst(repr->fields[x].ty); }) )
{
- // TODO: if the compiler doesn't allow zero-sized types, don't emit zero-sized fields.
- m_of << "\t\t";
- emit_ctype(repr->fields[idx].ty, FMT_CB(os, os << "var_" << idx));
- m_of << ";\n";
+ m_of << "\tunion {\n";
+ // > First field
+ {
+ m_of << "\t\t";
+ const auto& ty = repr->fields[0].ty;
+ if( this->type_is_bad_zst(ty) ) {
+ m_of << "// ZST: " << ty << "\n";
+ }
+ else {
+ emit_ctype( ty, FMT_CB(ss, ss << "var_0") );
+ m_of << ";\n";
+ //sized_fields ++;
+ }
+ }
+ // > All others
+ for(auto idx : union_fields)
+ {
+ m_of << "\t\t";
+
+ const auto& ty = repr->fields[idx].ty;
+ if( this->type_is_bad_zst(ty) ) {
+ m_of << "// ZST: " << ty << "\n";
+ }
+ else {
+ emit_ctype( ty, FMT_CB(ss, ss << "var_" << idx) );
+ m_of << ";\n";
+ //sized_fields ++;
+ }
+ }
+ m_of << "\t} DATA;\n";
}
- m_of << "\t} DATA;\n";
if( repr->fields.size() == 1 + union_fields.size() )
{
@@ -1334,6 +1444,10 @@ namespace {
}
m_of << "};\n";
+ if( true && repr->size > 0 )
+ {
+ m_of << "typedef char sizeof_assert_" << Trans_Mangle(p) << "[ (sizeof(struct e_" << Trans_Mangle(p) << ") == " << repr->size << ") ? 1 : -1 ];\n";
+ }
// ---
// - Drop Glue
@@ -1347,7 +1461,7 @@ namespace {
if( item.m_markings.has_drop_impl )
{
- m_of << "tUNIT " << Trans_Mangle(drop_impl_path) << "(struct e_" << Trans_Mangle(p) << "*rv);\n";
+ m_of << "void " << Trans_Mangle(drop_impl_path) << "(struct e_" << Trans_Mangle(p) << "*rv);\n";
}
m_of << "static void " << Trans_Mangle(drop_glue_path) << "(struct e_" << Trans_Mangle(p) << "* rv) {\n";
@@ -1383,7 +1497,7 @@ namespace {
var_lv.as_Downcast().variant_index = var_idx;
m_of << "\tcase " << e->values[var_idx] << ":\n";
emit_destructor_call(var_lv, repr->fields[var_idx].ty, /*unsized_valid=*/false, /*indent=*/2);
- m_of << "\tbreak;\n";
+ m_of << "\t\tbreak;\n";
}
m_of << "\t}\n";
}
@@ -1459,23 +1573,23 @@ namespace {
}
else
{
- m_of << " .DATA = { .var_" << var_idx << " = {";
if( this->type_is_bad_zst(repr->fields[var_idx].ty) )
{
- m_of << "\n\t\t0";
+ m_of << " .DATA = { /* ZST Variant */ }";
}
else
{
+ m_of << " .DATA = { .var_" << var_idx << " = {";
for(unsigned int i = 0; i < e.size(); i ++)
{
if(i != 0)
m_of << ",";
m_of << "\n\t\t_" << i;
}
+ m_of << "\n\t\t} }";
}
- m_of << "\n\t\t}";
}
- m_of << " }};\n";
+ m_of << " };\n";
m_of << "\treturn rv;\n";
m_of << "}\n";
m_mir_res = nullptr;
@@ -1722,10 +1836,16 @@ namespace {
else
{
m_of << "{";
- m_of << " { .var_" << e.idx << " = ";
- emit_literal(get_inner_type(e.idx, 0), *e.val, params);
- m_of << " }";
- m_of << ", .TAG = "; emit_enum_variant_val(repr, e.idx);
+ const auto& ity = get_inner_type(e.idx, 0);
+ if( this->type_is_bad_zst(ity) ) {
+ //m_of << " {}";
+ }
+ else {
+ m_of << " { .var_" << e.idx << " = ";
+ emit_literal(ity, *e.val, params);
+ m_of << " }, ";
+ }
+ m_of << ".TAG = "; emit_enum_variant_val(repr, e.idx);
m_of << "}";
}
),
@@ -2037,6 +2157,19 @@ namespace {
{
m_of << "static ";
}
+ else if( item.m_linkage.name == "_Unwind_RaiseException" )
+ {
+ MIR_ASSERT(*m_mir_res, m_compiler == Compiler::Gcc, item.m_linkage.name << " in non-GCC mode");
+ m_of << "// - Magic compiler impl\n";
+ m_of << "static ";
+ emit_function_header(p, item, params);
+ m_of << " {\n";
+ m_of << "\tif( !mrustc_panic_target ) abort();\n";
+ m_of << "\tmrustc_panic_value = arg0;\n";
+ m_of << "\tlongjmp(*mrustc_panic_target, 1);\n";
+ m_of << "}\n";
+ return;
+ }
else
{
m_of << "extern ";
@@ -2724,7 +2857,11 @@ namespace {
m_of << " = ";
// If the index is zero, then the best option is to borrow the source
- if( val_fp->field_index == 0 )
+ if( val_fp->val->is_Downcast() )
+ {
+ m_of << "(void*)& "; emit_lvalue(*val_fp->val->as_Downcast().val);
+ }
+ else if( val_fp->field_index == 0 )
{
m_of << "(void*)& "; emit_lvalue(*val_fp->val);
}
@@ -2931,10 +3068,7 @@ namespace {
switch (ve.op)
{
case ::MIR::eUniOp::NEG:
- emit_lvalue(e.dst);
- m_of << ".lo = -"; emit_lvalue(ve.val); m_of << ".lo; ";
- emit_lvalue(e.dst);
- m_of << ".hi = -"; emit_lvalue(ve.val); m_of << ".hi";
+ emit_lvalue(e.dst); m_of << " = neg128s("; emit_lvalue(ve.val); m_of << ")";
break;
case ::MIR::eUniOp::INV:
emit_lvalue(e.dst);
@@ -3046,9 +3180,20 @@ namespace {
}
else
{
- emit_lvalue(e.dst); m_of << ".TAG = "; emit_enum_variant_val(repr, ve.index); m_of << ";\n" << indent;
- emit_lvalue(e.dst); m_of << ".DATA";
- m_of << ".var_" << ve.index << " = "; emit_param(ve.val);
+ emit_lvalue(e.dst); m_of << ".TAG = "; emit_enum_variant_val(repr, ve.index);
+
+ ::HIR::TypeRef tmp;
+ const auto& vty = mir_res.get_param_type(tmp, ve.val);
+ if( this->type_is_bad_zst(vty) )
+ {
+ m_of << "/* ZST field */";
+ }
+ else
+ {
+ m_of << ";\n" << indent;
+ emit_lvalue(e.dst); m_of << ".DATA";
+ m_of << ".var_" << ve.index << " = "; emit_param(ve.val);
+ }
}
}
else
@@ -3893,13 +4038,15 @@ namespace {
m_of << name << o_before << "8" << o_after << "(";
break;
case ::HIR::CoreType::U16:
+ case ::HIR::CoreType::I16:
m_of << name << o_before << "16" << o_after << "(";
break;
case ::HIR::CoreType::U32:
+ case ::HIR::CoreType::I32:
m_of << name << o_before << o_after << "(";
break;
case ::HIR::CoreType::U64:
- //case ::HIR::CoreType::I64:
+ case ::HIR::CoreType::I64:
m_of << name << o_before << "64" << o_after << "(";
break;
case ::HIR::CoreType::Usize:
@@ -4207,8 +4354,35 @@ namespace {
m_of << "abort()";
}
else if( name == "try" ) {
+ // Register thread-local setjmp
+ switch(m_compiler)
+ {
+ case Compiler::Gcc:
+ m_of << "{ ";
+ m_of << " jmp_buf jmpbuf; mrustc_panic_target = &jmpbuf;";
+ m_of << " if(setjmp(jmpbuf)) {";
+ // NOTE: gcc unwind has a pointer as its `local_ptr` parameter
+ m_of << " *(void**)("; emit_param(e.args.at(2)); m_of << ") = mrustc_panic_value;";
+ m_of << " "; emit_lvalue(e.ret_val); m_of << " = 1;"; // Return value non-zero when panic happens
+ m_of << " } else {";
+ m_of << " ";
+ break;
+ default:
+ break;
+ }
emit_param(e.args.at(0)); m_of << "("; emit_param(e.args.at(1)); m_of << "); ";
emit_lvalue(e.ret_val); m_of << " = 0";
+ switch(m_compiler)
+ {
+ case Compiler::Gcc:
+ m_of << ";";
+ m_of << " }";
+ m_of << " mrustc_panic_target = NULL;";
+ m_of << " }";
+ break;
+ default:
+ break;
+ }
}
else if( name == "offset" ) {
emit_lvalue(e.ret_val); m_of << " = "; emit_param(e.args.at(0)); m_of << " + "; emit_param(e.args.at(1));
@@ -4914,9 +5088,14 @@ namespace {
{
case MetadataType::None:
- if( this->type_is_bad_zst(ty) && slot.is_Field() )
+ if( this->type_is_bad_zst(ty) && (slot.is_Field() || slot.is_Downcast()) )
{
- m_of << indent << Trans_Mangle(p) << "((void*)&"; emit_lvalue(*slot.as_Field().val); m_of << ");\n";
+ m_of << indent << Trans_Mangle(p) << "((void*)&";
+ if( slot.is_Field() )
+ emit_lvalue(*slot.as_Field().val);
+ else
+ emit_lvalue(*slot.as_Downcast().val);
+ m_of << ");\n";
}
else
{
@@ -5151,7 +5330,7 @@ namespace {
} break;
TU_ARM(repr->variants, Values, ve) {
emit_dst(); emit_enum_path(repr, ve.field); m_of << " = ";
-
+
emit_enum_variant_val(repr, e.idx);
if( TU_TEST1((*e.val), List, .empty() == false) )
{
diff --git a/src/trans/target.cpp b/src/trans/target.cpp
index c1dce972..f91b679a 100644
--- a/src/trans/target.cpp
+++ b/src/trans/target.cpp
@@ -684,13 +684,19 @@ bool Target_GetSizeAndAlignOf(const Span& sp, const StaticTraitResolve& resolve,
case ::HIR::CoreType::U64:
case ::HIR::CoreType::I64:
out_size = 8;
- out_align = 8;
+ // TODO: on x86, u64/i64 has an alignment of 4, while x86_64 has 8. What do other platforms have?
+ out_align = g_target.m_arch.m_name == "x86" ? 4 : 8;
return true;
case ::HIR::CoreType::U128:
case ::HIR::CoreType::I128:
out_size = 16;
- // TODO: If i128 is emulated, this can be 8
- out_align = 16;
+ // TODO: If i128 is emulated, this can be 8 (as it is on x86, where it's actually 4 due to the above comment)
+ if( g_target.m_arch.m_name == "x86" )
+ out_align = 4;
+ else if( /*g_target.m_arch.m_name == "x86_64" && */g_target.m_backend_c.m_codegen_mode == CodegenMode::Msvc )
+ out_align = 8;
+ else
+ out_align = 16;
return true;
case ::HIR::CoreType::Usize:
case ::HIR::CoreType::Isize:
@@ -703,7 +709,7 @@ bool Target_GetSizeAndAlignOf(const Span& sp, const StaticTraitResolve& resolve,
return true;
case ::HIR::CoreType::F64:
out_size = 8;
- out_align = 8;
+ out_align = g_target.m_arch.m_name == "x86" ? 4 : 8;
return true;
case ::HIR::CoreType::Str:
DEBUG("sizeof on a `str` - unsized");