diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/expand/asm.cpp | 42 | ||||
-rw-r--r-- | src/hir_typeck/helpers.cpp | 2 | ||||
-rw-r--r-- | src/main.cpp | 2 | ||||
-rw-r--r-- | src/mir/from_hir.cpp | 10 | ||||
-rw-r--r-- | src/trans/codegen_c.cpp | 90 | ||||
-rw-r--r-- | src/trans/target.cpp | 20 |
6 files changed, 143 insertions, 23 deletions
diff --git a/src/expand/asm.cpp b/src/expand/asm.cpp index 6ca90f3e..336321f7 100644 --- a/src/expand/asm.cpp +++ b/src/expand/asm.cpp @@ -49,9 +49,12 @@ class CAsmExpander: ::std::vector<::std::string> flags; // Outputs - if( lex.lookahead(0) == TOK_COLON ) + if( lex.lookahead(0) == TOK_COLON || lex.lookahead(0) == TOK_DOUBLE_COLON ) { GET_TOK(tok, lex); + if( tok.type() == TOK_DOUBLE_COLON ) { + lex.putback(Token(TOK_COLON)); + } while( lex.lookahead(0) == TOK_STRING ) { @@ -73,9 +76,12 @@ class CAsmExpander: } // Inputs - if( lex.lookahead(0) == TOK_COLON ) + if( lex.lookahead(0) == TOK_COLON || lex.lookahead(0) == TOK_DOUBLE_COLON ) { GET_TOK(tok, lex); + if( tok.type() == TOK_DOUBLE_COLON ) { + lex.putback(Token(TOK_COLON)); + } while( lex.lookahead(0) == TOK_STRING ) { @@ -95,9 +101,12 @@ class CAsmExpander: } // Clobbers - if( lex.lookahead(0) == TOK_COLON ) + if( lex.lookahead(0) == TOK_COLON || lex.lookahead(0) == TOK_DOUBLE_COLON ) { GET_TOK(tok, lex); + if( tok.type() == TOK_DOUBLE_COLON ) { + lex.putback(Token(TOK_COLON)); + } while( lex.lookahead(0) == TOK_STRING ) { @@ -111,9 +120,12 @@ class CAsmExpander: } // Flags - if( lex.lookahead(0) == TOK_COLON ) + if( lex.lookahead(0) == TOK_COLON || lex.lookahead(0) == TOK_DOUBLE_COLON ) { GET_TOK(tok, lex); + if( tok.type() == TOK_DOUBLE_COLON ) { + lex.putback(Token(TOK_COLON)); + } while( lex.lookahead(0) == TOK_STRING ) { @@ -126,6 +138,28 @@ class CAsmExpander: } } + if( lex.lookahead(0) == TOK_COLON || lex.lookahead(0) == TOK_DOUBLE_COLON ) + { + GET_TOK(tok, lex); + if( tok.type() == TOK_DOUBLE_COLON ) { + lex.putback(Token(TOK_COLON)); + } + + if( GET_TOK(tok, lex) == TOK_IDENT && tok.str() == "volatile" ) + { + flags.push_back( "volatile" ); + } + else + { + PUTBACK(tok, lex); + } + } + + if( lex.lookahead(0) != TOK_EOF ) + { + ERROR(sp, E0000, "Unexpected token in asm! - " << lex.getToken()); + } + ::AST::ExprNodeP rv = ::AST::ExprNodeP( new ::AST::ExprNode_Asm { mv$(template_text), mv$(outputs), mv$(inputs), mv$(clobbers), mv$(flags) } ); // TODO: Convert this into an AST node return box$( TTStreamO(TokenTree(Token( InterpolatedFragment(InterpolatedFragment::EXPR, rv.release()) )))); diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp index 94f7304d..0c8b87c5 100644 --- a/src/hir_typeck/helpers.cpp +++ b/src/hir_typeck/helpers.cpp @@ -2826,7 +2826,6 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp, auto rv = this->find_trait_impls(sp, real_trait_path.m_path, real_trait_path.m_params, real_type, [&](auto impl, auto impl_cmp) { DEBUG("[ftic_check_params] impl_cmp = " << impl_cmp << ", impl = " << impl); auto cmp = impl_cmp; -#if 1 if( cmp == ::HIR::Compare::Fuzzy ) { // If the match was fuzzy, try again filling in with `cb_match` @@ -2841,7 +2840,6 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp, cmp &= real_trait_path.m_params .match_test_generics_fuzz(sp, i_tp, cb_infer, cb_match); DEBUG("[ftic_check_params] - Re-check result: " << cmp); } -#endif for(const auto& assoc_bound : real_trait.m_type_bounds) { ::HIR::TypeRef tmp; const ::HIR::TypeRef* ty_p; diff --git a/src/main.cpp b/src/main.cpp index d2330568..c159ca4b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -29,7 +29,7 @@ // Hacky default target #ifdef _MSC_VER -#define DEFAULT_TARGET_NAME "x86_64-windows-msvc" +#define DEFAULT_TARGET_NAME "x86-windows-msvc" #elif defined(__GNU__) # if defined(__linux__) #define DEFAULT_TARGET_NAME "x86_64-linux-gnu" diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index 7773a81c..8ea22cef 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -506,6 +506,7 @@ namespace { TRACE_FUNCTION_F("_Asm"); ::std::vector< ::std::pair< ::std::string, ::MIR::LValue> > inputs; + // Inputs just need to be in lvalues for(auto& v : node.m_inputs) { this->visit_node_ptr(v.value); auto lv = m_builder.get_result_in_lvalue(v.value->span(), v.value->m_res_type); @@ -513,9 +514,16 @@ namespace { } ::std::vector< ::std::pair< ::std::string, ::MIR::LValue> > outputs; + // Outputs can also (sometimes) be rvalues (only for `*m`?) for(auto& v : node.m_outputs) { this->visit_node_ptr(v.value); - auto lv = m_builder.get_result_unwrap_lvalue(v.value->span()); + if( v.spec[0] != '=' ) + ERROR(node.span(), E0000, "Assembly output specifiers must start with ="); + ::MIR::LValue lv; + if(v.spec[1] == '*') + lv = m_builder.get_result_in_lvalue(v.value->span(), v.value->m_res_type); + else + lv = m_builder.get_result_unwrap_lvalue(v.value->span()); outputs.push_back( ::std::make_pair(v.spec, mv$(lv)) ); } diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index b942dae7..1ec2d2cd 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -520,7 +520,10 @@ namespace { is_windows = true; // TODO: Look up these paths in the registry and use CreateProcess instead of system args.push_back(cache_str( detect_msvc().path_vcvarsall )); - //args.push_back("amd64"); + if( Target_GetCurSpec().m_arch.m_pointer_bits == 64 ) + { + args.push_back("amd64"); // NOTE: Doesn't support inline assembly, only works with overrides + } args.push_back("&"); args.push_back("cl.exe"); args.push_back("/nologo"); @@ -584,6 +587,10 @@ namespace { cmd_ss << "&"; } else { + if( is_windows && strchr(arg, ' ') == nullptr ) { + cmd_ss << arg << " "; + continue ; + } cmd_ss << "\"" << FmtShell(arg, is_windows) << "\" "; } } @@ -628,7 +635,15 @@ namespace { void emit_type_id(const ::HIR::TypeRef& ty) override { - m_of << "tTYPEID __typeid_" << Trans_Mangle(ty) << " __attribute__((weak));\n"; + switch(m_compiler) + { + case Compiler::Gcc: + m_of << "tTYPEID __typeid_" << Trans_Mangle(ty) << " __attribute__((weak));\n"; + break; + case Compiler::Msvc: + m_of << "__declspec(selectany) tTYPEID __typeid_" << Trans_Mangle(ty) << ";\n"; + break; + } } void emit_type_proto(const ::HIR::TypeRef& ty) override { @@ -673,7 +688,21 @@ namespace { m_of << "typedef "; // TODO: ABI marker, need an ABI enum? // TODO: Better emit_ctype call for return type. - emit_ctype(*te.m_rettype); m_of << " (*"; emit_ctype(ty); m_of << ")("; + emit_ctype(*te.m_rettype); m_of << " ("; + if( m_compiler == Compiler::Msvc ) + { + if( te.m_abi == ABI_RUST ) + { + } + else if( te.m_abi == "system" ) + { + m_of << "__stdcall"; + } + else + { + } + } + m_of << "*"; emit_ctype(ty); m_of << ")("; if( te.m_arg_types.size() == 0 ) { m_of << "void)"; @@ -843,8 +872,16 @@ namespace { ::std::vector< ::std::pair<::HIR::Pattern,::HIR::TypeRef> > args; if( item.m_markings.has_drop_impl ) { + // If the type is defined outside the current crate, define as static (to avoid conflicts when we define it) if( p.m_path.m_crate_name != m_crate.m_crate_name ) - m_of << "static "; + { + if( item.m_params.m_types.size() > 0 ) { + m_of << "static "; + } + else { + m_of << "extern "; + } + } m_of << "tUNIT " << Trans_Mangle( ::HIR::Path(struct_ty.clone(), m_resolve.m_lang_Drop, "drop") ) << "("; emit_ctype(struct_ty_ptr, FMT_CB(ss, ss << "rv";)); m_of << ");\n"; } else if( m_resolve.is_type_owned_box(struct_ty) ) @@ -1433,6 +1470,8 @@ namespace { m_of << " "; emit_literal(get_inner_type(0, i), e[i], params); } + if(ty.m_data.is_Path() && e.size() == 0 && m_options.disallow_empty_structs) + m_of << "0"; m_of << " }"; if( ty.m_data.is_Array() ) m_of << "}"; @@ -1460,25 +1499,25 @@ namespace { } else { - m_of << "{" << e.idx << ", { "; + m_of << "{" << e.idx; if( e.vals.empty() ) { if( m_options.disallow_empty_structs && !enm.m_variants.at(e.idx).second.is_Unit() ) { - m_of << ".var_" << e.idx << " = {0} "; + m_of << ", { .var_" << e.idx << " = {0} }"; } } else { - m_of << ".var_" << e.idx << " = {"; + m_of << ", { .var_" << e.idx << " = {"; for(unsigned int i = 0; i < e.vals.size(); i ++) { if(i != 0) m_of << ","; m_of << " "; emit_literal(get_inner_type(e.idx, i), e.vals[i], params); } - m_of << "} "; + m_of << "} }"; } - m_of << "}}"; + m_of << "}"; } ), (Integer, @@ -1752,7 +1791,7 @@ namespace { } } - m_of << "// extern \"" << item.m_abi << "\" " << p << "\n"; + m_of << "// EXTERN extern \"" << item.m_abi << "\" " << p << "\n"; m_of << "extern "; emit_function_header(p, item, params); if( item.m_linkage.name != "" && m_compiler == Compiler::Gcc) @@ -1769,6 +1808,7 @@ namespace { m_mir_res = &top_mir_res; TRACE_FUNCTION_F(p); + m_of << "// PROTO extern \"" << item.m_abi << "\" " << p << "\n"; if( item.m_linkage.name != "" ) { m_of << "#define " << Trans_Mangle(p) << " " << item.m_linkage.name << "\n"; @@ -2942,9 +2982,37 @@ namespace { { auto indent = RepeatLitStr{ "\t", static_cast<int>(indent_level) }; + if( e.tpl == "fnstcw $0" ) + { + // HARD CODE: `fnstcw` -> _control87 + if( !(e.inputs.size() == 0 && e.outputs.size() == 1 && e.outputs[0].first == "=*m") ) + MIR_BUG(mir_res, "Hard-coded asm translation doesn't apply - `" << e.tpl << "` inputs=" << e.inputs << " outputs=" << e.outputs); + m_of << indent << "*("; emit_lvalue(e.outputs[0].second); m_of << ") = _control87(0,0);\n"; + return ; + } + else if( e.tpl == "fldcw $0" ) + { + // HARD CODE: `fldcw` -> _control87 + if( !(e.inputs.size() == 1 && e.inputs[0].first == "m" && e.outputs.size() == 0) ) + MIR_BUG(mir_res, "Hard-coded asm translation doesn't apply - `" << e.tpl << "` inputs=" << e.inputs << " outputs=" << e.outputs); + m_of << indent << "_control87("; emit_lvalue(e.inputs[0].second); m_of << ", 0xFFFF);\n"; + return ; + } + else if( e.tpl == "int $$0x29" ) + { + if( !(e.inputs.size() == 1 && e.inputs[0].first == "{ecx}" && e.outputs.size() == 0) ) + MIR_BUG(mir_res, "Hard-coded asm translation doesn't apply - `" << e.tpl << "` inputs=" << e.inputs << " outputs=" << e.outputs); + m_of << indent << "__fastfail("; emit_lvalue(e.inputs[0].second); m_of << ");\n"; + return ; + } + else + { + // No hard-coded translations. + } + if( !e.inputs.empty() || !e.outputs.empty() ) { - MIR_TODO(mir_res, "Inputs/outputs in msvc inline assembly"); + MIR_TODO(mir_res, "Inputs/outputs in msvc inline assembly - `" << e.tpl << "` inputs=" << e.inputs << " outputs=" << e.outputs); #if 0 m_of << indent << "{\n"; for(size_t i = 0; i < e.inputs.size(); i ++) diff --git a/src/trans/target.cpp b/src/trans/target.cpp index d4f57107..bb0227fc 100644 --- a/src/trans/target.cpp +++ b/src/trans/target.cpp @@ -15,6 +15,11 @@ TargetArch ARCH_X86_64 = { 64, false, { /*atomic(u8)=*/true, false, true, true, true } }; +TargetArch ARCH_X86 = { + "x86", + 32, false, + { /*atomic(u8)=*/true, false, true, false, true } +}; TargetSpec g_target; namespace @@ -43,13 +48,20 @@ namespace ARCH_X86_64 }; } - else if (target_name == "x86_64-windows-msvc") + else if (target_name == "x86-windows-msvc") { return TargetSpec { - "windows", "windows", "msvd", CodegenMode::Msvc, - ARCH_X86_64 - }; + "windows", "windows", "msvc", CodegenMode::Msvc, + ARCH_X86 + }; } + //else if (target_name == "x86_64-windows-msvc") + //{ + // return TargetSpec { + // "windows", "windows", "msvc", CodegenMode::Msvc, + // ARCH_X86_64 + // }; + //} else { ::std::cerr << "Unknown target name '" << target_name << "'" << ::std::endl; |