summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--src/trans/codegen_mmir.cpp13
-rw-r--r--tools/standalone_miri/hir_sim.cpp16
-rw-r--r--tools/standalone_miri/lex.cpp216
-rw-r--r--tools/standalone_miri/lex.hpp12
-rw-r--r--tools/standalone_miri/module_tree.cpp259
-rw-r--r--tools/standalone_miri/module_tree.hpp3
-rw-r--r--vsproject/build_rustc_minicargo.cmd2
-rw-r--r--vsproject/build_rustc_minicargo_mmir.cmd12
9 files changed, 453 insertions, 81 deletions
diff --git a/.gitignore b/.gitignore
index 3b3c93d3..62e8c51c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -53,4 +53,5 @@
/bnf/rust.output
/bnf/test.bin
/vsproject/output
+/vsproject/output_mmir
/vsproject/standalone_miri/x64
diff --git a/src/trans/codegen_mmir.cpp b/src/trans/codegen_mmir.cpp
index b3b73cdb..9ab406e0 100644
--- a/src/trans/codegen_mmir.cpp
+++ b/src/trans/codegen_mmir.cpp
@@ -147,24 +147,23 @@ namespace
{
if( is_executable )
{
- m_of << "fn main(i32, *const *const i8): i32 {\n";
- m_of << "\t0: {\n";
+ m_of << "fn ::main#(i32, *const *const i8): i32 {\n";
auto c_start_path = m_resolve.m_crate.get_lang_item_path_opt("mrustc-start");
if( c_start_path == ::HIR::SimplePath() )
{
- m_of << "\tlet m: fn();";
+ m_of << "\tlet m: fn();\n";
m_of << "\t0: {\n";
- m_of << "\t\tASSIGN m = " << Trans_Mangle( ::HIR::GenericPath(m_resolve.m_crate.get_lang_item_path(Span(), "mrustc-main")) ) << "\n";
- m_of << "\t\tCALL RETURN = " << Trans_Mangle(::HIR::GenericPath(c_start_path)) << "(m, arg1, arg2) goto 1 else 1;\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";
}
else
{
m_of << "\t0: {\n";
- m_of << "\t\tCALL RETURN = " << Trans_Mangle(::HIR::GenericPath(c_start_path)) << "(arg1, arg2) goto 1 else 1;\n";
+ m_of << "\t\tCALL RETURN = " << ::HIR::GenericPath(c_start_path) << "(arg1, arg2) goto 1 else 1;\n";
}
m_of << "\t}\n";
m_of << "\t1: {\n";
- m_of << "\t\tRETURN}\n";
+ m_of << "\t\tRETURN\n";
m_of << "\t}\n";
m_of << "}\n";
}
diff --git a/tools/standalone_miri/hir_sim.cpp b/tools/standalone_miri/hir_sim.cpp
index 090e0f6b..0010e202 100644
--- a/tools/standalone_miri/hir_sim.cpp
+++ b/tools/standalone_miri/hir_sim.cpp
@@ -12,6 +12,7 @@
size_t HIR::TypeRef::get_size(size_t ofs) const
{
+ const size_t POINTER_SIZE = 8;
if( this->wrappers.size() <= ofs )
{
switch(this->inner_type)
@@ -33,7 +34,12 @@ size_t HIR::TypeRef::get_size(size_t ofs) const
return 8;
case RawType::U128: case RawType::I128:
return 16;
+
+ case RawType::Function: // This should probably be invalid?
+ case RawType::USize: case RawType::ISize:
+ return POINTER_SIZE;
}
+ throw "";
}
switch(this->wrappers[ofs].type)
@@ -48,21 +54,21 @@ size_t HIR::TypeRef::get_size(size_t ofs) const
if( this->inner_type == RawType::Composite )
throw "TODO";
else if( this->inner_type == RawType::Str )
- return 8*2;
+ return POINTER_SIZE*2;
else if( this->inner_type == RawType::TraitObject )
- return 8*2;
+ return POINTER_SIZE*2;
else
{
- return 8;
+ return POINTER_SIZE;
}
}
else if( this->wrappers[ofs+1].type == TypeWrapper::Ty::Slice )
{
- return 8*2;
+ return POINTER_SIZE*2;
}
else
{
- return 8;
+ return POINTER_SIZE;
}
case TypeWrapper::Ty::Slice:
throw "Invalid";
diff --git a/tools/standalone_miri/lex.cpp b/tools/standalone_miri/lex.cpp
index a602128a..48a9e0cd 100644
--- a/tools/standalone_miri/lex.cpp
+++ b/tools/standalone_miri/lex.cpp
@@ -53,6 +53,9 @@ double Token::real() const
case TokenClass::String:
os << "\"" << x.strval << "\"";
break;
+ case TokenClass::ByteString:
+ os << "b\"" << x.strval << "\"";
+ break;
}
return os;
}
@@ -75,6 +78,18 @@ const Token& Lexer::next() const
{
return m_cur;
}
+const Token& Lexer::lookahead()
+{
+ if( !m_next_valid )
+ {
+ auto tmp = ::std::move(m_cur);
+ advance();
+ m_next = ::std::move(m_cur);
+ m_cur = ::std::move(tmp);
+ m_next_valid = true;
+ }
+ return m_next;
+}
Token Lexer::consume()
{
auto rv = ::std::move(m_cur);
@@ -107,6 +122,13 @@ void Lexer::check(const char* s)
void Lexer::advance()
{
+ if( m_next_valid )
+ {
+ m_cur = ::std::move(m_next);
+ m_next_valid = false;
+ return ;
+ }
+
char ch;
do
{
@@ -177,6 +199,20 @@ void Lexer::advance()
ch = '#';
}
+ if(ch == 'b')
+ {
+ ch = m_if.get();
+ if( ch == '"' ) {
+ auto val = this->parse_string();
+ m_cur = Token { TokenClass::ByteString, ::std::move(val) };
+ return ;
+ }
+ else {
+ m_if.unget();
+ }
+ ch = 'b';
+ }
+
if( m_if.eof() )
{
m_cur = Token { TokenClass::Eof, "" };
@@ -203,7 +239,7 @@ void Lexer::advance()
throw "ERROR";
uint64_t rv = 0;
- while(::std::isdigit(ch))
+ while(::std::isxdigit(ch))
{
rv *= 16;
if( ch <= '9' )
@@ -218,9 +254,65 @@ void Lexer::advance()
}
if( ch == '.' || ch == 'p' )
{
+ uint64_t frac = 0;
+ if( ch == '.' )
+ {
+ ch = m_if.get();
+ int pos = 0;
+ while(::std::isxdigit(ch))
+ {
+ frac *= 16;
+ if( ch <= '9' )
+ frac += ch - '0';
+ else if( ch <= 'F' )
+ frac += ch - 'A' + 10;
+ else if( ch <= 'f' )
+ frac += ch - 'a' + 10;
+ else
+ throw "";
+ pos ++;
+ ch = m_if.get();
+ }
+ while(pos < 52/4)
+ {
+ frac *= 16;
+ pos ++;
+ }
+ }
+ int exp = 0;
+ if( ch == 'p' )
+ {
+ ch = m_if.get();
+ bool neg = false;
+ if( ch == '-' ) {
+ neg = true;
+ ch = m_if.get();
+ }
+ if( !::std::isdigit(ch) )
+ throw "ERROR";
+ while(::std::isdigit(ch))
+ {
+ exp *= 10;
+ exp += ch - '0';
+ ch = m_if.get();
+ }
+ if(neg)
+ exp = -exp;
+ }
// Floats!
- ::std::cerr << *this << "TODO - Hex floats" << ::std::endl;
- throw "TODO";
+ //::std::cerr << *this << "TODO - Hex floats - " << rv << "." << frac << "p" << exp << ::std::endl;
+ if( rv != 1 ) {
+ ::std::cerr << *this << "Invalid hex float literal, whole component must be 1" << ::std::endl;
+ throw "ERROR";
+ }
+ if( frac >= (1ull << 52) ) {
+ ::std::cerr << *this << "Invalid hex float literal, fractional component is more than 52 bits" << ::std::endl;
+ throw "ERROR";
+ }
+ uint64_t vi = (static_cast<uint64_t>(exp) << 52) | frac;
+ m_cur = Token { TokenClass::Real, "" };
+ m_cur.numbers.real_val = *reinterpret_cast<const double*>(&vi);
+ return ;
}
m_if.unget();
@@ -254,31 +346,7 @@ void Lexer::advance()
}
else if( ch == '"' )
{
- ::std::string val;
- while( (ch = m_if.get()) != '"' )
- {
- if( ch == '\\' )
- {
- switch( (ch = m_if.get()) )
- {
- case '0': val.push_back(0); break;
- case 'n': val.push_back(10); break;
- case 'x': {
- char tmp[3] = { static_cast<char>(m_if.get()), static_cast<char>(m_if.get()), 0};
- val.push_back( static_cast<char>(::std::strtol(tmp, nullptr, 16)) );
- break; }
- case '"': val.push_back('"'); break;
- case '\\': val.push_back('\\'); break;
- default:
- ::std::cerr << *this << "Unexpected escape sequence '\\" << ch << "'" << ::std::endl;
- throw "ERROR";
- }
- }
- else
- {
- val.push_back(ch);
- }
- }
+ auto val = this->parse_string();
m_cur = Token { TokenClass::String, ::std::move(val) };
}
else
@@ -304,6 +372,7 @@ void Lexer::advance()
case '&': m_cur = Token { TokenClass::Symbol, "&" }; break;
case '*': m_cur = Token { TokenClass::Symbol, "*" }; break;
case '/': m_cur = Token { TokenClass::Symbol, "/" }; break;
+ case '%': m_cur = Token { TokenClass::Symbol, "%" }; break;
case '-': m_cur = Token { TokenClass::Symbol, "-" }; break;
case '+': m_cur = Token { TokenClass::Symbol, "+" }; break;
case '^': m_cur = Token { TokenClass::Symbol, "^" }; break;
@@ -314,7 +383,19 @@ void Lexer::advance()
case '(': m_cur = Token { TokenClass::Symbol, "(" }; break;
case ')': m_cur = Token { TokenClass::Symbol, ")" }; break;
- case '<': m_cur = Token { TokenClass::Symbol, "<" }; break;
+ case '<':
+ // Combine << (note, doesn't need to happen for >>)
+ ch = m_if.get();
+ if( ch == '<' )
+ {
+ m_cur = Token { TokenClass::Symbol, "<<" };
+ }
+ else
+ {
+ m_if.unget();
+ m_cur = Token { TokenClass::Symbol, "<" };
+ }
+ break;
case '>': m_cur = Token { TokenClass::Symbol, ">" }; break;
case '[': m_cur = Token { TokenClass::Symbol, "[" }; break;
case ']': m_cur = Token { TokenClass::Symbol, "]" }; break;
@@ -326,6 +407,83 @@ void Lexer::advance()
}
}
}
+::std::string Lexer::parse_string()
+{
+ ::std::string val;
+ char ch;
+ while( (ch = m_if.get()) != '"' )
+ {
+ if( ch == '\\' )
+ {
+ switch( (ch = m_if.get()) )
+ {
+ case '0': val.push_back(0); break;
+ case 'n': val.push_back(10); break;
+ case 'x': {
+ char tmp[3] = { static_cast<char>(m_if.get()), static_cast<char>(m_if.get()), 0};
+ val.push_back( static_cast<char>(::std::strtol(tmp, nullptr, 16)) );
+ } break;
+ case 'u': {
+ ch = m_if.get();
+ if( ch != '{' ) {
+ ::std::cerr << *this << "Unexpected character in unicode escape - '" << ch << "'" << ::std::endl;
+ throw "ERROR";
+ }
+ ch = m_if.get();
+ uint32_t v = 0;
+ do {
+ if( !isxdigit(ch) ) {
+ ::std::cerr << *this << "Unexpected character in unicode escape - '" << ch << "'" << ::std::endl;
+ throw "ERROR";
+ }
+ v *= 16;
+ if( ch <= '9' )
+ v += ch - '0';
+ else if( ch <= 'F' )
+ v += ch - 'A' + 10;
+ else if( ch <= 'f' )
+ v += ch - 'a' + 10;
+ else
+ throw "";
+ ch = m_if.get();
+ } while(ch != '}');
+
+ if( v < 0x80 ) {
+ val.push_back(static_cast<char>(v));
+ }
+ else if( v < (0x1F+1)<<(1*6) ) {
+ val += (char)(0xC0 | ((v >> 6) & 0x1F));
+ val += (char)(0x80 | ((v >> 0) & 0x3F));
+ }
+ else if( v < (0x0F+1)<<(2*6) ) {
+ val += (char)(0xE0 | ((v >> 12) & 0x0F));
+ val += (char)(0x80 | ((v >> 6) & 0x3F));
+ val += (char)(0x80 | ((v >> 0) & 0x3F));
+ }
+ else if( v < (0x07+1)<<(3*6) ) {
+ val += (char)(0xF0 | ((v >> 18) & 0x07));
+ val += (char)(0x80 | ((v >> 12) & 0x3F));
+ val += (char)(0x80 | ((v >> 6) & 0x3F));
+ val += (char)(0x80 | ((v >> 0) & 0x3F));
+ }
+ else {
+ throw "";
+ }
+ } break;
+ case '"': val.push_back('"'); break;
+ case '\\': val.push_back('\\'); break;
+ default:
+ ::std::cerr << *this << "Unexpected escape sequence '\\" << ch << "'" << ::std::endl;
+ throw "ERROR";
+ }
+ }
+ else
+ {
+ val.push_back(ch);
+ }
+ }
+ return val;
+}
::std::ostream& operator<<(::std::ostream& os, const Lexer& x)
{
diff --git a/tools/standalone_miri/lex.hpp b/tools/standalone_miri/lex.hpp
index 8c785a5f..95130111 100644
--- a/tools/standalone_miri/lex.hpp
+++ b/tools/standalone_miri/lex.hpp
@@ -13,6 +13,7 @@ enum class TokenClass
Integer,
Real,
String,
+ ByteString,
};
struct Token
@@ -43,16 +44,21 @@ class Lexer
unsigned m_cur_line;
::std::ifstream m_if;
Token m_cur;
+ bool m_next_valid = false;
+ Token m_next;
public:
Lexer(const ::std::string& path);
+
const Token& next() const;
+ const Token& lookahead();
Token consume();
void check(TokenClass tc);
void check(char ch);
void check(const char* s);
- void check_consume(char ch) { check(ch); consume(); }
- void check_consume(const char* s) { check(s); consume(); }
+ Token check_consume(TokenClass tc) { check(tc); return consume(); }
+ Token check_consume(char ch) { check(ch); return consume(); }
+ Token check_consume(const char* s) { check(s); return consume(); }
bool consume_if(char ch) { if(next() == ch) { consume(); return true; } return false; }
bool consume_if(const char* s) { if(next() == s) { consume(); return true; } return false; }
@@ -60,4 +66,6 @@ public:
private:
void advance();
+
+ ::std::string parse_string();
};
diff --git a/tools/standalone_miri/module_tree.cpp b/tools/standalone_miri/module_tree.cpp
index 34d0376b..f056481b 100644
--- a/tools/standalone_miri/module_tree.cpp
+++ b/tools/standalone_miri/module_tree.cpp
@@ -33,6 +33,12 @@ struct Parser
void ModuleTree::load_file(const ::std::string& path)
{
+ if( !loaded_files.insert(path).second )
+ {
+ ::std::cout << "DEBUG: load_file(" << path << ") - Already loaded" << ::std::endl;
+ return ;
+ }
+
::std::cout << "DEBUG: load_file(" << path << ")" << ::std::endl;
//TRACE_FUNCTION_F(path);
auto parse = Parser { *this, path };
@@ -74,9 +80,10 @@ bool Parser::parse_one()
while(lex.next() != ')')
{
arg_tys.push_back( parse_type() );
- lex.check_consume(',');
+ if( !lex.consume_if(',') )
+ break;
}
- lex.consume();
+ lex.check_consume(')');
::HIR::TypeRef rv_ty;
if( lex.consume_if(':') )
{
@@ -109,11 +116,6 @@ bool Parser::parse_one()
lex.check_consume(',');
lex.check_consume("ALIGN");
rv.alignment = lex.consume().integer();
- if( rv.alignment == 0 )
- {
- ::std::cerr << lex << "Alignment of zero is invalid, " << p << ::std::endl;
- throw "ERROR";
- }
lex.check_consume(';');
// TODO: DST Meta
@@ -145,10 +147,15 @@ bool Parser::parse_one()
lex.consume();
size_t base_idx = lex.consume().integer();
::std::vector<size_t> other_idx;
- while(lex.next() == ',')
+ if( lex.consume_if(',') )
{
- lex.consume();
- other_idx.push_back( lex.consume().integer() );
+ while(lex.next() != ']')
+ {
+ lex.check(TokenClass::Integer);
+ other_idx.push_back( lex.consume().integer() );
+ if( !lex.consume_if(',') )
+ break;
+ }
}
lex.check_consume(']');
lex.check_consume('=');
@@ -170,6 +177,12 @@ bool Parser::parse_one()
}
lex.check_consume('}');
+ if( rv.alignment == 0 && rv.fields.size() != 0 )
+ {
+ ::std::cerr << lex << "Alignment of zero with fields is invalid, " << p << ::std::endl;
+ throw "ERROR";
+ }
+
auto it = this->tree.data_types.find(p);
if( it != this->tree.data_types.end() )
{
@@ -179,7 +192,8 @@ bool Parser::parse_one()
}
else
{
- ::std::cerr << lex << "Duplicate definition of " << p << ::std::endl;
+ //::std::cerr << lex << "Duplicate definition of " << p << ::std::endl;
+
// Not really an error, can happen when loading crates
//throw "ERROR";
}
@@ -302,11 +316,37 @@ bool Parser::parse_one()
auto cty = p.parse_core_type();
return ::MIR::Constant::make_Uint({ static_cast<uint64_t>(v), cty });
}
+ else if( p.lex.next() == TokenClass::String ) {
+ auto v = ::std::move( p.lex.consume().strval );
+ return ::MIR::Constant::make_StaticString(::std::move(v));
+ }
+ else if( p.lex.next() == TokenClass::ByteString ) {
+ ::std::vector<uint8_t> v;
+ for(char c : p.lex.consume().strval )
+ {
+ v.push_back( static_cast<uint8_t>(c) );
+ }
+ return ::MIR::Constant::make_Bytes(::std::move(v));
+ }
else if( p.lex.next() == '+' || p.lex.next() == '-' ) {
bool is_neg = (p.lex.consume() == '-');
- auto v = static_cast<int64_t>(p.lex.consume().integer());
- auto cty = p.parse_core_type();
- return ::MIR::Constant::make_Int({ is_neg ? -v : v, cty });
+ if( p.lex.next() == TokenClass::Integer )
+ {
+ auto v = static_cast<int64_t>(p.lex.consume().integer());
+ auto cty = p.parse_core_type();
+ return ::MIR::Constant::make_Int({ is_neg ? -v : v, cty });
+ }
+ else if( p.lex.next() == TokenClass::Real )
+ {
+ auto v = p.lex.consume().real();
+ auto cty = p.parse_core_type();
+ return ::MIR::Constant::make_Float({ is_neg ? -v : v, cty });
+ }
+ else
+ {
+ ::std::cerr << p.lex << "Expected an integer or float, got " << p.lex.next() << ::std::endl;
+ throw "ERROR";
+ }
}
else if( p.lex.consume_if("true") ) {
return ::MIR::Constant::make_Bool({ true });
@@ -328,10 +368,15 @@ bool Parser::parse_one()
// Parse a "Param" (constant or lvalue)
static ::MIR::Param parse_param(Parser& p, ::std::vector<::std::string>& var_names)
{
- if( p.lex.next() == TokenClass::Integer || p.lex.next() == '+' || p.lex.next() == '-' || p.lex.next() == '&' || p.lex.next() == "true" || p.lex.next() == "false" ) {
+ if( p.lex.next() == TokenClass::Integer || p.lex.next() == TokenClass::String || p.lex.next() == TokenClass::ByteString
+ || p.lex.next() == '+' || p.lex.next() == '-' || p.lex.next() == '&'
+ || p.lex.next() == "true" || p.lex.next() == "false"
+ )
+ {
return parse_const(p);
}
- else {
+ else
+ {
return parse_lvalue(p, var_names);
}
}
@@ -384,7 +429,11 @@ bool Parser::parse_one()
lex.check_consume('=');
::MIR::RValue src_rval;
// Literals
- if( lex.next() == TokenClass::Integer || lex.next() == '+' || lex.next() == '-' || lex.next() == "true" || lex.next() == "false" ) {
+ if( lex.next() == TokenClass::Integer || lex.next() == TokenClass::String || lex.next() == TokenClass::ByteString
+ || lex.next() == '+' || lex.next() == '-'
+ || lex.next() == "true" || lex.next() == "false"
+ )
+ {
src_rval = H::parse_const(*this);
}
// LValue (prefixed by =)
@@ -513,8 +562,9 @@ bool Parser::parse_one()
case '|': op = ::MIR::eBinOp::BIT_OR ; break;
case '&': op = ::MIR::eBinOp::BIT_AND; break;
case '^': op = ::MIR::eBinOp::BIT_XOR; break;
+ case '%': op = ::MIR::eBinOp::MOD; break;
case '<':
- if( lex.consume_if('<') )
+ if( t.strval[1] == '<' )
op = ::MIR::eBinOp::BIT_SHL;
else if( lex.consume_if('=') )
op = ::MIR::eBinOp::LE;
@@ -530,7 +580,9 @@ bool Parser::parse_one()
op = ::MIR::eBinOp::GT;
break;
case '=':
- op = ::MIR::eBinOp::EQ; if(0)
+ op = ::MIR::eBinOp::EQ;
+ lex.check_consume('=');
+ break;
case '!':
op = ::MIR::eBinOp::NE;
lex.check_consume('=');
@@ -620,9 +672,57 @@ bool Parser::parse_one()
stmts.push_back(::MIR::Statement::make_Drop({ kind, ::std::move(slot), flag_idx }));
}
- else if(lex.next() == "ASM")
+ else if( lex.consume_if("ASM") )
{
- throw "TODO";
+ lex.check_consume('(');
+ ::std::vector<::std::pair<::std::string, ::MIR::LValue>> out_vals;
+ while(lex.next() != ')')
+ {
+ auto cons = ::std::move(lex.check_consume(TokenClass::String).strval);
+ lex.check_consume(':');
+ auto lv = H::parse_lvalue(*this, var_names);
+ if(!lex.consume_if(','))
+ break;
+ out_vals.push_back(::std::make_pair(::std::move(cons), ::std::move(lv)));
+ }
+ lex.check_consume(')');
+ lex.check_consume('=');
+ auto tpl = ::std::move(lex.check_consume(TokenClass::String).strval);
+
+ lex.check_consume('(');
+ ::std::vector<::std::pair<::std::string, ::MIR::LValue>> in_vals;
+ while(lex.next() != ')')
+ {
+ auto cons = ::std::move(lex.check_consume(TokenClass::String).strval);
+ lex.check_consume(':');
+ auto lv = H::parse_lvalue(*this, var_names);
+ if(!lex.consume_if(','))
+ break;
+ in_vals.push_back(::std::make_pair(::std::move(cons), ::std::move(lv)));
+ }
+ lex.check_consume(')');
+
+ lex.check_consume('[');
+ ::std::vector<::std::string> clobbers;
+ while(lex.next() != ':')
+ {
+ clobbers.push_back( ::std::move(lex.check_consume(TokenClass::String).strval) );
+ if(!lex.consume_if(','))
+ break;
+ }
+ lex.check_consume(':');
+ ::std::vector<::std::string> flags;
+ while(lex.next() != ']')
+ {
+ flags.push_back( ::std::move(lex.check_consume(TokenClass::Ident).strval) );
+ if(!lex.consume_if(','))
+ break;
+ }
+ lex.check_consume(']');
+
+ stmts.push_back(::MIR::Statement::make_Asm({
+ ::std::move(tpl), ::std::move(out_vals), ::std::move(in_vals), ::std::move(clobbers), ::std::move(flags)
+ }));
}
else
{
@@ -673,10 +773,57 @@ bool Parser::parse_one()
term = ::MIR::Terminator::make_Switch({ ::std::move(val), ::std::move(targets) });
}
- else if( lex.consume_if("SWITCHVAL") )
+ else if( lex.consume_if("SWITCHVALUE") )
{
auto val = H::parse_lvalue(*this, var_names);
- throw "TODO";
+ ::std::vector<::MIR::BasicBlockId> targets;
+ lex.check_consume('{');
+ ::MIR::SwitchValues vals;
+ if( lex.next() == TokenClass::Integer ) {
+ ::std::vector<uint64_t> values;
+ while(lex.next() != '_')
+ {
+ values.push_back( lex.check_consume(TokenClass::Integer).integer() );
+ lex.check_consume('=');
+ targets.push_back( static_cast<unsigned>( lex.check_consume(TokenClass::Integer).integer() ) );
+ lex.check_consume(',');
+ }
+ vals = ::MIR::SwitchValues::make_Unsigned(::std::move(values));
+ }
+ else if( lex.next() == '+' || lex.next() == '-' ) {
+ ::std::vector<int64_t> values;
+ while(lex.next() != '_')
+ {
+ auto neg = lex.consume() == '-';
+ int64_t val = static_cast<int64_t>( lex.check_consume(TokenClass::Integer).integer() );
+ values.push_back( neg ? -val : val );
+ lex.check_consume('=');
+ targets.push_back( static_cast<unsigned>( lex.check_consume(TokenClass::Integer).integer() ) );
+ lex.check_consume(',');
+ }
+ vals = ::MIR::SwitchValues::make_Signed(::std::move(values));
+ }
+ else if( lex.next() == TokenClass::String ) {
+ ::std::vector<::std::string> values;
+ while(lex.next() != '_')
+ {
+ values.push_back( ::std::move(lex.check_consume(TokenClass::String).strval) );
+ lex.check_consume('=');
+ targets.push_back( static_cast<unsigned>( lex.check_consume(TokenClass::Integer).integer() ) );
+ lex.check_consume(',');
+ }
+ vals = ::MIR::SwitchValues::make_String(::std::move(values));
+ }
+ else {
+ ::std::cerr << lex << "Unexpected token for SWITCHVALUE value - " << lex.next() << ::std::endl;
+ throw "ERROR";
+ }
+ lex.check_consume('_');
+ lex.check_consume('=');
+ auto def_tgt = static_cast<unsigned>( lex.check_consume(TokenClass::Integer).integer() );
+ lex.check_consume('}');
+
+ term = ::MIR::Terminator::make_SwitchValue({ ::std::move(val), def_tgt, ::std::move(targets), ::std::move(vals) });
}
else if( lex.consume_if("CALL") )
{
@@ -777,9 +924,12 @@ bool Parser::parse_one()
::HIR::SimplePath Parser::parse_simplepath()
{
lex.check_consume("::");
- lex.check(TokenClass::String);
- auto crate = lex.consume().strval;
- lex.check_consume("::");
+ ::std::string crate;
+ if( lex.next() == TokenClass::String )
+ {
+ crate = lex.consume().strval;
+ lex.check_consume("::");
+ }
::std::vector<::std::string> ents;
do
{
@@ -954,14 +1104,17 @@ RawType Parser::parse_core_type()
// Good.
return ::HIR::TypeRef(it->second.get());
}
- else if( lex.next() == "extern" || lex.next() == "fn" )
+ else if( lex.next() == "extern" || lex.next() == "fn" || lex.next() == "unsafe" )
{
+ bool is_unsafe = false;
::std::string abi = "Rust";
+ if( lex.consume_if("unsafe") )
+ {
+ is_unsafe = true;
+ }
if( lex.consume_if("extern") )
{
- // TODO: Save the ABI
- lex.check(TokenClass::String);
- abi = lex.consume().strval;
+ abi = ::std::move(lex.check_consume(TokenClass::String).strval);
}
lex.check_consume("fn");
lex.check_consume('(');
@@ -973,9 +1126,16 @@ RawType Parser::parse_core_type()
break;
}
lex.check_consume(')');
- lex.check_consume('-');
- lex.check_consume('>');
- auto ret_ty = parse_type();
+ ::HIR::TypeRef ret_ty;
+ if( lex.consume_if('-') )
+ {
+ lex.check_consume('>');
+ ret_ty = parse_type();
+ }
+ else
+ {
+ ret_ty = ::HIR::TypeRef::unit();
+ }
return ::HIR::TypeRef(RawType::Function);
// TODO: Use abi/ret_ty/args as part of that
}
@@ -983,19 +1143,41 @@ RawType Parser::parse_core_type()
{
lex.consume_if('(');
::HIR::GenericPath base_trait;
+ ::std::vector<::std::pair<::std::string, ::HIR::TypeRef>> atys;
if( lex.next() != '+' )
{
- base_trait = parse_genericpath();
+ // Custom TraitPath parsing.
+ base_trait.m_simplepath = parse_simplepath();
+ if( lex.consume_if('<') )
+ {
+ while(lex.next() != '>')
+ {
+ if( lex.next() == TokenClass::Ident && lex.lookahead() == '=' )
+ {
+ auto name = ::std::move(lex.consume().strval);
+ lex.check_consume('=');
+ auto ty = parse_type();
+ atys.push_back(::std::make_pair( ::std::move(name), ::std::move(ty) ));
+ }
+ else
+ {
+ base_trait.m_params.tys.push_back( parse_type() );
+ }
+ if( !lex.consume_if(',') )
+ break ;
+ }
+ lex.check_consume('>');
+ }
}
::std::vector<::HIR::GenericPath> markers;
while(lex.consume_if('+'))
{
+ // TODO: Detect/parse lifetimes?
markers.push_back(parse_genericpath());
- // TODO: Lifetimes?
}
lex.consume_if(')');
return ::HIR::TypeRef(RawType::TraitObject);
- // TODO: Figure out how to include the traits in this type.
+ // TODO: Generate the vtable path and locate that struct
}
else if( lex.next() == TokenClass::Ident )
{
@@ -1010,12 +1192,15 @@ RawType Parser::parse_core_type()
::HIR::SimplePath ModuleTree::find_lang_item(const char* name) const
{
- return ::HIR::SimplePath({ "core", { "start" } });
+ return ::HIR::SimplePath({ "", { "main#" } });
}
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 "";
+ }
return it->second;
} \ No newline at end of file
diff --git a/tools/standalone_miri/module_tree.hpp b/tools/standalone_miri/module_tree.hpp
index ecc19625..ce831621 100644
--- a/tools/standalone_miri/module_tree.hpp
+++ b/tools/standalone_miri/module_tree.hpp
@@ -5,6 +5,7 @@
#include <string>
#include <vector>
#include <map>
+#include <set>
#include "../../src/mir/mir.hpp"
#include "hir_sim.hpp"
@@ -21,6 +22,8 @@ class ModuleTree
{
friend struct Parser;
+ ::std::set<::std::string> loaded_files;
+
::std::map<::HIR::Path, Function> functions;
// Hack: Tuples are stored as `::""::<A,B,C,...>`
::std::map<::HIR::GenericPath, ::std::unique_ptr<DataType>> data_types;
diff --git a/vsproject/build_rustc_minicargo.cmd b/vsproject/build_rustc_minicargo.cmd
index 4e36dc89..c778502a 100644
--- a/vsproject/build_rustc_minicargo.cmd
+++ b/vsproject/build_rustc_minicargo.cmd
@@ -6,7 +6,7 @@ if %errorlevel% neq 0 exit /b %errorlevel%
x64\Release\minicargo.exe ..\rustc-1.19.0-src\src\libtest --script-overrides ..\script-overrides\stable-1.19.0
if %errorlevel% neq 0 exit /b %errorlevel%
-x64\Release\mrustc.exe ..\rustc-1.19.0-src\src\test\run-pass\hello.rs -L output -o hello.exe
+x64\Release\mrustc.exe ..\rustc-1.19.0-src\src\test\run-pass\hello.rs -L output -o output\hello.exe
if %errorlevel% neq 0 exit /b %errorlevel%
hello.exe
if %errorlevel% neq 0 exit /b %errorlevel% \ No newline at end of file
diff --git a/vsproject/build_rustc_minicargo_mmir.cmd b/vsproject/build_rustc_minicargo_mmir.cmd
new file mode 100644
index 00000000..a6409391
--- /dev/null
+++ b/vsproject/build_rustc_minicargo_mmir.cmd
@@ -0,0 +1,12 @@
+@echo off
+x64\Release\minicargo.exe ..\rustc-1.19.0-src\src\libstd --script-overrides ..\script-overrides\stable-1.19.0 --output-dir output_mmir -Z emit-mmir
+if %errorlevel% neq 0 exit /b %errorlevel%
+x64\Release\minicargo.exe ..\rustc-1.19.0-src\src\libpanic_unwind --script-overrides ..\script-overrides\stable-1.19.0 --output-dir output_mmir -Z emit-mmir
+if %errorlevel% neq 0 exit /b %errorlevel%
+x64\Release\minicargo.exe ..\rustc-1.19.0-src\src\libtest --script-overrides ..\script-overrides\stable-1.19.0 --output-dir output_mmir -Z emit-mmir
+if %errorlevel% neq 0 exit /b %errorlevel%
+
+x64\Release\mrustc.exe ..\rustc-1.19.0-src\src\test\run-pass\hello.rs -L output_mmir -o output_mmir\hello.exe -C codegen-type=monomir
+if %errorlevel% neq 0 exit /b %errorlevel%
+x64\Release\standalone_miri.exe output_mmir\hello.exe.mir
+if %errorlevel% neq 0 exit /b %errorlevel% \ No newline at end of file