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.cpp508
1 files changed, 461 insertions, 47 deletions
diff --git a/src/trans/target.cpp b/src/trans/target.cpp
index a91b1225..316749be 100644
--- a/src/trans/target.cpp
+++ b/src/trans/target.cpp
@@ -12,21 +12,37 @@
#include <map>
#include <hir/hir.hpp>
#include <hir_typeck/helpers.hpp>
+#include <toml.h> // tools/common
-TargetArch ARCH_X86_64 = {
+const TargetArch ARCH_X86_64 = {
"x86_64",
64, false,
- { /*atomic(u8)=*/true, false, true, true, true }
+ TargetArch::Atomics(/*atomic(u8)=*/true, false, true, true, true),
+ TargetArch::Alignments(2, 4, 8, 16, 4, 8, 8)
};
-TargetArch ARCH_X86 = {
+const TargetArch ARCH_X86 = {
"x86",
32, false,
- { /*atomic(u8)=*/true, false, true, false, true }
+ { /*atomic(u8)=*/true, false, true, false, true },
+ TargetArch::Alignments(2, 4, /*u64*/4, /*u128*/4, 4, 4, /*ptr*/4) // u128 has the same alignment as u64, which is u32's alignment. And f64 is 4 byte aligned
};
-TargetArch ARCH_ARM32 = {
+const TargetArch ARCH_ARM64 = {
+ "aarch64",
+ 64, false,
+ { /*atomic(u8)=*/true, true, true, true, true },
+ TargetArch::Alignments(2, 4, 8, 16, 4, 8, 8)
+};
+const TargetArch ARCH_ARM32 = {
"arm",
32, false,
- { /*atomic(u8)=*/true, false, true, false, true }
+ { /*atomic(u8)=*/true, false, true, false, true },
+ TargetArch::Alignments(2, 4, 8, 16, 4, 8, 4) // Note, all types are natively aligned (but i128 will be emulated)
+};
+const TargetArch ARCH_M68K = {
+ "m68k",
+ 32, true,
+ { /*atomic(u8)=*/true, false, true, false, true },
+ TargetArch::Alignments(2, 2, 2, 2, 2, 2, 2)
};
TargetSpec g_target;
@@ -37,91 +53,464 @@ namespace
{
TargetSpec load_spec_from_file(const ::std::string& filename)
{
- throw "";
+ TargetSpec rv;
+
+ TomlFile toml_file(filename);
+ for(auto key_val : toml_file)
+ {
+ // Assertion: The way toml works, there has to be at least two entries in every path.
+ assert(key_val.path.size() > 1);
+ DEBUG(key_val.path << " = " << key_val.value);
+
+ auto check_path_length = [&](const TomlKeyValue& kv, unsigned len) {
+ if( kv.path.size() != len ) {
+ if( kv.path.size() > len ) {
+ ::std::cerr << "ERROR: Unexpected sub-node to " << kv.path << " in " << filename << ::std::endl;
+ }
+ else {
+ ::std::cerr << "ERROR: Expected sub-nodes in " << kv.path << " in " << filename << ::std::endl;
+ }
+ exit(1);
+ }
+ };
+ auto check_path_length_min = [&](const TomlKeyValue& kv, unsigned len) {
+ if( kv.path.size() < len ) {
+ ::std::cerr << "ERROR: Expected sub-nodes in " << kv.path << " in " << filename << ::std::endl;
+ }
+ };
+
+ try
+ {
+ if( key_val.path[0] == "target" )
+ {
+ check_path_length_min(key_val, 2);
+ if( key_val.path[1] == "family" )
+ {
+ check_path_length(key_val, 2);
+ rv.m_family = key_val.value.as_string();
+ }
+ else if( key_val.path[1] == "os-name" )
+ {
+ check_path_length(key_val, 2);
+ rv.m_os_name = key_val.value.as_string();
+ }
+ else if( key_val.path[1] == "env-name" )
+ {
+ check_path_length(key_val, 2);
+ rv.m_env_name = key_val.value.as_string();
+ }
+ else if( key_val.path[1] == "arch" )
+ {
+ check_path_length(key_val, 2);
+ if( key_val.value.as_string() == ARCH_ARM32.m_name )
+ {
+ rv.m_arch = ARCH_ARM32;
+ }
+ else if( key_val.value.as_string() == ARCH_ARM64.m_name )
+ {
+ rv.m_arch = ARCH_ARM64;
+ }
+ else if( key_val.value.as_string() == ARCH_X86.m_name )
+ {
+ rv.m_arch = ARCH_X86;
+ }
+ else if( key_val.value.as_string() == ARCH_X86_64.m_name )
+ {
+ rv.m_arch = ARCH_X86_64;
+ }
+ else if( key_val.value.as_string() == ARCH_M68K.m_name )
+ {
+ rv.m_arch = ARCH_M68K;
+ }
+ else
+ {
+ // Error.
+ ::std::cerr << "ERROR: Unknown architecture name '" << key_val.value.as_string() << "' in " << filename << ::std::endl;
+ exit(1);
+ }
+ }
+ else
+ {
+ // Warning
+ ::std::cerr << "Warning: Unknown configuration item " << key_val.path[0] << "." << key_val.path[1] << " in " << filename << ::std::endl;
+ }
+ }
+ else if( key_val.path[0] == "backend" )
+ {
+ check_path_length_min(key_val, 2);
+ if( key_val.path[1] == "c" )
+ {
+ check_path_length_min(key_val, 3);
+
+ if( key_val.path[2] == "variant" )
+ {
+ check_path_length(key_val, 3);
+ if( key_val.value.as_string() == "msvc" )
+ {
+ rv.m_backend_c.m_codegen_mode = CodegenMode::Msvc;
+ }
+ else if( key_val.value.as_string() == "gnu" )
+ {
+ rv.m_backend_c.m_codegen_mode = CodegenMode::Gnu11;
+ }
+ else
+ {
+ ::std::cerr << "ERROR: Unknown C variant name '" << key_val.value.as_string() << "' in " << filename << ::std::endl;
+ exit(1);
+ }
+ }
+ else if( key_val.path[2] == "target" )
+ {
+ check_path_length(key_val, 3);
+ rv.m_backend_c.m_c_compiler = key_val.value.as_string();
+ }
+ else if( key_val.path[2] == "emulate-i128" )
+ {
+ check_path_length(key_val, 3);
+ rv.m_backend_c.m_emulated_i128 = key_val.value.as_bool();
+ }
+ 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
+ {
+ ::std::cerr << "WARNING: Unknown field backend.c." << key_val.path[2] << " in " << filename << ::std::endl;
+ }
+ }
+ // Does MMIR need configuration?
+ else
+ {
+ ::std::cerr << "WARNING: Unknown configuration item backend." << key_val.path[1] << " in " << filename << ::std::endl;
+ }
+ }
+ else if( key_val.path[0] == "arch" )
+ {
+ check_path_length_min(key_val, 2);
+ if( key_val.path[1] == "name" )
+ {
+ check_path_length(key_val, 2);
+ if( rv.m_arch.m_name != "" ) {
+ ::std::cerr << "ERROR: Architecture already specified to be '" << rv.m_arch.m_name << "'" << ::std::endl;
+ exit(1);
+ }
+ rv.m_arch.m_name = key_val.value.as_string();
+ }
+ else if( key_val.path[1] == "pointer-bits" )
+ {
+ check_path_length(key_val, 2);
+ rv.m_arch.m_pointer_bits = key_val.value.as_int();
+ }
+ else if( key_val.path[1] == "is-big-endian" )
+ {
+ check_path_length(key_val, 2);
+ rv.m_arch.m_big_endian = key_val.value.as_bool();
+ }
+ else if( key_val.path[1] == "has-atomic-u8" )
+ {
+ check_path_length(key_val, 2);
+ rv.m_arch.m_atomics.u8 = key_val.value.as_bool();
+ }
+ else if( key_val.path[1] == "has-atomic-u16" )
+ {
+ check_path_length(key_val, 2);
+ rv.m_arch.m_atomics.u16 = key_val.value.as_bool();
+ }
+ else if( key_val.path[1] == "has-atomic-u32" )
+ {
+ check_path_length(key_val, 2);
+ rv.m_arch.m_atomics.u32 = key_val.value.as_bool();
+ }
+ else if( key_val.path[1] == "has-atomic-u64" )
+ {
+ check_path_length(key_val, 2);
+ rv.m_arch.m_atomics.u64 = key_val.value.as_bool();
+ }
+ else if( key_val.path[1] == "has-atomic-ptr" )
+ {
+ check_path_length(key_val, 2);
+ rv.m_arch.m_atomics.ptr = key_val.value.as_bool();
+ }
+ else if( key_val.path[1] == "alignments" )
+ {
+ check_path_length(key_val, 3);
+ if( key_val.path[2] == "u16" )
+ {
+ rv.m_arch.m_alignments.u16 = key_val.value.as_int();
+ }
+ else if( key_val.path[2] == "u32" )
+ {
+ rv.m_arch.m_alignments.u32 = key_val.value.as_int();
+ }
+ else if( key_val.path[2] == "u64" )
+ {
+ rv.m_arch.m_alignments.u64 = key_val.value.as_int();
+ }
+ else if( key_val.path[2] == "u128" )
+ {
+ rv.m_arch.m_alignments.u128 = key_val.value.as_int();
+ }
+ else if( key_val.path[2] == "f32" )
+ {
+ rv.m_arch.m_alignments.f32 = key_val.value.as_int();
+ }
+ else if( key_val.path[2] == "f64" )
+ {
+ rv.m_arch.m_alignments.f64 = key_val.value.as_int();
+ }
+ else if( key_val.path[2] == "ptr" )
+ {
+ rv.m_arch.m_alignments.ptr = key_val.value.as_int();
+ }
+ else
+ {
+ ::std::cerr << "WARNING: Unknown field arch.alignments." << key_val.path[1] << " in " << filename << ::std::endl;
+ }
+ }
+ else
+ {
+ ::std::cerr << "WARNING: Unknown field arch." << key_val.path[1] << " in " << filename << ::std::endl;
+ }
+ }
+ else
+ {
+ ::std::cerr << "WARNING: Unknown configuration item " << key_val.path[0] << " in " << filename << ::std::endl;
+ }
+ }
+ catch(const TomlValue::TypeError& e)
+ {
+ ::std::cerr << "ERROR: Invalid type for " << key_val.path << " - " << e << ::std::endl;
+ exit(1);
+ }
+ }
+
+ // TODO: Ensure that everything is set
+ if( rv.m_arch.m_name == "" ) {
+ ::std::cerr << "ERROR: Architecture not specified in " << filename << ::std::endl;
+ exit(1);
+ }
+
+ 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 = ["; for(const auto& s : spec.m_backend_c.m_compiler_opts) of << "\"" << s << "\","; of << "]\n"
+ << "linker-opts = ["; for(const auto& s : spec.m_backend_c.m_linker_opts) of << "\"" << s << "\","; of << "]\n"
+ << "\n"
+ << "[arch]\n"
+ << "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"
+ << "alignments = {"
+ << " u16 = " << static_cast<int>(spec.m_arch.m_alignments.u16 ) << ","
+ << " u32 = " << static_cast<int>(spec.m_arch.m_alignments.u32 ) << ","
+ << " u64 = " << static_cast<int>(spec.m_arch.m_alignments.u64 ) << ","
+ << " u128 = " << static_cast<int>(spec.m_arch.m_alignments.u128) << ","
+ << " f32 = " << static_cast<int>(spec.m_arch.m_alignments.f32 ) << ","
+ << " f64 = " << static_cast<int>(spec.m_arch.m_alignments.f64 ) << ","
+ << " ptr = " << static_cast<int>(spec.m_arch.m_alignments.ptr )
+ << " }\n"
+ << "\n"
+ ;
}
TargetSpec init_from_spec_name(const ::std::string& target_name)
{
- if( ::std::ifstream(target_name).is_open() )
+ // 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 )
{
return load_spec_from_file(target_name);
}
else if(target_name == "i586-linux-gnu")
{
return TargetSpec {
- "unix", "linux", "gnu", CodegenMode::Gnu11, "i586-pc-linux-gnu",
+ "unix", "linux", "gnu", {CodegenMode::Gnu11, true, "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-pc-linux-gnu",
+ "unix", "linux", "gnu", {CodegenMode::Gnu11, false, "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, true, "arm-elf-eabi", BACKEND_C_OPTS_GNU},
ARCH_ARM32
};
}
+ else if(target_name == "aarch64-linux-gnu")
+ {
+ return TargetSpec {
+ "unix", "linux", "gnu", {CodegenMode::Gnu11, false, "aarch64-linux-gnu", BACKEND_C_OPTS_GNU},
+ ARCH_ARM64
+ };
+ }
+ else if(target_name == "m68k-linux-gnu")
+ {
+ return TargetSpec {
+ "unix", "linux", "gnu", {CodegenMode::Gnu11, true, "m68k-linux-gnu", BACKEND_C_OPTS_GNU},
+ ARCH_M68K
+ };
+ }
else if(target_name == "i586-windows-gnu")
{
return TargetSpec {
- "windows", "windows", "gnu", CodegenMode::Gnu11, "mingw32",
+ "windows", "windows", "gnu", {CodegenMode::Gnu11, true, "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, false, "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, true, "x86", {}, {}},
ARCH_X86
};
}
else if (target_name == "x86_64-windows-msvc")
{
return TargetSpec {
- "windows", "windows", "msvc", CodegenMode::Msvc, "amd64",
+ "windows", "windows", "msvc", {CodegenMode::Msvc, true, "amd64", {}, {}},
ARCH_X86_64
};
}
+ else if(target_name == "i686-unknown-freebsd")
+ {
+ return TargetSpec {
+ "unix", "freebsd", "gnu", {CodegenMode::Gnu11, true, "i686-unknown-freebsd", BACKEND_C_OPTS_GNU},
+ ARCH_X86
+ };
+ }
+ else if(target_name == "x86_64-unknown-freebsd")
+ {
+ return TargetSpec {
+ "unix", "freebsd", "gnu", {CodegenMode::Gnu11, false, "x86_64-unknown-freebsd", BACKEND_C_OPTS_GNU},
+ ARCH_X86_64
+ };
+ }
+ else if(target_name == "arm-unknown-freebsd")
+ {
+ return TargetSpec {
+ "unix", "freebsd", "gnu", {CodegenMode::Gnu11, true, "arm-unknown-freebsd", BACKEND_C_OPTS_GNU},
+ ARCH_ARM32
+ };
+ }
+ else if(target_name == "aarch64-unknown-freebsd")
+ {
+ return TargetSpec {
+ "unix", "freebsd", "gnu", {CodegenMode::Gnu11, false, "aarch64-unknown-freebsd", BACKEND_C_OPTS_GNU},
+ ARCH_ARM64
+ };
+ }
else if(target_name == "x86_64-unknown-netbsd")
{
return TargetSpec {
- "unix", "netbsd", "gnu", CodegenMode::Gnu11, "x86_64-unknown-netbsd",
+ "unix", "netbsd", "gnu", {CodegenMode::Gnu11, false, "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, true, "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, false, "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, true, "arm-unknown-openbsd", BACKEND_C_OPTS_GNU},
ARCH_ARM32
};
}
+ else if(target_name == "aarch64-unknown-openbsd")
+ {
+ return TargetSpec {
+ "unix", "openbsd", "gnu", {CodegenMode::Gnu11, false, "aarch64-unknown-openbsd", BACKEND_C_OPTS_GNU},
+ ARCH_ARM64
+ };
+ }
+ else if(target_name == "x86_64-unknown-dragonfly")
+ {
+ return TargetSpec {
+ "unix", "dragonfly", "gnu", {CodegenMode::Gnu11, false, "x86_64-unknown-dragonfly", BACKEND_C_OPTS_GNU},
+ ARCH_X86_64
+ };
+ }
+ else if(target_name == "x86_64-apple-macosx")
+ {
+ // NOTE: OSX uses Mach-O binaries, which don't fully support the defaults used for GNU targets
+ return TargetSpec {
+ "unix", "macos", "gnu", {CodegenMode::Gnu11, false, "x86_64-apple-darwin", {}, {}},
+ ARCH_X86_64
+ };
+ }
else
{
::std::cerr << "Unknown target name '" << target_name << "'" << ::std::endl;
@@ -135,6 +524,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);
@@ -152,28 +545,41 @@ void Target_SetCfg(const ::std::string& target_name)
Cfg_SetFlag("linux");
Cfg_SetValue("target_vendor", "gnu");
}
- Cfg_SetValue("target_env", g_target.m_env_name);
+
+ if( g_target.m_os_name == "freebsd" )
+ {
+ Cfg_SetFlag("freebsd");
+ Cfg_SetValue("target_vendor", "unknown");
+ }
if( g_target.m_os_name == "netbsd" )
{
Cfg_SetFlag("netbsd");
Cfg_SetValue("target_vendor", "unknown");
}
- Cfg_SetValue("target_env", g_target.m_env_name);
if( g_target.m_os_name == "openbsd" )
{
Cfg_SetFlag("openbsd");
Cfg_SetValue("target_vendor", "unknown");
}
- Cfg_SetValue("target_env", g_target.m_env_name);
+ if( g_target.m_os_name == "dragonfly" )
+ {
+ Cfg_SetFlag("dragonfly");
+ Cfg_SetValue("target_vendor", "unknown");
+ }
+
+ Cfg_SetValue("target_env", g_target.m_env_name);
Cfg_SetValue("target_os", g_target.m_os_name);
Cfg_SetValue("target_pointer_width", FMT(g_target.m_arch.m_pointer_bits));
Cfg_SetValue("target_endian", g_target.m_arch.m_big_endian ? "big" : "little");
Cfg_SetValue("target_arch", g_target.m_arch.m_name);
Cfg_SetValueCb("target_has_atomic", [&](const ::std::string& s) {
if(s == "8") return g_target.m_arch.m_atomics.u8; // Has an atomic byte
+ if(s == "16") return g_target.m_arch.m_atomics.u16;
+ if(s == "32") return g_target.m_arch.m_atomics.u32;
+ if(s == "64") return g_target.m_arch.m_atomics.u64;
if(s == "ptr") return g_target.m_arch.m_atomics.ptr; // Has an atomic pointer-sized value
return false;
});
@@ -233,8 +639,9 @@ namespace {
{
case ::HIR::Struct::Repr::Packed:
packed = true;
- TODO(sp, "make_struct_repr - repr(packed)"); // needs codegen help
+ TODO(sp, "make_struct_repr - repr(packed)"); // needs codegen to know to pack the structure
break;
+ case ::HIR::Struct::Repr::Simd:
case ::HIR::Struct::Repr::C:
// No sorting, no packing
break;
@@ -314,8 +721,6 @@ const StructRepr* Target_GetStructRepr(const Span& sp, const StaticTraitResolve&
return ires.first->second.get();
}
-// TODO: Include NonZero and other repr optimisations here
-
bool Target_GetSizeAndAlignOf(const Span& sp, const StaticTraitResolve& resolve, const ::HIR::TypeRef& ty, size_t& out_size, size_t& out_align)
{
TRACE_FUNCTION_FR(ty, "size=" << out_size << ", align=" << out_align);
@@ -335,42 +740,45 @@ bool Target_GetSizeAndAlignOf(const Span& sp, const StaticTraitResolve& resolve,
case ::HIR::CoreType::U8:
case ::HIR::CoreType::I8:
out_size = 1;
- out_align = 1;
+ out_align = 1; // u8 is always 1 aligned
return true;
case ::HIR::CoreType::U16:
case ::HIR::CoreType::I16:
out_size = 2;
- out_align = 2;
+ out_align = g_target.m_arch.m_alignments.u16;
return true;
case ::HIR::CoreType::U32:
case ::HIR::CoreType::I32:
case ::HIR::CoreType::Char:
out_size = 4;
- out_align = 4;
+ out_align = g_target.m_arch.m_alignments.u32;
return true;
case ::HIR::CoreType::U64:
case ::HIR::CoreType::I64:
out_size = 8;
- out_align = 8;
+ out_align = g_target.m_arch.m_alignments.u64;
return true;
case ::HIR::CoreType::U128:
case ::HIR::CoreType::I128:
out_size = 16;
- // TODO: If i128 is emulated, this can be 8
- out_align = 16;
+ // TODO: If i128 is emulated, this can be 8 (as it is on x86, where it's actually 4 due to the above comment)
+ if( g_target.m_backend_c.m_emulated_i128 )
+ out_align = g_target.m_arch.m_alignments.u64;
+ else
+ out_align = g_target.m_arch.m_alignments.u128;
return true;
case ::HIR::CoreType::Usize:
case ::HIR::CoreType::Isize:
out_size = g_target.m_arch.m_pointer_bits / 8;
- out_align = g_target.m_arch.m_pointer_bits / 8;
+ out_align = g_target.m_arch.m_alignments.ptr;
return true;
case ::HIR::CoreType::F32:
out_size = 4;
- out_align = 4;
+ out_align = g_target.m_arch.m_alignments.f32;
return true;
case ::HIR::CoreType::F64:
out_size = 8;
- out_align = 8;
+ out_align = g_target.m_arch.m_alignments.f64;
return true;
case ::HIR::CoreType::Str:
DEBUG("sizeof on a `str` - unsized");
@@ -472,8 +880,7 @@ bool Target_GetSizeAndAlignOf(const Span& sp, const StaticTraitResolve& resolve,
return true;
),
(Closure,
- // TODO.
- DEBUG("TODO Closure - " << ty);
+ BUG(sp, "Encountered closure type at trans stage - " << ty);
)
)
return false;
@@ -557,10 +964,12 @@ namespace {
switch(str.m_repr)
{
case ::HIR::Struct::Repr::Packed:
+ // packed, not sorted
packed = true;
- TODO(sp, "make_struct_repr - repr(packed)"); // needs codegen help
+ // NOTE: codegen_c checks m_repr for packing too
break;
case ::HIR::Struct::Repr::C:
+ case ::HIR::Struct::Repr::Simd:
// No sorting, no packing
break;
case ::HIR::Struct::Repr::Rust:
@@ -580,10 +989,6 @@ namespace {
DEBUG("Can't get size/align of " << t);
return nullptr;
}
- if( size == SIZE_MAX )
- {
- TODO(sp, "Unsized type in struct - " << t);
- }
ents.push_back(Ent { idx++, size, align });
fields.push_back(TypeRepr::Field { 0, t.clone() });
}
@@ -596,9 +1001,12 @@ namespace {
if( allow_sort )
{
- // TODO: Sort by alignment then size (largest first)
- // - Requires codegen to use this information
+ // Sort by alignment then size (largest first)
// - NOTE: ?Sized fields (which includes unsized fields) MUST be at the end, even after monomorph
+ // - This means that this code needs to know if a field was ?Sized
+ // TODO: Determine if a field was from a ?Sized generic (so should be fixed as last)
+ //auto cmpfn_lt = [](const Ent& a, const Ent& b){ return a.align == b.align ? a.size < b.size : a.align < b.size; };
+ //::std::sort(ents.begin(), ents.end(), cmpfn_lt);
}
TypeRepr rv;
@@ -619,7 +1027,7 @@ namespace {
fields[e.field].offset = cur_ofs;
if( e.size == SIZE_MAX )
{
- // TODO: Ensure that this is the last item
+ // Ensure that this is the last item
ASSERT_BUG(sp, &e == &ents.back(), "Unsized item isn't the last item in " << ty);
cur_ofs = SIZE_MAX;
}
@@ -664,6 +1072,13 @@ namespace {
return true;
}
}
+ // Handle the NonZero lang item (Note: Checks just the simplepath part)
+ if( te.path.m_data.as_Generic().m_path == resolve.m_crate.get_lang_item_path(sp, "non_zero") )
+ {
+ out_path.sub_fields.push_back(0);
+ out_path.size = r->size;
+ return true;
+ }
}
} break;
TU_ARM(ty.m_data, Borrow, _te) { (void)_te;
@@ -707,6 +1122,7 @@ namespace {
{
nz_path.index = 1;
::std::reverse(nz_path.sub_fields.begin(), nz_path.sub_fields.end());
+ DEBUG("nz_path = " << nz_path.sub_fields);
size_t max_size = 0;
size_t max_align = 0;
for(auto& t : mono_types)
@@ -757,7 +1173,7 @@ namespace {
max_size ++;
}
size_t tag_size = 0;
- // TODO: repr(C) enums
+ // TODO: repr(C) enums - they have different rules
if( mono_types.size() == 0 ) {
// Unreachable
}
@@ -802,8 +1218,6 @@ namespace {
{
ASSERT_BUG(sp, max_size == 0, "Zero alignment, but non-zero size");
}
-
- // TODO: Variants.
}
} break;
TU_ARM(enm.m_data, Value, e) {