summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2019-10-26 17:15:23 +0800
committerJohn Hodge <tpg@mutabah.net>2019-10-26 17:15:23 +0800
commit99904636d2e1e335238552cbb5b8b23dd06b7295 (patch)
tree5fd6470fb702b2a26253d380d47d5b6fd232607f /src
parent7ca04e2d668fa44a1663158f844cb912e396cb32 (diff)
parentebd8edeb4f1861943cc82d310564b1f592e63272 (diff)
downloadmrust-99904636d2e1e335238552cbb5b8b23dd06b7295.tar.gz
Merge remote-tracking branch 'remotes/origin/master' into nightly-1.29
Diffstat (limited to 'src')
-rw-r--r--src/ast/expr.hpp1
-rw-r--r--src/expand/derive.cpp1
-rw-r--r--src/expand/proc_macro.cpp2
-rw-r--r--src/hir/expr.hpp1
-rw-r--r--src/hir/expr_ptr.hpp2
-rw-r--r--src/hir_typeck/expr_cs.cpp8
-rw-r--r--src/hir_typeck/helpers.cpp4
-rw-r--r--src/include/span.hpp10
-rw-r--r--src/include/synext_decorator.hpp1
-rw-r--r--src/macro_rules/macro_rules_ptr.hpp2
-rw-r--r--src/macro_rules/mod.cpp6
-rw-r--r--src/macro_rules/parse.cpp1
-rw-r--r--src/main.cpp32
-rw-r--r--src/mir/cleanup.cpp2
-rw-r--r--src/parse/token.cpp1
-rw-r--r--src/parse/tokenstream.cpp2
-rw-r--r--src/rc_string.cpp4
-rw-r--r--src/span.cpp9
-rw-r--r--src/trans/codegen_c.cpp45
-rw-r--r--src/trans/codegen_mmir.cpp20
-rw-r--r--src/trans/target.cpp163
-rw-r--r--src/trans/target.hpp42
22 files changed, 253 insertions, 106 deletions
diff --git a/src/ast/expr.hpp b/src/ast/expr.hpp
index a9c82efa..6cfda001 100644
--- a/src/ast/expr.hpp
+++ b/src/ast/expr.hpp
@@ -636,6 +636,7 @@ struct ExprNode_UniOp:
class NodeVisitor
{
public:
+ virtual ~NodeVisitor() = default;
inline void visit(const unique_ptr<ExprNode>& cnode) {
if(cnode.get())
cnode->visit(*this);
diff --git a/src/expand/derive.cpp b/src/expand/derive.cpp
index 0ccda406..a14a12a3 100644
--- a/src/expand/derive.cpp
+++ b/src/expand/derive.cpp
@@ -156,6 +156,7 @@ struct DeriveOpts
/// Interface for derive handlers
struct Deriver
{
+ virtual ~Deriver() = default;
virtual const char* trait_name() const = 0;
virtual AST::Impl handle_item(Span sp, const DeriveOpts& opts, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const = 0;
virtual AST::Impl handle_item(Span sp, const DeriveOpts& opts, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const = 0;
diff --git a/src/expand/proc_macro.cpp b/src/expand/proc_macro.cpp
index 3b23184e..bc882d77 100644
--- a/src/expand/proc_macro.cpp
+++ b/src/expand/proc_macro.cpp
@@ -1008,7 +1008,7 @@ uint64_t ProcMacroInv::recv_v128u()
for(;;)
{
auto b = recv_u8();
- v |= static_cast<uint64_t>(b) << ofs;
+ v |= static_cast<uint64_t>(b & 0x7F) << ofs;
if( (b & 0x80) == 0 )
break;
ofs += 7;
diff --git a/src/hir/expr.hpp b/src/hir/expr.hpp
index 2ca960e3..c87ae3a7 100644
--- a/src/hir/expr.hpp
+++ b/src/hir/expr.hpp
@@ -821,6 +821,7 @@ struct ExprNode_Closure:
class ExprVisitor
{
public:
+ virtual ~ExprVisitor() = default;
virtual void visit_node_ptr(::std::unique_ptr<ExprNode>& node_ptr);
virtual void visit_node(ExprNode& node);
#define NV(nt) virtual void visit(nt& n) = 0;
diff --git a/src/hir/expr_ptr.hpp b/src/hir/expr_ptr.hpp
index 58fa3762..512921eb 100644
--- a/src/hir/expr_ptr.hpp
+++ b/src/hir/expr_ptr.hpp
@@ -12,7 +12,7 @@
#include <mir/mir_ptr.hpp>
-class Span;
+struct Span;
namespace HIR {
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp
index 10cb9407..8a374946 100644
--- a/src/hir_typeck/expr_cs.cpp
+++ b/src/hir_typeck/expr_cs.cpp
@@ -46,6 +46,7 @@ struct Context
class Revisitor
{
public:
+ virtual ~Revisitor() = default;
virtual const Span& span() const = 0;
virtual void fmt(::std::ostream& os) const = 0;
virtual bool revisit(Context& context, bool is_fallback) = 0;
@@ -6667,13 +6668,8 @@ namespace {
if( H::type_is_num(left) && H::type_is_num(right) ) {
DEBUG("- Magic inferrence link for binops on numerics");
context.equate_types(sp, res, left);
- const auto& right = context.get_type(v.params.m_types.at(0));
- context.equate_types_to_shadow(sp, right);
- }
- else
- {
- context.equate_types_to_shadow(sp, right);
}
+ context.equate_types_to_shadow(sp, /*right*/v.params.m_types.at(0)); // RHS, can't use `right` because it might be freed by the above equate.
}
else
{
diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp
index 08e817de..010df546 100644
--- a/src/hir_typeck/helpers.cpp
+++ b/src/hir_typeck/helpers.cpp
@@ -636,7 +636,7 @@ void HMTypeInferrence::set_ivar_to(unsigned int slot, ::HIR::TypeRef type)
}
else
#endif
- root_ivar.type = box$( mv$(type) );
+ root_ivar.type = box$( type );
}
this->mark_change();
@@ -1648,7 +1648,7 @@ bool TraitResolution::has_associated_type(const ::HIR::TypeRef& input) const
//TRACE_FUNCTION_F(input);
TU_MATCH(::HIR::TypeRef::Data, (input.m_data), (e),
(Infer,
- auto& ty = this->m_ivars.get_type(input);
+ const auto& ty = this->m_ivars.get_type(input);
if( ty != input ) {
return this->has_associated_type(ty);
}
diff --git a/src/include/span.hpp b/src/include/span.hpp
index 51c3440c..970a2ad0 100644
--- a/src/include/span.hpp
+++ b/src/include/span.hpp
@@ -29,9 +29,9 @@ struct ProtoSpan
unsigned int start_line;
unsigned int start_ofs;
};
-class Span
+struct Span
{
-public:
+//public:
::std::shared_ptr<Span> outer_span; // Expansion target for macros
RcString filename;
@@ -47,10 +47,14 @@ public:
end_line(end_line),
end_ofs(end_ofs)
{}
- Span(const Span& x);
+ Span(const Span& x) = default;
+ Span(Span&& x) = default;
Span(const Position& position);
Span();
+ Span& operator=(const Span& x) = default;
+ Span& operator=(Span&& x) = default;
+
void bug(::std::function<void(::std::ostream&)> msg) const;
void error(ErrorType tag, ::std::function<void(::std::ostream&)> msg) const;
void warning(WarningType tag, ::std::function<void(::std::ostream&)> msg) const;
diff --git a/src/include/synext_decorator.hpp b/src/include/synext_decorator.hpp
index c910f6c0..88a6258c 100644
--- a/src/include/synext_decorator.hpp
+++ b/src/include/synext_decorator.hpp
@@ -46,6 +46,7 @@ class ExpandDecorator
{
void unexpected(const Span& sp, const AST::Attribute& mi, const char* loc_str) const;
public:
+ virtual ~ExpandDecorator() = default;
virtual AttrStage stage() const = 0;
virtual void handle(const Span& sp, const AST::Attribute& mi, AST::Crate& crate) const { unexpected(sp, mi, "crate"); }
diff --git a/src/macro_rules/macro_rules_ptr.hpp b/src/macro_rules/macro_rules_ptr.hpp
index fdb01fbe..5dbfd032 100644
--- a/src/macro_rules/macro_rules_ptr.hpp
+++ b/src/macro_rules/macro_rules_ptr.hpp
@@ -14,7 +14,7 @@ class MacroRulesPtr
MacroRules* m_ptr;
public:
MacroRulesPtr(): m_ptr(nullptr) {}
- MacroRulesPtr(MacroRules* p): m_ptr(p) {}
+ MacroRulesPtr(MacroRules* p);
MacroRulesPtr(MacroRulesPtr&& x):
m_ptr(x.m_ptr)
{
diff --git a/src/macro_rules/mod.cpp b/src/macro_rules/mod.cpp
index e9ecb504..2ad325b8 100644
--- a/src/macro_rules/mod.cpp
+++ b/src/macro_rules/mod.cpp
@@ -168,10 +168,16 @@ bool is_token_vis(eTokenType tt) {
}
}
+MacroRulesPtr::MacroRulesPtr(MacroRules* p):
+ m_ptr(p)
+{
+ //::std::cout << "MRP new " << m_ptr << ::std::endl;
+}
MacroRulesPtr::~MacroRulesPtr()
{
if(m_ptr)
{
+ //::std::cout << "MRP delete " << m_ptr << ::std::endl;
delete m_ptr;
m_ptr = nullptr;
}
diff --git a/src/macro_rules/parse.cpp b/src/macro_rules/parse.cpp
index 43ffb097..6a476ef1 100644
--- a/src/macro_rules/parse.cpp
+++ b/src/macro_rules/parse.cpp
@@ -265,6 +265,7 @@ MacroRule Parse_MacroRules_Var(TokenStream& lex)
{
case TOK_BRACE_OPEN: close = TOK_BRACE_CLOSE; break;
case TOK_PAREN_OPEN: close = TOK_PAREN_CLOSE; break;
+ case TOK_SQUARE_OPEN: close = TOK_SQUARE_CLOSE; break;
default:
throw ParseError::Unexpected(lex, tok);
}
diff --git a/src/main.cpp b/src/main.cpp
index 0efddc5f..c722bc73 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -38,6 +38,7 @@ TargetVersion gTargetVersion = TargetVersion::Rustc1_29;
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" );
@@ -159,6 +160,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
@@ -217,8 +221,21 @@ int main(int argc, char *argv[])
Cfg_SetValueCb("feature", [&params](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 )
{
@@ -1100,6 +1117,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;
}
@@ -1110,12 +1134,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_TARGET_VER") )
{
diff --git a/src/mir/cleanup.cpp b/src/mir/cleanup.cpp
index ef2a24aa..6b8bcf79 100644
--- a/src/mir/cleanup.cpp
+++ b/src/mir/cleanup.cpp
@@ -1264,7 +1264,7 @@ void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path,
void MIR_CleanupCrate(::HIR::Crate& crate)
{
- ::MIR::OuterVisitor ov { crate, [&](const auto& res, const auto& p, auto& expr_ptr, const auto& args, const auto& ty){
+ ::MIR::OuterVisitor ov { crate, [&](const auto& res, const auto& p, ::HIR::ExprPtr& expr_ptr, const auto& args, const auto& ty){
MIR_Cleanup(res, p, expr_ptr.get_mir_or_error_mut(Span()), args, ty);
} };
ov.visit_crate(crate);
diff --git a/src/parse/token.cpp b/src/parse/token.cpp
index 900108ab..f9ecd028 100644
--- a/src/parse/token.cpp
+++ b/src/parse/token.cpp
@@ -229,6 +229,7 @@ Token Token::clone() const
BUG(m_pos, "Fragment with invalid token type (" << *this << ")");
break;
}
+ assert(rv.m_data.is_Fragment());
)
)
return rv;
diff --git a/src/parse/tokenstream.cpp b/src/parse/tokenstream.cpp
index 957bc673..6f0c57a1 100644
--- a/src/parse/tokenstream.cpp
+++ b/src/parse/tokenstream.cpp
@@ -125,7 +125,7 @@ ProtoSpan TokenStream::start_span() const
Span TokenStream::end_span(ProtoSpan ps) const
{
auto p = this->getPosition();
- auto rv = Span( ps.filename, ps.start_line, ps.start_ofs, p.line, p.ofs );
+ auto rv = Span( ::std::move(ps.filename), ps.start_line, ps.start_ofs, p.line, p.ofs );
rv.outer_span = this->outerSpan();
return rv;
}
diff --git a/src/rc_string.cpp b/src/rc_string.cpp
index 260ba90a..b56f2e62 100644
--- a/src/rc_string.cpp
+++ b/src/rc_string.cpp
@@ -23,6 +23,8 @@ RcString::RcString(const char* s, unsigned int len):
for(unsigned int j = 0; j < len; j ++ )
data_mut[j] = s[j];
data_mut[len] = '\0';
+
+ //::std::cout << "RcString(" << m_ptr << " \"" << *this << "\") - " << *m_ptr << " (creation)" << ::std::endl;
}
}
RcString::~RcString()
@@ -30,7 +32,7 @@ RcString::~RcString()
if(m_ptr)
{
*m_ptr -= 1;
- //::std::cout << "RcString(\"" << *this << "\") - " << *m_ptr << " refs left" << ::std::endl;
+ //::std::cout << "RcString(" << m_ptr << " \"" << *this << "\") - " << *m_ptr << " refs left (drop)" << ::std::endl;
if( *m_ptr == 0 )
{
delete[] m_ptr;
diff --git a/src/span.cpp b/src/span.cpp
index 035258d6..7e3968d1 100644
--- a/src/span.cpp
+++ b/src/span.cpp
@@ -11,15 +11,6 @@
#include <parse/lex.hpp>
#include <common.hpp>
-Span::Span(const Span& x):
- outer_span(x.outer_span),
- filename(x.filename),
- start_line(x.start_line),
- start_ofs(x.start_ofs),
- end_line(x.end_line),
- end_ofs(x.end_ofs)
-{
-}
Span::Span(const Position& pos):
outer_span(),
filename(pos.filename),
diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp
index 8ecf988a..8a392f86 100644
--- a/src/trans/codegen_c.cpp
+++ b/src/trans/codegen_c.cpp
@@ -200,20 +200,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;
}
@@ -297,7 +300,7 @@ namespace {
// 64-bit bit ops (gcc intrinsics)
m_of
<< "static inline uint64_t __builtin_clz64(uint64_t v) {\n"
- << "\treturn (v >> 32 != 0 ? __builtin_clz(v>>32) : 32 + __builtin_clz(v));\n"
+ << "\treturn ( (v >> 32) != 0 ? __builtin_clz(v>>32) : 32 + __builtin_clz(v));\n"
<< "}\n"
<< "static inline uint64_t __builtin_ctz64(uint64_t v) {\n"
<< "\treturn ((v&0xFFFFFFFF) == 0 ? __builtin_ctz(v>>32) + 32 : __builtin_ctz(v));\n"
@@ -322,10 +325,10 @@ namespace {
<< "static inline uint64_t __builtin_popcount(uint64_t v) {\n"
<< "\treturn (v >> 32 != 0 ? __popcnt64(v>>32) : 32 + __popcnt64(v));\n"
<< "}\n"
- << "static inline int __builtin_ctz(uint32_t v) { int rv; _BitScanReverse(&rv, v); return rv; }\n"
- << "static inline int __builtin_clz(uint32_t v) { int rv; _BitScanForward(&rv, v); return rv; }\n"
+ << "static inline int __builtin_ctz(uint32_t v) { int rv; _BitScanForward(&rv, v); return rv; }\n"
+ << "static inline int __builtin_clz(uint32_t v) { int rv; _BitScanReverse(&rv, v); return 31 - rv; }\n"
<< "static inline uint64_t __builtin_clz64(uint64_t v) {\n"
- << "\treturn (v >> 32 != 0 ? __builtin_clz(v>>32) : 32 + __builtin_clz(v));\n"
+ << "\treturn ( (v >> 32) != 0 ? __builtin_clz(v>>32) : 32 + __builtin_clz(v) );\n"
<< "}\n"
<< "static inline uint64_t __builtin_ctz64(uint64_t v) {\n"
<< "\treturn ((v&0xFFFFFFFF) == 0 ? __builtin_ctz(v>>32) + 32 : __builtin_ctz(v));\n"
@@ -776,13 +779,14 @@ namespace {
if( getenv(varname.c_str()) ) {
args.push_back( getenv(varname.c_str()) );
}
+ else if (system(("which " + Target_GetCurSpec().m_backend_c.m_c_compiler + "-gcc" + " >/dev/null 2>&1").c_str()) == 0) {
+ args.push_back( Target_GetCurSpec().m_backend_c.m_c_compiler + "-gcc" );
+ }
else if( getenv("CC") ) {
args.push_back( getenv("CC") );
}
else {
- // TODO: Determine if the compiler can't be found, and fall back to `gcc` if that's the case
- args.push_back( Target_GetCurSpec().m_backend_c.m_c_compiler + "-gcc" );
- //args.push_back( "gcc" );
+ args.push_back("gcc");
}
}
for( const auto& a : Target_GetCurSpec().m_backend_c.m_compiler_opts )
@@ -1561,7 +1565,7 @@ namespace {
assert(1 + union_fields.size() + 1 >= repr->fields.size());
// Make the union!
// NOTE: The way the structure generation works is that enum variants are always first, so the field index = the variant index
- // TODO:
+ // TODO:
if( !this->type_is_bad_zst(repr->fields[0].ty) || ::std::any_of(union_fields.begin(), union_fields.end(), [this,repr](auto x){ return !this->type_is_bad_zst(repr->fields[x].ty); }) )
{
m_of << "\tunion {\n";
@@ -2176,7 +2180,11 @@ namespace {
(String,
m_of << "{ ";
this->print_escaped_string(e);
- m_of << ", " << e.size() << "}";
+ // TODO: Better type checking?
+ if( !ty.m_data.is_Array() ) {
+ m_of << ", " << e.size();
+ }
+ m_of << "}";
)
)
}
@@ -2219,9 +2227,8 @@ namespace {
m_of << "\\x0" << (unsigned int)static_cast<uint8_t>(v);
else
m_of << "\\x" << (unsigned int)static_cast<uint8_t>(v);
- // If the next character is a hex digit,
- // close/reopen the string.
- if( isxdigit(*(&v+1)) )
+ // If the next character is a hex digit, close/reopen the string.
+ if( &v < &s.back() && isxdigit(*(&v+1)) )
m_of << "\"\"";
}
}
@@ -3927,7 +3934,7 @@ namespace {
m_of << "(";
for(unsigned int j = 0; j < e.args.size(); j ++) {
if(j != 0) m_of << ",";
- m_of << " ";
+ m_of << " ";
if( m_options.disallow_empty_structs && TU_TEST1(e.args[j], LValue, .is_Field()) )
{
::HIR::TypeRef tmp;
@@ -4176,7 +4183,7 @@ namespace {
void emit_intrinsic_call(const RcString& name, const ::HIR::PathParams& params, const ::MIR::Terminator::Data_Call& e)
{
const auto& mir_res = *m_mir_res;
- enum class Ordering
+ enum class Ordering
{
SeqCst,
Acquire,
@@ -4341,7 +4348,7 @@ namespace {
m_of << "*(volatile uint8_t*)";
else
m_of << "*(volatile int8_t*)";
- emit_param(e.args.at(0));
+ emit_param(e.args.at(0));
switch(op)
{
case AtomicOp::Add: m_of << " += "; break;
diff --git a/src/trans/codegen_mmir.cpp b/src/trans/codegen_mmir.cpp
index 97ac00eb..58739805 100644
--- a/src/trans/codegen_mmir.cpp
+++ b/src/trans/codegen_mmir.cpp
@@ -20,6 +20,14 @@ namespace
{
size_t PTR_BASE = 0x1000; // See matching value in standalone_miri value.hpp
+ size_t Target_GetSizeOf_Required(const Span& sp, const StaticTraitResolve& resolve, const ::HIR::TypeRef& ty)
+ {
+ size_t size;
+ bool type_has_size = Target_GetSizeOf(sp, resolve, ty, size);
+ ASSERT_BUG(sp, type_has_size, "Attempting to get the size of a unsized type");
+ return size;
+ }
+
template<typename T>
struct Fmt
{
@@ -874,8 +882,7 @@ namespace
cur_ofs ++;
}
emit_literal_as_bytes(le[i], repr->fields[i].ty, out_relocations, base_ofs + cur_ofs);
- size_t size;
- assert(Target_GetSizeOf(sp, m_resolve, repr->fields[i].ty, size));
+ size_t size = Target_GetSizeOf_Required(sp, m_resolve, repr->fields[i].ty);
cur_ofs += size;
}
while(cur_ofs < repr->size)
@@ -898,8 +905,7 @@ namespace
emit_literal_as_bytes(*le.val, repr->fields[le.idx].ty, out_relocations, base_ofs + cur_ofs);
- size_t size;
- assert(Target_GetSizeOf(sp, m_resolve, repr->fields[le.idx].ty, size));
+ size_t size = Target_GetSizeOf_Required(sp, m_resolve, repr->fields[le.idx].ty);
cur_ofs += size;
}
@@ -914,8 +920,7 @@ namespace
auto v = ::HIR::Literal::make_Integer(le.idx);
emit_literal_as_bytes(v, repr->fields[ve->field.index].ty, out_relocations, base_ofs + cur_ofs);
- size_t size;
- assert(Target_GetSizeOf(sp, m_resolve, repr->fields[ve->field.index].ty, size));
+ size_t size = Target_GetSizeOf_Required(sp, m_resolve, repr->fields[ve->field.index].ty);
cur_ofs += size;
}
// TODO: Nonzero?
@@ -989,8 +994,7 @@ namespace
for(const auto& v : lit.as_List())
{
emit_literal_as_bytes(v, *te.inner, out_relocations, base_ofs);
- size_t size;
- assert(Target_GetSizeOf(sp, m_resolve, *te.inner, size));
+ size_t size = Target_GetSizeOf(sp, m_resolve, *te.inner, size);
base_ofs += size;
}
} break;
diff --git a/src/trans/target.cpp b/src/trans/target.cpp
index 5f52912e..9172481a 100644
--- a/src/trans/target.cpp
+++ b/src/trans/target.cpp
@@ -17,22 +17,32 @@
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)
};
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
};
const TargetArch ARCH_ARM64 = {
"aarch64",
64, false,
- { /*atomic(u8)=*/true, true, true, true, true }
+ { /*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;
@@ -108,6 +118,10 @@ namespace
{
rv.m_arch = ARCH_X86_64;
}
+ else if( key_val.value.as_string() == ARCH_M68K.m_name )
+ {
+ rv.m_arch = ARCH_M68K;
+ }
else
{
// Error.
@@ -150,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);
@@ -224,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;
@@ -281,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"
@@ -293,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)
@@ -307,42 +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, 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
};
}
@@ -350,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
};
}
@@ -435,7 +507,21 @@ 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
+ };
+ }
+ else if(target_name == "arm-unknown-haiku")
+ {
+ return TargetSpec {
+ "unix", "haiku", "gnu", {CodegenMode::Gnu11, true, "arm-unknown-haiku", {}, {}},
+ ARCH_ARM32
+ };
+ }
+ else if(target_name == "x86_64-unknown-haiku")
+ {
+ return TargetSpec {
+ "unix", "haiku", "gnu", {CodegenMode::Gnu11, false, "x86_64-unknown-haiku", {}, {}},
ARCH_X86_64
};
}
@@ -536,48 +622,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 107d19e1..3433483b 100644
--- a/src/trans/target.hpp
+++ b/src/trans/target.hpp
@@ -17,23 +17,53 @@ 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;
- struct {
- bool u8;
- bool u16;
- bool u32;
- bool u64;
- bool ptr;
+ struct Atomics {
+ bool u8 = true;
+ bool u16 = true;
+ bool u32 = true;
+ bool u64 = false;
+ bool ptr = true;
+ Atomics(bool u8 = true, bool u16 = true, bool u32 = true, bool u64 = false, bool ptr = true)
+ :u8(u8)
+ ,u16(u16)
+ ,u32(u32)
+ ,u64(u64)
+ ,ptr(ptr)
+ {
+ }
} m_atomics;
+
+ struct Alignments {
+ uint8_t u16;
+ uint8_t u32;
+ uint8_t u64;
+ uint8_t u128;
+ uint8_t f32;
+ uint8_t f64;
+ uint8_t ptr;
+ Alignments(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)
+ :u16 (u16)
+ ,u32 (u32 )
+ ,u64 (u64 )
+ ,u128(u128)
+ ,f32 (f32 )
+ ,f64 (f64 )
+ ,ptr (ptr )
+ {
+ }
+ } 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;