summaryrefslogtreecommitdiff
path: root/src/trans/codegen_mmir.cpp
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2018-02-11 21:57:10 +0800
committerJohn Hodge <tpg@mutabah.net>2018-02-11 21:57:10 +0800
commita3a0c6437302c60bd6f521fc11e30c0a16bd79fc (patch)
tree83b536f1d5b170a88417015ec0a7f378ab6ea4c4 /src/trans/codegen_mmir.cpp
parent14fea32f414df2d1e0b8e2669c8fe13132210ae9 (diff)
downloadmrust-a3a0c6437302c60bd6f521fc11e30c0a16bd79fc.tar.gz
Standalone MIRI - Implementation sprint, statics in process.
Diffstat (limited to 'src/trans/codegen_mmir.cpp')
-rw-r--r--src/trans/codegen_mmir.cpp274
1 files changed, 271 insertions, 3 deletions
diff --git a/src/trans/codegen_mmir.cpp b/src/trans/codegen_mmir.cpp
index 09167486..d4b9f799 100644
--- a/src/trans/codegen_mmir.cpp
+++ b/src/trans/codegen_mmir.cpp
@@ -97,6 +97,9 @@ namespace
os << (sign ? "-" : "+") << "0x1." << ::std::setw(52/4) << ::std::setfill('0') << ::std::hex << frac << ::std::dec << "p" << (exp - 1023);
os << " " << v.t;
} break;
+ TU_ARM(e, ItemAddr, v) {
+ os << "ADDROF " << v;
+ } break;
default:
os << e;
break;
@@ -160,13 +163,13 @@ namespace
{
m_of << "\tlet m: fn();\n";
m_of << "\t0: {\n";
- m_of << "\t\tASSIGN m = &" << ::HIR::GenericPath(m_resolve.m_crate.get_lang_item_path(Span(), "mrustc-main")) << ";\n";
- m_of << "\t\tCALL RETURN = " << ::HIR::GenericPath(m_resolve.m_crate.get_lang_item_path(Span(), "start")) << "(m, arg1, arg2) goto 1 else 1\n";
+ m_of << "\t\tASSIGN m = ADDROF " << ::HIR::GenericPath(m_resolve.m_crate.get_lang_item_path(Span(), "mrustc-main")) << ";\n";
+ m_of << "\t\tCALL RETURN = " << ::HIR::GenericPath(m_resolve.m_crate.get_lang_item_path(Span(), "start")) << "(m, arg0, arg1) goto 1 else 1\n";
}
else
{
m_of << "\t0: {\n";
- m_of << "\t\tCALL RETURN = " << ::HIR::GenericPath(c_start_path) << "(arg1, arg2) goto 1 else 1;\n";
+ m_of << "\t\tCALL RETURN = " << ::HIR::GenericPath(c_start_path) << "(arg0, arg1) goto 1 else 1;\n";
}
m_of << "\t}\n";
m_of << "\t1: {\n";
@@ -509,6 +512,271 @@ namespace
#endif
m_mir_res = nullptr;
}
+ struct Reloc {
+ size_t ofs;
+ size_t len;
+ const ::HIR::Path* p;
+ ::std::string bytes;
+ };
+ void emit_literal_as_bytes(const ::HIR::Literal& lit, const ::HIR::TypeRef& ty, ::std::vector<Reloc>& 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( true ) {
+ putu32(v );
+ putu32(v >> 32);
+ }
+ else {
+ putu32(v );
+ }
+ };
+ switch(ty.m_data.tag())
+ {
+ case ::HIR::TypeRef::Data::TAGDEAD: throw "";
+ case ::HIR::TypeRef::Data::TAG_Generic:
+ case ::HIR::TypeRef::Data::TAG_ErasedType:
+ case ::HIR::TypeRef::Data::TAG_Diverge:
+ case ::HIR::TypeRef::Data::TAG_Infer:
+ case ::HIR::TypeRef::Data::TAG_TraitObject:
+ case ::HIR::TypeRef::Data::TAG_Slice:
+ case ::HIR::TypeRef::Data::TAG_Closure:
+ BUG(sp, "Unexpected " << ty << " in decoding literal");
+ TU_ARM(ty.m_data, Primitive, te) {
+ switch(te)
+ {
+ case ::HIR::CoreType::U8:
+ case ::HIR::CoreType::I8:
+ case ::HIR::CoreType::Bool:
+ ASSERT_BUG(sp, lit.is_Integer(), ty << " not Literal::Integer - " << lit);
+ putb(lit.as_Integer());
+ break;
+ case ::HIR::CoreType::U16:
+ case ::HIR::CoreType::I16:
+ ASSERT_BUG(sp, lit.is_Integer(), ty << " not Literal::Integer - " << lit);
+ putb(lit.as_Integer() & 0xFF);
+ putb(lit.as_Integer() >> 8);
+ break;
+ case ::HIR::CoreType::U32:
+ case ::HIR::CoreType::I32:
+ case ::HIR::CoreType::Char:
+ ASSERT_BUG(sp, lit.is_Integer(), ty << " not Literal::Integer - " << lit);
+ putu32(lit.as_Integer() );
+ break;
+ case ::HIR::CoreType::U64:
+ case ::HIR::CoreType::I64:
+ ASSERT_BUG(sp, lit.is_Integer(), ty << " not Literal::Integer - " << lit);
+ putu32(lit.as_Integer() );
+ putu32(lit.as_Integer() >> 32);
+ break;
+ case ::HIR::CoreType::U128:
+ case ::HIR::CoreType::I128:
+ ASSERT_BUG(sp, lit.is_Integer(), ty << " not Literal::Integer - " << lit);
+ putu32(lit.as_Integer() );
+ putu32(lit.as_Integer() >> 32);
+ putu32(0);
+ putu32(0);
+ break;
+ case ::HIR::CoreType::Usize:
+ case ::HIR::CoreType::Isize:
+ ASSERT_BUG(sp, lit.is_Integer(), ty << " not Literal::Integer - " << lit);
+ putsize(lit.as_Integer());
+ break;
+ case ::HIR::CoreType::F32: {
+ ASSERT_BUG(sp, lit.is_Float(), "not Literal::Float - " << lit);
+ uint32_t v;
+ memcpy(&v, &double(lit.as_Float()), 4);
+ putu32(v);
+ } break;
+ case ::HIR::CoreType::F64: {
+ ASSERT_BUG(sp, lit.is_Float(), "not Literal::Float - " << lit);
+ uint64_t v;
+ memcpy(&v, &lit.as_Float(), 8);
+ putu32(v);
+ } break;
+ case ::HIR::CoreType::Str:
+ BUG(sp, "Unexpected " << ty << " in decoding literal");
+ }
+ } break;
+ case ::HIR::TypeRef::Data::TAG_Path:
+ case ::HIR::TypeRef::Data::TAG_Tuple: {
+ const auto* repr = Target_GetTypeRepr(sp, m_resolve, ty);
+ assert(repr);
+ size_t cur_ofs = 0;
+ if( lit.is_List() )
+ {
+ const auto& le = lit.as_List();
+ assert(le.size() == repr->fields.size());
+ for(size_t i = 0; i < repr->fields.size(); i ++)
+ {
+ assert(cur_ofs <= repr->fields[i].offset);
+ while(cur_ofs < repr->fields[i].offset)
+ {
+ putb(0);
+ cur_ofs ++;
+ }
+ emit_literal_as_bytes(le[i], repr->fields[i].ty, out_relocations, base_ofs + cur_ofs);
+ size_t size;
+ assert(Target_GetSizeOf(sp, m_resolve, repr->fields[i].ty, size));
+ cur_ofs += size;
+ }
+ while(cur_ofs < repr->size)
+ {
+ putb(0);
+ cur_ofs ++;
+ }
+ }
+ else if( lit.is_Variant() )
+ {
+ const auto& le = lit.as_Variant();
+ if( *le.val != ::HIR::Literal::make_List({}) )
+ {
+ assert(le.idx < repr->fields.size());
+ while(cur_ofs < repr->fields[le.idx].offset)
+ {
+ putb(0);
+ cur_ofs ++;
+ }
+
+ emit_literal_as_bytes(*le.val, repr->fields[le.idx].ty, out_relocations, base_ofs + cur_ofs);
+
+ size_t size;
+ assert(Target_GetSizeOf(sp, m_resolve, repr->fields[le.idx].ty, size));
+ cur_ofs += size;
+ }
+
+ if(const auto* ve = repr->variants.opt_Values())
+ {
+ ASSERT_BUG(sp, cur_ofs <= repr->fields[ve->field.index].offset, "Bad offset before enum tag");
+ while(cur_ofs < repr->fields[ve->field.index].offset)
+ {
+ putb(0);
+ cur_ofs ++;
+ }
+ auto v = ::HIR::Literal::make_Integer(le.idx);
+ emit_literal_as_bytes(v, repr->fields[ve->field.index].ty, out_relocations, base_ofs + cur_ofs);
+ }
+ // TODO: Nonzero?
+ while(cur_ofs < repr->size)
+ {
+ putb(0);
+ cur_ofs ++;
+ }
+ }
+ else
+ {
+ TODO(sp, "Composites - " << ty << " w/ " << lit);
+ }
+ } break;
+ case ::HIR::TypeRef::Data::TAG_Borrow:
+ if( *ty.m_data.as_Borrow().inner == ::HIR::CoreType::Str )
+ {
+ ASSERT_BUG(sp, lit.is_String(), ty << " not Literal::String - " << lit);
+ const auto& s = lit.as_String();
+ putsize(0);
+ putsize(s.size());
+ out_relocations.push_back(Reloc { base_ofs, 8, nullptr, s });
+ break;
+ }
+ // fall
+ case ::HIR::TypeRef::Data::TAG_Pointer: {
+ const auto& ity = (ty.m_data.is_Borrow() ? *ty.m_data.as_Borrow().inner : *ty.m_data.as_Pointer().inner);
+ size_t ity_size, ity_align;
+ Target_GetSizeAndAlignOf(sp, m_resolve, ity, ity_size, ity_align);
+ bool is_unsized = (ity_size == SIZE_MAX);
+ if( lit.is_BorrowPath() )
+ {
+ putsize(0);
+ out_relocations.push_back(Reloc { base_ofs, 8, &lit.as_BorrowPath(), "" });
+ if( is_unsized )
+ {
+ // TODO: Get the size of the pointed-to array
+ // OR: Find out the source item type and the target trait.
+ putsize(0);
+ }
+ break;
+ }
+ else if( lit.is_Integer() )
+ {
+ ASSERT_BUG(sp, lit.as_Integer() == 0, "Pointer from integer not 0");
+ ASSERT_BUG(sp, ty.m_data.is_Pointer(), "Borrow from integer");
+ putsize(0);
+ if( is_unsized )
+ {
+ putsize(0);
+ }
+ break;
+ }
+ TODO(sp, "Pointers - " << ty << " w/ " << lit);
+ } break;
+ case ::HIR::TypeRef::Data::TAG_Function:
+ ASSERT_BUG(sp, lit.is_BorrowPath(), ty << " not Literal::BorrowPath - " << lit);
+ putsize(0);
+ out_relocations.push_back(Reloc { base_ofs, 8, &lit.as_BorrowPath(), "" });
+ break;
+ TU_ARM(ty.m_data, Array, te) {
+ // What about byte strings?
+ // TODO: Assert size
+ ASSERT_BUG(sp, lit.is_List(), "not Literal::List - " << lit);
+ for(const auto& v : lit.as_List())
+ {
+ emit_literal_as_bytes(v, *te.inner, out_relocations, base_ofs);
+ size_t size;
+ assert(Target_GetSizeOf(sp, m_resolve, *te.inner, size));
+ base_ofs += size;
+ }
+ } break;
+ }
+ }
+ void emit_static_local(const ::HIR::Path& p, const ::HIR::Static& item, const Trans_Params& params) override
+ {
+ ::MIR::Function empty_fcn;
+ ::MIR::TypeResolve top_mir_res { sp, m_resolve, FMT_CB(ss, ss << "static " << p;), ::HIR::TypeRef(), {}, empty_fcn };
+ m_mir_res = &top_mir_res;
+
+ TRACE_FUNCTION_F(p);
+
+ ::std::vector<Reloc> relocations;
+
+ auto type = params.monomorph(m_resolve, item.m_type);
+ m_of << "static " << p << ": " << type << " = \"";
+ emit_literal_as_bytes(item.m_value_res, type, relocations, 0);
+ m_of << "\"";
+ m_of << "{";
+ for(const auto& r : relocations)
+ {
+ // TODO.
+ }
+ m_of << "}";
+ m_of << ";\n";
+
+ m_mir_res = nullptr;
+ }
void emit_function_code(const ::HIR::Path& p, const ::HIR::Function& item, const Trans_Params& params, bool is_extern_def, const ::MIR::FunctionPointer& code) override
{
TRACE_FUNCTION_F(p);