diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/main.cpp | 25 | ||||
-rw-r--r-- | src/trans/codegen_c.cpp | 82 | ||||
-rw-r--r-- | src/trans/target.cpp | 67 | ||||
-rw-r--r-- | src/trans/target.hpp | 3 |
4 files changed, 158 insertions, 19 deletions
diff --git a/src/main.cpp b/src/main.cpp index 79426abc..0435a90b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -27,6 +27,21 @@ #include "expand/cfg.hpp" +// Hacky default target +#ifdef _MSC_VER +#define DEFAULT_TARGET_NAME "x86_64-windows-msvc" +#elif defined(__GNU__) +# if defined(__linux__) +#define DEFAULT_TARGET_NAME "x86_64-linux-gnu" +# elif defined(_WIN64) +#define DEFAULT_TARGET_NAME "x86_64-windows-gnu" +# else +#define DEFAULT_TARGET_NAME "x86_64-windows-gnu" +# endif +#else +#define DEFAULT_TARGET_NAME "x86_64-linux-gnu" +#endif + int g_debug_indent_level = 0; bool g_debug_enabled = true; ::std::string g_cur_phase; @@ -129,6 +144,7 @@ struct ProgramParams ::std::string infile; ::std::string outfile; ::std::string output_dir = ""; + ::std::string target = DEFAULT_TARGET_NAME; const char *crate_path = "."; ::AST::Crate::Type crate_type = ::AST::Crate::Type::Unknown; @@ -186,7 +202,7 @@ int main(int argc, char *argv[]) Cfg_SetValueCb("feature", [¶ms](const ::std::string& s) { return params.features.count(s) != 0; }); - Target_SetCfg(); + Target_SetCfg(params.target); if( params.test_harness ) @@ -721,6 +737,13 @@ ProgramParams::ProgramParams(int argc, char *argv[]) Cfg_SetFlag(opt_and_val); } } + else if( strcmp(arg, "--target") == 0 ) { + if (i == argc - 1) { + ::std::cerr << "Flag " << arg << " requires an argument" << ::std::endl; + exit(1); + } + this->target = argv[++i]; + } else if( strcmp(arg, "--stop-after") == 0 ) { if( i == argc - 1 ) { ::std::cerr << "Flag --stop-after requires an argument" << ::std::endl; diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 9ef60523..aa0d6cb8 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -15,7 +15,58 @@ #include <hir_typeck/static.hpp> #include <mir/helpers.hpp> #include "codegen_c.hpp" +#include "target.hpp" +namespace { + struct FmtShell + { + const ::std::string& s; + bool is_win; + FmtShell(const ::std::string& s, bool is_win=false): + s(s), + is_win(is_win) + { + } + }; +} + +::std::ostream& operator<<(::std::ostream& os, const FmtShell& x) +{ + if( x.is_win ) + { + // TODO: Two layers of translation, one for CommandLineToArgW (inner), and one for cmd.exe (outer) + for(auto it = x.s.begin(); it != x.s.end(); ++it) + { + switch (*it) + { + // Backslashes are only escaped if they would trigger an escape + case '\"': + case '^': + os << "^"; + default: + break; + } + os << *it; + } + } + else + { + for (char c : x.s) + { + // Backslash and double quote need escaping + switch(c) + { + case '\\': + case '\"': + case ' ': + os << "\\"; + default: + os << c; + } + } + } + return os; +} namespace { class CodeGenerator_C: @@ -61,6 +112,16 @@ namespace { m_outfile_path_c(outfile + ".c"), m_of(m_outfile_path_c) { + switch(Target_GetCurSpec().m_codegen_mode) + { + case CodegenMode::Gnu11: + m_compiler = Compiler::Gcc; + break; + case CodegenMode::Msvc: + m_compiler = Compiler::Msvc; + break; + } + m_of << "/*\n" << " * AUTOGENERATED by mrustc\n" @@ -156,11 +217,13 @@ namespace { } m_of.flush(); + m_of.close(); // Execute $CC with the required libraries ::std::vector<::std::string> tmp; auto cache_str = [&](::std::string s){ tmp.push_back(::std::move(s)); return tmp.back().c_str(); }; ::std::vector<const char*> args; + bool is_windows = false; switch( m_compiler ) { case Compiler::Gcc: @@ -218,7 +281,10 @@ namespace { } break; case Compiler::Msvc: - args.push_back( "cl.exe" ); + is_windows = true; + args.push_back("C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\vcvarsall.bat"); + args.push_back("&"); + args.push_back("cl.exe"); args.push_back(m_outfile_path_c.c_str()); switch(opt.opt_level) { @@ -263,16 +329,24 @@ namespace { else { args.push_back("/c"); - args.push_back(cache_str( FMT("/Fo" + m_outfile_path) )); + args.push_back(cache_str( FMT("/Fo" << m_outfile_path) )); } break; } ::std::stringstream cmd_ss; + if (is_windows) + { + cmd_ss << "echo \"\" & "; + } for(const auto& arg : args) { - // TODO: use a formatter specific to shell escaping - cmd_ss << "\"" << FmtEscaped(arg) << "\" "; + if(arg == "&" && is_windows) { + cmd_ss << "&"; + } + else { + cmd_ss << "\"" << FmtShell(arg, is_windows) << "\" "; + } } //DEBUG("- " << cmd_ss.str()); ::std::cout << "Running comamnd - " << cmd_ss.str() << ::std::endl; diff --git a/src/trans/target.cpp b/src/trans/target.cpp index d9b3486e..43b63822 100644 --- a/src/trans/target.cpp +++ b/src/trans/target.cpp @@ -8,24 +8,65 @@ #include "target.hpp" #include <algorithm> #include "../expand/cfg.hpp" +#include <fstream> -// TODO: Replace with target selection -#define POINTER_SIZE_BYTES 8 +TargetArch ARCH_X86_64 = { + "x86_64", + 64, false, + { true, false, true, true, true } + }; +TargetSpec g_target; -TargetSpec g_target = { - "unix", - "linux", - "gnu", - CodegenMode::Gnu11, - TargetArch { - "x86_64", - 64, false, - { true, false, true, true, true } +namespace +{ + TargetSpec load_spec_from_file(const ::std::string& filename) + { + throw ""; + } + TargetSpec init_from_spec_name(const ::std::string& target_name) + { + if( ::std::ifstream(target_name).is_open() ) + { + return load_spec_from_file(target_name); } - }; + else if(target_name == "x86_64-linux-gnu") + { + return TargetSpec { + "unix", "linux", "gnu", CodegenMode::Gnu11, + ARCH_X86_64 + }; + } + else if(target_name == "x86_64-windows-gnu") + { + return TargetSpec { + "windows", "windows", "gnu", CodegenMode::Gnu11, + ARCH_X86_64 + }; + } + else if (target_name == "x86_64-windows-msvc") + { + return TargetSpec { + "windows", "windows", "msvd", CodegenMode::Msvc, + ARCH_X86_64 + }; + } + else + { + ::std::cerr << "Unknown target name '" << target_name << "'" << ::std::endl; + abort(); + } + throw ""; + } +} -void Target_SetCfg() +const TargetSpec& Target_GetCurSpec() { + return g_target; +} +void Target_SetCfg(const ::std::string& target_name) +{ + g_target = init_from_spec_name(target_name); + if(g_target.m_family == "unix") { Cfg_SetFlag("unix"); } diff --git a/src/trans/target.hpp b/src/trans/target.hpp index 80ba0bf2..f39882e6 100644 --- a/src/trans/target.hpp +++ b/src/trans/target.hpp @@ -41,7 +41,8 @@ struct TargetSpec }; -extern void Target_SetCfg(); +extern const TargetSpec& Target_GetCurSpec(); +extern void Target_SetCfg(const ::std::string& target_name); extern bool Target_GetSizeOf(const Span& sp, const ::HIR::TypeRef& ty, size_t& out_size); extern bool Target_GetAlignOf(const Span& sp, const ::HIR::TypeRef& ty, size_t& out_align); |