diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | src/include/tagged_union.hpp | 2 | ||||
-rw-r--r-- | src/mir/mir.hpp | 1 | ||||
-rw-r--r-- | tools/standalone_miri/hir/type.hpp | 1 | ||||
-rw-r--r-- | tools/standalone_miri/hir_sim.cpp | 201 | ||||
-rw-r--r-- | tools/standalone_miri/hir_sim.hpp | 235 | ||||
-rw-r--r-- | tools/standalone_miri/lex.cpp | 220 | ||||
-rw-r--r-- | tools/standalone_miri/lex.hpp | 57 | ||||
-rw-r--r-- | tools/standalone_miri/main.cpp | 325 | ||||
-rw-r--r-- | tools/standalone_miri/mir.cpp | 299 | ||||
-rw-r--r-- | tools/standalone_miri/module_tree.cpp | 616 | ||||
-rw-r--r-- | tools/standalone_miri/module_tree.hpp | 52 | ||||
-rw-r--r-- | tools/standalone_miri/value.cpp | 178 | ||||
-rw-r--r-- | tools/standalone_miri/value.hpp | 69 | ||||
-rw-r--r-- | vsproject/mrustc.sln | 10 | ||||
-rw-r--r-- | vsproject/standalone_miri/standalone_miri.vcxproj | 173 | ||||
-rw-r--r-- | vsproject/standalone_miri/standalone_miri.vcxproj.filters | 57 | ||||
-rw-r--r-- | vsproject/standalone_miri/targetver.h | 8 |
18 files changed, 2504 insertions, 1 deletions
@@ -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> |