diff options
author | John Hodge <tpg@ucc.asn.au> | 2018-12-15 14:47:08 +0800 |
---|---|---|
committer | John Hodge <tpg@ucc.asn.au> | 2018-12-15 14:47:08 +0800 |
commit | f6209dce15ce863e15dc3063d78e43eeb0db25ee (patch) | |
tree | 9b041d4b32fc6907867412203db18d8c06fcf674 /src | |
parent | 539ecb375c8b86bb0b3c2d64d73dfa6d5b56c2b9 (diff) | |
download | mrust-f6209dce15ce863e15dc3063d78e43eeb0db25ee.tar.gz |
Targets - Add alignment to the target specs, along with a saveback test.
Diffstat (limited to 'src')
-rw-r--r-- | src/main.cpp | 32 | ||||
-rw-r--r-- | src/trans/codegen_c.cpp | 11 | ||||
-rw-r--r-- | src/trans/target.cpp | 137 | ||||
-rw-r--r-- | src/trans/target.hpp | 28 |
4 files changed, 147 insertions, 61 deletions
diff --git a/src/main.cpp b/src/main.cpp index 2dd05a05..a50fe095 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -36,6 +36,7 @@ bool g_debug_enabled = true; void init_debug_list() { + g_debug_disable_map.insert( "Target Load" ); g_debug_disable_map.insert( "Parse" ); g_debug_disable_map.insert( "LoadCrates" ); g_debug_disable_map.insert( "Expand" ); @@ -156,6 +157,9 @@ struct ProgramParams bool test_harness = false; + // NOTE: If populated, nothing happens except for loading the target + ::std::string target_saveback; + ::std::vector<const char*> lib_search_dirs; ::std::vector<const char*> libraries; ::std::map<::std::string, ::std::string> crate_overrides; // --extern name=path @@ -214,8 +218,21 @@ int main(int argc, char *argv[]) Cfg_SetValueCb("feature", [¶ms](const ::std::string& s) { return params.features.count(s) != 0; }); - Target_SetCfg(params.target); + CompilePhaseV("Target Load", [&]() { + Target_SetCfg(params.target); + }); + if( params.target_saveback != "") + { + Target_ExportCurSpec(params.target_saveback); + return 0; + } + + if( params.infile == "" ) + { + ::std::cerr << "No input file passed" << ::std::endl; + return 1; + } if( params.test_harness ) { @@ -1060,6 +1077,13 @@ ProgramParams::ProgramParams(int argc, char *argv[]) } this->target = argv[++i]; } + else if( strcmp(arg, "--dump-target-spec") == 0 ) { + if (i == argc - 1) { + ::std::cerr << "Flag " << arg << " requires an argument" << ::std::endl; + exit(1); + } + this->target_saveback = argv[++i]; + } else if( strcmp(arg, "--test") == 0 ) { this->test_harness = true; } @@ -1070,12 +1094,6 @@ ProgramParams::ProgramParams(int argc, char *argv[]) } } - if (this->infile == "") - { - ::std::cerr << "No input file passed" << ::std::endl; - exit(1); - } - if( const auto* a = getenv("MRUSTC_DUMP") ) { while( a[0] ) diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 55b3ea1a..84a538d5 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -205,20 +205,23 @@ namespace { m_outfile_path_c(outfile + ".c"), m_of(m_outfile_path_c) { + m_options.emulated_i128 = Target_GetCurSpec().m_backend_c.m_emulated_i128; switch(Target_GetCurSpec().m_backend_c.m_codegen_mode) { case CodegenMode::Gnu11: m_compiler = Compiler::Gcc; - m_options.emulated_i128 = false; - if( Target_GetCurSpec().m_arch.m_pointer_bits < 64 ) + if( Target_GetCurSpec().m_arch.m_pointer_bits < 64 && !m_options.emulated_i128 ) { - m_options.emulated_i128 = true; + WARNING(Span(), W0000, "Potentially misconfigured target, 32-bit targets require i128 emulation"); } m_options.disallow_empty_structs = true; break; case CodegenMode::Msvc: m_compiler = Compiler::Msvc; - m_options.emulated_i128 = true; + if( !m_options.emulated_i128 ) + { + WARNING(Span(), W0000, "Potentially misconfigured target, MSVC requires i128 emulation"); + } m_options.disallow_empty_structs = true; break; } diff --git a/src/trans/target.cpp b/src/trans/target.cpp index 64cf19c6..332a7e04 100644 --- a/src/trans/target.cpp +++ b/src/trans/target.cpp @@ -17,27 +17,32 @@ const TargetArch ARCH_X86_64 = { "x86_64", 64, false, - { /*atomic(u8)=*/true, false, true, true, true } + { /*atomic(u8)=*/true, false, true, true, true }, + { 2, 4, 8, 16, 4, 8, 8 }, }; const TargetArch ARCH_X86 = { "x86", 32, false, - { /*atomic(u8)=*/true, false, true, false, true } + { /*atomic(u8)=*/true, false, true, false, true }, + { 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 }; const TargetArch ARCH_ARM64 = { "aarch64", 64, false, - { /*atomic(u8)=*/true, true, true, true, true } + { /*atomic(u8)=*/true, true, true, true, true }, + { 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 }, + { 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 } + { /*atomic(u8)=*/true, false, true, false, true }, + { 2, 4, 8, 16, 4, 8, 4 } // TODO: Does m68k have lower alignments? }; TargetSpec g_target; @@ -159,6 +164,11 @@ namespace 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); @@ -233,6 +243,42 @@ namespace 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; @@ -290,10 +336,10 @@ namespace << "[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" + << "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]" + << "[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" @@ -302,6 +348,16 @@ namespace << "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) @@ -316,49 +372,49 @@ namespace else if(target_name == "i586-linux-gnu") { return TargetSpec { - "unix", "linux", "gnu", {CodegenMode::Gnu11, "i586-linux-gnu", BACKEND_C_OPTS_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-linux-gnu", BACKEND_C_OPTS_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", BACKEND_C_OPTS_GNU}, + "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, "aarch64-linux-gnu", BACKEND_C_OPTS_GNU}, + "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, "m68k-linux-gnu", BACKEND_C_OPTS_GNU}, + "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", BACKEND_C_OPTS_GNU}, + "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", BACKEND_C_OPTS_GNU}, + "windows", "windows", "gnu", {CodegenMode::Gnu11, false, "x86_64-w64-mingw32", BACKEND_C_OPTS_GNU}, ARCH_X86_64 }; } @@ -366,84 +422,84 @@ namespace { // 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, "i686-unknown-freebsd", BACKEND_C_OPTS_GNU}, + "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, "x86_64-unknown-freebsd", BACKEND_C_OPTS_GNU}, + "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, "arm-unknown-freebsd", BACKEND_C_OPTS_GNU}, + "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, "aarch64-unknown-freebsd", BACKEND_C_OPTS_GNU}, + "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", BACKEND_C_OPTS_GNU}, + "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", BACKEND_C_OPTS_GNU}, + "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", BACKEND_C_OPTS_GNU}, + "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", BACKEND_C_OPTS_GNU}, + "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, "aarch64-unknown-openbsd", BACKEND_C_OPTS_GNU}, + "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, "x86_64-unknown-dragonfly", BACKEND_C_OPTS_GNU}, + "unix", "dragonfly", "gnu", {CodegenMode::Gnu11, false, "x86_64-unknown-dragonfly", BACKEND_C_OPTS_GNU}, ARCH_X86_64 }; } @@ -451,7 +507,7 @@ namespace { // NOTE: OSX uses Mach-O binaries, 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, false, "x86_64-apple-darwin", {}, {}}, ARCH_X86_64 }; } @@ -684,48 +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; - // TODO: on x86, u64/i64 has an alignment of 4, while x86_64 has 8. What do other platforms have? - out_align = g_target.m_arch.m_name == "x86" ? 4 : 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 (as it is on x86, where it's actually 4 due to the above comment) - if( g_target.m_arch.m_name == "x86" ) - out_align = 4; - else if( /*g_target.m_arch.m_name == "x86_64" && */g_target.m_backend_c.m_codegen_mode == CodegenMode::Msvc ) - out_align = 8; - else - out_align = 16; + 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 = g_target.m_arch.m_name == "x86" ? 4 : 8; + out_align = g_target.m_arch.m_alignments.f64; return true; case ::HIR::CoreType::Str: DEBUG("sizeof on a `str` - unsized"); diff --git a/src/trans/target.hpp b/src/trans/target.hpp index b1ed9456..b6f04a42 100644 --- a/src/trans/target.hpp +++ b/src/trans/target.hpp @@ -17,23 +17,35 @@ enum class CodegenMode Msvc, }; +// NOTE: The default architecture is an unnamed 32-bit little-endian arch with all types natively aligned struct TargetArch { - ::std::string m_name; - unsigned m_pointer_bits; - bool m_big_endian; + ::std::string m_name = ""; + unsigned m_pointer_bits = 32; + bool m_big_endian = false; struct { - bool u8; - bool u16; - bool u32; - bool u64; - bool ptr; + bool u8 = true; + bool u16 = true; + bool u32 = true; + bool u64 = false; + bool ptr = true; } m_atomics; + + struct { + uint8_t u16 = 2; + uint8_t u32 = 4; + uint8_t u64 = 8; + uint8_t u128 = 16; + uint8_t f32 = 4; + uint8_t f64 = 8; + uint8_t ptr = 4; + } m_alignments; }; struct BackendOptsC { CodegenMode m_codegen_mode; + bool m_emulated_i128; // Influences the chosen alignment for i128/u128 ::std::string m_c_compiler; // MSVC arch / GNU triplet ::std::vector< ::std::string> m_compiler_opts; ::std::vector< ::std::string> m_linker_opts; |