From f5168113b6dcdfc8e9713dcf122b99ca6e26a4fc Mon Sep 17 00:00:00 2001 From: John Hodge Date: Fri, 19 Oct 2018 07:40:53 +0800 Subject: Codegen C - Fix incorrect use of ZST in enum constructor shim (fixes #86) --- src/trans/codegen_c.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 0ced3150..b578c09b 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -1538,7 +1538,7 @@ namespace { { if( this->type_is_bad_zst(repr->fields[var_idx].ty) ) { - m_of << " .DATA = { /* ZST Variant */ }"; + //m_of << " .DATA = { /* ZST Variant */ }"; } else { -- cgit v1.2.3 From 9dd5e5364bacf75e8b7f034e61a7f536d0a6344c Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 21 Oct 2018 09:53:43 +0800 Subject: Windows build fixes --- src/hir/expr_ptr.hpp | 2 +- src/mir/cleanup.cpp | 2 +- vsproject/mrustc.vcxproj | 1 - vsproject/mrustc.vcxproj.filters | 3 --- 4 files changed, 2 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/hir/expr_ptr.hpp b/src/hir/expr_ptr.hpp index b510e737..2f0f30e4 100644 --- a/src/hir/expr_ptr.hpp +++ b/src/hir/expr_ptr.hpp @@ -12,7 +12,7 @@ #include -class Span; +struct Span; namespace HIR { diff --git a/src/mir/cleanup.cpp b/src/mir/cleanup.cpp index 37d256df..eae24031 100644 --- a/src/mir/cleanup.cpp +++ b/src/mir/cleanup.cpp @@ -1218,7 +1218,7 @@ void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path, void MIR_CleanupCrate(::HIR::Crate& crate) { - ::MIR::OuterVisitor ov { crate, [&](const auto& res, const auto& p, auto& expr_ptr, const auto& args, const auto& ty){ + ::MIR::OuterVisitor ov { crate, [&](const auto& res, const auto& p, ::HIR::ExprPtr& expr_ptr, const auto& args, const auto& ty){ MIR_Cleanup(res, p, expr_ptr.get_mir_or_error_mut(Span()), args, ty); } }; ov.visit_crate(crate); diff --git a/vsproject/mrustc.vcxproj b/vsproject/mrustc.vcxproj index 13c4a23e..234ce37b 100644 --- a/vsproject/mrustc.vcxproj +++ b/vsproject/mrustc.vcxproj @@ -206,7 +206,6 @@ - diff --git a/vsproject/mrustc.vcxproj.filters b/vsproject/mrustc.vcxproj.filters index 755013af..cedc5fd1 100644 --- a/vsproject/mrustc.vcxproj.filters +++ b/vsproject/mrustc.vcxproj.filters @@ -98,9 +98,6 @@ Source Files\hir_expand - - Source Files\hir_expand - Source Files\hir_conv -- cgit v1.2.3 From bd32801622229ba3ac02924852f2835bed9debc3 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 3 Nov 2018 22:09:14 +0800 Subject: HIR Typecheck - Fix mixup between assignment SHR/SHL operator traits --- src/hir_typeck/expr_check.cpp | 4 ++-- src/hir_typeck/expr_cs.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/hir_typeck/expr_check.cpp b/src/hir_typeck/expr_check.cpp index 985fe15f..319124ad 100644 --- a/src/hir_typeck/expr_check.cpp +++ b/src/hir_typeck/expr_check.cpp @@ -177,8 +177,8 @@ namespace { case ::HIR::ExprNode_Assign::Op::And: lang_item = "bitand_assign"; break; case ::HIR::ExprNode_Assign::Op::Or : lang_item = "bitor_assign" ; break; case ::HIR::ExprNode_Assign::Op::Xor: lang_item = "bitxor_assign"; break; - case ::HIR::ExprNode_Assign::Op::Shr: lang_item = "shl_assign"; break; - case ::HIR::ExprNode_Assign::Op::Shl: lang_item = "shr_assign"; break; + case ::HIR::ExprNode_Assign::Op::Shr: lang_item = "shr_assign"; break; + case ::HIR::ExprNode_Assign::Op::Shl: lang_item = "shl_assign"; break; } assert(lang_item); const auto& trait_path = this->get_lang_item_path(node.span(), lang_item); diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index 62f50ed9..b62ea1cc 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -846,8 +846,8 @@ namespace { case ::HIR::ExprNode_Assign::Op::And: lang_item = "bitand_assign"; break; case ::HIR::ExprNode_Assign::Op::Or : lang_item = "bitor_assign" ; break; case ::HIR::ExprNode_Assign::Op::Xor: lang_item = "bitxor_assign"; break; - case ::HIR::ExprNode_Assign::Op::Shr: lang_item = "shl_assign"; break; - case ::HIR::ExprNode_Assign::Op::Shl: lang_item = "shr_assign"; break; + case ::HIR::ExprNode_Assign::Op::Shr: lang_item = "shr_assign"; break; + case ::HIR::ExprNode_Assign::Op::Shl: lang_item = "shl_assign"; break; } assert(lang_item); const auto& trait_path = this->context.m_crate.get_lang_item_path(node.span(), lang_item); -- cgit v1.2.3 From a51eea542ae086687ea2c4cb09321785f5cc6269 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 4 Nov 2018 08:22:18 +0800 Subject: Typecheck Expressions - Fix a use-after-free, impacts #85 --- src/hir_typeck/expr_cs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index b62ea1cc..554fea69 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -5204,7 +5204,7 @@ namespace { DEBUG("- Magic inferrence link for binops on numerics"); context.equate_types(sp, res, left); } - context.equate_types_to_shadow(sp, right); + context.equate_types_to_shadow(sp, /*right*/v.params.m_types.at(0)); // RHS, can't use `right` because it might be freed by the above equate. } else { -- cgit v1.2.3 From 9afb96ccf062961c663e4c84f803e3a01054ea7a Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 4 Nov 2018 08:24:41 +0800 Subject: Typecheck Expressions - (minor) Slight cleanup --- src/hir_typeck/helpers.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp index 22291123..0a56e9cb 100644 --- a/src/hir_typeck/helpers.cpp +++ b/src/hir_typeck/helpers.cpp @@ -622,7 +622,7 @@ void HMTypeInferrence::set_ivar_to(unsigned int slot, ::HIR::TypeRef type) ) else #endif - root_ivar.type = box$( mv$(type) ); + root_ivar.type = box$( type ); } this->mark_change(); @@ -1544,7 +1544,7 @@ bool TraitResolution::has_associated_type(const ::HIR::TypeRef& input) const //TRACE_FUNCTION_F(input); TU_MATCH(::HIR::TypeRef::Data, (input.m_data), (e), (Infer, - auto& ty = this->m_ivars.get_type(input); + const auto& ty = this->m_ivars.get_type(input); if( ty != input ) { return this->has_associated_type(ty); } -- cgit v1.2.3 From 1726886913173c2828e962d7c5d384e3915d0ae3 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 4 Nov 2018 20:28:32 +0800 Subject: All - Cleaning up some memory leaks --- src/include/rc_string.hpp | 37 +++++++++---------------- src/include/span.hpp | 6 ++++- src/macro_rules/macro_rules_ptr.hpp | 2 +- src/macro_rules/mod.cpp | 6 +++++ src/parse/pattern.cpp | 54 ++++++++++++++++++------------------- src/parse/root.cpp | 22 +++++++-------- src/parse/token.cpp | 1 + src/parse/tokenstream.cpp | 2 +- src/parse/types.cpp | 26 +++++++++--------- src/rc_string.cpp | 14 +++++++++- src/span.cpp | 9 ------- 11 files changed, 90 insertions(+), 89 deletions(-) (limited to 'src') diff --git a/src/include/rc_string.hpp b/src/include/rc_string.hpp index eec47d80..914228c6 100644 --- a/src/include/rc_string.hpp +++ b/src/include/rc_string.hpp @@ -29,12 +29,7 @@ public: { } - RcString(const RcString& x): - m_ptr(x.m_ptr), - m_len(x.m_len) - { - if( m_ptr ) *m_ptr += 1; - } + RcString(const RcString& x); RcString(RcString&& x): m_ptr(x.m_ptr), m_len(x.m_len) @@ -47,36 +42,28 @@ public: RcString& operator=(const RcString& x) { - if( &x != this ) - { - this->~RcString(); - m_ptr = x.m_ptr; - m_len = x.m_len; - if( m_ptr ) *m_ptr += 1; - } + if( !(&x != this) ) throw ""; + + this->~RcString(); + new (this) RcString(x); + return *this; } RcString& operator=(RcString&& x) { - if( &x != this ) - { - this->~RcString(); - m_ptr = x.m_ptr; - m_len = x.m_len; - x.m_ptr = nullptr; - x.m_len = 0; - } + if( !(&x != this) ) throw ""; + + this->~RcString(); + new (this) RcString( ::std::move(x) ); return *this; } const char* c_str() const { - if( m_len > 0 ) - { + if( m_len > 0 ) { return reinterpret_cast(m_ptr + 1); } - else - { + else { return ""; } } diff --git a/src/include/span.hpp b/src/include/span.hpp index 68d6bfdf..d41fa81e 100644 --- a/src/include/span.hpp +++ b/src/include/span.hpp @@ -46,10 +46,14 @@ struct Span end_line(end_line), end_ofs(end_ofs) {} - Span(const Span& x); + Span(const Span& x) = default; + Span(Span&& x) = default; Span(const Position& position); Span(); + Span& operator=(const Span& x) = default; + Span& operator=(Span&& x) = default; + void bug(::std::function msg) const; void error(ErrorType tag, ::std::function msg) const; void warning(WarningType tag, ::std::function msg) const; diff --git a/src/macro_rules/macro_rules_ptr.hpp b/src/macro_rules/macro_rules_ptr.hpp index fdb01fbe..5dbfd032 100644 --- a/src/macro_rules/macro_rules_ptr.hpp +++ b/src/macro_rules/macro_rules_ptr.hpp @@ -14,7 +14,7 @@ class MacroRulesPtr MacroRules* m_ptr; public: MacroRulesPtr(): m_ptr(nullptr) {} - MacroRulesPtr(MacroRules* p): m_ptr(p) {} + MacroRulesPtr(MacroRules* p); MacroRulesPtr(MacroRulesPtr&& x): m_ptr(x.m_ptr) { diff --git a/src/macro_rules/mod.cpp b/src/macro_rules/mod.cpp index 6410d334..f9754286 100644 --- a/src/macro_rules/mod.cpp +++ b/src/macro_rules/mod.cpp @@ -157,10 +157,16 @@ bool is_token_item(eTokenType tt) { } } +MacroRulesPtr::MacroRulesPtr(MacroRules* p): + m_ptr(p) +{ + //::std::cout << "MRP new " << m_ptr << ::std::endl; +} MacroRulesPtr::~MacroRulesPtr() { if(m_ptr) { + //::std::cout << "MRP delete " << m_ptr << ::std::endl; delete m_ptr; m_ptr = nullptr; } diff --git a/src/parse/pattern.cpp b/src/parse/pattern.cpp index f6d61728..e2949a63 100644 --- a/src/parse/pattern.cpp +++ b/src/parse/pattern.cpp @@ -92,7 +92,7 @@ AST::Pattern Parse_Pattern(TokenStream& lex, bool is_refutable) if( GET_TOK(tok, lex) != TOK_AT ) { PUTBACK(tok, lex); - return AST::Pattern(AST::Pattern::TagBind(), lex.end_span(ps), mv$(bind_name), bind_type, is_mut); + return AST::Pattern(AST::Pattern::TagBind(), lex.end_span(mv$(ps)), mv$(bind_name), bind_type, is_mut); } binding = AST::PatternBinding( mv$(bind_name), bind_type, is_mut ); @@ -126,11 +126,11 @@ AST::Pattern Parse_Pattern(TokenStream& lex, bool is_refutable) if( is_refutable ) { assert(bind_type == ::AST::PatternBinding::Type::MOVE); assert(is_mut == false); - return AST::Pattern(AST::Pattern::TagMaybeBind(), lex.end_span(ps), mv$(name)); + return AST::Pattern(AST::Pattern::TagMaybeBind(), lex.end_span(mv$(ps)), mv$(name)); } // Otherwise, it IS a binding else { - return AST::Pattern(AST::Pattern::TagBind(), lex.end_span(ps), mv$(name), bind_type, is_mut); + return AST::Pattern(AST::Pattern::TagBind(), lex.end_span(mv$(ps)), mv$(name), bind_type, is_mut); } break;} } @@ -188,11 +188,11 @@ AST::Pattern Parse_PatternReal1(TokenStream& lex, bool is_refutable) switch( GET_TOK(tok, lex) ) { case TOK_UNDERSCORE: - return AST::Pattern( lex.end_span(ps), AST::Pattern::Data() ); + return AST::Pattern( lex.end_span(mv$(ps)), AST::Pattern::Data() ); //case TOK_DOUBLE_DOT: // return AST::Pattern( AST::Pattern::TagWildcard() ); case TOK_RWORD_BOX: - return AST::Pattern( AST::Pattern::TagBox(), lex.end_span(ps), Parse_Pattern(lex, is_refutable) ); + return AST::Pattern( AST::Pattern::TagBox(), lex.end_span(mv$(ps)), Parse_Pattern(lex, is_refutable) ); case TOK_DOUBLE_AMP: lex.putback(TOK_AMP); case TOK_AMP: { @@ -203,7 +203,7 @@ AST::Pattern Parse_PatternReal1(TokenStream& lex, bool is_refutable) is_mut = true; else PUTBACK(tok, lex); - return AST::Pattern( AST::Pattern::TagReference(), lex.end_span(ps), is_mut, Parse_Pattern(lex, is_refutable) ); + return AST::Pattern( AST::Pattern::TagReference(), lex.end_span(mv$(ps)), is_mut, Parse_Pattern(lex, is_refutable) ); } case TOK_RWORD_SELF: case TOK_RWORD_SUPER: @@ -221,44 +221,44 @@ AST::Pattern Parse_PatternReal1(TokenStream& lex, bool is_refutable) { auto dt = tok.datatype(); // TODO: Ensure that the type is ANY or a signed integer - return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(ps), AST::Pattern::Value::make_Integer({dt, -tok.intval()}) ); + return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(mv$(ps)), AST::Pattern::Value::make_Integer({dt, -tok.intval()}) ); } else if( tok.type() == TOK_FLOAT ) { - return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(ps), AST::Pattern::Value::make_Float({tok.datatype(), -tok.floatval()}) ); + return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(mv$(ps)), AST::Pattern::Value::make_Float({tok.datatype(), -tok.floatval()}) ); } else { throw ParseError::Unexpected(lex, tok, {TOK_INTEGER, TOK_FLOAT}); } case TOK_FLOAT: - return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(ps), AST::Pattern::Value::make_Float({tok.datatype(), tok.floatval()}) ); + return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(mv$(ps)), AST::Pattern::Value::make_Float({tok.datatype(), tok.floatval()}) ); case TOK_INTEGER: - return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(ps), AST::Pattern::Value::make_Integer({tok.datatype(), tok.intval()}) ); + return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(mv$(ps)), AST::Pattern::Value::make_Integer({tok.datatype(), tok.intval()}) ); case TOK_RWORD_TRUE: - return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(ps), AST::Pattern::Value::make_Integer({CORETYPE_BOOL, 1}) ); + return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(mv$(ps)), AST::Pattern::Value::make_Integer({CORETYPE_BOOL, 1}) ); case TOK_RWORD_FALSE: - return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(ps), AST::Pattern::Value::make_Integer({CORETYPE_BOOL, 0}) ); + return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(mv$(ps)), AST::Pattern::Value::make_Integer({CORETYPE_BOOL, 0}) ); case TOK_STRING: - return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(ps), AST::Pattern::Value::make_String( mv$(tok.str()) ) ); + return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(mv$(ps)), AST::Pattern::Value::make_String( mv$(tok.str()) ) ); case TOK_BYTESTRING: - return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(ps), AST::Pattern::Value::make_ByteString({ mv$(tok.str()) }) ); + return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(mv$(ps)), AST::Pattern::Value::make_ByteString({ mv$(tok.str()) }) ); case TOK_INTERPOLATED_EXPR: { auto e = tok.take_frag_node(); if( auto* n = dynamic_cast(e.get()) ) { - return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(ps), AST::Pattern::Value::make_String( mv$(n->m_value) ) ); + return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(mv$(ps)), AST::Pattern::Value::make_String( mv$(n->m_value) ) ); } //else if( auto* n = dynamic_cast(e.get()) ) { - // return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(ps), AST::Pattern::Value::make_ByteString( mv$(n->m_value) ) ); + // return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(mv$(ps)), AST::Pattern::Value::make_ByteString( mv$(n->m_value) ) ); //} else if( auto* n = dynamic_cast(e.get()) ) { - return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(ps), AST::Pattern::Value::make_Integer({CORETYPE_BOOL, n->m_value}) ); + return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(mv$(ps)), AST::Pattern::Value::make_Integer({CORETYPE_BOOL, n->m_value}) ); } else if( auto* n = dynamic_cast(e.get()) ) { - return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(ps), AST::Pattern::Value::make_Integer({n->m_datatype, n->m_value}) ); + return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(mv$(ps)), AST::Pattern::Value::make_Integer({n->m_datatype, n->m_value}) ); } else if( auto* n = dynamic_cast(e.get()) ) { - return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(ps), AST::Pattern::Value::make_Float({n->m_datatype, n->m_value}) ); + return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(mv$(ps)), AST::Pattern::Value::make_Float({n->m_datatype, n->m_value}) ); } else { TODO(lex.point_span(), "Convert :expr into a pattern value - " << *e); @@ -266,7 +266,7 @@ AST::Pattern Parse_PatternReal1(TokenStream& lex, bool is_refutable) } break; case TOK_PAREN_OPEN: - return AST::Pattern( AST::Pattern::TagTuple(), lex.end_span(ps), Parse_PatternTuple(lex, is_refutable) ); + return AST::Pattern( AST::Pattern::TagTuple(), lex.end_span(mv$(ps)), Parse_PatternTuple(lex, is_refutable) ); case TOK_SQUARE_OPEN: return Parse_PatternReal_Slice(lex, is_refutable); default: @@ -280,12 +280,12 @@ AST::Pattern Parse_PatternReal_Path(TokenStream& lex, ProtoSpan ps, AST::Path pa switch( GET_TOK(tok, lex) ) { case TOK_PAREN_OPEN: - return AST::Pattern( AST::Pattern::TagNamedTuple(), lex.end_span(ps), mv$(path), Parse_PatternTuple(lex, is_refutable) ); + return AST::Pattern( AST::Pattern::TagNamedTuple(), lex.end_span(mv$(ps)), mv$(path), Parse_PatternTuple(lex, is_refutable) ); case TOK_BRACE_OPEN: return Parse_PatternStruct(lex, ps, mv$(path), is_refutable); default: PUTBACK(tok, lex); - return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(ps), AST::Pattern::Value::make_Named(mv$(path)) ); + return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(mv$(ps)), AST::Pattern::Value::make_Named(mv$(path)) ); } } @@ -323,7 +323,7 @@ AST::Pattern Parse_PatternReal_Slice(TokenStream& lex, bool is_refutable) if( has_binding ) { if(is_split) - ERROR(lex.end_span(ps), E0000, "Multiple instances of .. in a slice pattern"); + ERROR(lex.end_span(mv$(ps)), E0000, "Multiple instances of .. in a slice pattern"); inner_binding = mv$(binding); is_split = true; @@ -346,13 +346,13 @@ AST::Pattern Parse_PatternReal_Slice(TokenStream& lex, bool is_refutable) if( is_split ) { - return ::AST::Pattern( lex.end_span(ps), ::AST::Pattern::Data::make_SplitSlice({ mv$(leading), mv$(inner_binding), mv$(trailing) }) ); + return ::AST::Pattern( lex.end_span(mv$(ps)), ::AST::Pattern::Data::make_SplitSlice({ mv$(leading), mv$(inner_binding), mv$(trailing) }) ); } else { assert( !inner_binding.is_valid() ); assert( trailing.empty() ); - return ::AST::Pattern( lex.end_span(ps), ::AST::Pattern::Data::make_Slice({ mv$(leading) }) ); + return ::AST::Pattern( lex.end_span(mv$(ps)), ::AST::Pattern::Data::make_Slice({ mv$(leading) }) ); } } @@ -452,7 +452,7 @@ AST::Pattern Parse_PatternStruct(TokenStream& lex, ProtoSpan ps, AST::Path path, i ++; } - return AST::Pattern(AST::Pattern::TagNamedTuple(), lex.end_span(ps), mv$(path), AST::Pattern::TuplePat { mv$(leading), has_split, mv$(trailing) }); + return AST::Pattern(AST::Pattern::TagNamedTuple(), lex.end_span(mv$(ps)), mv$(path), AST::Pattern::TuplePat { mv$(leading), has_split, mv$(trailing) }); } bool is_exhaustive = true; @@ -521,6 +521,6 @@ AST::Pattern Parse_PatternStruct(TokenStream& lex, ProtoSpan ps, AST::Path path, } while( GET_TOK(tok, lex) == TOK_COMMA ); CHECK_TOK(tok, TOK_BRACE_CLOSE); - return AST::Pattern(AST::Pattern::TagStruct(), lex.end_span(ps), ::std::move(path), ::std::move(subpats), is_exhaustive); + return AST::Pattern(AST::Pattern::TagStruct(), lex.end_span(mv$(ps)), ::std::move(path), ::std::move(subpats), is_exhaustive); } diff --git a/src/parse/root.cpp b/src/parse/root.cpp index 68ad570b..bc001c99 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -25,7 +25,7 @@ Spanned get_spanned(TokenStream& lex, ::std::function f) { auto ps = lex.start_span(); auto v = f(); return Spanned { - lex.end_span(ps), + lex.end_span( mv$(ps) ), mv$(v) }; } @@ -499,7 +499,7 @@ AST::Function Parse_FunctionDef(TokenStream& lex, ::std::string abi, bool allow_ PUTBACK(tok, lex); } - return AST::Function(lex.end_span(ps), mv$(params), mv$(abi), is_unsafe, is_const, is_variadic, mv$(ret_type), mv$(args)); + return AST::Function(lex.end_span( mv$(ps) ), mv$(params), mv$(abi), is_unsafe, is_const, is_variadic, mv$(ret_type), mv$(args)); } AST::Function Parse_FunctionDefWithCode(TokenStream& lex, ::std::string abi, bool allow_self, bool is_unsafe, bool is_const) @@ -1003,12 +1003,12 @@ AST::Attribute Parse_MetaItem(TokenStream& lex) switch(GET_TOK(tok, lex)) { case TOK_STRING: - return AST::Attribute(lex.end_span(ps), name, tok.str()); + return AST::Attribute(lex.end_span(mv$(ps)), name, tok.str()); case TOK_INTERPOLATED_EXPR: { auto n = tok.take_frag_node(); if( auto* v = dynamic_cast<::AST::ExprNode_String*>(&*n) ) { - return AST::Attribute(lex.end_span(ps), name, mv$(v->m_value)); + return AST::Attribute(lex.end_span(mv$(ps)), name, mv$(v->m_value)); } else { @@ -1031,10 +1031,10 @@ AST::Attribute Parse_MetaItem(TokenStream& lex) items.push_back(Parse_MetaItem(lex)); } while(GET_TOK(tok, lex) == TOK_COMMA); CHECK_TOK(tok, TOK_PAREN_CLOSE); - return AST::Attribute(lex.end_span(ps), name, mv$(items)); } + return AST::Attribute(lex.end_span(mv$(ps)), name, mv$(items)); } default: PUTBACK(tok, lex); - return AST::Attribute(lex.end_span(ps), name); + return AST::Attribute(lex.end_span(mv$(ps)), name); } } @@ -1229,7 +1229,7 @@ void Parse_Impl_Item(TokenStream& lex, AST::Impl& impl) throw ParseError::Unexpected(lex, tok); } - impl.items().back().data->span = lex.end_span(ps); + impl.items().back().data->span = lex.end_span(mv$(ps)); impl.items().back().data->attrs = mv$(item_attrs); // Empty for functions } @@ -1262,7 +1262,7 @@ AST::ExternBlock Parse_ExternBlock(TokenStream& lex, ::std::string abi, ::AST::A GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); i.attrs = mv$(meta_items); - i.span = lex.end_span(ps); + i.span = lex.end_span(mv$(ps)); rv.add_item( AST::Named { mv$(name), mv$(i), is_public } ); break; } @@ -1280,7 +1280,7 @@ AST::ExternBlock Parse_ExternBlock(TokenStream& lex, ::std::string abi, ::AST::A auto i = ::AST::Item(::AST::Static( (is_mut ? ::AST::Static::MUT : ::AST::Static::STATIC), mv$(type), ::AST::Expr() )); i.attrs = mv$(meta_items); - i.span = lex.end_span(ps); + i.span = lex.end_span(mv$(ps)); rv.add_item( AST::Named { mv$(name), mv$(i), is_public } ); break; } default: @@ -1504,7 +1504,7 @@ bool Parse_MacroInvocation_Opt(TokenStream& lex, AST::MacroInvocation& out_inv) { item_data = ::AST::Item( mv$(inv) ); item_data.attrs = mv$(meta_items); - item_data.span = lex.end_span(ps); + item_data.span = lex.end_span(mv$(ps)); return ::AST::Named< ::AST::Item> { "", mv$(item_data), false }; } @@ -1875,7 +1875,7 @@ bool Parse_MacroInvocation_Opt(TokenStream& lex, AST::MacroInvocation& out_inv) } item_data.attrs = mv$(meta_items); - item_data.span = lex.end_span(ps); + item_data.span = lex.end_span(mv$(ps)); return ::AST::Named< ::AST::Item> { mv$(item_name), mv$(item_data), is_public }; } diff --git a/src/parse/token.cpp b/src/parse/token.cpp index 115df135..2e5a61d4 100644 --- a/src/parse/token.cpp +++ b/src/parse/token.cpp @@ -207,6 +207,7 @@ Token Token::clone() const BUG(m_pos, "Fragment with invalid token type (" << *this << ")"); break; } + assert(rv.m_data.is_Fragment()); ) ) return rv; diff --git a/src/parse/tokenstream.cpp b/src/parse/tokenstream.cpp index 611df2ff..889c626c 100644 --- a/src/parse/tokenstream.cpp +++ b/src/parse/tokenstream.cpp @@ -125,7 +125,7 @@ ProtoSpan TokenStream::start_span() const Span TokenStream::end_span(ProtoSpan ps) const { auto p = this->getPosition(); - auto rv = Span( ps.filename, ps.start_line, ps.start_ofs, p.line, p.ofs ); + auto rv = Span( ::std::move(ps.filename), ps.start_line, ps.start_ofs, p.line, p.ofs ); rv.outer_span = this->outerSpan(); return rv; } diff --git a/src/parse/types.cpp b/src/parse/types.cpp index a07e66f8..ca5b7892 100644 --- a/src/parse/types.cpp +++ b/src/parse/types.cpp @@ -61,7 +61,7 @@ TypeRef Parse_Type_Int(TokenStream& lex, bool allow_trait_list) case TOK_DOUBLE_LT: { PUTBACK(tok, lex); auto path = Parse_Path(lex, PATH_GENERIC_TYPE); - return TypeRef(TypeRef::TagPath(), lex.end_span(ps), mv$(path)); + return TypeRef(TypeRef::TagPath(), lex.end_span(mv$(ps)), mv$(path)); } // case TOK_RWORD_FOR: { @@ -122,7 +122,7 @@ TypeRef Parse_Type_Int(TokenStream& lex, bool allow_trait_list) else { PUTBACK(tok, lex); } - return TypeRef(TypeRef::TagReference(), lex.end_span(ps), ::std::move(lifetime), is_mut, Parse_Type(lex, false)); + return TypeRef(TypeRef::TagReference(), lex.end_span(mv$(ps)), ::std::move(lifetime), is_mut, Parse_Type(lex, false)); } // '*' - Raw pointer case TOK_STAR: @@ -131,10 +131,10 @@ TypeRef Parse_Type_Int(TokenStream& lex, bool allow_trait_list) { case TOK_RWORD_MUT: // Mutable pointer - return TypeRef(TypeRef::TagPointer(), lex.end_span(ps), true, Parse_Type(lex, false)); + return TypeRef(TypeRef::TagPointer(), lex.end_span(mv$(ps)), true, Parse_Type(lex, false)); case TOK_RWORD_CONST: // Immutable pointer - return TypeRef(TypeRef::TagPointer(), lex.end_span(ps), false, Parse_Type(lex, false)); + return TypeRef(TypeRef::TagPointer(), lex.end_span(mv$(ps)), false, Parse_Type(lex, false)); default: throw ParseError::Unexpected(lex, tok, {TOK_RWORD_CONST, TOK_RWORD_MUT}); } @@ -147,11 +147,11 @@ TypeRef Parse_Type_Int(TokenStream& lex, bool allow_trait_list) // Sized array AST::Expr array_size = Parse_Expr(lex); GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE); - return TypeRef(TypeRef::TagSizedArray(), lex.end_span(ps), mv$(inner), array_size.take_node()); + return TypeRef(TypeRef::TagSizedArray(), lex.end_span(mv$(ps)), mv$(inner), array_size.take_node()); } else if( tok.type() == TOK_SQUARE_CLOSE ) { - return TypeRef(TypeRef::TagUnsizedArray(), lex.end_span(ps), mv$(inner)); + return TypeRef(TypeRef::TagUnsizedArray(), lex.end_span(mv$(ps)), mv$(inner)); } else { throw ParseError::Unexpected(lex, tok/*, "; or ]"*/); @@ -162,7 +162,7 @@ TypeRef Parse_Type_Int(TokenStream& lex, bool allow_trait_list) case TOK_PAREN_OPEN: { DEBUG("Tuple"); if( GET_TOK(tok, lex) == TOK_PAREN_CLOSE ) - return TypeRef(TypeRef::TagTuple(), lex.end_span(ps), {}); + return TypeRef(TypeRef::TagTuple(), lex.end_span(mv$(ps)), {}); PUTBACK(tok, lex); TypeRef inner = Parse_Type(lex, true); @@ -185,7 +185,7 @@ TypeRef Parse_Type_Int(TokenStream& lex, bool allow_trait_list) types.push_back( Parse_Type(lex) ); } CHECK_TOK(tok, TOK_PAREN_CLOSE); - return TypeRef(TypeRef::TagTuple(), lex.end_span(ps), mv$(types)); } + return TypeRef(TypeRef::TagTuple(), lex.end_span(mv$(ps)), mv$(types)); } } default: throw ParseError::Unexpected(lex, tok); @@ -259,7 +259,7 @@ TypeRef Parse_Type_Fn(TokenStream& lex, ::AST::HigherRankedBounds hrbs) PUTBACK(tok, lex); } - return TypeRef(TypeRef::TagFunction(), lex.end_span(ps), mv$(hrbs), is_unsafe, mv$(abi), mv$(args), is_variadic, mv$(ret_type)); + return TypeRef(TypeRef::TagFunction(), lex.end_span(mv$(ps)), mv$(hrbs), is_unsafe, mv$(abi), mv$(args), is_variadic, mv$(ret_type)); } TypeRef Parse_Type_Path(TokenStream& lex, ::AST::HigherRankedBounds hrbs, bool allow_trait_list) @@ -270,7 +270,7 @@ TypeRef Parse_Type_Path(TokenStream& lex, ::AST::HigherRankedBounds hrbs, bool a if( hrbs.empty() && !allow_trait_list ) { - return TypeRef(TypeRef::TagPath(), lex.end_span(ps), Parse_Path(lex, PATH_GENERIC_TYPE)); + return TypeRef(TypeRef::TagPath(), lex.end_span(mv$(ps)), Parse_Path(lex, PATH_GENERIC_TYPE)); } else { @@ -303,11 +303,11 @@ TypeRef Parse_Type_Path(TokenStream& lex, ::AST::HigherRankedBounds hrbs, bool a { if( lifetimes.empty()) lifetimes.push_back(AST::LifetimeRef()); - return TypeRef(lex.end_span(ps), mv$(traits), mv$(lifetimes)); + return TypeRef(lex.end_span(mv$(ps)), mv$(traits), mv$(lifetimes)); } else { - return TypeRef(TypeRef::TagPath(), lex.end_span(ps), mv$(traits.at(0).path)); + return TypeRef(TypeRef::TagPath(), lex.end_span(mv$(ps)), mv$(traits.at(0).path)); } } } @@ -335,6 +335,6 @@ TypeRef Parse_Type_ErasedType(TokenStream& lex, bool allow_trait_list) } while( GET_TOK(tok, lex) == TOK_PLUS ); PUTBACK(tok, lex); - return TypeRef(lex.end_span(ps), TypeData::make_ErasedType({ mv$(traits), mv$(lifetimes) })); + return TypeRef(lex.end_span(mv$(ps)), TypeData::make_ErasedType({ mv$(traits), mv$(lifetimes) })); } diff --git a/src/rc_string.cpp b/src/rc_string.cpp index 46f36923..4025d8c8 100644 --- a/src/rc_string.cpp +++ b/src/rc_string.cpp @@ -21,6 +21,18 @@ RcString::RcString(const char* s, unsigned int len): for(unsigned int j = 0; j < len; j ++ ) data_mut[j] = s[j]; data_mut[len] = '\0'; + + //::std::cout << "RcString(" << m_ptr << " \"" << *this << "\") - " << *m_ptr << " (creation)" << ::std::endl; + } +} +RcString::RcString(const RcString& x): + m_ptr(x.m_ptr), + m_len(x.m_len) +{ + if( m_ptr ) + { + *m_ptr += 1; + //::std::cout << "RcString(" << m_ptr << " \"" << *this << "\") - " << *m_ptr << " refs present (copy)" << ::std::endl; } } RcString::~RcString() @@ -28,7 +40,7 @@ RcString::~RcString() if(m_ptr) { *m_ptr -= 1; - //::std::cout << "RcString(\"" << *this << "\") - " << *m_ptr << " refs left" << ::std::endl; + //::std::cout << "RcString(" << m_ptr << " \"" << *this << "\") - " << *m_ptr << " refs left (drop)" << ::std::endl; if( *m_ptr == 0 ) { delete[] m_ptr; diff --git a/src/span.cpp b/src/span.cpp index eacdc7aa..34f2637e 100644 --- a/src/span.cpp +++ b/src/span.cpp @@ -11,15 +11,6 @@ #include #include -Span::Span(const Span& x): - outer_span(x.outer_span), - filename(x.filename), - start_line(x.start_line), - start_ofs(x.start_ofs), - end_line(x.end_line), - end_ofs(x.end_ofs) -{ -} Span::Span(const Position& pos): outer_span(), filename(pos.filename), -- cgit v1.2.3 From 16e05c582c39e0aa4f0ef6dd70756fded6516d25 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 4 Nov 2018 22:09:28 +0800 Subject: Codegen C - Fix minor OOB string read --- src/trans/codegen_c.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index b578c09b..55b3ea1a 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -1975,9 +1975,8 @@ namespace { m_of << "\\x0" << (unsigned int)static_cast(v); else m_of << "\\x" << (unsigned int)static_cast(v); - // If the next character is a hex digit, - // close/reopen the string. - if( isxdigit(*(&v+1)) ) + // If the next character is a hex digit, close/reopen the string. + if( &v < &s.back() && isxdigit(*(&v+1)) ) m_of << "\"\""; } } -- cgit v1.2.3 From ad1cec3df31470a1b97f1c672a45ae57495945a5 Mon Sep 17 00:00:00 2001 From: John Paul Adrian Glaubitz Date: Wed, 14 Nov 2018 12:33:24 +0100 Subject: Trans - Add initial support for m68k --- src/trans/target.cpp | 16 ++++++++++++++++ tools/common/target_detect.h | 2 ++ 2 files changed, 18 insertions(+) (limited to 'src') diff --git a/src/trans/target.cpp b/src/trans/target.cpp index f91b679a..64cf19c6 100644 --- a/src/trans/target.cpp +++ b/src/trans/target.cpp @@ -34,6 +34,11 @@ const TargetArch ARCH_ARM32 = { 32, false, { /*atomic(u8)=*/true, false, true, false, true } }; +const TargetArch ARCH_M68K = { + "m68k", + 32, true, + { /*atomic(u8)=*/true, false, true, false, true } +}; TargetSpec g_target; @@ -108,6 +113,10 @@ namespace { rv.m_arch = ARCH_X86_64; } + else if( key_val.value.as_string() == ARCH_M68K.m_name ) + { + rv.m_arch = ARCH_M68K; + } else { // Error. @@ -332,6 +341,13 @@ namespace ARCH_ARM64 }; } + else if(target_name == "m68k-linux-gnu") + { + return TargetSpec { + "unix", "linux", "gnu", {CodegenMode::Gnu11, "m68k-linux-gnu", BACKEND_C_OPTS_GNU}, + ARCH_M68K + }; + } else if(target_name == "i586-windows-gnu") { return TargetSpec { diff --git a/tools/common/target_detect.h b/tools/common/target_detect.h index a4c44ba4..0812c363 100644 --- a/tools/common/target_detect.h +++ b/tools/common/target_detect.h @@ -24,6 +24,8 @@ # define DEFAULT_TARGET_NAME "arm-linux-gnu" # elif defined(__i386__) # define DEFAULT_TARGET_NAME "i586-linux-gnu" +# elif defined(__m68k__) +# define DEFAULT_TARGET_NAME "m68k-linux-gnu" # else # warning "Unable to detect a suitable default target (linux-gnu)" # endif -- cgit v1.2.3 From c2f9278596a4f1eec3e611d3425edd10e0d15c83 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 24 Nov 2018 14:48:58 +0800 Subject: HIR - Fix struct/class mismatch --- src/hir/expr_state.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/hir/expr_state.hpp b/src/hir/expr_state.hpp index 5491b4d3..11fffe67 100644 --- a/src/hir/expr_state.hpp +++ b/src/hir/expr_state.hpp @@ -10,8 +10,9 @@ namespace HIR { -struct ExprState +class ExprState { +public: ::HIR::SimplePath m_mod_path; const ::HIR::Module& m_module; -- cgit v1.2.3 From c4939c4e12ac66aa3ac92470169abca16bb9ce5b Mon Sep 17 00:00:00 2001 From: Arlie Davis Date: Wed, 28 Nov 2018 13:53:38 -0800 Subject: Mark destructors in base classes as virtual. This is required for correctness, and when using -fsized-deallocation the previous code fails. --- src/ast/expr.hpp | 1 + src/expand/derive.cpp | 1 + src/hir/expr.hpp | 1 + src/hir_typeck/expr_cs.cpp | 1 + src/include/synext_decorator.hpp | 1 + src/include/synext_macro.hpp | 1 + 6 files changed, 6 insertions(+) (limited to 'src') diff --git a/src/ast/expr.hpp b/src/ast/expr.hpp index f3981db5..264b37e9 100644 --- a/src/ast/expr.hpp +++ b/src/ast/expr.hpp @@ -623,6 +623,7 @@ struct ExprNode_UniOp: class NodeVisitor { public: + virtual ~NodeVisitor() = default; inline void visit(const unique_ptr& cnode) { if(cnode.get()) cnode->visit(*this); diff --git a/src/expand/derive.cpp b/src/expand/derive.cpp index 5e97c888..5bbef62c 100644 --- a/src/expand/derive.cpp +++ b/src/expand/derive.cpp @@ -72,6 +72,7 @@ struct DeriveOpts /// Interface for derive handlers struct Deriver { + virtual ~Deriver() = default; virtual const char* trait_name() const = 0; virtual AST::Impl handle_item(Span sp, const DeriveOpts& opts, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const = 0; virtual AST::Impl handle_item(Span sp, const DeriveOpts& opts, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const = 0; diff --git a/src/hir/expr.hpp b/src/hir/expr.hpp index 55a4eaf2..00d22c00 100644 --- a/src/hir/expr.hpp +++ b/src/hir/expr.hpp @@ -815,6 +815,7 @@ struct ExprNode_Closure: class ExprVisitor { public: + virtual ~ExprVisitor() = default; virtual void visit_node_ptr(::std::unique_ptr& node_ptr); virtual void visit_node(ExprNode& node); #define NV(nt) virtual void visit(nt& n) = 0; diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index 554fea69..363dfeeb 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -25,6 +25,7 @@ struct Context class Revisitor { public: + virtual ~Revisitor() = default; virtual void fmt(::std::ostream& os) const = 0; virtual bool revisit(Context& context) = 0; }; diff --git a/src/include/synext_decorator.hpp b/src/include/synext_decorator.hpp index eaed3154..1e16ce09 100644 --- a/src/include/synext_decorator.hpp +++ b/src/include/synext_decorator.hpp @@ -45,6 +45,7 @@ class ExpandDecorator { void unexpected(const Span& sp, const AST::Attribute& mi, const char* loc_str) const; public: + virtual ~ExpandDecorator() = default; virtual AttrStage stage() const = 0; virtual void handle(const Span& sp, const AST::Attribute& mi, AST::Crate& crate) const { unexpected(sp, mi, "crate"); } diff --git a/src/include/synext_macro.hpp b/src/include/synext_macro.hpp index d414ceb0..60b52d89 100644 --- a/src/include/synext_macro.hpp +++ b/src/include/synext_macro.hpp @@ -27,6 +27,7 @@ class TokenStream; class ExpandProcMacro { public: + virtual ~ExpandProcMacro() = default; virtual ::std::unique_ptr expand(const Span& sp, const AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) = 0; }; -- cgit v1.2.3 From f6209dce15ce863e15dc3063d78e43eeb0db25ee Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 15 Dec 2018 14:47:08 +0800 Subject: Targets - Add alignment to the target specs, along with a saveback test. --- Makefile | 9 ++- samples/target_stress_test.toml | 22 +++++++ src/main.cpp | 32 ++++++++-- src/trans/codegen_c.cpp | 11 ++-- src/trans/target.cpp | 137 ++++++++++++++++++++++++++++------------ src/trans/target.hpp | 28 +++++--- tools/common/toml.cpp | 85 ++++++++++++++++--------- tools/common/toml.h | 21 +++++- 8 files changed, 252 insertions(+), 93 deletions(-) create mode 100644 samples/target_stress_test.toml (limited to 'src') diff --git a/Makefile b/Makefile index 1eda93dd..23c799d2 100644 --- a/Makefile +++ b/Makefile @@ -276,7 +276,14 @@ output/rust/test_run-pass_hello_out.txt: output/rust/test_run-pass_hello # # TEST: Rust standard library and the "hello, world" run-pass test # -test: output/libstd.hir output/rust/test_run-pass_hello_out.txt $(BIN) +test: output/libstd.hir output/rust/test_run-pass_hello_out.txt $(BIN) TEST_targetsaveback + +.PHONY: TEST_targetsaveback +TEST_targetsaveback: + $(BIN) --target ./samples/target_stress_test.toml --dump-target-spec TMP-dump-target_stress_test.toml + $(BIN) --target ./TMP-dump-target_stress_test.toml --dump-target-spec TMP-dump-target_stress_test-2.toml + diff ./samples/target_stress_test.toml TMP-dump-target_stress_test.toml + diff TMP-dump-target_stress_test.toml TMP-dump-target_stress_test-2.toml # # TEST: Attempt to compile rust_os (Tifflin) from ../rust_os diff --git a/samples/target_stress_test.toml b/samples/target_stress_test.toml new file mode 100644 index 00000000..c7630567 --- /dev/null +++ b/samples/target_stress_test.toml @@ -0,0 +1,22 @@ +[target] +family = "fake" +os-name = "fakest" +env-name = "faker" + +[backend.c] +variant = "msvc" +target = "x86_64-linux-msvc" +compiler-opts = ["/W:1234",] +linker-opts = ["/K",] + +[arch] +name = "fubar" +pointer-bits = 128 +is-big-endian = true +has-atomic-u8 = false +has-atomic-u16 = false +has-atomic-u32 = false +has-atomic-u64 = false +has-atomic-ptr = false +alignments = { u16 = 1, u32 = 2, u64 = 4, u128 = 8, f32 = 3, f64 = 5, ptr = 16 } + diff --git a/src/main.cpp b/src/main.cpp index 2dd05a05..a50fe095 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -36,6 +36,7 @@ bool g_debug_enabled = true; void init_debug_list() { + g_debug_disable_map.insert( "Target Load" ); g_debug_disable_map.insert( "Parse" ); g_debug_disable_map.insert( "LoadCrates" ); g_debug_disable_map.insert( "Expand" ); @@ -156,6 +157,9 @@ struct ProgramParams bool test_harness = false; + // NOTE: If populated, nothing happens except for loading the target + ::std::string target_saveback; + ::std::vector lib_search_dirs; ::std::vector libraries; ::std::map<::std::string, ::std::string> crate_overrides; // --extern name=path @@ -214,8 +218,21 @@ int main(int argc, char *argv[]) Cfg_SetValueCb("feature", [¶ms](const ::std::string& s) { return params.features.count(s) != 0; }); - Target_SetCfg(params.target); + CompilePhaseV("Target Load", [&]() { + Target_SetCfg(params.target); + }); + if( params.target_saveback != "") + { + Target_ExportCurSpec(params.target_saveback); + return 0; + } + + if( params.infile == "" ) + { + ::std::cerr << "No input file passed" << ::std::endl; + return 1; + } if( params.test_harness ) { @@ -1060,6 +1077,13 @@ ProgramParams::ProgramParams(int argc, char *argv[]) } this->target = argv[++i]; } + else if( strcmp(arg, "--dump-target-spec") == 0 ) { + if (i == argc - 1) { + ::std::cerr << "Flag " << arg << " requires an argument" << ::std::endl; + exit(1); + } + this->target_saveback = argv[++i]; + } else if( strcmp(arg, "--test") == 0 ) { this->test_harness = true; } @@ -1070,12 +1094,6 @@ ProgramParams::ProgramParams(int argc, char *argv[]) } } - if (this->infile == "") - { - ::std::cerr << "No input file passed" << ::std::endl; - exit(1); - } - if( const auto* a = getenv("MRUSTC_DUMP") ) { while( a[0] ) diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 55b3ea1a..84a538d5 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -205,20 +205,23 @@ namespace { m_outfile_path_c(outfile + ".c"), m_of(m_outfile_path_c) { + m_options.emulated_i128 = Target_GetCurSpec().m_backend_c.m_emulated_i128; switch(Target_GetCurSpec().m_backend_c.m_codegen_mode) { case CodegenMode::Gnu11: m_compiler = Compiler::Gcc; - m_options.emulated_i128 = false; - if( Target_GetCurSpec().m_arch.m_pointer_bits < 64 ) + if( Target_GetCurSpec().m_arch.m_pointer_bits < 64 && !m_options.emulated_i128 ) { - m_options.emulated_i128 = true; + WARNING(Span(), W0000, "Potentially misconfigured target, 32-bit targets require i128 emulation"); } m_options.disallow_empty_structs = true; break; case CodegenMode::Msvc: m_compiler = Compiler::Msvc; - m_options.emulated_i128 = true; + if( !m_options.emulated_i128 ) + { + WARNING(Span(), W0000, "Potentially misconfigured target, MSVC requires i128 emulation"); + } m_options.disallow_empty_structs = true; break; } diff --git a/src/trans/target.cpp b/src/trans/target.cpp index 64cf19c6..332a7e04 100644 --- a/src/trans/target.cpp +++ b/src/trans/target.cpp @@ -17,27 +17,32 @@ const TargetArch ARCH_X86_64 = { "x86_64", 64, false, - { /*atomic(u8)=*/true, false, true, true, true } + { /*atomic(u8)=*/true, false, true, true, true }, + { 2, 4, 8, 16, 4, 8, 8 }, }; const TargetArch ARCH_X86 = { "x86", 32, false, - { /*atomic(u8)=*/true, false, true, false, true } + { /*atomic(u8)=*/true, false, true, false, true }, + { 2, 4, /*u64*/4, /*u128*/4, 4, 4, /*ptr*/4 } // u128 has the same alignment as u64, which is u32's alignment. And f64 is 4 byte aligned }; const TargetArch ARCH_ARM64 = { "aarch64", 64, false, - { /*atomic(u8)=*/true, true, true, true, true } + { /*atomic(u8)=*/true, true, true, true, true }, + { 2, 4, 8, 16, 4, 8, 8 }, }; const TargetArch ARCH_ARM32 = { "arm", 32, false, - { /*atomic(u8)=*/true, false, true, false, true } + { /*atomic(u8)=*/true, false, true, false, true }, + { 2, 4, 8, 16, 4, 8, 4 } // Note, all types are natively aligned (but i128 will be emulated) }; const TargetArch ARCH_M68K = { "m68k", 32, true, - { /*atomic(u8)=*/true, false, true, false, true } + { /*atomic(u8)=*/true, false, true, false, true }, + { 2, 4, 8, 16, 4, 8, 4 } // TODO: Does m68k have lower alignments? }; TargetSpec g_target; @@ -159,6 +164,11 @@ namespace check_path_length(key_val, 3); rv.m_backend_c.m_c_compiler = key_val.value.as_string(); } + else if( key_val.path[2] == "emulate-i128" ) + { + check_path_length(key_val, 3); + rv.m_backend_c.m_emulated_i128 = key_val.value.as_bool(); + } else if( key_val.path[2] == "compiler-opts" ) { check_path_length(key_val, 3); @@ -233,6 +243,42 @@ namespace check_path_length(key_val, 2); rv.m_arch.m_atomics.ptr = key_val.value.as_bool(); } + else if( key_val.path[1] == "alignments" ) + { + check_path_length(key_val, 3); + if( key_val.path[2] == "u16" ) + { + rv.m_arch.m_alignments.u16 = key_val.value.as_int(); + } + else if( key_val.path[2] == "u32" ) + { + rv.m_arch.m_alignments.u32 = key_val.value.as_int(); + } + else if( key_val.path[2] == "u64" ) + { + rv.m_arch.m_alignments.u64 = key_val.value.as_int(); + } + else if( key_val.path[2] == "u128" ) + { + rv.m_arch.m_alignments.u128 = key_val.value.as_int(); + } + else if( key_val.path[2] == "f32" ) + { + rv.m_arch.m_alignments.f32 = key_val.value.as_int(); + } + else if( key_val.path[2] == "f64" ) + { + rv.m_arch.m_alignments.f64 = key_val.value.as_int(); + } + else if( key_val.path[2] == "ptr" ) + { + rv.m_arch.m_alignments.ptr = key_val.value.as_int(); + } + else + { + ::std::cerr << "WARNING: Unknown field arch.alignments." << key_val.path[1] << " in " << filename << ::std::endl; + } + } else { ::std::cerr << "WARNING: Unknown field arch." << key_val.path[1] << " in " << filename << ::std::endl; @@ -290,10 +336,10 @@ namespace << "[backend.c]\n" << "variant = \"" << H::c_variant_name(spec.m_backend_c.m_codegen_mode) << "\"\n" << "target = \"" << spec.m_backend_c.m_c_compiler << "\"\n" - << "compiler-opts = [" << spec.m_backend_c.m_compiler_opts << "]\n" - << "linker-opts = [" << spec.m_backend_c.m_linker_opts << "]\n" + << "compiler-opts = ["; for(const auto& s : spec.m_backend_c.m_compiler_opts) of << "\"" << s << "\","; of << "]\n" + << "linker-opts = ["; for(const auto& s : spec.m_backend_c.m_linker_opts) of << "\"" << s << "\","; of << "]\n" << "\n" - << "[arch]" + << "[arch]\n" << "name = \"" << spec.m_arch.m_name << "\"\n" << "pointer-bits = " << spec.m_arch.m_pointer_bits << "\n" << "is-big-endian = " << H::tfstr(spec.m_arch.m_big_endian) << "\n" @@ -302,6 +348,16 @@ namespace << "has-atomic-u32 = " << H::tfstr(spec.m_arch.m_atomics.u32) << "\n" << "has-atomic-u64 = " << H::tfstr(spec.m_arch.m_atomics.u64) << "\n" << "has-atomic-ptr = " << H::tfstr(spec.m_arch.m_atomics.ptr) << "\n" + << "alignments = {" + << " u16 = " << static_cast(spec.m_arch.m_alignments.u16 ) << "," + << " u32 = " << static_cast(spec.m_arch.m_alignments.u32 ) << "," + << " u64 = " << static_cast(spec.m_arch.m_alignments.u64 ) << "," + << " u128 = " << static_cast(spec.m_arch.m_alignments.u128) << "," + << " f32 = " << static_cast(spec.m_arch.m_alignments.f32 ) << "," + << " f64 = " << static_cast(spec.m_arch.m_alignments.f64 ) << "," + << " ptr = " << static_cast(spec.m_arch.m_alignments.ptr ) + << " }\n" + << "\n" ; } TargetSpec init_from_spec_name(const ::std::string& target_name) @@ -316,49 +372,49 @@ namespace else if(target_name == "i586-linux-gnu") { return TargetSpec { - "unix", "linux", "gnu", {CodegenMode::Gnu11, "i586-linux-gnu", BACKEND_C_OPTS_GNU}, + "unix", "linux", "gnu", {CodegenMode::Gnu11, true, "i586-linux-gnu", BACKEND_C_OPTS_GNU}, ARCH_X86 }; } else if(target_name == "x86_64-linux-gnu") { return TargetSpec { - "unix", "linux", "gnu", {CodegenMode::Gnu11, "x86_64-linux-gnu", BACKEND_C_OPTS_GNU}, + "unix", "linux", "gnu", {CodegenMode::Gnu11, false, "x86_64-linux-gnu", BACKEND_C_OPTS_GNU}, ARCH_X86_64 }; } else if(target_name == "arm-linux-gnu") { return TargetSpec { - "unix", "linux", "gnu", {CodegenMode::Gnu11, "arm-elf-eabi", BACKEND_C_OPTS_GNU}, + "unix", "linux", "gnu", {CodegenMode::Gnu11, true, "arm-elf-eabi", BACKEND_C_OPTS_GNU}, ARCH_ARM32 }; } else if(target_name == "aarch64-linux-gnu") { return TargetSpec { - "unix", "linux", "gnu", {CodegenMode::Gnu11, "aarch64-linux-gnu", BACKEND_C_OPTS_GNU}, + "unix", "linux", "gnu", {CodegenMode::Gnu11, false, "aarch64-linux-gnu", BACKEND_C_OPTS_GNU}, ARCH_ARM64 }; } else if(target_name == "m68k-linux-gnu") { return TargetSpec { - "unix", "linux", "gnu", {CodegenMode::Gnu11, "m68k-linux-gnu", BACKEND_C_OPTS_GNU}, + "unix", "linux", "gnu", {CodegenMode::Gnu11, true, "m68k-linux-gnu", BACKEND_C_OPTS_GNU}, ARCH_M68K }; } else if(target_name == "i586-windows-gnu") { return TargetSpec { - "windows", "windows", "gnu", {CodegenMode::Gnu11, "mingw32", BACKEND_C_OPTS_GNU}, + "windows", "windows", "gnu", {CodegenMode::Gnu11, true, "mingw32", BACKEND_C_OPTS_GNU}, ARCH_X86 }; } else if(target_name == "x86_64-windows-gnu") { return TargetSpec { - "windows", "windows", "gnu", {CodegenMode::Gnu11, "x86_64-w64-mingw32", BACKEND_C_OPTS_GNU}, + "windows", "windows", "gnu", {CodegenMode::Gnu11, false, "x86_64-w64-mingw32", BACKEND_C_OPTS_GNU}, ARCH_X86_64 }; } @@ -366,84 +422,84 @@ namespace { // TODO: Should this include the "kernel32.lib" inclusion? return TargetSpec { - "windows", "windows", "msvc", {CodegenMode::Msvc, "x86", {}, {}}, + "windows", "windows", "msvc", {CodegenMode::Msvc, true, "x86", {}, {}}, ARCH_X86 }; } else if (target_name == "x86_64-windows-msvc") { return TargetSpec { - "windows", "windows", "msvc", {CodegenMode::Msvc, "amd64", {}, {}}, + "windows", "windows", "msvc", {CodegenMode::Msvc, true, "amd64", {}, {}}, ARCH_X86_64 }; } else if(target_name == "i686-unknown-freebsd") { return TargetSpec { - "unix", "freebsd", "gnu", {CodegenMode::Gnu11, "i686-unknown-freebsd", BACKEND_C_OPTS_GNU}, + "unix", "freebsd", "gnu", {CodegenMode::Gnu11, true, "i686-unknown-freebsd", BACKEND_C_OPTS_GNU}, ARCH_X86 }; } else if(target_name == "x86_64-unknown-freebsd") { return TargetSpec { - "unix", "freebsd", "gnu", {CodegenMode::Gnu11, "x86_64-unknown-freebsd", BACKEND_C_OPTS_GNU}, + "unix", "freebsd", "gnu", {CodegenMode::Gnu11, false, "x86_64-unknown-freebsd", BACKEND_C_OPTS_GNU}, ARCH_X86_64 }; } else if(target_name == "arm-unknown-freebsd") { return TargetSpec { - "unix", "freebsd", "gnu", {CodegenMode::Gnu11, "arm-unknown-freebsd", BACKEND_C_OPTS_GNU}, + "unix", "freebsd", "gnu", {CodegenMode::Gnu11, true, "arm-unknown-freebsd", BACKEND_C_OPTS_GNU}, ARCH_ARM32 }; } else if(target_name == "aarch64-unknown-freebsd") { return TargetSpec { - "unix", "freebsd", "gnu", {CodegenMode::Gnu11, "aarch64-unknown-freebsd", BACKEND_C_OPTS_GNU}, + "unix", "freebsd", "gnu", {CodegenMode::Gnu11, false, "aarch64-unknown-freebsd", BACKEND_C_OPTS_GNU}, ARCH_ARM64 }; } else if(target_name == "x86_64-unknown-netbsd") { return TargetSpec { - "unix", "netbsd", "gnu", {CodegenMode::Gnu11, "x86_64-unknown-netbsd", BACKEND_C_OPTS_GNU}, + "unix", "netbsd", "gnu", {CodegenMode::Gnu11, false, "x86_64-unknown-netbsd", BACKEND_C_OPTS_GNU}, ARCH_X86_64 }; } else if(target_name == "i686-unknown-openbsd") { return TargetSpec { - "unix", "openbsd", "gnu", {CodegenMode::Gnu11, "i686-unknown-openbsd", BACKEND_C_OPTS_GNU}, + "unix", "openbsd", "gnu", {CodegenMode::Gnu11, true, "i686-unknown-openbsd", BACKEND_C_OPTS_GNU}, ARCH_X86 }; } else if(target_name == "x86_64-unknown-openbsd") { return TargetSpec { - "unix", "openbsd", "gnu", {CodegenMode::Gnu11, "x86_64-unknown-openbsd", BACKEND_C_OPTS_GNU}, + "unix", "openbsd", "gnu", {CodegenMode::Gnu11, false, "x86_64-unknown-openbsd", BACKEND_C_OPTS_GNU}, ARCH_X86_64 }; } else if(target_name == "arm-unknown-openbsd") { return TargetSpec { - "unix", "openbsd", "gnu", {CodegenMode::Gnu11, "arm-unknown-openbsd", BACKEND_C_OPTS_GNU}, + "unix", "openbsd", "gnu", {CodegenMode::Gnu11, true, "arm-unknown-openbsd", BACKEND_C_OPTS_GNU}, ARCH_ARM32 }; } else if(target_name == "aarch64-unknown-openbsd") { return TargetSpec { - "unix", "openbsd", "gnu", {CodegenMode::Gnu11, "aarch64-unknown-openbsd", BACKEND_C_OPTS_GNU}, + "unix", "openbsd", "gnu", {CodegenMode::Gnu11, false, "aarch64-unknown-openbsd", BACKEND_C_OPTS_GNU}, ARCH_ARM64 }; } else if(target_name == "x86_64-unknown-dragonfly") { return TargetSpec { - "unix", "dragonfly", "gnu", {CodegenMode::Gnu11, "x86_64-unknown-dragonfly", BACKEND_C_OPTS_GNU}, + "unix", "dragonfly", "gnu", {CodegenMode::Gnu11, false, "x86_64-unknown-dragonfly", BACKEND_C_OPTS_GNU}, ARCH_X86_64 }; } @@ -451,7 +507,7 @@ namespace { // NOTE: OSX uses Mach-O binaries, which don't fully support the defaults used for GNU targets return TargetSpec { - "unix", "macos", "gnu", {CodegenMode::Gnu11, "x86_64-apple-darwin", {}, {}}, + "unix", "macos", "gnu", {CodegenMode::Gnu11, false, "x86_64-apple-darwin", {}, {}}, ARCH_X86_64 }; } @@ -684,48 +740,45 @@ bool Target_GetSizeAndAlignOf(const Span& sp, const StaticTraitResolve& resolve, case ::HIR::CoreType::U8: case ::HIR::CoreType::I8: out_size = 1; - out_align = 1; + out_align = 1; // u8 is always 1 aligned return true; case ::HIR::CoreType::U16: case ::HIR::CoreType::I16: out_size = 2; - out_align = 2; + out_align = g_target.m_arch.m_alignments.u16; return true; case ::HIR::CoreType::U32: case ::HIR::CoreType::I32: case ::HIR::CoreType::Char: out_size = 4; - out_align = 4; + out_align = g_target.m_arch.m_alignments.u32; return true; case ::HIR::CoreType::U64: case ::HIR::CoreType::I64: out_size = 8; - // TODO: on x86, u64/i64 has an alignment of 4, while x86_64 has 8. What do other platforms have? - out_align = g_target.m_arch.m_name == "x86" ? 4 : 8; + out_align = g_target.m_arch.m_alignments.u64; return true; case ::HIR::CoreType::U128: case ::HIR::CoreType::I128: out_size = 16; // TODO: If i128 is emulated, this can be 8 (as it is on x86, where it's actually 4 due to the above comment) - if( g_target.m_arch.m_name == "x86" ) - out_align = 4; - else if( /*g_target.m_arch.m_name == "x86_64" && */g_target.m_backend_c.m_codegen_mode == CodegenMode::Msvc ) - out_align = 8; - else - out_align = 16; + if( g_target.m_backend_c.m_emulated_i128 ) + out_align = g_target.m_arch.m_alignments.u64; + else + out_align = g_target.m_arch.m_alignments.u128; return true; case ::HIR::CoreType::Usize: case ::HIR::CoreType::Isize: out_size = g_target.m_arch.m_pointer_bits / 8; - out_align = g_target.m_arch.m_pointer_bits / 8; + out_align = g_target.m_arch.m_alignments.ptr; return true; case ::HIR::CoreType::F32: out_size = 4; - out_align = 4; + out_align = g_target.m_arch.m_alignments.f32; return true; case ::HIR::CoreType::F64: out_size = 8; - out_align = g_target.m_arch.m_name == "x86" ? 4 : 8; + out_align = g_target.m_arch.m_alignments.f64; return true; case ::HIR::CoreType::Str: DEBUG("sizeof on a `str` - unsized"); diff --git a/src/trans/target.hpp b/src/trans/target.hpp index b1ed9456..b6f04a42 100644 --- a/src/trans/target.hpp +++ b/src/trans/target.hpp @@ -17,23 +17,35 @@ enum class CodegenMode Msvc, }; +// NOTE: The default architecture is an unnamed 32-bit little-endian arch with all types natively aligned struct TargetArch { - ::std::string m_name; - unsigned m_pointer_bits; - bool m_big_endian; + ::std::string m_name = ""; + unsigned m_pointer_bits = 32; + bool m_big_endian = false; struct { - bool u8; - bool u16; - bool u32; - bool u64; - bool ptr; + bool u8 = true; + bool u16 = true; + bool u32 = true; + bool u64 = false; + bool ptr = true; } m_atomics; + + struct { + uint8_t u16 = 2; + uint8_t u32 = 4; + uint8_t u64 = 8; + uint8_t u128 = 16; + uint8_t f32 = 4; + uint8_t f64 = 8; + uint8_t ptr = 4; + } m_alignments; }; struct BackendOptsC { CodegenMode m_codegen_mode; + bool m_emulated_i128; // Influences the chosen alignment for i128/u128 ::std::string m_c_compiler; // MSVC arch / GNU triplet ::std::vector< ::std::string> m_compiler_opts; ::std::vector< ::std::string> m_linker_opts; diff --git a/tools/common/toml.cpp b/tools/common/toml.cpp index 489f32b6..285d22a4 100644 --- a/tools/common/toml.cpp +++ b/tools/common/toml.cpp @@ -80,11 +80,8 @@ struct Token }; TomlFile::TomlFile(const ::std::string& filename): - m_if(filename) + m_lexer(filename) { - if( !m_if.is_open() ) { - throw ::std::runtime_error("Unable to open file '" + filename + "'"); - } } TomlFileIter TomlFile::begin() { @@ -99,12 +96,14 @@ TomlFileIter TomlFile::end() TomlKeyValue TomlFile::get_next_value() { - auto t = Token::lex_from(m_if); + auto t = m_lexer.get_token(); if(m_current_composite.empty()) { while( t.m_type == Token::Type::Newline ) - t = Token::lex_from(m_if); + { + t = m_lexer.get_token(); + } // Expect '[', a string, or an identifier switch(t.m_type) @@ -116,32 +115,32 @@ TomlKeyValue TomlFile::get_next_value() m_current_block.clear(); do { - t = Token::lex_from(m_if); + t = m_lexer.get_token(); bool is_array = false; if(t.m_type == Token::Type::SquareOpen) { is_array = true; - t = Token::lex_from(m_if); + t = m_lexer.get_token(); } assert(t.m_type == Token::Type::Ident || t.m_type == Token::Type::String); m_current_block.push_back(t.as_string()); if(is_array) { m_current_block.push_back(::format(m_array_counts[t.as_string()]++)); - t = Token::lex_from(m_if); + t = m_lexer.get_token(); assert(t.m_type == Token::Type::SquareClose); } - t = Token::lex_from(m_if); + t = m_lexer.get_token(); } while(t.m_type == Token::Type::Dot); if( t.m_type != Token::Type::SquareClose ) { - throw ::std::runtime_error(::format("Unexpected token in block header - ", t)); + throw ::std::runtime_error(::format(m_lexer, ": Unexpected token in block header - ", t)); } - t = Token::lex_from(m_if); + t = m_lexer.get_token(); if (t.m_type != Token::Type::Newline) { - throw ::std::runtime_error(::format("Unexpected token after block block - ", t)); + throw ::std::runtime_error(::format(m_lexer, ": Unexpected token after block block - ", t)); } DEBUG("Start block " << m_current_block); // Recurse! @@ -156,7 +155,7 @@ TomlKeyValue TomlFile::get_next_value() if( t.m_type == Token::Type::Eof ) { // EOF isn't allowed here - throw ::std::runtime_error(::format("Unexpected EOF in composite")); + throw ::std::runtime_error(::format(m_lexer, ": Unexpected EOF in composite")); } } switch (t.m_type) @@ -165,14 +164,14 @@ TomlKeyValue TomlFile::get_next_value() case Token::Type::Ident: break; default: - throw ::std::runtime_error(::format("Unexpected token for key - ", t)); + throw ::std::runtime_error(::format(m_lexer, ": Unexpected token for key - ", t)); } ::std::string key_name = t.as_string(); - t = Token::lex_from(m_if); + t = m_lexer.get_token(); if(t.m_type != Token::Type::Assign) - throw ::std::runtime_error(::format("Unexpected token after key - ", t)); - t = Token::lex_from(m_if); + throw ::std::runtime_error(::format(m_lexer, ": Unexpected token after key - ", t)); + t = m_lexer.get_token(); // --- Value --- TomlKeyValue rv; @@ -193,10 +192,12 @@ TomlKeyValue TomlFile::get_next_value() rv.path.push_back(key_name); rv.value.m_type = TomlValue::Type::List; - while( (t = Token::lex_from(m_if)).m_type != Token::Type::SquareClose ) + while( (t = m_lexer.get_token()).m_type != Token::Type::SquareClose ) { while( t.m_type == Token::Type::Newline ) - t = Token::lex_from(m_if); + { + t = m_lexer.get_token(); + } if( t.m_type == Token::Type::SquareClose ) break; @@ -208,15 +209,15 @@ TomlKeyValue TomlFile::get_next_value() rv.value.m_sub_values.push_back(TomlValue { t.as_string() }); break; default: - throw ::std::runtime_error(::format("Unexpected token in array value position - ", t)); + throw ::std::runtime_error(::format(m_lexer, ": Unexpected token in array value position - ", t)); } - t = Token::lex_from(m_if); + t = m_lexer.get_token(); if(t.m_type != Token::Type::Comma) break; } if(t.m_type != Token::Type::SquareClose) - throw ::std::runtime_error(::format("Unexpected token after array - ", t)); + throw ::std::runtime_error(::format(m_lexer, ": Unexpected token after array - ", t)); break; case Token::Type::BraceOpen: m_current_composite.push_back(key_name); @@ -228,7 +229,7 @@ TomlKeyValue TomlFile::get_next_value() rv.path.insert(rv.path.end(), m_current_composite.begin(), m_current_composite.end()); rv.path.push_back(key_name); rv.value = TomlValue { t.m_intval }; - return rv; + break; case Token::Type::Ident: if( t.m_data == "true" ) { @@ -247,34 +248,58 @@ TomlKeyValue TomlFile::get_next_value() } else { - throw ::std::runtime_error(::format("Unexpected identifier in value position - ", t)); + throw ::std::runtime_error(::format(m_lexer, ": Unexpected identifier in value position - ", t)); } break; default: - throw ::std::runtime_error(::format("Unexpected token in value position - ", t)); + throw ::std::runtime_error(::format(m_lexer, ": Unexpected token in value position - ", t)); } - t = Token::lex_from(m_if); + t = m_lexer.get_token(); while (!m_current_composite.empty() && t.m_type == Token::Type::BraceClose) { DEBUG("Leave composite block " << m_current_block << ", " << m_current_composite); m_current_composite.pop_back(); - t = Token::lex_from(m_if); + t = m_lexer.get_token(); } if( m_current_composite.empty() ) { // TODO: Allow EOF? if(t.m_type != Token::Type::Newline) - throw ::std::runtime_error(::format("Unexpected token in TOML file after entry - ", t)); + throw ::std::runtime_error(::format(m_lexer, ": Unexpected token in TOML file after entry - ", t)); } else { if( t.m_type != Token::Type::Comma ) - throw ::std::runtime_error(::format("Unexpected token in TOML file after composite entry - ", t)); + throw ::std::runtime_error(::format(m_lexer, ": Unexpected token in TOML file after composite entry - ", t)); } return rv; } +TomlLexer::TomlLexer(const ::std::string& filename) + :m_if(filename) + ,m_filename(filename) + ,m_line(1) +{ + if( !m_if.is_open() ) { + throw ::std::runtime_error("Unable to open file '" + filename + "'"); + } +} +Token TomlLexer::get_token() +{ + auto rv = Token::lex_from(m_if); + if( rv.m_type == Token::Type::Newline ) + { + m_line ++; + } + return rv; +} +::std::ostream& operator<<(::std::ostream& os, const TomlLexer& x) +{ + os << x.m_filename << ":" << x.m_line; + return os; +} + Token Token::lex_from(::std::ifstream& is) { auto rv = Token::lex_from_inner(is); diff --git a/tools/common/toml.h b/tools/common/toml.h index 4c97e7f2..17e05142 100644 --- a/tools/common/toml.h +++ b/tools/common/toml.h @@ -15,11 +15,28 @@ class TomlFileIter; struct TomlKeyValue; -class TomlFile +struct Token; +class TomlLexer { + friend class TomlFile; /// Input file stream ::std::ifstream m_if; + ::std::string m_filename; + unsigned m_line; +protected: + TomlLexer(const ::std::string& filename); + Token get_token(); + +public: + friend ::std::ostream& operator<<(::std::ostream& os, const TomlLexer& x); +}; + +class TomlFile +{ + /// Input file stream + TomlLexer m_lexer; + /// Name of the current `[]` block ::std::vector<::std::string> m_current_block; @@ -40,6 +57,8 @@ public: // Obtain the next value in the file TomlKeyValue get_next_value(); + + const TomlLexer& lexer() const; }; struct TomlValue -- cgit v1.2.3 From f893005e2b0a207826d56782afcd456754adb643 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 15 Dec 2018 15:40:54 +0800 Subject: Trans Target - Fix MSVC build --- src/trans/target.cpp | 12 ++++++------ src/trans/target.hpp | 42 ++++++++++++++++++++++++++++++------------ 2 files changed, 36 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/trans/target.cpp b/src/trans/target.cpp index 332a7e04..53d84030 100644 --- a/src/trans/target.cpp +++ b/src/trans/target.cpp @@ -17,32 +17,32 @@ const TargetArch ARCH_X86_64 = { "x86_64", 64, false, - { /*atomic(u8)=*/true, false, true, true, true }, - { 2, 4, 8, 16, 4, 8, 8 }, + TargetArch::Atomics(/*atomic(u8)=*/true, false, true, true, true), + TargetArch::Alignments(2, 4, 8, 16, 4, 8, 8) }; const TargetArch ARCH_X86 = { "x86", 32, false, { /*atomic(u8)=*/true, false, true, false, true }, - { 2, 4, /*u64*/4, /*u128*/4, 4, 4, /*ptr*/4 } // u128 has the same alignment as u64, which is u32's alignment. And f64 is 4 byte aligned + TargetArch::Alignments(2, 4, /*u64*/4, /*u128*/4, 4, 4, /*ptr*/4) // u128 has the same alignment as u64, which is u32's alignment. And f64 is 4 byte aligned }; const TargetArch ARCH_ARM64 = { "aarch64", 64, false, { /*atomic(u8)=*/true, true, true, true, true }, - { 2, 4, 8, 16, 4, 8, 8 }, + TargetArch::Alignments(2, 4, 8, 16, 4, 8, 8) }; const TargetArch ARCH_ARM32 = { "arm", 32, false, { /*atomic(u8)=*/true, false, true, false, true }, - { 2, 4, 8, 16, 4, 8, 4 } // Note, all types are natively aligned (but i128 will be emulated) + TargetArch::Alignments(2, 4, 8, 16, 4, 8, 4) // Note, all types are natively aligned (but i128 will be emulated) }; const TargetArch ARCH_M68K = { "m68k", 32, true, { /*atomic(u8)=*/true, false, true, false, true }, - { 2, 4, 8, 16, 4, 8, 4 } // TODO: Does m68k have lower alignments? + TargetArch::Alignments(2, 4, 8, 16, 4, 8, 4) // TODO: Does m68k have lower alignments? }; TargetSpec g_target; diff --git a/src/trans/target.hpp b/src/trans/target.hpp index b6f04a42..4e0309dd 100644 --- a/src/trans/target.hpp +++ b/src/trans/target.hpp @@ -20,26 +20,44 @@ enum class CodegenMode // NOTE: The default architecture is an unnamed 32-bit little-endian arch with all types natively aligned struct TargetArch { - ::std::string m_name = ""; - unsigned m_pointer_bits = 32; - bool m_big_endian = false; + ::std::string m_name; + unsigned m_pointer_bits; + bool m_big_endian; - struct { + struct Atomics { bool u8 = true; bool u16 = true; bool u32 = true; bool u64 = false; bool ptr = true; + Atomics(bool u8 = true, bool u16 = true, bool u32 = true, bool u64 = false, bool ptr = true) + :u8(u8) + ,u16(u16) + ,u32(u32) + ,u64(u64) + ,ptr(ptr) + { + } } m_atomics; - struct { - uint8_t u16 = 2; - uint8_t u32 = 4; - uint8_t u64 = 8; - uint8_t u128 = 16; - uint8_t f32 = 4; - uint8_t f64 = 8; - uint8_t ptr = 4; + struct Alignments { + uint8_t u16; + uint8_t u32; + uint8_t u64; + uint8_t u128; + uint8_t f32; + uint8_t f64; + uint8_t ptr; + Alignments(uint8_t u16 = 2, uint8_t u32 = 4, uint8_t u64 = 8, uint8_t u128 = 16, uint8_t f32 = 4, uint8_t f64 = 8, uint8_t ptr = 4) + :u16 (u16) + ,u32 (u32 ) + ,u64 (u64 ) + ,u128(u128) + ,f32 (f32 ) + ,f64 (f64 ) + ,ptr (ptr ) + { + } } m_alignments; }; struct BackendOptsC -- cgit v1.2.3 From efc95784c83cc054ed5a0f2d71ff0c66e3dfb2cf Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 22 Dec 2018 18:40:23 +0800 Subject: Codegen MMIR - Remove places where assert body needs to be evaluated (ref #97) --- src/trans/codegen_mmir.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/trans/codegen_mmir.cpp b/src/trans/codegen_mmir.cpp index b2c5282a..a7d47c0e 100644 --- a/src/trans/codegen_mmir.cpp +++ b/src/trans/codegen_mmir.cpp @@ -18,6 +18,14 @@ namespace { + size_t Target_GetSizeOf_Required(const Span& sp, const StaticTraitResolve& resolve, const ::HIR::TypeRef& ty) + { + size_t size; + bool type_has_size = Target_GetSizeOf(sp, resolve, ty, size); + ASSERT_BUG(sp, type_has_size, "Attempting to get the size of a unsized type"); + return size; + } + template struct Fmt { @@ -779,8 +787,7 @@ namespace cur_ofs ++; } emit_literal_as_bytes(le[i], repr->fields[i].ty, out_relocations, base_ofs + cur_ofs); - size_t size; - assert(Target_GetSizeOf(sp, m_resolve, repr->fields[i].ty, size)); + size_t size = Target_GetSizeOf_Required(sp, m_resolve, repr->fields[i].ty); cur_ofs += size; } while(cur_ofs < repr->size) @@ -803,8 +810,7 @@ namespace emit_literal_as_bytes(*le.val, repr->fields[le.idx].ty, out_relocations, base_ofs + cur_ofs); - size_t size; - assert(Target_GetSizeOf(sp, m_resolve, repr->fields[le.idx].ty, size)); + size_t size = Target_GetSizeOf(sp, m_resolve, repr->fields[le.idx].ty); cur_ofs += size; } @@ -819,8 +825,7 @@ namespace auto v = ::HIR::Literal::make_Integer(le.idx); emit_literal_as_bytes(v, repr->fields[ve->field.index].ty, out_relocations, base_ofs + cur_ofs); - size_t size; - assert(Target_GetSizeOf(sp, m_resolve, repr->fields[ve->field.index].ty, size)); + size_t size = Target_GetSizeOf_Required(sp, m_resolve, repr->fields[ve->field.index].ty) cur_ofs += size; } // TODO: Nonzero? @@ -888,8 +893,7 @@ namespace for(const auto& v : lit.as_List()) { emit_literal_as_bytes(v, *te.inner, out_relocations, base_ofs); - size_t size; - assert(Target_GetSizeOf(sp, m_resolve, *te.inner, size)); + size_t size = Target_GetSizeOf(sp, m_resolve, *te.inner, size); base_ofs += size; } } break; -- cgit v1.2.3 From ad5d36e85a25d1addb4c854114102bef696d4472 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 22 Dec 2018 18:41:23 +0800 Subject: (minor) Whitespace cleaup --- src/trans/codegen_mmir.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/trans/codegen_mmir.cpp b/src/trans/codegen_mmir.cpp index a7d47c0e..4c17fe47 100644 --- a/src/trans/codegen_mmir.cpp +++ b/src/trans/codegen_mmir.cpp @@ -332,7 +332,7 @@ namespace else if( t.m_data.is_Slice() ) { return ::HIR::CoreType::Usize; } - else if( t.m_data.is_TraitObject() ) { + else if( t.m_data.is_TraitObject() ) { const auto& te = t.m_data.as_TraitObject(); //auto vtp = t.m_data.as_TraitObject().m_trait.m_path; @@ -389,7 +389,7 @@ namespace { m_of << "fn " << drop_glue_path << "(&move " << ty << ") {\n"; m_of << "\tlet unit: ();\n"; - + if( const auto* ity = m_resolve.is_type_owned_box(ty) ) { m_of << "\t0: {\n"; -- cgit v1.2.3 From 8e8e51ac1b04c7cc85a4a81d9c1906fb9f5a4d58 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 22 Dec 2018 18:42:50 +0800 Subject: Codegen MMIR - Forgot to compile before commit, fix syntax errors. --- src/trans/codegen_mmir.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/trans/codegen_mmir.cpp b/src/trans/codegen_mmir.cpp index 4c17fe47..73de19d3 100644 --- a/src/trans/codegen_mmir.cpp +++ b/src/trans/codegen_mmir.cpp @@ -810,7 +810,7 @@ namespace emit_literal_as_bytes(*le.val, repr->fields[le.idx].ty, out_relocations, base_ofs + cur_ofs); - size_t size = Target_GetSizeOf(sp, m_resolve, repr->fields[le.idx].ty); + size_t size = Target_GetSizeOf_Required(sp, m_resolve, repr->fields[le.idx].ty); cur_ofs += size; } @@ -825,7 +825,7 @@ namespace auto v = ::HIR::Literal::make_Integer(le.idx); emit_literal_as_bytes(v, repr->fields[ve->field.index].ty, out_relocations, base_ofs + cur_ofs); - size_t size = Target_GetSizeOf_Required(sp, m_resolve, repr->fields[ve->field.index].ty) + size_t size = Target_GetSizeOf_Required(sp, m_resolve, repr->fields[ve->field.index].ty); cur_ofs += size; } // TODO: Nonzero? -- cgit v1.2.3 From 17f910e871e70a5edbf32ea05ef8f68bc71003c9 Mon Sep 17 00:00:00 2001 From: John Paul Adrian Glaubitz Date: Sat, 22 Dec 2018 15:49:16 +0100 Subject: Trans - Fix alignment values for m68k --- src/trans/target.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/trans/target.cpp b/src/trans/target.cpp index 53d84030..316749be 100644 --- a/src/trans/target.cpp +++ b/src/trans/target.cpp @@ -42,7 +42,7 @@ const TargetArch ARCH_M68K = { "m68k", 32, true, { /*atomic(u8)=*/true, false, true, false, true }, - TargetArch::Alignments(2, 4, 8, 16, 4, 8, 4) // TODO: Does m68k have lower alignments? + TargetArch::Alignments(2, 2, 2, 2, 2, 2, 2) }; TargetSpec g_target; -- cgit v1.2.3 From cbed0d2930168ef15bfdeb02c6f12991094b1480 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Mon, 21 Jan 2019 23:30:06 +0000 Subject: targets: Add x86_64 and arm targets for Haiku --- src/trans/target.cpp | 14 ++++++++++++++ tools/common/target_detect.h | 9 +++++++++ 2 files changed, 23 insertions(+) (limited to 'src') diff --git a/src/trans/target.cpp b/src/trans/target.cpp index 316749be..70996fb0 100644 --- a/src/trans/target.cpp +++ b/src/trans/target.cpp @@ -511,6 +511,20 @@ namespace ARCH_X86_64 }; } + else if(target_name == "arm-unknown-haiku") + { + return TargetSpec { + "unix", "haiku", "gnu", {CodegenMode::Gnu11, true, "arm-unknown-haiku", {}, {}}, + ARCH_ARM32 + }; + } + else if(target_name == "x86_64-unknown-haiku") + { + return TargetSpec { + "unix", "haiku", "gnu", {CodegenMode::Gnu11, false, "x86_64-unknown-haiku", {}, {}}, + ARCH_X86_64 + }; + } else { ::std::cerr << "Unknown target name '" << target_name << "'" << ::std::endl; diff --git a/tools/common/target_detect.h b/tools/common/target_detect.h index 0812c363..1bfc7dd9 100644 --- a/tools/common/target_detect.h +++ b/tools/common/target_detect.h @@ -75,6 +75,15 @@ // - Apple devices #elif defined(__APPLE__) # define DEFAULT_TARGET_NAME "x86_64-apple-macosx" +// - Haiku +#elif defined(__HAIKU__) +# if defined(__x86_64__) +# define DEFAULT_TARGET_NAME "x86_64-unknown-haiku" +# elif defined(__arm__) +# define DEFAULT_TARGET_NAME "arm-unknown-haiku" +# else +# warning "Unable to detect a suitable default target (Haiku)" +# endif // - Unknown #else # warning "Unable to detect a suitable default target" -- cgit v1.2.3 From 3108cf9eea6dfd801136987568c072f4105b9b7a Mon Sep 17 00:00:00 2001 From: Danny Milosavljevic Date: Mon, 4 Feb 2019 18:16:58 +0100 Subject: Fix recv_v128u procedural macro plugin decoder --- src/expand/proc_macro.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/expand/proc_macro.cpp b/src/expand/proc_macro.cpp index d34a91a5..be0b4ce6 100644 --- a/src/expand/proc_macro.cpp +++ b/src/expand/proc_macro.cpp @@ -970,7 +970,7 @@ uint64_t ProcMacroInv::recv_v128u() for(;;) { auto b = recv_u8(); - v |= static_cast(b) << ofs; + v |= static_cast(b & 0x7F) << ofs; if( (b & 0x80) == 0 ) break; ofs += 7; -- cgit v1.2.3 From 0992c4af5242fc95e8cc028c5af7fb86424e624c Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 6 Oct 2018 18:11:40 +0800 Subject: HIR - (minor) Handle equal function pointers when doing fuzzy --- src/hir/hir.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/hir/hir.cpp b/src/hir/hir.cpp index 9f9bc1c3..5d67ac5f 100644 --- a/src/hir/hir.cpp +++ b/src/hir/hir.cpp @@ -450,7 +450,9 @@ namespace { ), (Function, TU_IFLET(::HIR::TypeRef::Data, right.m_data, Function, re, - TODO(sp, "Function"); + if( left == right ) + return ::OrdEqual; + TODO(sp, "Function - " << left << " and " << right); //return typelist_ord_specific(sp, le.arg_types, re.arg_types); ) else { -- cgit v1.2.3 From 9b706e3beaa59db561008fd5ad13f2674da12861 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 23 Feb 2019 13:53:12 +0800 Subject: Codegen C - Fix msvc clz/ctz --- src/trans/codegen_c.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 84a538d5..56b03f9c 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -305,7 +305,7 @@ namespace { // 64-bit bit ops (gcc intrinsics) m_of << "static inline uint64_t __builtin_clz64(uint64_t v) {\n" - << "\treturn (v >> 32 != 0 ? __builtin_clz(v>>32) : 32 + __builtin_clz(v));\n" + << "\treturn ( (v >> 32) != 0 ? __builtin_clz(v>>32) : 32 + __builtin_clz(v));\n" << "}\n" << "static inline uint64_t __builtin_ctz64(uint64_t v) {\n" << "\treturn ((v&0xFFFFFFFF) == 0 ? __builtin_ctz(v>>32) + 32 : __builtin_ctz(v));\n" @@ -317,10 +317,10 @@ namespace { << "static inline uint64_t __builtin_popcount(uint64_t v) {\n" << "\treturn (v >> 32 != 0 ? __popcnt64(v>>32) : 32 + __popcnt64(v));\n" << "}\n" - << "static inline int __builtin_ctz(uint32_t v) { int rv; _BitScanReverse(&rv, v); return rv; }\n" - << "static inline int __builtin_clz(uint32_t v) { int rv; _BitScanForward(&rv, v); return rv; }\n" + << "static inline int __builtin_ctz(uint32_t v) { int rv; _BitScanForward(&rv, v); return rv; }\n" + << "static inline int __builtin_clz(uint32_t v) { int rv; _BitScanReverse(&rv, v); return 31 - rv; }\n" << "static inline uint64_t __builtin_clz64(uint64_t v) {\n" - << "\treturn (v >> 32 != 0 ? __builtin_clz(v>>32) : 32 + __builtin_clz(v));\n" + << "\treturn ( (v >> 32) != 0 ? __builtin_clz(v>>32) : 32 + __builtin_clz(v) );\n" << "}\n" << "static inline uint64_t __builtin_ctz64(uint64_t v) {\n" << "\treturn ((v&0xFFFFFFFF) == 0 ? __builtin_ctz(v>>32) + 32 : __builtin_ctz(v));\n" @@ -1935,7 +1935,11 @@ namespace { (String, m_of << "{ "; this->print_escaped_string(e); - m_of << ", " << e.size() << "}"; + // TODO: Better type checking? + if( !ty.m_data.is_Array() ) { + m_of << ", " << e.size(); + } + m_of << "}"; ) ) } -- cgit v1.2.3 From 5ecf83cb46c08532b541416b571effe0dfe2831a Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Sun, 24 Feb 2019 14:23:46 +0100 Subject: Implement compiler check TODO. (#112) Checks if `-gcc` exists before trying to call it, and does so before trying $CC --- src/trans/codegen_c.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 56b03f9c..538c3bb2 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -648,13 +648,14 @@ namespace { if( getenv(varname.c_str()) ) { args.push_back( getenv(varname.c_str()) ); } + else if (system(("which " + Target_GetCurSpec().m_backend_c.m_c_compiler + "-gcc" + " >/dev/null 2>&1").c_str()) == 0) { + args.push_back( Target_GetCurSpec().m_backend_c.m_c_compiler + "-gcc" ); + } else if( getenv("CC") ) { args.push_back( getenv("CC") ); } else { - // TODO: Determine if the compiler can't be found, and fall back to `gcc` if that's the case - args.push_back( Target_GetCurSpec().m_backend_c.m_c_compiler + "-gcc" ); - //args.push_back( "gcc" ); + args.push_back("gcc"); } } for( const auto& a : Target_GetCurSpec().m_backend_c.m_compiler_opts ) @@ -1324,7 +1325,7 @@ namespace { assert(1 + union_fields.size() + 1 >= repr->fields.size()); // Make the union! // NOTE: The way the structure generation works is that enum variants are always first, so the field index = the variant index - // TODO: + // TODO: if( !this->type_is_bad_zst(repr->fields[0].ty) || ::std::any_of(union_fields.begin(), union_fields.end(), [this,repr](auto x){ return !this->type_is_bad_zst(repr->fields[x].ty); }) ) { m_of << "\tunion {\n"; @@ -3667,7 +3668,7 @@ namespace { m_of << "("; for(unsigned int j = 0; j < e.args.size(); j ++) { if(j != 0) m_of << ","; - m_of << " "; + m_of << " "; if( m_options.disallow_empty_structs && TU_TEST1(e.args[j], LValue, .is_Field()) ) { ::HIR::TypeRef tmp; @@ -3916,7 +3917,7 @@ namespace { void emit_intrinsic_call(const ::std::string& name, const ::HIR::PathParams& params, const ::MIR::Terminator::Data_Call& e) { const auto& mir_res = *m_mir_res; - enum class Ordering + enum class Ordering { SeqCst, Acquire, @@ -4081,7 +4082,7 @@ namespace { m_of << "*(volatile uint8_t*)"; else m_of << "*(volatile int8_t*)"; - emit_param(e.args.at(0)); + emit_param(e.args.at(0)); switch(op) { case AtomicOp::Add: m_of << " += "; break; -- cgit v1.2.3 From f41f2197456be87c7c63582dbeee4667bfae35e8 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 28 May 2019 14:42:59 -0700 Subject: Allow square brackets in macro definitions Fixes #103 --- samples/test/issue-mrustc-103.rs | 9 +++++++++ src/macro_rules/parse.cpp | 1 + 2 files changed, 10 insertions(+) create mode 100644 samples/test/issue-mrustc-103.rs (limited to 'src') diff --git a/samples/test/issue-mrustc-103.rs b/samples/test/issue-mrustc-103.rs new file mode 100644 index 00000000..f27fe6de --- /dev/null +++ b/samples/test/issue-mrustc-103.rs @@ -0,0 +1,9 @@ +macro_rules! pat { + [$a:expr;$b:expr] => ( + println!("{} {}", $a, $b); + ) +} +fn main() { + pat![4;5]; +} + diff --git a/src/macro_rules/parse.cpp b/src/macro_rules/parse.cpp index b3b1014e..0cc7b3a8 100644 --- a/src/macro_rules/parse.cpp +++ b/src/macro_rules/parse.cpp @@ -254,6 +254,7 @@ MacroRule Parse_MacroRules_Var(TokenStream& lex) { case TOK_BRACE_OPEN: close = TOK_BRACE_CLOSE; break; case TOK_PAREN_OPEN: close = TOK_PAREN_CLOSE; break; + case TOK_SQUARE_OPEN: close = TOK_SQUARE_CLOSE; break; default: throw ParseError::Unexpected(lex, tok); } -- cgit v1.2.3