summaryrefslogtreecommitdiff
path: root/src/trans/target.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/trans/target.cpp')
-rw-r--r--src/trans/target.cpp104
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);