diff options
Diffstat (limited to 'src/trans/target.cpp')
-rw-r--r-- | src/trans/target.cpp | 104 |
1 files changed, 87 insertions, 17 deletions
diff --git a/src/trans/target.cpp b/src/trans/target.cpp index 87b5aa1d..1727cdba 100644 --- a/src/trans/target.cpp +++ b/src/trans/target.cpp @@ -133,11 +133,11 @@ namespace check_path_length(key_val, 3); if( key_val.value.as_string() == "msvc" ) { - rv.m_codegen_mode = CodegenMode::Msvc; + rv.m_backend_c.m_codegen_mode = CodegenMode::Msvc; } else if( key_val.value.as_string() == "gnu" ) { - rv.m_codegen_mode = CodegenMode::Gnu11; + rv.m_backend_c.m_codegen_mode = CodegenMode::Gnu11; } else { @@ -148,7 +148,23 @@ namespace else if( key_val.path[2] == "target" ) { check_path_length(key_val, 3); - rv.m_c_compiler = key_val.value.as_string(); + rv.m_backend_c.m_c_compiler = key_val.value.as_string(); + } + else if( key_val.path[2] == "compiler-opts" ) + { + check_path_length(key_val, 3); + for(const auto& v : key_val.value.as_list()) + { + rv.m_backend_c.m_compiler_opts.push_back( v.as_string() ); + } + } + else if( key_val.path[2] == "linker-opts" ) + { + check_path_length(key_val, 3); + for(const auto& v : key_val.value.as_list()) + { + rv.m_backend_c.m_linker_opts.push_back( v.as_string() ); + } } else { @@ -233,8 +249,56 @@ namespace return rv; } + void save_spec_to_file(const ::std::string& filename, const TargetSpec& spec) + { + // TODO: Have a round-trip unit test + ::std::ofstream of(filename); + + struct H + { + static const char* tfstr(bool v) + { + return v ? "true" : "false"; + } + static const char* c_variant_name(const CodegenMode m) + { + switch(m) + { + case CodegenMode::Gnu11: return "gnu"; + case CodegenMode::Msvc: return "msvc"; + } + return ""; + } + }; + + of + << "[target]\n" + << "family = \"" << spec.m_family << "\"\n" + << "os-name = \"" << spec.m_os_name << "\"\n" + << "env-name = \"" << spec.m_env_name << "\"\n" + //<< "arch = \"" << spec.m_arch.m_name << "\"\n" + << "\n" + << "[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" + << "\n" + << "[arch]" + << "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" + << "has-atomic-u8 = " << H::tfstr(spec.m_arch.m_atomics.u8) << "\n" + << "has-atomic-u16 = " << H::tfstr(spec.m_arch.m_atomics.u16) << "\n" + << "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" + ; + } TargetSpec init_from_spec_name(const ::std::string& target_name) { + // Options for all the fully-GNU environments + #define BACKEND_C_OPTS_GNU {"-ffunction-sections", "-pthread"}, {"-Wl,--gc-sections"} // If there's a '/' or a '\' in the filename, open it as a path, otherwise assume it's a triple. if( target_name.find('/') != ::std::string::npos || target_name.find('\\') != ::std::string::npos ) { @@ -243,98 +307,100 @@ namespace else if(target_name == "i586-linux-gnu") { return TargetSpec { - "unix", "linux", "gnu", CodegenMode::Gnu11, "i586-linux-gnu", + "unix", "linux", "gnu", {CodegenMode::Gnu11, "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", + "unix", "linux", "gnu", {CodegenMode::Gnu11, "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", + "unix", "linux", "gnu", {CodegenMode::Gnu11, "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", + "unix", "linux", "gnu", {CodegenMode::Gnu11, "aarch64-linux-gnu", BACKEND_C_OPTS_GNU}, ARCH_ARM64 }; } else if(target_name == "i586-windows-gnu") { return TargetSpec { - "windows", "windows", "gnu", CodegenMode::Gnu11, "mingw32", + "windows", "windows", "gnu", {CodegenMode::Gnu11, "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", + "windows", "windows", "gnu", {CodegenMode::Gnu11, "x86_64-w64-mingw32", BACKEND_C_OPTS_GNU}, ARCH_X86_64 }; } else if (target_name == "x86-windows-msvc") { + // TODO: Should this include the "kernel32.lib" inclusion? return TargetSpec { - "windows", "windows", "msvc", CodegenMode::Msvc, "x86", + "windows", "windows", "msvc", {CodegenMode::Msvc, "x86", {}, {}}, ARCH_X86 }; } else if (target_name == "x86_64-windows-msvc") { return TargetSpec { - "windows", "windows", "msvc", CodegenMode::Msvc, "amd64", + "windows", "windows", "msvc", {CodegenMode::Msvc, "amd64", {}, {}}, ARCH_X86_64 }; } else if(target_name == "x86_64-unknown-netbsd") { return TargetSpec { - "unix", "netbsd", "gnu", CodegenMode::Gnu11, "x86_64-unknown-netbsd", + "unix", "netbsd", "gnu", {CodegenMode::Gnu11, "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", + "unix", "openbsd", "gnu", {CodegenMode::Gnu11, "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", + "unix", "openbsd", "gnu", {CodegenMode::Gnu11, "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", + "unix", "openbsd", "gnu", {CodegenMode::Gnu11, "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", + "unix", "openbsd", "gnu", {CodegenMode::Gnu11, "aarch64-unknown-openbsd", BACKEND_C_OPTS_GNU}, ARCH_ARM64 }; } else if(target_name == "x86_64-apple-macosx") { + // NOTE: OSX uses clang and lld, 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, "x86_64-apple-darwin", {}, {}}, ARCH_X86_64 }; } @@ -351,6 +417,10 @@ const TargetSpec& Target_GetCurSpec() { return g_target; } +void Target_ExportCurSpec(const ::std::string& filename) +{ + save_spec_to_file(filename, g_target); +} void Target_SetCfg(const ::std::string& target_name) { g_target = init_from_spec_name(target_name); |