diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | src/trans/codegen_mmir.cpp | 13 | ||||
-rw-r--r-- | tools/standalone_miri/hir_sim.cpp | 16 | ||||
-rw-r--r-- | tools/standalone_miri/lex.cpp | 216 | ||||
-rw-r--r-- | tools/standalone_miri/lex.hpp | 12 | ||||
-rw-r--r-- | tools/standalone_miri/module_tree.cpp | 259 | ||||
-rw-r--r-- | tools/standalone_miri/module_tree.hpp | 3 | ||||
-rw-r--r-- | vsproject/build_rustc_minicargo.cmd | 2 | ||||
-rw-r--r-- | vsproject/build_rustc_minicargo_mmir.cmd | 12 |
9 files changed, 453 insertions, 81 deletions
@@ -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 |