summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2018-01-24 21:04:58 +0800
committerJohn Hodge <tpg@mutabah.net>2018-01-24 21:04:58 +0800
commit3fe277c60d6d30b30554e78be13fe5990dd9e608 (patch)
treedbbaaf42ac0b04318265820f573b1500a315fbd0
parent7932cf76d7e783ea76a9b117f33ca45d07db26af (diff)
downloadmrust-3fe277c60d6d30b30554e78be13fe5990dd9e608.tar.gz
standalone_miri - New side-tool to attempt to execute pre-monomorphised MIR
-rw-r--r--.gitignore1
-rw-r--r--src/include/tagged_union.hpp2
-rw-r--r--src/mir/mir.hpp1
-rw-r--r--tools/standalone_miri/hir/type.hpp1
-rw-r--r--tools/standalone_miri/hir_sim.cpp201
-rw-r--r--tools/standalone_miri/hir_sim.hpp235
-rw-r--r--tools/standalone_miri/lex.cpp220
-rw-r--r--tools/standalone_miri/lex.hpp57
-rw-r--r--tools/standalone_miri/main.cpp325
-rw-r--r--tools/standalone_miri/mir.cpp299
-rw-r--r--tools/standalone_miri/module_tree.cpp616
-rw-r--r--tools/standalone_miri/module_tree.hpp52
-rw-r--r--tools/standalone_miri/value.cpp178
-rw-r--r--tools/standalone_miri/value.hpp69
-rw-r--r--vsproject/mrustc.sln10
-rw-r--r--vsproject/standalone_miri/standalone_miri.vcxproj173
-rw-r--r--vsproject/standalone_miri/standalone_miri.vcxproj.filters57
-rw-r--r--vsproject/standalone_miri/targetver.h8
18 files changed, 2504 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore
index 2c8fbbc1..3b3c93d3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -53,3 +53,4 @@
/bnf/rust.output
/bnf/test.bin
/vsproject/output
+/vsproject/standalone_miri/x64
diff --git a/src/include/tagged_union.hpp b/src/include/tagged_union.hpp
index 3afea50b..6e113d27 100644
--- a/src/include/tagged_union.hpp
+++ b/src/include/tagged_union.hpp
@@ -110,7 +110,7 @@
#define TU_IFLET(CLASS, VAR, TAG, NAME, ...) if(VAR.tag() == CLASS::TAG_##TAG) { auto& NAME = VAR.as_##TAG(); (void)&NAME; __VA_ARGS__ }
// Evil hack: two for loops, the inner stops the outer after it's done.
-#define TU_ARM(VAR, TAG, NAME) case ::std::remove_reference<decltype(VAR)>::type::TAG_##TAG: for(bool tu_lc = true; tu_lc;) for(auto& NAME = VAR.as_##TAG(); true; tu_lc=false)
+#define TU_ARM(VAR, TAG, NAME) case ::std::remove_reference<decltype(VAR)>::type::TAG_##TAG: for(bool tu_lc = true; tu_lc;) for(auto& NAME = VAR.as_##TAG(); tu_lc; tu_lc=false)
//#define TU_TEST(VAL, ...) (VAL.is_##TAG() && VAL.as_##TAG() TEST)
#define TU_TEST1(VAL, TAG1, TEST) (VAL.is_##TAG1() && VAL.as_##TAG1() TEST)
diff --git a/src/mir/mir.hpp b/src/mir/mir.hpp
index 2a623d3c..d4b797ea 100644
--- a/src/mir/mir.hpp
+++ b/src/mir/mir.hpp
@@ -9,6 +9,7 @@
#include <tagged_union.hpp>
#include <vector>
#include <string>
+#include <memory> // std::unique_ptr
#include <hir/type.hpp>
namespace MIR {
diff --git a/tools/standalone_miri/hir/type.hpp b/tools/standalone_miri/hir/type.hpp
new file mode 100644
index 00000000..2e566691
--- /dev/null
+++ b/tools/standalone_miri/hir/type.hpp
@@ -0,0 +1 @@
+#include "../hir_sim.hpp" \ No newline at end of file
diff --git a/tools/standalone_miri/hir_sim.cpp b/tools/standalone_miri/hir_sim.cpp
new file mode 100644
index 00000000..4072c323
--- /dev/null
+++ b/tools/standalone_miri/hir_sim.cpp
@@ -0,0 +1,201 @@
+//
+//
+//
+#include <iostream>
+
+#include "hir_sim.hpp"
+#include "module_tree.hpp"
+
+//::HIR::Path::Path(::HIR::SimplePath sp)
+//{
+//}
+
+size_t HIR::TypeRef::get_size(size_t ofs) const
+{
+ if( this->wrappers.size() <= ofs )
+ {
+ switch(this->inner_type)
+ {
+ case RawType::Unit:
+ return 0;
+ case RawType::Composite:
+ return this->composite_type->size;
+ case RawType::Unreachable:
+ case RawType::Str:
+ throw "Invalid";
+ case RawType::U8: case RawType::I8:
+ return 1;
+ case RawType::U16: case RawType::I16:
+ return 2;
+ case RawType::U32: case RawType::I32:
+ return 4;
+ case RawType::U64: case RawType::I64:
+ return 8;
+ case RawType::U128: case RawType::I128:
+ return 16;
+ }
+ }
+
+ switch(this->wrappers[ofs].type)
+ {
+ case TypeWrapper::Ty::Array:
+ return this->get_size(1) * this->wrappers[ofs].size;
+ case TypeWrapper::Ty::Borrow:
+ case TypeWrapper::Ty::Pointer:
+ if( this->wrappers.size() == ofs+1 )
+ {
+ // Need to look up the metadata type for the actual type
+ if( this->inner_type == RawType::Composite )
+ throw "TODO";
+ else if( this->inner_type == RawType::Str )
+ return 8*2;
+ else if( this->inner_type == RawType::TraitObject )
+ return 8*2;
+ else
+ {
+ return 8;
+ }
+ }
+ else if( this->wrappers[ofs+1].type == TypeWrapper::Ty::Slice )
+ {
+ return 8*2;
+ }
+ else
+ {
+ return 8;
+ }
+ case TypeWrapper::Ty::Slice:
+ throw "Invalid";
+ }
+ throw "";
+}
+
+HIR::TypeRef HIR::TypeRef::get_inner() const
+{
+ if( this->wrappers.empty() )
+ {
+ throw "ERROR";
+ }
+ auto ity = *this;
+ ity.wrappers.erase(ity.wrappers.begin());
+ return ity;
+}
+
+HIR::TypeRef HIR::TypeRef::get_field(size_t idx, size_t& ofs) const
+{
+ if( this->wrappers.empty() )
+ {
+ if( this->inner_type == RawType::Composite )
+ {
+ ofs = this->composite_type->fields.at(idx).first;
+ return this->composite_type->fields.at(idx).second;
+ }
+ else
+ {
+ ::std::cerr << *this << " doesn't have fields" << ::std::endl;
+ throw "ERROR";
+ }
+ }
+ else if( this->wrappers.front().type == TypeWrapper::Ty::Slice )
+ {
+ // TODO
+ throw "TODO";
+ }
+ else if( this->wrappers.front().type == TypeWrapper::Ty::Array )
+ {
+ auto ity = this->get_inner();
+ ofs = ity.get_size() * idx;
+ return ity;
+ }
+ else
+ {
+ throw "ERROR";
+ }
+}
+
+namespace HIR {
+ ::std::ostream& operator<<(::std::ostream& os, const ::HIR::BorrowType& x)
+ {
+ switch(x)
+ {
+ case ::HIR::BorrowType::Move: os << "Move"; break;
+ case ::HIR::BorrowType::Unique: os << "Unique"; break;
+ case ::HIR::BorrowType::Shared: os << "Shared"; break;
+ }
+ return os;
+ }
+ ::std::ostream& operator<<(::std::ostream& os, const ::HIR::TypeRef& x)
+ {
+ for(auto it = x.wrappers.begin(); it != x.wrappers.end(); ++it)
+ {
+ switch(it->type)
+ {
+ case TypeWrapper::Ty::Array:
+ case TypeWrapper::Ty::Slice:
+ os << "[";
+ break;
+ case TypeWrapper::Ty::Pointer:
+ os << "*";
+ break;
+ case TypeWrapper::Ty::Borrow:
+ os << "&";
+ break;
+ }
+ }
+ switch(x.inner_type)
+ {
+ case RawType::Unit:
+ os << "()";
+ break;
+ case RawType::Composite:
+ os << "composite_" << x.composite_type;
+ break;
+ case RawType::Unreachable:
+ os << "!";
+ break;
+ case RawType::Str:
+ os << "str";
+ break;
+ case RawType::U8: os << "u8"; break;
+ case RawType::I8: os << "i8"; break;
+ case RawType::U16: os << "u16"; break;
+ case RawType::I16: os << "i16"; break;
+ case RawType::U32: os << "u32"; break;
+ case RawType::I32: os << "i32"; break;
+ case RawType::U64: os << "u64"; break;
+ case RawType::I64: os << "i64"; break;
+ case RawType::U128: os << "u128"; break;
+ case RawType::I128: os << "i128"; break;
+ }
+ for(auto it = x.wrappers.rbegin(); it != x.wrappers.rend(); ++it)
+ {
+ switch(it->type)
+ {
+ case TypeWrapper::Ty::Array:
+ os << ";" << it->size;
+ case TypeWrapper::Ty::Slice:
+ os << "]";
+ break;
+ case TypeWrapper::Ty::Pointer:
+ case TypeWrapper::Ty::Borrow:
+ break;
+ }
+ }
+ return os;
+ }
+ ::std::ostream& operator<<(::std::ostream& os, const ::HIR::PathParams& x)
+ {
+ if( !x.tys.empty() )
+ {
+ os << "<";
+ for(const auto& t : x.tys)
+ os << t << ",";
+ os << ">";
+ }
+ return os;
+ }
+ ::std::ostream& operator<<(::std::ostream& os, const ::HIR::Path& x)
+ {
+ return os;
+ }
+} \ No newline at end of file
diff --git a/tools/standalone_miri/hir_sim.hpp b/tools/standalone_miri/hir_sim.hpp
new file mode 100644
index 00000000..5a9ddf41
--- /dev/null
+++ b/tools/standalone_miri/hir_sim.hpp
@@ -0,0 +1,235 @@
+//
+//
+//
+#pragma once
+#include <string>
+#include <vector>
+#include <memory>
+
+#define __NE(fld) if(this->fld != x.fld) return true
+#define __LT(fld) if(this->fld != x.fld) return this->fld < x.fld
+
+enum Ordering
+{
+ OrdLess,
+ OrdEqual,
+ OrdGreater,
+};
+
+struct DataType;
+
+enum class RawType
+{
+ Unreachable,
+ Unit,
+
+ Bool,
+ U8, I8,
+ U16, I16,
+ U32, I32,
+ U64, I64,
+ U128, I128,
+
+ F32, F64,
+
+ Char, Str,
+
+ Composite, // Struct, Enum, Union, tuple, ...
+ TraitObject, // Data pointer is `*const ()`, metadata type stored in `composite_type`
+};
+struct TypeWrapper
+{
+ enum class Ty
+ {
+ Array, // With size
+ Borrow, // With BorrowType
+ Pointer, // With BorrowType
+ Slice, // Must be bottom
+ } type;
+ size_t size;
+
+ bool operator==(const TypeWrapper& x) const {
+ return !(*this != x);
+ }
+ bool operator!=(const TypeWrapper& x) const {
+ __NE(type);
+ __NE(size);
+ return false;
+ }
+ bool operator<(const TypeWrapper& x) const {
+ __LT(type);
+ __LT(size);
+ return false;
+ }
+};
+
+
+namespace HIR {
+
+ enum class BorrowType
+ {
+ Shared,
+ Unique,
+ Move,
+ };
+ ::std::ostream& operator<<(::std::ostream& os, const BorrowType& x);
+ struct CoreType
+ {
+ RawType raw_type;
+ };
+ /// Definition of a type
+ struct TypeRef
+ {
+ ::std::vector<TypeWrapper> wrappers;
+ RawType inner_type = RawType::Unit;
+ const DataType* composite_type = nullptr;
+
+ TypeRef()
+ {
+ }
+
+ explicit TypeRef(const DataType* dt):
+ inner_type(RawType::Composite),
+ composite_type(dt)
+ {
+ }
+ explicit TypeRef(RawType rt):
+ inner_type(rt)
+ {
+ }
+ explicit TypeRef(CoreType ct):
+ inner_type(ct.raw_type)
+ {
+ }
+ static TypeRef diverge() {
+ TypeRef rv;
+ rv.inner_type = RawType::Unreachable;
+ return rv;
+ }
+ static TypeRef unit() {
+ TypeRef rv;
+ rv.inner_type = RawType::Unit;
+ return rv;
+ }
+
+ size_t get_size(size_t ofs=0) const;
+ TypeRef get_inner() const;
+ TypeRef get_field(size_t idx, size_t& ofs) const;
+
+ bool operator==(const TypeRef& x) const {
+ return !(*this != x);
+ }
+ bool operator!=(const TypeRef& x) const {
+ __NE(wrappers);
+ __NE(inner_type);
+ __NE(composite_type);
+ return false;
+ }
+ bool operator<(const TypeRef& x) const {
+ __LT(wrappers);
+ __LT(inner_type);
+ __LT(composite_type);
+ return false;
+ }
+
+ friend ::std::ostream& operator<<(::std::ostream& os, const TypeRef& x);
+ };
+
+ struct SimplePath
+ {
+ ::std::string crate_name;
+ ::std::vector<::std::string> ents;
+ bool operator==(const SimplePath& x) const {
+ return !(*this != x);
+ }
+ bool operator!=(const SimplePath& x) const {
+ __NE(crate_name);
+ __NE(ents);
+ return false;
+ }
+ bool operator<(const SimplePath& x) const {
+ __LT(crate_name);
+ __LT(ents);
+ return false;
+ }
+ };
+
+ struct PathParams
+ {
+ ::std::vector<TypeRef> tys;
+
+ friend ::std::ostream& operator<<(::std::ostream& os, const PathParams& x);
+ };
+ struct GenericPath
+ {
+ SimplePath m_simplepath;
+ PathParams m_params;
+
+ GenericPath() {}
+ GenericPath(SimplePath sp):
+ m_simplepath(sp)
+ {
+ }
+ bool operator==(const GenericPath& x) const {
+ return !(*this != x);
+ }
+ bool operator!=(const GenericPath& x) const {
+ __NE(m_simplepath);
+ __NE(m_params.tys);
+ return false;
+ }
+ bool operator<(const GenericPath& x) const {
+ __LT(m_simplepath);
+ __LT(m_params.tys);
+ return false;
+ }
+ };
+ struct Path
+ {
+ TypeRef m_type;
+ GenericPath m_trait;
+ ::std::string m_name; // if empty, the path is Generic in m_trait
+ PathParams m_params;
+
+ Path(SimplePath sp):
+ Path(GenericPath(sp))
+ {
+ }
+ Path(GenericPath gp):
+ m_trait(gp)
+ {
+ }
+ Path(TypeRef ty, GenericPath trait, ::std::string name, PathParams params):
+ m_type(ty),
+ m_trait(::std::move(trait)),
+ m_name(name),
+ m_params(params)
+ {
+ }
+
+ bool operator==(const Path& x) const {
+ return !(*this != x);
+ }
+ bool operator!=(const Path& x) const {
+ __NE(m_type);
+ __NE(m_trait);
+ __NE(m_name);
+ __NE(m_params.tys);
+ return false;
+ }
+ bool operator<(const Path& x) const {
+ __LT(m_type);
+ __LT(m_trait);
+ __LT(m_name);
+ __LT(m_params.tys);
+ return false;
+ }
+
+ friend ::std::ostream& operator<<(::std::ostream& os, const Path& x);
+ };
+
+} // nameapce HIR
+
+
+#undef __NE
+#undef __LT
diff --git a/tools/standalone_miri/lex.cpp b/tools/standalone_miri/lex.cpp
new file mode 100644
index 00000000..7650ec78
--- /dev/null
+++ b/tools/standalone_miri/lex.cpp
@@ -0,0 +1,220 @@
+//
+//
+//
+#include "lex.hpp"
+#include <cctype>
+#include <iostream>
+
+bool Token::operator==(TokenClass tc) const
+{
+ return this->type == tc;
+}
+bool Token::operator==(char c) const
+{
+ return this->strval.size() == 1 && this->strval[0] == c;
+}
+bool Token::operator==(const char* s) const
+{
+ return this->strval == s;
+}
+
+uint64_t Token::integer() const
+{
+ if( this->type != TokenClass::Integer )
+ throw "";
+ return this->numbers.int_val;
+}
+double Token::real() const
+{
+ if( this->type != TokenClass::Real )
+ throw "";
+ return this->numbers.real_val;
+}
+
+Lexer::Lexer(const ::std::string& path):
+ m_if(path)
+{
+ if( !m_if.good() )
+ {
+ throw "ERROR";
+ }
+
+ advance();
+}
+
+const Token& Lexer::next() const
+{
+ return m_cur;
+}
+Token Lexer::consume()
+{
+ auto rv = ::std::move(m_cur);
+
+ advance();
+
+ return rv;
+}
+void Lexer::check(TokenClass tc)
+{
+ if( next() != tc ) {
+ ::std::cerr << "Syntax error: Expected token class #" << int(tc) << " - got '" << next().strval << "'" << ::std::endl;
+ throw "ERROR";
+ }
+}
+void Lexer::check(char ch)
+{
+ if( next() != ch ) {
+ ::std::cerr << "Syntax error: Expected '" << ch << "' - got '" << next().strval << "'" << ::std::endl;
+ throw "ERROR";
+ }
+}
+void Lexer::check(const char* s)
+{
+ if( next() != s ) {
+ ::std::cerr << "Syntax error: Expected '" << s << "' - got '" << next().strval << "'" << ::std::endl;
+ throw "ERROR";
+ }
+}
+
+void Lexer::advance()
+{
+ char ch;
+ while( ::std::isblank(ch = m_if.get()) || ch == '\n' || ch == '\r')
+ ;
+ //::std::cout << "ch=" << ch << ::std::endl;
+ if( m_if.eof() )
+ {
+ m_cur = Token { TokenClass::Eof, "" };
+ }
+ else if( ::std::isalpha(ch) )
+ {
+ ::std::string val;
+ while(::std::isalnum(ch) || ch == '_')
+ {
+ val.push_back(ch);
+ ch = m_if.get();
+ }
+ m_if.unget();
+ m_cur = Token { TokenClass::Ident, ::std::move(val) };
+ }
+ else if( ::std::isdigit(ch) )
+ {
+ if( ch == '0' )
+ {
+ ch = m_if.get();
+ if( ch == 'x' ) {
+ ch = m_if.get();
+ if( !::std::isxdigit(ch) )
+ throw "ERROR";
+
+ uint64_t rv = 0;
+ while(::std::isdigit(ch))
+ {
+ rv *= 16;
+ if( ch <= '9' )
+ rv += ch - '0';
+ else if( ch <= 'F' )
+ rv += ch - 'A' + 10;
+ else if( ch <= 'f' )
+ rv += ch - 'a' + 10;
+ else
+ throw "";
+ ch = m_if.get();
+ }
+ if( ch == '.' || ch == 'p' )
+ {
+ // Floats!
+ throw "TODO";
+ }
+ m_if.unget();
+
+ m_cur = Token { TokenClass::Integer, "" };
+ m_cur.numbers.int_val = rv;
+ return ;
+ }
+ else {
+ m_if.unget();
+ ch = '0';
+ }
+ }
+
+ uint64_t rv = 0;
+ while(::std::isdigit(ch))
+ {
+ rv *= 10;
+ rv += ch - '0';
+ ch = m_if.get();
+ }
+ if( ch == '.' || ch == 'e' )
+ {
+ // Floats!
+ throw "TODO";
+ }
+ m_if.unget();
+
+ m_cur = Token { TokenClass::Integer, "" };
+ m_cur.numbers.int_val = rv;
+ }
+ 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;
+ default:
+ ::std::cerr << "Unexpected escape sequence '\\" << ch << "'" << ::std::endl;
+ throw "ERROR";
+ }
+ }
+ else
+ {
+ val.push_back(ch);
+ }
+ }
+ m_cur = Token { TokenClass::String, ::std::move(val) };
+ }
+ else
+ {
+ switch(ch)
+ {
+ case ':':
+ switch(m_if.get())
+ {
+ case ':':
+ m_cur = Token { TokenClass::Symbol, "::" };
+ break;
+ default:
+ m_if.unget();
+ m_cur = Token { TokenClass::Symbol, ":" };
+ break;
+ }
+ 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;
+ 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;
+ default:
+ ::std::cerr << "Unexpected chracter '" << ch << "'" << ::std::endl;
+ throw "ERROR";
+ }
+ }
+}
diff --git a/tools/standalone_miri/lex.hpp b/tools/standalone_miri/lex.hpp
new file mode 100644
index 00000000..c01a23a4
--- /dev/null
+++ b/tools/standalone_miri/lex.hpp
@@ -0,0 +1,57 @@
+//
+//
+//
+#pragma once
+#include <string>
+#include <fstream>
+
+enum class TokenClass
+{
+ Eof,
+ Symbol,
+ Ident,
+ Integer,
+ Real,
+ String,
+};
+
+struct Token
+{
+ TokenClass type;
+ ::std::string strval;
+ union {
+ double real_val;
+ uint64_t int_val;
+ } numbers;
+
+ bool operator==(TokenClass tc) const;
+ bool operator!=(TokenClass tc) const { return !(*this == tc); }
+ bool operator==(char c) const;
+ bool operator!=(char c) const { return !(*this == c); }
+ bool operator==(const char* s) const;
+ bool operator!=(const char* s) const { return !(*this == s); }
+
+ uint64_t integer() const;
+ double real() const;
+};
+
+class Lexer
+{
+ ::std::ifstream m_if;
+ Token m_cur;
+public:
+ Lexer(const ::std::string& path);
+
+ const Token& next() const;
+ 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(); }
+ 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; }
+
+private:
+ void advance();
+}; \ No newline at end of file
diff --git a/tools/standalone_miri/main.cpp b/tools/standalone_miri/main.cpp
new file mode 100644
index 00000000..a6a58a91
--- /dev/null
+++ b/tools/standalone_miri/main.cpp
@@ -0,0 +1,325 @@
+//
+//
+//
+#include <iostream>
+#include "module_tree.hpp"
+#include "value.hpp"
+#include <algorithm>
+#include <iomanip>
+
+#pragma warning( error : 4061)
+
+struct ProgramOptions
+{
+ ::std::string infile;
+
+ int parse(int argc, const char* argv[]);
+};
+
+Value MIRI_Invoke(const ModuleTree& modtree, ::HIR::Path path, ::std::vector<Value> args);
+
+int main(int argc, const char* argv[])
+{
+ ProgramOptions opts;
+
+ if( opts.parse(argc, argv) )
+ {
+ return 1;
+ }
+
+ auto tree = ModuleTree {};
+
+ tree.load_file(opts.infile);
+
+ auto rv = MIRI_Invoke(tree, tree.find_lang_item("start"), {});
+ ::std::cout << rv << ::std::endl;
+
+ return 0;
+}
+
+Value MIRI_Invoke(const ModuleTree& modtree, ::HIR::Path path, ::std::vector<Value> args)
+{
+ const auto& fcn = modtree.get_function(path);
+
+ ::std::vector<bool> drop_flags = fcn.m_mir.drop_flags;
+ ::std::vector<Value> locals; locals.reserve( fcn.m_mir.locals.size() );
+
+ Value ret_val = Value(fcn.ret_ty);
+ for(const auto& ty : fcn.m_mir.locals)
+ {
+ locals.push_back(Value(ty));
+ }
+
+ struct State
+ {
+ const Function& fcn;
+ Value ret;
+ ::std::vector<Value> args;
+ ::std::vector<Value> locals;
+
+ State(const Function& fcn, ::std::vector<Value> args):
+ fcn(fcn),
+ ret(fcn.ret_ty),
+ args(::std::move(args))
+ {
+ locals.reserve(fcn.m_mir.locals.size());
+ for(const auto& ty : fcn.m_mir.locals)
+ {
+ locals.push_back(Value(ty));
+ }
+ }
+
+ Value& get_value_type_and_ofs(const ::MIR::LValue& lv, size_t& ofs, ::HIR::TypeRef& ty)
+ {
+ switch(lv.tag())
+ {
+ TU_ARM(lv, Return, _e) {
+ ofs = 0;
+ ty = fcn.ret_ty;
+ return ret;
+ } break;
+ TU_ARM(lv, Local, e) {
+ ofs = 0;
+ ty = fcn.m_mir.locals.at(e);
+ return locals.at(e);
+ } break;
+ TU_ARM(lv, Argument, e) {
+ ofs = 0;
+ ty = fcn.args.at(e.idx);
+ return args.at(e.idx);
+ } break;
+ TU_ARM(lv, Index, e) {
+ auto idx = read_lvalue(*e.idx).as_usize();
+ ::HIR::TypeRef array_ty;
+ auto& base_val = get_value_type_and_ofs(*e.val, ofs, array_ty);
+ if( array_ty.wrappers.empty() )
+ throw "ERROR";
+ if( array_ty.wrappers.front().type == TypeWrapper::Ty::Array )
+ {
+ ty = array_ty.get_inner();
+ ofs += ty.get_size() * idx;
+ return base_val;
+ }
+ else if( array_ty.wrappers.front().type == TypeWrapper::Ty::Slice )
+ {
+ throw "TODO";
+ }
+ else
+ {
+ throw "ERROR";
+ }
+ } break;
+ TU_ARM(lv, Field, e) {
+ ::HIR::TypeRef composite_ty;
+ auto& base_val = get_value_type_and_ofs(*e.val, ofs, composite_ty);
+ ::std::cout << "get_type_and_ofs: " << composite_ty << ::std::endl;
+ size_t inner_ofs;
+ ty = composite_ty.get_field(e.field_index, inner_ofs);
+ ofs += inner_ofs;
+ return base_val;
+ }
+ }
+ throw "";
+ }
+
+ ::HIR::TypeRef get_lvalue_ty(const ::MIR::LValue& lv)
+ {
+ ::HIR::TypeRef ty;
+ size_t ofs = 0;
+ get_value_type_and_ofs(lv, ofs, ty);
+ return ty;
+ }
+
+ Value read_lvalue_with_ty(const ::MIR::LValue& lv, ::HIR::TypeRef& ty)
+ {
+ ::std::cout << "read_lvalue_with_ty: " << lv << ::std::endl;
+ size_t ofs = 0;
+ Value& base_value = get_value_type_and_ofs(lv, ofs, ty);
+
+ ::std::cout << "> read_lvalue_with_ty: " << ty << ::std::endl;
+
+ return base_value.read_value(ofs, ty.get_size());
+ }
+ Value read_lvalue(const ::MIR::LValue& lv)
+ {
+ ::std::cout << "read_lvalue: " << lv << ::std::endl;
+ ::HIR::TypeRef ty;
+ return read_lvalue_with_ty(lv, ty);
+ }
+ void write_lvalue(const ::MIR::LValue& lv, Value val)
+ {
+ ::std::cout << "write_lvaue: " << lv << ::std::endl;
+ //::std::cout << "write_lvaue: " << lv << " = " << val << ::std::endl;
+ ::HIR::TypeRef ty;
+ size_t ofs = 0;
+ Value& base_value = get_value_type_and_ofs(lv, ofs, ty);
+
+ base_value.write_value(ofs, val);
+ }
+
+ Value const_to_value(const ::MIR::Constant& c, ::HIR::TypeRef& ty)
+ {
+ switch(c.tag())
+ {
+ TU_ARM(c, Int, ce) {
+ ty = ::HIR::TypeRef(ce.t);
+ Value val = Value(ty);
+ val.write_bytes(0, &ce.v, ::std::min(ty.get_size(), sizeof(ce.v))); // TODO: Endian
+ // TODO: If the write was clipped, sign-extend
+ return val;
+ } break;
+ TU_ARM(c, Uint, ce) {
+ ty = ::HIR::TypeRef(ce.t);
+ Value val = Value(ty);
+ val.write_bytes(0, &ce.v, ::std::min(ty.get_size(), sizeof(ce.v))); // TODO: Endian
+ return val;
+ } break;
+ }
+ throw "";
+ }
+ Value const_to_value(const ::MIR::Constant& c)
+ {
+ ::HIR::TypeRef ty;
+ return const_to_value(c, ty);
+ }
+ Value param_to_value(const ::MIR::Param& p, ::HIR::TypeRef& ty)
+ {
+ switch(p.tag())
+ {
+ TU_ARM(p, Constant, pe)
+ return const_to_value(pe, ty);
+ TU_ARM(p, LValue, pe)
+ return read_lvalue_with_ty(pe, ty);
+ }
+ throw "";
+ }
+ Value param_to_value(const ::MIR::Param& p)
+ {
+ ::HIR::TypeRef ty;
+ return param_to_value(p, ty);
+ }
+ } state { fcn, ::std::move(args) };
+
+ size_t bb_idx = 0;
+ for(;;)
+ {
+ const auto& bb = fcn.m_mir.blocks.at(bb_idx);
+
+ for(const auto& stmt : bb.statements)
+ {
+ ::std::cout << "BB" << bb_idx << "/" << (&stmt - bb.statements.data()) << ": " << stmt << ::std::endl;
+ switch(stmt.tag())
+ {
+ TU_ARM(stmt, Assign, se) {
+ Value val;
+ switch(se.src.tag())
+ {
+ TU_ARM(se.src, Use, re) {
+ state.write_lvalue(se.dst, state.read_lvalue(re));
+ } break;
+ TU_ARM(se.src, Constant, re) {
+ state.write_lvalue(se.dst, state.const_to_value(re));
+ } break;
+ TU_ARM(se.src, SizedArray, re) {
+ throw "TODO";
+ } break;
+ TU_ARM(se.src, Cast, re) {
+ throw "TODO";
+ } break;
+ TU_ARM(se.src, BinOp, re) {
+ throw "TODO";
+ } break;
+ TU_ARM(se.src, UniOp, re) {
+ throw "TODO";
+ } break;
+ TU_ARM(se.src, DstMeta, re) {
+ throw "TODO";
+ } break;
+ TU_ARM(se.src, DstPtr, re) {
+ throw "TODO";
+ } break;
+ TU_ARM(se.src, MakeDst, re) {
+ throw "TODO";
+ } break;
+ TU_ARM(se.src, Tuple, re) {
+ ::HIR::TypeRef dst_ty;
+ size_t ofs = 0;
+ Value& base_value = state.get_value_type_and_ofs(se.dst, ofs, dst_ty);
+
+ for(size_t i = 0; i < re.vals.size(); i++)
+ {
+ auto fld_ofs = dst_ty.composite_type->fields.at(i).first;
+ base_value.write_value(ofs + fld_ofs, state.param_to_value(re.vals[i]));
+ }
+ } break;
+ TU_ARM(se.src, Array, re) {
+ throw "TODO";
+ } break;
+ TU_ARM(se.src, Variant, re) {
+ throw "TODO";
+ } break;
+ TU_ARM(se.src, Struct, re) {
+ throw "TODO";
+ } break;
+ }
+ } break;
+ case ::MIR::Statement::TAG_Asm:
+ throw "TODO";
+ break;
+ case ::MIR::Statement::TAG_Drop:
+ throw "TODO";
+ break;
+ case ::MIR::Statement::TAG_SetDropFlag:
+ throw "TODO";
+ break;
+ }
+ }
+
+ ::std::cout << "BB" << bb_idx << "/TERM: " << bb.terminator << ::std::endl;
+ switch(bb.terminator.tag())
+ {
+ TU_ARM(bb.terminator, Goto, te)
+ bb_idx = te;
+ continue;
+ TU_ARM(bb.terminator, Return, _te)
+ return state.ret;
+ }
+ throw "";
+ }
+
+ throw "";
+}
+
+int ProgramOptions::parse(int argc, const char* argv[])
+{
+ bool all_free = false;
+ for(int argidx = 1; argidx < argc; argidx ++)
+ {
+ const char* arg = argv[argidx];
+ if( arg[0] != '-' || all_free )
+ {
+ // Free
+ if( this->infile == "" )
+ {
+ this->infile = arg;
+ }
+ else
+ {
+ // TODO: Too many free arguments
+ }
+ }
+ else if( arg[1] != '-' )
+ {
+ // Short
+ }
+ else if( arg[2] != '\0' )
+ {
+ // Long
+ }
+ else
+ {
+ all_free = true;
+ }
+ }
+ return 0;
+}
diff --git a/tools/standalone_miri/mir.cpp b/tools/standalone_miri/mir.cpp
new file mode 100644
index 00000000..4593fb44
--- /dev/null
+++ b/tools/standalone_miri/mir.cpp
@@ -0,0 +1,299 @@
+/*
+ * MRustC - Rust Compiler
+ * - By John Hodge (Mutabah/thePowersGang)
+ *
+ * mir/mir.cpp
+ * - MIR (Middle Intermediate Representation) definitions
+ */
+#include "../../src/mir/mir.hpp"
+#include "hir_sim.hpp"
+
+namespace std {
+ template <typename T>
+ inline ::std::ostream& operator<<(::std::ostream& os, const ::std::vector<T>& v) {
+ if( v.size() > 0 )
+ {
+ bool is_first = true;
+ for( const auto& i : v )
+ {
+ if(!is_first)
+ os << ", ";
+ is_first = false;
+ os << i;
+ }
+ }
+ return os;
+ }
+}
+
+namespace MIR {
+ ::std::ostream& operator<<(::std::ostream& os, const Constant& v) {
+ TU_MATCHA( (v), (e),
+ (Int,
+ os << (e.v < 0 ? "-" : "+");
+ os << (e.v < 0 ? -e.v : e.v);
+ ),
+ (Uint,
+ os << e.v;
+ ),
+ (Float,
+ os << e.v;
+ ),
+ (Bool,
+ os << (e.v ? "true" : "false");
+ ),
+ (Bytes,
+ os << "b\"";
+ os << ::std::hex;
+ for(auto v : e)
+ {
+ if( ' ' <= v && v < 0x7F && v != '"' && v != '\\' )
+ os << v;
+ else if( v < 16 )
+ os << "\\x0" << (unsigned int)v;
+ else
+ os << "\\x" << ((unsigned int)v & 0xFF);
+ }
+ os << "\"";
+ os << ::std::dec;
+ ),
+ (StaticString,
+ os << "\"" << e << "\"";
+ ),
+ (Const,
+ os << e.p;
+ ),
+ (ItemAddr,
+ os << "&" << e;
+ )
+ )
+ return os;
+ }
+ ::std::ostream& operator<<(::std::ostream& os, const LValue& x)
+ {
+ TU_MATCHA( (x), (e),
+ (Return,
+ os << "Return";
+ ),
+ (Argument,
+ os << "Argument(" << e.idx << ")";
+ ),
+ (Local,
+ os << "Local(" << e << ")";
+ ),
+ (Static,
+ os << "Static(" << e << ")";
+ ),
+ (Field,
+ os << "Field(" << e.field_index << ", " << *e.val << ")";
+ ),
+ (Deref,
+ os << "Deref(" << *e.val << ")";
+ ),
+ (Index,
+ os << "Index(" << *e.val << ", " << *e.idx << ")";
+ ),
+ (Downcast,
+ os << "Downcast(" << e.variant_index << ", " << *e.val << ")";
+ )
+ )
+ return os;
+ }
+ ::std::ostream& operator<<(::std::ostream& os, const Param& x)
+ {
+ TU_MATCHA( (x), (e),
+ (LValue,
+ os << e;
+ ),
+ (Constant,
+ os << e;
+ )
+ )
+ return os;
+ }
+ ::std::ostream& operator<<(::std::ostream& os, const RValue& x)
+ {
+ TU_MATCHA( (x), (e),
+ (Use,
+ os << "Use(" << e << ")";
+ ),
+ (Constant,
+ os << "Constant(" << e << ")";
+ ),
+ (SizedArray,
+ os << "SizedArray(" << e.val << "; " << e.count << ")";
+ ),
+ (Borrow,
+ os << "Borrow(" << e.region << ", " << e.type << ", " << e.val << ")";
+ ),
+ (Cast,
+ os << "Cast(" << e.val << " as " << e.type << ")";
+ ),
+ (BinOp,
+ os << "BinOp(" << e.val_l << " ";
+ switch(e.op)
+ {
+ case ::MIR::eBinOp::ADD: os << "ADD"; break;
+ case ::MIR::eBinOp::SUB: os << "SUB"; break;
+ case ::MIR::eBinOp::MUL: os << "MUL"; break;
+ case ::MIR::eBinOp::DIV: os << "DIV"; break;
+ case ::MIR::eBinOp::MOD: os << "MOD"; break;
+ case ::MIR::eBinOp::ADD_OV: os << "ADD_OV"; break;
+ case ::MIR::eBinOp::SUB_OV: os << "SUB_OV"; break;
+ case ::MIR::eBinOp::MUL_OV: os << "MUL_OV"; break;
+ case ::MIR::eBinOp::DIV_OV: os << "DIV_OV"; break;
+
+ case ::MIR::eBinOp::BIT_OR : os << "BIT_OR" ; break;
+ case ::MIR::eBinOp::BIT_AND: os << "BIT_AND"; break;
+ case ::MIR::eBinOp::BIT_XOR: os << "BIT_XOR"; break;
+ case ::MIR::eBinOp::BIT_SHL: os << "BIT_SHL"; break;
+ case ::MIR::eBinOp::BIT_SHR: os << "BIT_SHR"; break;
+
+ case ::MIR::eBinOp::EQ: os << "EQ"; break;
+ case ::MIR::eBinOp::NE: os << "NE"; break;
+ case ::MIR::eBinOp::GT: os << "GT"; break;
+ case ::MIR::eBinOp::GE: os << "GE"; break;
+ case ::MIR::eBinOp::LT: os << "LT"; break;
+ case ::MIR::eBinOp::LE: os << "LE"; break;
+ }
+ os << " " << e.val_r << ")";
+ ),
+ (UniOp,
+ os << "UniOp(" << e.val << " " << static_cast<int>(e.op) << ")";
+ ),
+ (DstMeta,
+ os << "DstMeta(" << e.val << ")";
+ ),
+ (DstPtr,
+ os << "DstPtr(" << e.val << ")";
+ ),
+ (MakeDst,
+ os << "MakeDst(" << e.ptr_val << ", " << e.meta_val << ")";
+ ),
+ (Tuple,
+ os << "Tuple(" << e.vals << ")";
+ ),
+ (Array,
+ os << "Array(" << e.vals << ")";
+ ),
+ (Variant,
+ os << "Variant(" << e.path << " #" << e.index << ", " << e.val << ")";
+ ),
+ (Struct,
+ os << "Struct(" << e.path << ", {" << e.vals << "})";
+ )
+ )
+ return os;
+ }
+ ::std::ostream& operator<<(::std::ostream& os, const Terminator& x)
+ {
+ TU_MATCHA( (x), (e),
+ (Incomplete,
+ os << "Invalid";
+ ),
+ (Return,
+ os << "Return";
+ ),
+ (Diverge,
+ os << "Diverge";
+ ),
+ (Goto,
+ os << "Goto(" << e << ")";
+ ),
+ (Panic,
+ os << "Panic(" << e.dst << ";)";
+ ),
+ (If,
+ os << "If( " << e.cond << " : " << e.bb0 << ", " << e.bb1 << ")";
+ ),
+ (Switch,
+ os << "Switch( " << e.val << " : ";
+ for(unsigned int j = 0; j < e.targets.size(); j ++)
+ os << j << " => bb" << e.targets[j] << ", ";
+ os << ")";
+ ),
+ (SwitchValue,
+ os << "SwitchValue( " << e.val << " : ";
+ TU_MATCHA( (e.values), (ve),
+ (Unsigned,
+ for(unsigned int j = 0; j < e.targets.size(); j ++)
+ os << ve[j] << " => bb" << e.targets[j] << ", ";
+ ),
+ (Signed,
+ for(unsigned int j = 0; j < e.targets.size(); j ++)
+ os << (ve[j] >= 0 ? "+" : "") << ve[j] << " => bb" << e.targets[j] << ", ";
+ ),
+ (String,
+ for(unsigned int j = 0; j < e.targets.size(); j ++)
+ os << "\"" << ve[j] << "\" => bb" << e.targets[j] << ", ";
+ )
+ )
+ os << "else bb" << e.def_target << ")";
+ ),
+ (Call,
+ os << "Call( " << e.ret_val << " = ";
+ TU_MATCHA( (e.fcn), (e2),
+ (Value,
+ os << "(" << e2 << ")";
+ ),
+ (Path,
+ os << e2;
+ ),
+ (Intrinsic,
+ os << "\"" << e2.name << "\"::" << e2.params;
+ )
+ )
+ os << "( ";
+ for(const auto& arg : e.args)
+ os << arg << ", ";
+ os << "), bb" << e.ret_block << ", bb" << e.panic_block << ")";
+ )
+ )
+
+ return os;
+ }
+ ::std::ostream& operator<<(::std::ostream& os, const Statement& x)
+ {
+ TU_MATCHA( (x), (e),
+ (Assign,
+ os << e.dst << " = " << e.src;
+ ),
+ (Asm,
+ os << "(";
+ for(const auto& spec : e.outputs)
+ os << "\"" << spec.first << "\" : " << spec.second << ", ";
+ os << ") = asm!(\"\", input=( ";
+ for(const auto& spec : e.inputs)
+ os << "\"" << spec.first << "\" : " << spec.second << ", ";
+ os << "), clobbers=[" << e.clobbers << "], flags=[" << e.flags << "])";
+ ),
+ (SetDropFlag,
+ os << "df$" << e.idx << " = ";
+ if( e.other == ~0u )
+ {
+ os << e.new_val;
+ }
+ else
+ {
+ os << (e.new_val ? "!" : "") << "df$" << e.other;
+ }
+ ),
+ (Drop,
+ os << "drop(" << e.slot;
+ if(e.kind == ::MIR::eDropKind::SHALLOW)
+ os << " SHALLOW";
+ if(e.flag_idx != ~0u)
+ os << " IF df$" << e.flag_idx;
+ os << ")";
+ ),
+ (ScopeEnd,
+ os << "ScopeEnd(";
+ for(auto idx : e.slots)
+ os << "_$" << idx << ",";
+ os << ")";
+ )
+ )
+ return os;
+ }
+}
+
diff --git a/tools/standalone_miri/module_tree.cpp b/tools/standalone_miri/module_tree.cpp
new file mode 100644
index 00000000..27737ea5
--- /dev/null
+++ b/tools/standalone_miri/module_tree.cpp
@@ -0,0 +1,616 @@
+//
+//
+//
+#include "module_tree.hpp"
+#include "lex.hpp"
+#include <iostream>
+
+ModuleTree::ModuleTree()
+{
+}
+
+struct Parser
+{
+ ModuleTree& tree;
+ Lexer lex;
+ Parser(ModuleTree& tree, const ::std::string& path):
+ tree(tree),
+ lex(path)
+ {
+ }
+
+ bool parse_one();
+
+ ::MIR::Function parse_body();
+ ::HIR::Path parse_path();
+ ::HIR::GenericPath parse_genericpath();
+ ::HIR::SimplePath parse_simplepath();
+ RawType parse_core_type();
+ ::HIR::TypeRef parse_type();
+ ::HIR::GenericPath parse_tuple();
+};
+
+void ModuleTree::load_file(const ::std::string& path)
+{
+ auto parse = Parser { *this, path };
+
+ while(parse.parse_one())
+ {
+ // Keep going!
+ }
+}
+// Parse a single item from a .mir file
+bool Parser::parse_one()
+{
+ if( lex.next() == "" ) // EOF?
+ {
+ return false;
+ }
+
+ if( lex.consume_if("fn") )
+ {
+ auto p = parse_path();
+ lex.check_consume('(');
+ ::std::vector<::HIR::TypeRef> arg_tys;
+ while(lex.next() != ')')
+ {
+ arg_tys.push_back( parse_type() );
+ lex.check_consume(',');
+ }
+ lex.consume();
+ ::HIR::TypeRef rv_ty;
+ if( lex.consume_if(':') )
+ {
+ rv_ty = parse_type();
+ }
+ auto body = parse_body();
+
+ tree.functions.insert( ::std::make_pair(::std::move(p), Function { ::std::move(arg_tys), rv_ty, ::std::move(body) }) );
+ }
+ else if( lex.consume_if("static") )
+ {
+ auto p = parse_path();
+ lex.check_consume('=');
+ // TODO: Body? Value?
+ //auto body = parse_body();
+ //auto data = ::std::move(lex.consume().strval);
+ throw "TODO";
+ }
+ else if( lex.consume_if("type") )
+ {
+ auto p = (lex.consume_if('(')) ? parse_tuple() : parse_genericpath();
+
+ auto rv = ::std::make_unique<DataType>();
+
+ lex.check_consume('{');
+ lex.check_consume("SIZE");
+ rv->size = lex.consume().integer();
+ lex.check_consume(',');
+ lex.check_consume("ALIGN");
+ rv->alignment = lex.consume().integer();
+ lex.check_consume(';');
+
+ // TODO: DST Meta
+ if( lex.consume_if("DSTMETA") )
+ {
+ //rv->dst_meta = parse_type();
+ lex.check_consume(';');
+ throw "TODO";
+ }
+ else
+ {
+ //rv->dst_meta = ::HIR::TypeRef::diverge();
+ }
+
+ // Data
+ while(lex.next() == TokenClass::Integer)
+ {
+ size_t ofs = lex.consume().integer();
+ lex.check_consume('=');
+ auto ty = parse_type();
+ lex.check_consume(',');
+
+ rv->fields.push_back(::std::make_pair(ofs, ::std::move(ty)));
+ }
+ // Variants
+ while(lex.next() == '[')
+ {
+ lex.consume();
+ size_t base_idx = lex.consume().integer();
+ ::std::vector<size_t> other_idx;
+ while(lex.next() == ',')
+ {
+ lex.consume();
+ other_idx.push_back( lex.consume().integer() );
+ }
+ lex.check_consume(']');
+ lex.check_consume('=');
+ lex.check(TokenClass::String);
+ uint64_t v = 0;
+ int pos = 0;
+ for(auto ch : lex.next().strval)
+ {
+ if(pos < 64)
+ {
+ v |= static_cast<uint64_t>(ch) << pos;
+ }
+ pos += 8;
+ }
+ lex.consume();
+ lex.check_consume(',');
+
+ rv->variants.push_back({ base_idx, other_idx, v });
+ }
+ lex.check_consume('}');
+
+ auto r = this->tree.data_types.insert(::std::make_pair( ::std::move(p), ::std::move(rv) ));
+ if( !r.second )
+ {
+ // Duplicate definition of a type
+ throw "ERROR";
+ }
+ }
+ else
+ {
+ // Unknown item type
+ throw "ERROR";
+ }
+
+ return true;
+}
+::MIR::Function Parser::parse_body()
+{
+ ::MIR::Function rv;
+ ::std::vector<::std::string> drop_flag_names;
+ ::std::vector<::std::string> var_names;
+
+ struct H
+ {
+ static ::std::unique_ptr<::MIR::LValue> make_lvp(::MIR::LValue&& lv) {
+ return ::std::unique_ptr<::MIR::LValue>(new ::MIR::LValue(::std::move(lv)));
+ }
+ static ::MIR::LValue parse_lvalue(Lexer& lex, ::std::vector<::std::string>& var_names)
+ {
+ int deref = 0;
+ while(lex.consume_if('*') ) {
+ deref ++;
+ }
+ ::MIR::LValue lv;
+ if( lex.consume_if('(') ) {
+ lv = parse_lvalue(lex, var_names);
+ lex.check_consume(')');
+ }
+ else if( lex.next() == TokenClass::Ident ) {
+ auto name = ::std::move(lex.consume().strval);
+ //::std::cout << "name=" << name << "\n";
+ if( name.substr(0,3) == "arg" ) {
+ auto idx = static_cast<unsigned>( ::std::stol(name.substr(4)) );
+
+ lv = ::MIR::LValue::make_Argument({ idx });
+ }
+ else if( name == "RETURN" ) {
+ lv = ::MIR::LValue::make_Return({});
+ }
+ else {
+ auto it = ::std::find(var_names.begin(), var_names.end(), name);
+ if( it == var_names.end() ) {
+ throw "ERROR";
+ }
+ lv = ::MIR::LValue::make_Local(static_cast<unsigned>(it - var_names.begin()));
+ }
+ }
+ else {
+ throw "ERROR";
+ }
+ for(;;)
+ {
+ if( lex.consume_if('.') )
+ {
+ auto idx = static_cast<unsigned>( lex.consume().integer() );
+ lv = ::MIR::LValue::make_Field({ make_lvp(::std::move(lv)), idx });
+ }
+ else if( lex.next() == '[' )
+ {
+ lex.consume();
+ auto idx_lv = parse_lvalue(lex, var_names);
+ lv = ::MIR::LValue::make_Index({ make_lvp(::std::move(lv)), make_lvp(::std::move(idx_lv)) });
+ lex.check_consume(']');
+ }
+ else
+ {
+ break;
+ }
+ }
+ while(deref --)
+ {
+ lv = ::MIR::LValue::make_Deref({ make_lvp(::std::move(lv)) });
+ }
+ return lv;
+ }
+
+ static ::MIR::Param parse_param(Parser& p, ::std::vector<::std::string>& var_names)
+ {
+ if( p.lex.next() == TokenClass::Integer ) {
+ auto v = p.lex.consume().integer();
+ auto cty = p.parse_core_type();
+ return ::MIR::Constant::make_Int({ static_cast<int64_t>(v), cty });
+ }
+ else {
+ return parse_lvalue(p.lex, var_names);
+ }
+ }
+ };
+
+ lex.check_consume('{');
+
+ // 1. Locals + Drop flags
+ while(lex.next() == "let")
+ {
+ lex.consume();
+ auto name = ::std::move(lex.consume().strval);
+ if(lex.next() == '=')
+ {
+ lex.consume();
+ rv.drop_flags.push_back(lex.consume().integer() != 0);
+ drop_flag_names.push_back(::std::move(name));
+ }
+ else if(lex.next() == ':')
+ {
+ lex.consume();
+ var_names.push_back(::std::move(name));
+ rv.locals.push_back( parse_type() );
+ }
+ else
+ {
+ throw "ERROR";
+ }
+ lex.check_consume(';');
+ }
+
+ // 3. BBs + statements
+ while(lex.next() == TokenClass::Integer)
+ {
+ ::std::vector<::MIR::Statement> stmts;
+ ::MIR::Terminator term;
+
+ lex.consume();
+ lex.check_consume(':');
+ lex.check_consume('{');
+ for(;;)
+ {
+ lex.check(TokenClass::Ident);
+ if( lex.consume_if("ASSIGN") )
+ {
+ auto dst_val = H::parse_lvalue(lex, var_names);
+ lex.check_consume('=');
+ ::MIR::RValue src_rval;
+ if( lex.next() == TokenClass::Integer ) {
+ auto v = lex.consume().integer();
+ auto cty = parse_core_type();
+ src_rval = ::MIR::Constant::make_Int({ static_cast<int64_t>(v), cty });
+ }
+ else if( lex.consume_if('(') ) {
+ ::std::vector<::MIR::Param> vals;
+ while( lex.next() != ')' )
+ {
+ vals.push_back( H::parse_param(*this, var_names) );
+ lex.check_consume(',');
+ }
+ lex.consume();
+ src_rval = ::MIR::RValue::make_Tuple({ ::std::move(vals) });
+ }
+ else if( lex.consume_if("USE") ) {
+ src_rval = H::parse_lvalue(lex, var_names);
+ }
+ else {
+ throw "";
+ }
+
+ stmts.push_back(::MIR::Statement::make_Assign({ ::std::move(dst_val), ::std::move(src_rval) }));
+ }
+ else if( lex.consume_if("SETFLAG") )
+ {
+ auto df_it = ::std::find(drop_flag_names.begin(), drop_flag_names.end(), lex.next().strval);
+ if( df_it == drop_flag_names.end() ) {
+ throw "ERROR";
+ }
+ auto df_idx = static_cast<unsigned>( df_it - drop_flag_names.begin() );
+ lex.check_consume('=');
+ if( lex.next() == TokenClass::Integer ) {
+ bool val = lex.consume().integer() != 0;
+ stmts.push_back(::MIR::Statement::make_SetDropFlag({ df_idx, val, ~0u }));
+ }
+ else {
+ bool inv = false;
+ if( lex.next() == '!' ) {
+ inv = true;
+ lex.consume();
+ }
+ df_it = ::std::find(drop_flag_names.begin(), drop_flag_names.end(), lex.next().strval);
+ if( df_it == drop_flag_names.end() ) {
+ throw "ERROR";
+ }
+ auto other_idx = static_cast<unsigned>( df_it - drop_flag_names.begin() );
+
+ stmts.push_back(::MIR::Statement::make_SetDropFlag({ df_idx, inv, other_idx }));
+ }
+ }
+ else if(lex.next() == "DROP")
+ {
+ throw "TODO";
+ }
+ else if(lex.next() == "ASM")
+ {
+ throw "TODO";
+ }
+ else
+ {
+ break;
+ }
+ lex.check_consume(';');
+ }
+
+ lex.check(TokenClass::Ident);
+ if( lex.consume_if("GOTO") )
+ {
+ term = ::MIR::Terminator::make_Goto(static_cast<unsigned>(lex.consume().integer()));
+ }
+ else if( lex.consume_if("RETURN") )
+ {
+ term = ::MIR::Terminator::make_Return({});
+ }
+ else if(lex.next() == "IF")
+ {
+ auto val = H::parse_lvalue(lex, var_names);
+ lex.check_consume("goto");
+ auto tgt_true = static_cast<unsigned>(lex.consume().integer());
+ lex.check_consume("else");
+ auto tgt_false = static_cast<unsigned>(lex.consume().integer());
+ term = ::MIR::Terminator::make_If({ ::std::move(val), tgt_true, tgt_false });
+ }
+ else if(lex.next() == "SWITCH")
+ {
+ auto val = H::parse_lvalue(lex, var_names);
+ throw "TODO";
+ }
+ else if(lex.next() == "SWITCHVAL")
+ {
+ auto val = H::parse_lvalue(lex, var_names);
+ throw "TODO";
+ }
+ else if(lex.next() == "CALL")
+ {
+ throw "TODO";
+ }
+ else
+ {
+ throw "ERROR";
+ }
+
+ lex.check_consume('}');
+
+ rv.blocks.push_back(::MIR::BasicBlock { ::std::move(stmts), ::std::move(term) });
+ }
+
+ lex.check_consume('}');
+ return rv;
+}
+::HIR::Path Parser::parse_path()
+{
+ if( lex.consume_if('<') )
+ {
+ auto ty = parse_type();
+ ::HIR::GenericPath trait;
+ if( lex.consume_if("as") )
+ {
+ trait = parse_genericpath();
+ }
+ lex.check_consume('>');
+ lex.check_consume("::");
+ lex.check(TokenClass::Ident);
+ auto item_name = ::std::move(lex.consume().strval);
+
+ ::HIR::PathParams params;
+ if( lex.consume_if('<') )
+ {
+ do
+ {
+ params.tys.push_back( parse_type() );
+ } while( lex.consume_if(',') );
+ lex.check_consume('>');
+ }
+ throw "TODO";
+ }
+ else
+ {
+ return parse_genericpath();
+ }
+}
+::HIR::GenericPath Parser::parse_genericpath()
+{
+ ::HIR::GenericPath rv;
+ rv.m_simplepath = parse_simplepath();
+ if( lex.consume_if('<') )
+ {
+ do
+ {
+ rv.m_params.tys.push_back( parse_type() );
+ } while( lex.consume_if(',') );
+ lex.check_consume('>');
+ }
+ return rv;
+}
+::HIR::SimplePath Parser::parse_simplepath()
+{
+ lex.check_consume("::");
+ lex.check(TokenClass::String);
+ auto crate = lex.consume().strval;
+ lex.check_consume("::");
+ ::std::vector<::std::string> ents;
+ do
+ {
+ lex.check(TokenClass::Ident);
+ ents.push_back( lex.consume().strval );
+ } while(lex.consume_if("::"));
+
+ return ::HIR::SimplePath { ::std::move(crate), ::std::move(ents) };
+}
+::HIR::GenericPath Parser::parse_tuple()
+{
+ // Tuples! Should point to a composite
+ ::HIR::GenericPath gp;
+ do
+ {
+ gp.m_params.tys.push_back(parse_type());
+ lex.check_consume(',');
+ } while( lex.next() != ')' );
+ lex.consume();
+
+ return gp;
+}
+RawType Parser::parse_core_type()
+{
+ auto tok = lex.consume();
+ // Primitive type.
+ if( tok == "u8" ) {
+ return RawType::U8;
+ }
+ else if( tok == "u16" ) {
+ return RawType::U16;
+ }
+ else if( tok == "u32" ) {
+ return RawType::U32;
+ }
+ else if( tok == "u64" ) {
+ return RawType::U64;
+ }
+ else if( tok == "u128" ) {
+ return RawType::U128;
+ }
+ else if( tok == "i8" ) {
+ return RawType::I8;
+ }
+ else if( tok == "i16" ) {
+ return RawType::I16;
+ }
+ else if( tok == "i32" ) {
+ return RawType::I32;
+ }
+ else if( tok == "i64" ) {
+ return RawType::I64;
+ }
+ else if( tok == "i128" ) {
+ return RawType::I128;
+ }
+ else if( tok == "f32" ) {
+ return RawType::F32;
+ }
+ else if( tok == "f64" ) {
+ return RawType::F64;
+ }
+ else if( tok == "bool" ) {
+ return RawType::Bool;
+ }
+ else if( tok == "str" ) {
+ return RawType::Str;
+ }
+ else {
+ throw "ERROR";
+ }
+}
+::HIR::TypeRef Parser::parse_type()
+{
+ if( lex.consume_if('(') )
+ {
+ if( lex.consume_if(')') ) {
+ // Unit!
+ return ::HIR::TypeRef::unit();
+ }
+ // Tuples! Should point to a composite
+ ::HIR::GenericPath gp = parse_tuple();
+
+ auto rv = this->tree.data_types.find(gp);
+ if( rv == this->tree.data_types.end() )
+ {
+ throw "ERROR";
+ }
+
+ return ::HIR::TypeRef(rv->second.get());
+ }
+ else if( lex.next() == '[' )
+ {
+ auto rv = parse_type();
+ if( lex.consume_if(';') )
+ {
+ size_t size = lex.next().integer();
+ lex.consume();
+ rv.wrappers.insert( rv.wrappers.begin(), { TypeWrapper::Ty::Array, size });
+ }
+ else
+ {
+ // TODO: How to handle arrays?
+ rv.wrappers.insert( rv.wrappers.begin(), { TypeWrapper::Ty::Slice, 0 });
+ }
+ lex.check_consume(']');
+ return rv;
+ }
+ else if( lex.next() == '!' )
+ {
+ return ::HIR::TypeRef::diverge();
+ }
+ else if( lex.next() == '&' )
+ {
+ auto bt = ::HIR::BorrowType::Shared;
+ if( lex.consume_if("move") )
+ bt = ::HIR::BorrowType::Move;
+ else if( lex.consume_if("mut") )
+ bt = ::HIR::BorrowType::Unique;
+ else
+ ; // keep as shared
+ auto rv = parse_type();
+ rv.wrappers.insert( rv.wrappers.begin(), { TypeWrapper::Ty::Borrow, 0 });
+ return rv;
+ }
+ else if( lex.next() == '*' )
+ {
+ auto bt = ::HIR::BorrowType::Shared;
+ if( lex.consume_if("move") )
+ bt = ::HIR::BorrowType::Move;
+ else if( lex.consume_if("mut") )
+ bt = ::HIR::BorrowType::Unique;
+ else if( lex.consume_if("const") )
+ ; // keep as shared
+ else
+ throw "ERROR";
+ auto rv = parse_type();
+ rv.wrappers.insert( rv.wrappers.begin(), { TypeWrapper::Ty::Pointer, 0 });
+ return rv;
+ }
+ 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?
+ throw "TODO";
+ }
+ else if( lex.next() == TokenClass::Ident )
+ {
+ return ::HIR::TypeRef(parse_core_type());
+ }
+ else
+ {
+ throw "ERROR";
+ }
+}
+
+::HIR::SimplePath ModuleTree::find_lang_item(const char* name) const
+{
+ return ::HIR::SimplePath({ "core", { "start" } });
+}
+const Function& ModuleTree::get_function(const ::HIR::Path& p) const
+{
+ auto it = functions.find(p);
+ if(it == functions.end())
+ 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
new file mode 100644
index 00000000..7475953b
--- /dev/null
+++ b/tools/standalone_miri/module_tree.hpp
@@ -0,0 +1,52 @@
+//
+//
+//
+#pragma once
+#include <string>
+#include <vector>
+#include <map>
+
+#include "../../src/mir/mir.hpp"
+#include "hir_sim.hpp"
+
+struct Function
+{
+ ::std::vector<::HIR::TypeRef> args;
+ ::HIR::TypeRef ret_ty;
+ ::MIR::Function m_mir;
+};
+
+/// Container for loaded code and structures
+class ModuleTree
+{
+ friend struct Parser;
+
+ ::std::map<::HIR::Path, Function> functions;
+ // Hack: Tuples are stored as `::""::<A,B,C,...>`
+ ::std::map<::HIR::GenericPath, ::std::unique_ptr<DataType>> data_types;
+public:
+ ModuleTree();
+
+ void load_file(const ::std::string& path);
+
+ ::HIR::SimplePath find_lang_item(const char* name) const;
+ const Function& get_function(const ::HIR::Path& p) const;
+};
+
+// struct/union/enum
+struct DataType
+{
+ // TODO: Metadata type! (indicates an unsized wrapper)
+
+ size_t alignment;
+ size_t size;
+ // Offset and datatype
+ ::std::vector<::std::pair<size_t, ::HIR::TypeRef>> fields;
+ // Values for variants
+ struct VariantValue {
+ size_t base_field;
+ ::std::vector<size_t> field_path;
+ uint64_t value; // TODO: This should be arbitary data? what size?
+ };
+ ::std::vector<VariantValue> variants;
+};
diff --git a/tools/standalone_miri/value.cpp b/tools/standalone_miri/value.cpp
new file mode 100644
index 00000000..e04154f6
--- /dev/null
+++ b/tools/standalone_miri/value.cpp
@@ -0,0 +1,178 @@
+//
+//
+//
+#include "value.hpp"
+#include "hir_sim.hpp"
+#include "module_tree.hpp"
+#include <iostream>
+#include <iomanip>
+#include <algorithm>
+
+Value::Value()
+{
+ this->meta.direct_data.size = 0;
+ this->meta.direct_data.mask[0] = 0;
+ this->meta.direct_data.mask[1] = 0;
+}
+Value::Value(::HIR::TypeRef ty)
+{
+ size_t size = ty.get_size();
+#if 1
+ if( ty.get_size() <= sizeof(this->meta.direct_data.data) )
+ {
+ struct H
+ {
+ static bool has_pointer(const ::HIR::TypeRef& ty)
+ {
+ if( ty.wrappers.empty() || ::std::all_of(ty.wrappers.begin(), ty.wrappers.end(), [](const auto& x){ return x.type == TypeWrapper::Ty::Array; }) )
+ {
+ // Check the inner type
+ if( ty.inner_type != RawType::Composite )
+ {
+ return false;
+ }
+ // Still not sure, check the inner for any pointers.
+ for(const auto& fld : ty.composite_type->fields)
+ {
+ if( H::has_pointer(fld.second) )
+ return true;
+ }
+ return false;
+ }
+ return true;
+ }
+ };
+ if( ! H::has_pointer(ty) )
+ {
+ // Will fit in a inline allocation, nice.
+ this->meta.direct_data.size = static_cast<uint8_t>(size);
+ return ;
+ }
+ }
+#endif
+
+ // Fallback: Make a new allocation
+ throw "TODO";
+}
+
+void Value::check_bytes_valid(size_t ofs, size_t size) const
+{
+ if( this->allocation )
+ {
+ throw "TODO";
+ }
+ else
+ {
+ for(size_t i = 0; i < this->meta.direct_data.size; i++)
+ {
+ if( !(this->meta.direct_data.mask[i/8] & (1 << i%8)) )
+ {
+ throw "ERROR";
+ }
+ }
+ }
+}
+void Value::mark_bytes_valid(size_t ofs, size_t size)
+{
+ if( this->allocation )
+ {
+ throw "TODO";
+ }
+ else
+ {
+ for(size_t i = 0; i < this->meta.direct_data.size; i++)
+ {
+ this->meta.direct_data.mask[i/8] |= (1 << i%8);
+ }
+ }
+}
+
+Value Value::read_value(size_t ofs, size_t size) const
+{
+ ::std::cout << "Value::read_value(" << ofs << ", " << size << ")" << ::std::endl;
+ check_bytes_valid(ofs, size);
+ if( this->allocation )
+ {
+ throw "TODO";
+ }
+ else
+ {
+ // Inline can become inline.
+ Value rv;
+ rv.meta.direct_data.size = static_cast<uint8_t>(size);
+ rv.write_bytes(0, this->meta.direct_data.data+ofs, size);
+ return rv;
+ }
+}
+void Value::read_bytes(size_t ofs, void* dst, size_t count) const
+{
+ check_bytes_valid(ofs, count);
+ throw "TODO";
+}
+
+void Value::write_bytes(size_t ofs, const void* src, size_t count)
+{
+ if( this->allocation )
+ {
+ throw "TODO";
+ }
+ else
+ {
+ if(ofs >= this->meta.direct_data.size )
+ throw "ERROR";
+ if(count > this->meta.direct_data.size )
+ throw "ERROR";
+ if(ofs+count > this->meta.direct_data.size )
+ throw "ERROR";
+ ::std::memcpy(this->meta.direct_data.data+ofs, src, count);
+ mark_bytes_valid(ofs, count);
+ }
+}
+void Value::write_value(size_t ofs, Value v)
+{
+ if( v.allocation )
+ {
+ throw "TODO";
+ }
+ else
+ {
+ v.check_bytes_valid(0, v.meta.direct_data.size);
+ write_bytes(ofs, v.meta.direct_data.data, v.meta.direct_data.size);
+ mark_bytes_valid(ofs, meta.direct_data.size);
+ }
+}
+
+size_t Value::as_usize() const
+{
+ uint64_t v;
+ this->read_bytes(0, &v, 8);
+ // TODO: Handle endian
+ return v;
+}
+::std::ostream& operator<<(::std::ostream& os, const Value& v)
+{
+ auto flags = os.flags();
+ os << ::std::hex;
+ if( v.allocation )
+ {
+ throw "TODO";
+ }
+ else
+ {
+ for(size_t i = 0; i < v.meta.direct_data.size; i++)
+ {
+ if( i != 0 )
+ os << " ";
+ if( v.meta.direct_data.mask[i/8] & (1 << i%8) )
+ {
+ os << ::std::setw(2) << ::std::setfill('0') << (int)v.meta.direct_data.data[i];
+ }
+ else
+ {
+ os << "--";
+ }
+ }
+ }
+ os.setf(flags);
+ return os;
+} \ No newline at end of file
diff --git a/tools/standalone_miri/value.hpp b/tools/standalone_miri/value.hpp
new file mode 100644
index 00000000..65403a81
--- /dev/null
+++ b/tools/standalone_miri/value.hpp
@@ -0,0 +1,69 @@
+//
+//
+//
+#pragma once
+
+#include <vector>
+#include <memory>
+#include <cstdint>
+
+namespace HIR {
+ struct TypeRef;
+}
+class Allocation;
+
+class AllocationPtr
+{
+ friend class Allocation;
+ Allocation* m_ptr;
+public:
+ AllocationPtr(): m_ptr(nullptr) {}
+
+ operator bool() const { return m_ptr != 0; }
+ Allocation& operator*() { return *m_ptr; }
+ Allocation* operator->() { return m_ptr; }
+};
+struct Relocation
+{
+ size_t slot_ofs;
+ AllocationPtr backing_alloc;
+};
+class Allocation
+{
+ size_t refcount;
+public:
+ ::std::vector<uint64_t> data;
+ ::std::vector<Relocation> relocations;
+};
+
+struct Value
+{
+ // If NULL, data is direct
+ AllocationPtr allocation;
+ union {
+ struct {
+ size_t size;
+ size_t offset;
+ } indirect_meta;
+ struct {
+ uint8_t data[2*sizeof(size_t)-3]; // 16-3 = 13, fits in 16 bits of mask
+ uint8_t mask[2];
+ uint8_t size;
+ } direct_data;
+ } meta;
+
+ Value();
+ Value(::HIR::TypeRef ty);
+
+ void check_bytes_valid(size_t ofs, size_t size) const;
+ void mark_bytes_valid(size_t ofs, size_t size);
+
+ Value read_value(size_t ofs, size_t size) const;
+ void read_bytes(size_t ofs, void* dst, size_t count) const;
+
+ void write_value(size_t ofs, Value v);
+ void write_bytes(size_t ofs, const void* src, size_t count);
+
+ size_t as_usize() const;
+};
+extern ::std::ostream& operator<<(::std::ostream& os, const Value& v);
diff --git a/vsproject/mrustc.sln b/vsproject/mrustc.sln
index 2493170e..08acf4af 100644
--- a/vsproject/mrustc.sln
+++ b/vsproject/mrustc.sln
@@ -14,6 +14,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minicargo", "minicargo\mini
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testrunner", "testrunner\testrunner.vcxproj", "{A6679301-7BF1-4B37-9468-687769472E24}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "standalone_miri", "standalone_miri\standalone_miri.vcxproj", "{253306D0-355B-41F2-A2F6-033DED548878}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -54,6 +56,14 @@ Global
{A6679301-7BF1-4B37-9468-687769472E24}.Release|x64.Build.0 = Release|x64
{A6679301-7BF1-4B37-9468-687769472E24}.Release|x86.ActiveCfg = Release|Win32
{A6679301-7BF1-4B37-9468-687769472E24}.Release|x86.Build.0 = Release|Win32
+ {253306D0-355B-41F2-A2F6-033DED548878}.Debug|x64.ActiveCfg = Debug|x64
+ {253306D0-355B-41F2-A2F6-033DED548878}.Debug|x64.Build.0 = Debug|x64
+ {253306D0-355B-41F2-A2F6-033DED548878}.Debug|x86.ActiveCfg = Debug|Win32
+ {253306D0-355B-41F2-A2F6-033DED548878}.Debug|x86.Build.0 = Debug|Win32
+ {253306D0-355B-41F2-A2F6-033DED548878}.Release|x64.ActiveCfg = Release|x64
+ {253306D0-355B-41F2-A2F6-033DED548878}.Release|x64.Build.0 = Release|x64
+ {253306D0-355B-41F2-A2F6-033DED548878}.Release|x86.ActiveCfg = Release|Win32
+ {253306D0-355B-41F2-A2F6-033DED548878}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/vsproject/standalone_miri/standalone_miri.vcxproj b/vsproject/standalone_miri/standalone_miri.vcxproj
new file mode 100644
index 00000000..e992e3df
--- /dev/null
+++ b/vsproject/standalone_miri/standalone_miri.vcxproj
@@ -0,0 +1,173 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{253306D0-355B-41F2-A2F6-033DED548878}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>standalone_miri</RootNamespace>
+ <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="Shared">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <SDLCheck>true</SDLCheck>
+ <AdditionalIncludeDirectories>$(SolutionDir)..\src\include;$(SolutionDir)..\tools\standalone_miri;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <SDLCheck>true</SDLCheck>
+ <AdditionalIncludeDirectories>$(SolutionDir)..\src\include;$(SolutionDir)..\tools\standalone_miri;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <SDLCheck>true</SDLCheck>
+ <AdditionalIncludeDirectories>$(SolutionDir)..\src\include;$(SolutionDir)..\tools\standalone_miri;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <SDLCheck>true</SDLCheck>
+ <AdditionalIncludeDirectories>$(SolutionDir)..\src\include;$(SolutionDir)..\tools\standalone_miri;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <Text Include="ReadMe.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\tools\standalone_miri\hir_sim.hpp" />
+ <ClInclude Include="..\..\tools\standalone_miri\lex.hpp" />
+ <ClInclude Include="..\..\tools\standalone_miri\module_tree.hpp" />
+ <ClInclude Include="..\..\tools\standalone_miri\value.hpp" />
+ <ClInclude Include="targetver.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\tools\standalone_miri\hir_sim.cpp" />
+ <ClCompile Include="..\..\tools\standalone_miri\lex.cpp" />
+ <ClCompile Include="..\..\tools\standalone_miri\main.cpp" />
+ <ClCompile Include="..\..\tools\standalone_miri\mir.cpp" />
+ <ClCompile Include="..\..\tools\standalone_miri\module_tree.cpp" />
+ <ClCompile Include="..\..\tools\standalone_miri\value.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/vsproject/standalone_miri/standalone_miri.vcxproj.filters b/vsproject/standalone_miri/standalone_miri.vcxproj.filters
new file mode 100644
index 00000000..3010940e
--- /dev/null
+++ b/vsproject/standalone_miri/standalone_miri.vcxproj.filters
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <Text Include="ReadMe.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="targetver.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\tools\standalone_miri\module_tree.hpp">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\tools\standalone_miri\hir_sim.hpp">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\tools\standalone_miri\value.hpp">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\tools\standalone_miri\lex.hpp">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\tools\standalone_miri\main.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tools\standalone_miri\module_tree.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tools\standalone_miri\hir_sim.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tools\standalone_miri\lex.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tools\standalone_miri\mir.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tools\standalone_miri\value.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/vsproject/standalone_miri/targetver.h b/vsproject/standalone_miri/targetver.h
new file mode 100644
index 00000000..87c0086d
--- /dev/null
+++ b/vsproject/standalone_miri/targetver.h
@@ -0,0 +1,8 @@
+#pragma once
+
+// Including SDKDDKVer.h defines the highest available Windows platform.
+
+// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
+// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
+
+#include <SDKDDKVer.h>