summaryrefslogtreecommitdiff
path: root/tools/standalone_miri/module_tree.cpp
diff options
context:
space:
mode:
authorJohn Hodge <tpg@ucc.asn.au>2018-06-03 14:57:05 +0800
committerJohn Hodge <tpg@ucc.asn.au>2018-06-03 14:57:05 +0800
commitbf8f8b4b4a9fe273451be59f68acafbe61968b83 (patch)
tree82993550cb3c88de0edbd55d79e4ea8e8cefffac /tools/standalone_miri/module_tree.cpp
parent39b3cf53798683e496804f8322da2254b10850f4 (diff)
parenta7fb27789a2b34543851d207120e2c0001ee9c27 (diff)
downloadmrust-bf8f8b4b4a9fe273451be59f68acafbe61968b83.tar.gz
Merge branch 'master' of https://github.com/thepowersgang/mrustc
Diffstat (limited to 'tools/standalone_miri/module_tree.cpp')
-rw-r--r--tools/standalone_miri/module_tree.cpp214
1 files changed, 108 insertions, 106 deletions
diff --git a/tools/standalone_miri/module_tree.cpp b/tools/standalone_miri/module_tree.cpp
index 2513140a..8beba018 100644
--- a/tools/standalone_miri/module_tree.cpp
+++ b/tools/standalone_miri/module_tree.cpp
@@ -5,6 +5,7 @@
#include "lex.hpp"
#include "value.hpp"
#include <iostream>
+#include <algorithm> // std::find
#include "debug.hpp"
ModuleTree::ModuleTree()
@@ -31,18 +32,19 @@ struct Parser
RawType parse_core_type();
::HIR::TypeRef parse_type();
::HIR::GenericPath parse_tuple();
+
+ const DataType* get_composite(::HIR::GenericPath gp);
};
void ModuleTree::load_file(const ::std::string& path)
{
if( !loaded_files.insert(path).second )
{
- ::std::cout << "DEBUG: load_file(" << path << ") - Already loaded" << ::std::endl;
+ LOG_DEBUG("load_file(" << path << ") - Already loaded");
return ;
}
- ::std::cout << "DEBUG: load_file(" << path << ")" << ::std::endl;
- //TRACE_FUNCTION_F(path);
+ TRACE_FUNCTION_R(path, "");
auto parse = Parser { *this, path };
while(parse.parse_one())
@@ -53,8 +55,8 @@ void ModuleTree::load_file(const ::std::string& path)
// Parse a single item from a .mir file
bool Parser::parse_one()
{
- //::std::cout << "DEBUG: parse_one" << ::std::endl;
- if( lex.next() == "" ) // EOF?
+ //TRACE_FUNCTION_F("");
+ if( lex.next() == TokenClass::Eof )
{
return false;
}
@@ -65,7 +67,7 @@ bool Parser::parse_one()
lex.check(TokenClass::String);
auto path = ::std::move(lex.next().strval);
lex.consume();
- //::std::cout << "DEBUG: parse_one - crate '" << path << "'" << ::std::endl;
+ //LOG_TRACE(lex << "crate '" << path << "'");
lex.check_consume(';');
@@ -75,7 +77,7 @@ bool Parser::parse_one()
else if( lex.consume_if("fn") )
{
auto p = parse_path();
- //::std::cout << "DEBUG: parse_one - fn " << p << ::std::endl;
+ //LOG_TRACE(lex << "fn " << p);
lex.check_consume('(');
::std::vector<::HIR::TypeRef> arg_tys;
@@ -91,7 +93,7 @@ bool Parser::parse_one()
{
rv_ty = parse_type();
}
-
+
if( lex.consume_if('=') )
{
auto link_name = ::std::move(lex.check_consume(TokenClass::String).strval);
@@ -99,6 +101,7 @@ bool Parser::parse_one()
auto abi = ::std::move(lex.check_consume(TokenClass::String).strval);
lex.check_consume(';');
+ LOG_DEBUG(lex << "extern fn " << p);
auto p2 = p;
tree.functions.insert( ::std::make_pair(::std::move(p), Function { ::std::move(p2), ::std::move(arg_tys), rv_ty, {link_name, abi}, {} }) );
}
@@ -106,6 +109,7 @@ bool Parser::parse_one()
{
auto body = parse_body();
+ LOG_DEBUG(lex << "fn " << p);
auto p2 = p;
tree.functions.insert( ::std::make_pair(::std::move(p), Function { ::std::move(p2), ::std::move(arg_tys), rv_ty, {}, ::std::move(body) }) );
}
@@ -113,13 +117,22 @@ bool Parser::parse_one()
else if( lex.consume_if("static") )
{
auto p = parse_path();
- //::std::cout << "DEBUG: parse_one - static " << p << ::std::endl;
+ //LOG_TRACE(lex << "static " << p);
lex.check_consume(':');
auto ty = parse_type();
// TODO: externs?
lex.check_consume('=');
lex.check(TokenClass::String);
auto data = ::std::move(lex.consume().strval);
+
+ Static s;
+ s.val = Value(ty);
+ // - Statics need to always have an allocation (for references)
+ if( !s.val.allocation )
+ s.val.create_allocation();
+ s.val.write_bytes(0, data.data(), data.size());
+ s.ty = ty;
+
if( lex.consume_if('{') )
{
while( !lex.consume_if('}') )
@@ -134,15 +147,20 @@ bool Parser::parse_one()
if( lex.next() == TokenClass::String )
{
auto reloc_str = ::std::move(lex.consume().strval);
- // TODO: Add relocation
+
+ auto a = Allocation::new_alloc( reloc_str.size() );
+ //a.alloc().set_tag();
+ a->write_bytes(0, reloc_str.data(), reloc_str.size());
+ s.val.allocation->relocations.push_back({ ofs, /*size,*/ RelocationPtr::new_alloc(::std::move(a)) });
}
- else if( lex.next() == "::" )
+ else if( lex.next() == "::" || lex.next() == "<" )
{
auto reloc_path = parse_path();
- // TODO: Add relocation
+ s.val.allocation->relocations.push_back({ ofs, /*size,*/ RelocationPtr::new_fcn(reloc_path) });
}
else
{
+ LOG_FATAL(lex << "Unexepcted token " << lex.next() << " in relocation value");
throw "ERROR";
}
if( ! lex.consume_if(',') ) {
@@ -153,15 +171,13 @@ bool Parser::parse_one()
}
lex.check_consume(';');
- Value val = Value(ty);
- val.write_bytes(0, data.data(), data.size());
-
- tree.statics.insert(::std::make_pair( ::std::move(p), ::std::move(val) ));
+ LOG_DEBUG(lex << "static " << p);
+ tree.statics.insert(::std::make_pair( ::std::move(p), ::std::move(s) ));
}
else if( lex.consume_if("type") )
{
auto p = (lex.consume_if('(')) ? parse_tuple() : parse_genericpath();
- //::std::cout << "DEBUG: parse_one - type " << p << ::std::endl;
+ //LOG_TRACE("type " << p);
auto rv = DataType {};
rv.my_path = p;
@@ -206,7 +222,7 @@ bool Parser::parse_one()
lex.check_consume('=');
auto ty = parse_type();
lex.check_consume(';');
- //::std::cout << ofs << " " << ty << ::std::endl;
+ //LOG_DEBUG(ofs << " " << ty);
rv.fields.push_back(::std::make_pair(ofs, ::std::move(ty)));
}
@@ -250,7 +266,7 @@ bool Parser::parse_one()
//const auto* tag_ty = &rv.fields.at(base_idx).second;
//for(auto idx : other_idx)
//{
- // assert(tag_ty->wrappers.size() == 0);
+ // assert(tag_ty->get_wrapper() == nullptr);
// assert(tag_ty->inner_type == RawType::Composite);
// LOG_TODO(lex << "Calculate tag offset with nested tag - " << idx << " ty=" << *tag_ty);
//}
@@ -272,10 +288,10 @@ bool Parser::parse_one()
if( rv.alignment == 0 && rv.fields.size() != 0 )
{
- ::std::cerr << lex << "Alignment of zero with fields is invalid, " << p << ::std::endl;
- throw "ERROR";
+ LOG_ERROR(lex << "Alignment of zero with fields is invalid, " << p);
}
+ LOG_DEBUG(lex << "type " << p);
auto it = this->tree.data_types.find(p);
if( it != this->tree.data_types.end() )
{
@@ -285,10 +301,7 @@ bool Parser::parse_one()
}
else
{
- //::std::cerr << lex << "Duplicate definition of " << p << ::std::endl;
-
- // Not really an error, can happen when loading crates
- //throw "ERROR";
+ //LOG_ERROR(lex << "Duplicate definition of " << p);
}
}
else
@@ -298,7 +311,7 @@ bool Parser::parse_one()
}
else
{
- ::std::cerr << lex << "Unexpected token at root - " << lex.next() << ::std::endl;
+ LOG_ERROR(lex << "Unexpected token at root - " << lex.next());
// Unknown item type
throw "ERROR";
@@ -342,8 +355,7 @@ bool Parser::parse_one()
lv = ::MIR::LValue::make_Argument({ idx });
}
catch(const ::std::exception& e) {
- ::std::cerr << lex << "Invalid argument name - " << name << " - " << e.what() << ::std::endl;
- throw "ERROR";
+ LOG_ERROR(lex << "Invalid argument name - " << name << " - " << e.what());
}
}
// Hard-coded "RETURN" lvalue
@@ -354,8 +366,7 @@ bool Parser::parse_one()
else {
auto it = ::std::find(var_names.begin(), var_names.end(), name);
if( it == var_names.end() ) {
- ::std::cerr << lex << "Cannot find variable named '" << name << "'" << ::std::endl;
- throw "ERROR";
+ LOG_ERROR(lex << "Cannot find variable named '" << name << "'");
}
lv = ::MIR::LValue::make_Local(static_cast<unsigned>(it - var_names.begin()));
}
@@ -366,8 +377,7 @@ bool Parser::parse_one()
lv = ::MIR::LValue( ::std::move(path) );
}
else {
- ::std::cerr << lex << "Unexpected token in LValue - " << lex.next() << ::std::endl;
- throw "ERROR";
+ LOG_ERROR(lex << "Unexpected token in LValue - " << lex.next());
}
for(;;)
{
@@ -437,8 +447,7 @@ bool Parser::parse_one()
}
else
{
- ::std::cerr << p.lex << "Expected an integer or float, got " << p.lex.next() << ::std::endl;
- throw "ERROR";
+ LOG_ERROR(p.lex << "Expected an integer or float, got " << p.lex.next());
}
}
else if( p.lex.consume_if("true") ) {
@@ -453,8 +462,7 @@ bool Parser::parse_one()
return ::MIR::Constant::make_ItemAddr({ ::std::move(path) });
}
else {
- ::std::cerr << p.lex << "BUG? " << p.lex.next() << ::std::endl;
- throw "ERROR";
+ LOG_BUG(p.lex << "BUG? " << p.lex.next());
}
}
@@ -635,8 +643,7 @@ bool Parser::parse_one()
op = ::MIR::eUniOp::NEG;
}
else {
- ::std::cerr << lex << "Unexpected token in uniop - " << lex.next() << ::std::endl;
- throw "ERROR";
+ LOG_ERROR(lex << "Unexpected token in uniop - " << lex.next());
}
auto lv = H::parse_lvalue(*this, var_names);
@@ -661,7 +668,7 @@ bool Parser::parse_one()
case '<':
if( t.strval[1] == '<' )
op = ::MIR::eBinOp::BIT_SHL;
- else if( lex.consume_if('=') )
+ else if( t.strval[1] == '=' )
op = ::MIR::eBinOp::LE;
else
op = ::MIR::eBinOp::LT;
@@ -683,8 +690,7 @@ bool Parser::parse_one()
lex.check_consume('=');
break;
default:
- ::std::cerr << lex << "Unexpected token " << t << " in BINOP" << ::std::endl;
- throw "ERROR";
+ LOG_ERROR(lex << "Unexpected token " << t << " in BINOP");
}
auto lv2 = H::parse_param(*this, var_names);
@@ -705,8 +711,7 @@ bool Parser::parse_one()
src_rval = ::MIR::RValue::make_DstMeta({ ::std::move(lv) });
}
else {
- ::std::cerr << lex << "Unexpected token in RValue - " << lex.next() << ::std::endl;
- throw "ERROR";
+ LOG_ERROR(lex << "Unexpected token in RValue - " << lex.next());
}
stmts.push_back(::MIR::Statement::make_Assign({ ::std::move(dst_val), ::std::move(src_rval) }));
@@ -717,8 +722,7 @@ bool Parser::parse_one()
auto name = ::std::move(lex.consume().strval);
auto df_it = ::std::find(drop_flag_names.begin(), drop_flag_names.end(), name);
if( df_it == drop_flag_names.end() ) {
- ::std::cerr << lex << "Unable to find drop flag '" << name << "'" << ::std::endl;
- throw "ERROR";
+ LOG_ERROR(lex << "Unable to find drop flag '" << name << "'");
}
auto df_idx = static_cast<unsigned>( df_it - drop_flag_names.begin() );
lex.check_consume('=');
@@ -736,8 +740,7 @@ bool Parser::parse_one()
auto name = ::std::move(lex.consume().strval);
df_it = ::std::find(drop_flag_names.begin(), drop_flag_names.end(), name);
if( df_it == drop_flag_names.end() ) {
- ::std::cerr << lex << "Unable to find drop flag '" << name << "'" << ::std::endl;
- throw "ERROR";
+ LOG_ERROR(lex << "Unable to find drop flag '" << name << "'");
}
auto other_idx = static_cast<unsigned>( df_it - drop_flag_names.begin() );
@@ -759,8 +762,7 @@ bool Parser::parse_one()
auto name = ::std::move(lex.consume().strval);
auto df_it = ::std::find(drop_flag_names.begin(), drop_flag_names.end(), name);
if( df_it == drop_flag_names.end() ) {
- ::std::cerr << lex << "Unable to find drop flag '" << name << "'" << ::std::endl;
- throw "ERROR";
+ LOG_ERROR(lex << "Unable to find drop flag '" << name << "'");
}
flag_idx = static_cast<unsigned>( df_it - drop_flag_names.begin() );
}
@@ -824,7 +826,7 @@ bool Parser::parse_one()
break;
}
lex.check_consume(';');
- //::std::cout << stmts.back() << ::std::endl;
+ //LOG_TRACE(stmts.back());
}
lex.check(TokenClass::Ident);
@@ -910,8 +912,7 @@ bool Parser::parse_one()
vals = ::MIR::SwitchValues::make_String(::std::move(values));
}
else {
- ::std::cerr << lex << "Unexpected token for SWITCHVALUE value - " << lex.next() << ::std::endl;
- throw "ERROR";
+ LOG_ERROR(lex << "Unexpected token for SWITCHVALUE value - " << lex.next());
}
lex.check_consume('_');
lex.check_consume('=');
@@ -958,8 +959,7 @@ bool Parser::parse_one()
}
else
{
- ::std::cerr << lex << "Unexpected token at terminator - " << lex.next() << ::std::endl;
- throw "ERROR";
+ LOG_ERROR(lex << "Unexpected token at terminator - " << lex.next());
}
lex.check_consume('}');
@@ -1050,7 +1050,7 @@ bool Parser::parse_one()
}
RawType Parser::parse_core_type()
{
- //::std::cout << lex.next() << ::std::endl;
+ //LOG_TRACE(lex.next());
lex.check(TokenClass::Ident);
auto tok = lex.consume();
// Primitive type.
@@ -1106,8 +1106,7 @@ RawType Parser::parse_core_type()
return RawType::Str;
}
else {
- ::std::cerr << lex << "Unknown core type " << tok << "'" << ::std::endl;
- throw "ERROR";
+ LOG_ERROR(lex << "Unknown core type " << tok << "'");
}
}
::HIR::TypeRef Parser::parse_type()
@@ -1121,19 +1120,8 @@ RawType Parser::parse_core_type()
// Tuples! Should point to a composite
::HIR::GenericPath gp = parse_tuple();
- // Look up this type, then create a TypeRef referring to the type in the datastore
- // - May need to create an unpopulated type?
- auto it = tree.data_types.find(gp);
- if( it == tree.data_types.end() )
- {
- // TODO: Later on need to check if the type is valid.
- auto v = ::std::make_unique<DataType>(DataType {});
- v->my_path = gp;
- auto ir = tree.data_types.insert(::std::make_pair( ::std::move(gp), ::std::move(v)) );
- it = ir.first;
- }
// Good.
- return ::HIR::TypeRef(it->second.get());
+ return ::HIR::TypeRef( this->get_composite(::std::move(gp)) );
}
else if( lex.consume_if('[') )
{
@@ -1142,15 +1130,14 @@ RawType Parser::parse_core_type()
{
size_t size = lex.next().integer();
lex.consume();
- rv.wrappers.insert( rv.wrappers.begin(), { TypeWrapper::Ty::Array, size });
+ lex.check_consume(']');
+ return ::std::move(rv).wrap( TypeWrapper::Ty::Array, size );
}
else
{
- // TODO: How to handle arrays?
- rv.wrappers.insert( rv.wrappers.begin(), { TypeWrapper::Ty::Slice, 0 });
+ lex.check_consume(']');
+ return ::std::move(rv).wrap( TypeWrapper::Ty::Slice, 0 );
}
- lex.check_consume(']');
- return rv;
}
else if( lex.consume_if('!') )
{
@@ -1158,6 +1145,11 @@ RawType Parser::parse_core_type()
}
else if( lex.consume_if('&') )
{
+ if( lex.next() == TokenClass::Lifetime )
+ {
+ // TODO: Handle lifetime names (require them?)
+ lex.consume();
+ }
auto bt = ::HIR::BorrowType::Shared;
if( lex.consume_if("move") )
bt = ::HIR::BorrowType::Move;
@@ -1165,9 +1157,7 @@ RawType Parser::parse_core_type()
bt = ::HIR::BorrowType::Unique;
else
; // keep as shared
- auto rv = parse_type();
- rv.wrappers.insert( rv.wrappers.begin(), { TypeWrapper::Ty::Borrow, static_cast<size_t>(bt) });
- return rv;
+ return parse_type().wrap( TypeWrapper::Ty::Borrow, static_cast<size_t>(bt) );
}
else if( lex.consume_if('*') )
{
@@ -1180,26 +1170,12 @@ RawType Parser::parse_core_type()
; // keep as shared
else
throw "ERROR";
- auto rv = parse_type();
- rv.wrappers.insert( rv.wrappers.begin(), { TypeWrapper::Ty::Pointer, static_cast<size_t>(bt) });
- return rv;
+ return parse_type().wrap( TypeWrapper::Ty::Pointer, static_cast<size_t>(bt) );
}
else if( lex.next() == "::" )
{
auto path = parse_genericpath();
- // Look up this type, then create a TypeRef referring to the type in the datastore
- // - May need to create an unpopulated type?
- auto it = tree.data_types.find(path);
- if( it == tree.data_types.end() )
- {
- // TODO: Later on need to check if the type is valid.
- auto v = ::std::make_unique<DataType>(DataType {});
- v->my_path = path;
- auto ir = tree.data_types.insert(::std::make_pair( ::std::move(path), ::std::move(v)) );
- it = ir.first;
- }
- // Good.
- return ::HIR::TypeRef(it->second.get());
+ return ::HIR::TypeRef( this->get_composite(::std::move(path)));
}
else if( lex.next() == "extern" || lex.next() == "fn" || lex.next() == "unsafe" )
{
@@ -1269,12 +1245,28 @@ RawType Parser::parse_core_type()
::std::vector<::HIR::GenericPath> markers;
while(lex.consume_if('+'))
{
- // TODO: Detect/parse lifetimes?
- markers.push_back(parse_genericpath());
+ if( lex.next() == TokenClass::Lifetime )
+ {
+ // TODO: Include lifetimes in output?
+ lex.consume();
+ }
+ else
+ {
+ markers.push_back(parse_genericpath());
+ }
}
lex.consume_if(')');
- return ::HIR::TypeRef(RawType::TraitObject);
- // TODO: Generate the vtable path and locate that struct
+
+ auto rv = ::HIR::TypeRef(RawType::TraitObject);
+ if( base_trait != ::HIR::GenericPath() )
+ {
+ // Generate vtable path
+ auto vtable_path = base_trait;
+ vtable_path.m_simplepath.ents.back() += "#vtable";
+ // - TODO: Associated types?
+ rv.composite_type = this->get_composite( ::std::move(vtable_path) );
+ }
+ return rv;
}
else if( lex.next() == TokenClass::Ident )
{
@@ -1282,10 +1274,22 @@ RawType Parser::parse_core_type()
}
else
{
- ::std::cerr << lex << "Unexpected token in type - " << lex.next() << ::std::endl;
- throw "ERROR";
+ LOG_ERROR(lex << "Unexpected token in type - " << lex.next());
}
}
+const DataType* Parser::get_composite(::HIR::GenericPath gp)
+{
+ auto it = tree.data_types.find(gp);
+ if( it == tree.data_types.end() )
+ {
+ // TODO: Later on need to check if the type is valid.
+ auto v = ::std::make_unique<DataType>(DataType {});
+ v->my_path = gp;
+ auto ir = tree.data_types.insert(::std::make_pair( ::std::move(gp), ::std::move(v)) );
+ it = ir.first;
+ }
+ return it->second.get();
+}
::HIR::SimplePath ModuleTree::find_lang_item(const char* name) const
{
@@ -1296,8 +1300,7 @@ const Function& ModuleTree::get_function(const ::HIR::Path& p) const
auto it = functions.find(p);
if(it == functions.end())
{
- ::std::cerr << "Unable to find function " << p << " for invoke" << ::std::endl;
- throw "";
+ LOG_ERROR("Unable to find function " << p << " for invoke");
}
return it->second;
}
@@ -1310,17 +1313,16 @@ const Function* ModuleTree::get_function_opt(const ::HIR::Path& p) const
}
return &it->second;
}
-Value& ModuleTree::get_static(const ::HIR::Path& p)
+Static& ModuleTree::get_static(const ::HIR::Path& p)
{
auto it = statics.find(p);
if(it == statics.end())
{
- ::std::cerr << "Unable to find static " << p << " for invoke" << ::std::endl;
- throw "";
+ LOG_ERROR("Unable to find static " << p << " for invoke");
}
return it->second;
}
-Value* ModuleTree::get_static_opt(const ::HIR::Path& p)
+Static* ModuleTree::get_static_opt(const ::HIR::Path& p)
{
auto it = statics.find(p);
if(it == statics.end())
@@ -1328,4 +1330,4 @@ Value* ModuleTree::get_static_opt(const ::HIR::Path& p)
return nullptr;
}
return &it->second;
-} \ No newline at end of file
+}