diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ast/crate.cpp | 23 | ||||
-rw-r--r-- | src/ast/crate.hpp | 3 | ||||
-rw-r--r-- | src/expand/format_args.cpp | 2 | ||||
-rw-r--r-- | src/hir/from_ast_expr.cpp | 2 | ||||
-rw-r--r-- | src/main.cpp | 11 | ||||
-rw-r--r-- | src/trans/codegen_c.cpp | 246 |
6 files changed, 198 insertions, 89 deletions
diff --git a/src/ast/crate.cpp b/src/ast/crate.cpp index 394cd47b..f003a00b 100644 --- a/src/ast/crate.cpp +++ b/src/ast/crate.cpp @@ -8,6 +8,9 @@ #include <hir/main_bindings.hpp> // HIR_Deserialise #include <fstream> +::std::vector<::std::string> AST::g_crate_load_dirs = { }; +::std::map<::std::string, ::std::string> AST::g_crate_overrides; + namespace { bool check_item_cfg(const ::AST::MetaItems& attrs) { @@ -99,15 +102,23 @@ void Crate::load_externs() void Crate::load_extern_crate(Span sp, const ::std::string& name) { DEBUG("Loading crate '" << name << "'"); - // TODO: Search a list of load paths for the crate - ::std::vector< ::std::string> paths { "output/", "output/test_deps/" }; ::std::string path; - for(const auto& p : paths){ - path = p + "lib" + name + ".hir"; + auto it = g_crate_overrides.find(name); + if(it != g_crate_overrides.end()) + { + path = it->second; + } + else + { + // Search a list of load paths for the crate + for(const auto& p : g_crate_load_dirs) + { + path = p + "/lib" + name + ".hir"; - if( ::std::ifstream(path).good() ) { - break ; + if( ::std::ifstream(path).good() ) { + break ; + } } } if( !::std::ifstream(path).good() ) { diff --git a/src/ast/crate.hpp b/src/ast/crate.hpp index f9594a83..53dea1b9 100644 --- a/src/ast/crate.hpp +++ b/src/ast/crate.hpp @@ -89,4 +89,7 @@ public: const MacroRules* find_macro_rules(const ::std::string& name) const; }; +extern ::std::vector<::std::string> g_crate_load_dirs; +extern ::std::map<::std::string, ::std::string> g_crate_overrides; + } // namespace AST diff --git a/src/expand/format_args.cpp b/src/expand/format_args.cpp index 92afcbb2..e4c02b8b 100644 --- a/src/expand/format_args.cpp +++ b/src/expand/format_args.cpp @@ -477,7 +477,7 @@ class CFormatArgsExpander: auto expr_tt = TokenTree(Token( InterpolatedFragment(InterpolatedFragment::EXPR, Parse_Expr0(lex).release()) )); - auto ins_rv = named_args_index.insert( ::std::make_pair(mv$(name), named_args.size()) ); + auto ins_rv = named_args_index.insert( ::std::make_pair(mv$(name), static_cast<unsigned>(named_args.size())) ); if( ins_rv.second == false ) { ERROR(sp, E0000, "Duplicate definition of named argument `" << ins_rv.first->first << "`"); } diff --git a/src/hir/from_ast_expr.cpp b/src/hir/from_ast_expr.cpp index 9bbb0418..545873ed 100644 --- a/src/hir/from_ast_expr.cpp +++ b/src/hir/from_ast_expr.cpp @@ -441,6 +441,8 @@ struct LowerHIR_ExprNode_Visitor: case CORETYPE_U32: return ::HIR::CoreType::U32; case CORETYPE_I64: return ::HIR::CoreType::I64; case CORETYPE_U64: return ::HIR::CoreType::U64; + case CORETYPE_I128: return ::HIR::CoreType::I128; + case CORETYPE_U128: return ::HIR::CoreType::U128; case CORETYPE_INT: return ::HIR::CoreType::Isize; case CORETYPE_UINT: return ::HIR::CoreType::Usize; diff --git a/src/main.cpp b/src/main.cpp index 7b1d94be..b883a828 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -224,6 +224,11 @@ int main(int argc, char *argv[]) // Load external crates. CompilePhaseV("LoadCrates", [&]() { + // Hacky! + for(const auto& ld : params.lib_search_dirs) + { + AST::g_crate_load_dirs.push_back(ld); + } crate.load_externs(); }); @@ -570,6 +575,12 @@ int main(int argc, char *argv[]) // ::std::cerr << "Internal Compiler Error: " << e << ::std::endl; // return 2; //} + + // TODO: Make this conditional +#if 0 + ::std::cout << "Press enter to exit..." << ::std::endl; + ::std::cin.get(); +#endif return 0; } diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 973aa33a..b7c3806a 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -499,7 +499,9 @@ namespace { break; case Compiler::Msvc: 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"); args.push_back("&"); args.push_back("cl.exe"); args.push_back("/nologo"); @@ -568,8 +570,9 @@ namespace { } //DEBUG("- " << cmd_ss.str()); ::std::cout << "Running comamnd - " << cmd_ss.str() << ::std::endl; - if( system(cmd_ss.str().c_str()) ) + if( system(cmd_ss.str().c_str()) != 0 ) { + ::std::cerr << "C Compiler failed to execute" << ::std::endl; abort(); } } @@ -2036,82 +2039,17 @@ namespace { if( e.flag_idx != ~0u ) m_of << indent << "}\n"; break; } - case ::MIR::Statement::TAG_Asm: { - const auto& e = stmt.as_Asm(); - - struct H { - static bool has_flag(const ::std::vector<::std::string>& flags, const char* des) { - return ::std::find_if(flags.begin(), flags.end(), [des](const auto&x){return x==des;}) != flags.end(); - } - static const char* convert_reg(const char* r) { - if( ::std::strcmp(r, "{eax}") == 0 || ::std::strcmp(r, "{rax}") == 0 ) { - return "a"; - } - else { - return r; - } - } - }; - bool is_volatile = H::has_flag(e.flags, "volatile"); - bool is_intel = H::has_flag(e.flags, "intel"); - - m_of << indent << "__asm__ "; - if(is_volatile) m_of << "__volatile__"; - // TODO: Convert format string? - // TODO: Use a C-specific escaper here. - m_of << "(\"" << (is_intel ? ".syntax intel; " : ""); - for(auto it = e.tpl.begin(); it != e.tpl.end(); ++it) - { - if( *it == '\n' ) - m_of << ";\\n"; - else if( *it == '"' ) - m_of << "\\\""; - else if( *it == '\\' ) - m_of << "\\\\"; - else if( *it == '/' && *(it+1) == '/' ) - { - while( it != e.tpl.end() || *it == '\n' ) - ++it; - -- it; - } - else if( *it == '%' && *(it+1) == '%' ) - m_of << "%"; - else if( *it == '%' && !isdigit(*(it+1)) ) - m_of << "%%"; - else - m_of << *it; - } - m_of << (is_intel ? ".syntax att; " : "") << "\""; - m_of << ": "; - for(unsigned int i = 0; i < e.outputs.size(); i ++ ) - { - const auto& v = e.outputs[i]; - if( i != 0 ) m_of << ", "; - m_of << "\""; - switch(v.first[0]) - { - case '=': m_of << "="; break; - case '+': m_of << "+"; break; - default: MIR_TODO(mir_res, "Handle asm! output leader '" << v.first[0] << "'"); - } - m_of << H::convert_reg(v.first.c_str()+1); - m_of << "\"("; emit_lvalue(v.second); m_of << ")"; - } - m_of << ": "; - for(unsigned int i = 0; i < e.inputs.size(); i ++ ) - { - const auto& v = e.inputs[i]; - if( i != 0 ) m_of << ", "; - m_of << "\"" << v.first << "\"("; emit_lvalue(v.second); m_of << ")"; - } - m_of << ": "; - for(unsigned int i = 0; i < e.clobbers.size(); i ++ ) + case ::MIR::Statement::TAG_Asm: + switch(m_compiler) { - if( i != 0 ) m_of << ", "; - m_of << "\"" << e.clobbers[i] << "\""; + case Compiler::Gcc: + this->emit_asm_gcc(mir_res, stmt.as_Asm(), indent_level); + break; + case Compiler::Msvc: + this->emit_asm_msvc(mir_res, stmt.as_Asm(), indent_level); + break; } - m_of << ");\n"; - break; } + break; case ::MIR::Statement::TAG_Assign: { const auto& e = stmt.as_Assign(); DEBUG("- " << e.dst << " = " << e.src); @@ -2815,6 +2753,121 @@ namespace { } m_of << " );\n"; } + void emit_asm_gcc(const ::MIR::TypeResolve& mir_res, const ::MIR::Statement::Data_Asm& e, unsigned indent_level) + { + auto indent = RepeatLitStr{ "\t", static_cast<int>(indent_level) }; + struct H { + static bool has_flag(const ::std::vector<::std::string>& flags, const char* des) { + return ::std::find_if(flags.begin(), flags.end(), [des](const auto&x) {return x == des; }) != flags.end(); + } + static const char* convert_reg(const char* r) { + if (::std::strcmp(r, "{eax}") == 0 || ::std::strcmp(r, "{rax}") == 0) { + return "a"; + } + else { + return r; + } + } + }; + bool is_volatile = H::has_flag(e.flags, "volatile"); + bool is_intel = H::has_flag(e.flags, "intel"); + + + m_of << indent << "__asm__ "; + if (is_volatile) m_of << "__volatile__"; + // TODO: Convert format string? + // TODO: Use a C-specific escaper here. + m_of << "(\"" << (is_intel ? ".syntax intel; " : ""); + for (auto it = e.tpl.begin(); it != e.tpl.end(); ++it) + { + if (*it == '\n') + m_of << ";\\n"; + else if (*it == '"') + m_of << "\\\""; + else if (*it == '\\') + m_of << "\\\\"; + else if (*it == '/' && *(it + 1) == '/') + { + while (it != e.tpl.end() || *it == '\n') + ++it; + --it; + } + else if (*it == '%' && *(it + 1) == '%') + m_of << "%"; + else if (*it == '%' && !isdigit(*(it + 1))) + m_of << "%%"; + else + m_of << *it; + } + m_of << (is_intel ? ".syntax att; " : "") << "\""; + m_of << ": "; + for (unsigned int i = 0; i < e.outputs.size(); i++) + { + const auto& v = e.outputs[i]; + if (i != 0) m_of << ", "; + m_of << "\""; + switch (v.first[0]) + { + case '=': m_of << "="; break; + case '+': m_of << "+"; break; + default: MIR_TODO(mir_res, "Handle asm! output leader '" << v.first[0] << "'"); + } + m_of << H::convert_reg(v.first.c_str() + 1); + m_of << "\"("; emit_lvalue(v.second); m_of << ")"; + } + m_of << ": "; + for (unsigned int i = 0; i < e.inputs.size(); i++) + { + const auto& v = e.inputs[i]; + if (i != 0) m_of << ", "; + m_of << "\"" << v.first << "\"("; emit_lvalue(v.second); m_of << ")"; + } + m_of << ": "; + for (unsigned int i = 0; i < e.clobbers.size(); i++) + { + if (i != 0) m_of << ", "; + m_of << "\"" << e.clobbers[i] << "\""; + } + m_of << ");\n"; + } + void emit_asm_msvc(const ::MIR::TypeResolve& mir_res, const ::MIR::Statement::Data_Asm& e, unsigned indent_level) + { + auto indent = RepeatLitStr{ "\t", static_cast<int>(indent_level) }; + + if( !e.inputs.empty() || !e.outputs.empty() ) + { + MIR_TODO(mir_res, "Inputs/outputs in msvc inline assembly"); +#if 0 + m_of << indent << "{\n"; + for(size_t i = 0; i < e.inputs.size(); i ++) + { + m_of << indent << "auto asm_i_" << i << " = "; + emit_lvalue(e.inputs[i]); + } +#endif + } + + m_of << indent << "__asm {\n"; + + m_of << indent << "\t"; + for (auto it = e.tpl.begin(); it != e.tpl.end(); ++it) + { + if (*it == ';') + { + m_of << "\n"; + m_of << indent << "\t"; + } + else + m_of << *it; + } + + m_of << "\n" << indent << "}"; + if (!e.inputs.empty() || !e.outputs.empty()) + { + m_of << "}"; + } + m_of << ";\n"; + } private: const ::HIR::TypeRef& monomorphise_fcn_return(::HIR::TypeRef& tmp, const ::HIR::Function& item, const Trans_Params& params) { @@ -2960,6 +3013,7 @@ namespace { m_of << ", "<<o_succ<<", "<<o_fail<<")"; break; case Compiler::Msvc: + emit_lvalue(e.ret_val); m_of << "._0 = "; emit_msvc_atomic_op("InterlockedCompareExchange", ""); // TODO: Use ordering if(params.m_types.at(0) == ::HIR::CoreType::Usize || params.m_types.at(0) == ::HIR::CoreType::Isize) { @@ -2969,6 +3023,8 @@ namespace { { emit_param(e.args.at(0)); m_of << ", "; emit_param(e.args.at(1)); m_of << ", "; emit_param(e.args.at(2)); m_of << ")"; } + m_of << ";\n\t"; + emit_lvalue(e.ret_val); m_of << "._1 = ("; emit_lvalue(e.ret_val); m_of << "._0 == "; emit_param(e.args.at(2)); m_of << ")"; break; } }; @@ -3349,7 +3405,16 @@ namespace { { m_of << "shl128"; if(params.m_types.at(0) == ::HIR::CoreType::I128) m_of << "s"; - m_of << "("; emit_param(e.args.at(0)); m_of << ", "; emit_param(e.args.at(1)); m_of << ")"; + m_of << "("; emit_param(e.args.at(0)); m_of << ", "; + emit_param(e.args.at(1)); + // If the shift type is a u128/i128, get the inner + ::HIR::TypeRef tmp; + const auto& shift_ty = mir_res.get_param_type(tmp, e.args.at(1)); + if( shift_ty == ::HIR::CoreType::I128 || shift_ty == ::HIR::CoreType::U128 ) + { + m_of << ".lo"; + } + m_of << ")"; } else { @@ -3362,7 +3427,16 @@ namespace { { m_of << "shr128"; if (params.m_types.at(0) == ::HIR::CoreType::I128) m_of << "s"; - m_of << "("; emit_param(e.args.at(0)); m_of << ", "; emit_param(e.args.at(1)); m_of << ")"; + m_of << "("; emit_param(e.args.at(0)); m_of << ", "; + emit_param(e.args.at(1)); + // If the shift type is a u128/i128, get the inner + ::HIR::TypeRef tmp; + const auto& shift_ty = mir_res.get_param_type(tmp, e.args.at(1)); + if( shift_ty == ::HIR::CoreType::I128 || shift_ty == ::HIR::CoreType::U128 ) + { + m_of << ".lo"; + } + m_of << ")"; } else { @@ -4154,13 +4228,21 @@ namespace { m_of << "\", " << ::std::dec << c.size() << ")"; ), (Const, - // TODO: This should have been eliminated? - // NOTE: GCC hack - statement expressions + // TODO: This should have been eliminated? ("MIR Cleanup" should have removed all inline Const references) ::HIR::TypeRef ty; const auto& lit = get_literal_for_const(c.p, ty); - m_of << "({"; emit_ctype(ty, FMT_CB(ss, ss<<"v";)); m_of << "; "; - assign_from_literal([&](){ m_of << "v"; }, ty, lit); - m_of << "; v;})"; + if(lit.is_Integer() || lit.is_Float() || lit.is_String()) + { + emit_literal(ty, lit, {}); + } + else + { + // NOTE: GCC hack - statement expressions + MIR_ASSERT(*m_mir_res, m_compiler == Compiler::Gcc, "TODO: Support inline constants without statement expressions"); + m_of << "({"; emit_ctype(ty, FMT_CB(ss, ss<<"v";)); m_of << "; "; + assign_from_literal([&](){ m_of << "v"; }, ty, lit); + m_of << "; v;})"; + } ), (ItemAddr, TU_MATCHA( (c.m_data), (pe), |