summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.cpp25
-rw-r--r--src/trans/codegen_c.cpp82
-rw-r--r--src/trans/target.cpp67
-rw-r--r--src/trans/target.hpp3
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", [&params](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);