summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2017-07-08 18:09:35 +0800
committerJohn Hodge <tpg@mutabah.net>2017-07-08 18:09:35 +0800
commit4a954d768f5d314133e85629546fdb4a4f587d2d (patch)
tree2e498bc166b5809fe1d8afc879b92033760ff86b /src
parent029dd3f14422f0587b63e33781afe072bafc094a (diff)
downloadmrust-4a954d768f5d314133e85629546fdb4a4f587d2d.tar.gz
Codegen+Loading - MSVC support draft (libcore compiles, doesn't load)
Diffstat (limited to 'src')
-rw-r--r--src/hir/deserialise.cpp13
-rw-r--r--src/hir/serialise_lowlevel.cpp10
-rw-r--r--src/mir/helpers.cpp9
-rw-r--r--src/mir/helpers.hpp1
-rw-r--r--src/trans/codegen_c.cpp724
-rw-r--r--src/trans/target.cpp2
6 files changed, 628 insertions, 131 deletions
diff --git a/src/hir/deserialise.cpp b/src/hir/deserialise.cpp
index 3cb58a2e..2e05cac1 100644
--- a/src/hir/deserialise.cpp
+++ b/src/hir/deserialise.cpp
@@ -5,7 +5,7 @@
* hir/serialise.cpp
* - HIR (De)Serialisation for crate metadata
*/
-#define DISABLE_DEBUG // Disable debug for this function - too hot
+//#define DISABLE_DEBUG // Disable debug for this function - too hot
#include "hir.hpp"
#include "main_bindings.hpp"
#include <serialiser_texttree.hpp>
@@ -1132,17 +1132,22 @@ namespace {
::HIR::CratePtr HIR_Deserialise(const ::std::string& filename, const ::std::string& loaded_name)
{
- ::HIR::serialise::Reader in { filename };
- HirDeserialiser s { loaded_name, in };
-
try
{
+ ::HIR::serialise::Reader in{ filename };
+ HirDeserialiser s { loaded_name, in };
+
::HIR::Crate rv = s.deserialise_crate();
return ::HIR::CratePtr( mv$(rv) );
}
catch(int)
{ ::std::abort(); }
+ catch(const ::std::runtime_error& e)
+ {
+ ::std::cerr << "Unable to deserialise crate metadata from " << filename << ": " << e.what() << ::std::endl;
+ ::std::abort();
+ }
#if 0
catch(const char*)
{
diff --git a/src/hir/serialise_lowlevel.cpp b/src/hir/serialise_lowlevel.cpp
index a3bb3870..19e8c6b4 100644
--- a/src/hir/serialise_lowlevel.cpp
+++ b/src/hir/serialise_lowlevel.cpp
@@ -43,7 +43,7 @@ void Writer::write(const void* buf, size_t len)
WriterInner::WriterInner(const ::std::string& filename):
- m_backing( filename ),
+ m_backing( filename, ::std::ios_base::out | ::std::ios_base::binary),
m_zstream(),
m_buffer( 16*1024 )
//m_buffer( 4*1024 )
@@ -177,7 +177,7 @@ size_t ReadBuffer::read(void* dst, size_t len)
void ReadBuffer::populate(ReaderInner& is)
{
m_backing.resize( m_backing.capacity(), 0 );
- auto len = is.read(m_backing.data(), m_backing.capacity());
+ auto len = is.read(m_backing.data(), m_backing.size());
m_backing.resize( len );
m_ofs = 0;
}
@@ -217,10 +217,14 @@ void Reader::read(void* buf, size_t len)
ReaderInner::ReaderInner(const ::std::string& filename):
- m_backing(filename),
+ m_backing(filename, ::std::ios_base::in|::std::ios_base::binary),
m_zstream(),
m_buffer(16*1024)
{
+ ::std::memset(&m_zstream, 0, sizeof m_zstream);
+ if( !m_backing.is_open() )
+ throw ::std::runtime_error("Unable to open file");
+
m_zstream.zalloc = Z_NULL;
m_zstream.zfree = Z_NULL;
m_zstream.opaque = Z_NULL;
diff --git a/src/mir/helpers.cpp b/src/mir/helpers.cpp
index e51c9180..b90f3cf6 100644
--- a/src/mir/helpers.cpp
+++ b/src/mir/helpers.cpp
@@ -251,6 +251,15 @@ const ::HIR::TypeRef& ::MIR::TypeResolve::get_lvalue_type(::HIR::TypeRef& tmp, c
)
throw "";
}
+const ::HIR::TypeRef& MIR::TypeResolve::get_param_type(::HIR::TypeRef& tmp, const ::MIR::Param& val) const
+{
+ if (const auto* p = val.opt_LValue()) {
+ return get_lvalue_type(tmp, *p);
+ }
+ else {
+ return tmp = get_const_type(val.as_Constant());
+ }
+}
::HIR::TypeRef MIR::TypeResolve::get_const_type(const ::MIR::Constant& c) const
{
diff --git a/src/mir/helpers.hpp b/src/mir/helpers.hpp
index f241753e..12fd4ddf 100644
--- a/src/mir/helpers.hpp
+++ b/src/mir/helpers.hpp
@@ -101,6 +101,7 @@ public:
const ::HIR::TypeRef& get_static_type(::HIR::TypeRef& tmp, const ::HIR::Path& path) const;
const ::HIR::TypeRef& get_lvalue_type(::HIR::TypeRef& tmp, const ::MIR::LValue& val) const;
+ const ::HIR::TypeRef& get_param_type(::HIR::TypeRef& tmp, const ::MIR::Param& val) const;
::HIR::TypeRef get_const_type(const ::MIR::Constant& c) const;
diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp
index 24930378..4eda24ac 100644
--- a/src/trans/codegen_c.cpp
+++ b/src/trans/codegen_c.cpp
@@ -69,6 +69,32 @@ namespace {
}
namespace {
+ struct MsvcDetection
+ {
+ ::std::string path_vcvarsall;
+ };
+
+ MsvcDetection detect_msvc()
+ {
+ auto rv = MsvcDetection {
+ "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\vcvarsall.bat"
+ };
+ if( ::std::ifstream("P:\\Program Files (x86)\\Microsoft Visual Studio\\VS2015\\VC\\vcvarsall.bat").is_open() )
+ {
+ rv.path_vcvarsall = "P:\\Program Files (x86)\\Microsoft Visual Studio\\VS2015\\VC\\vcvarsall.bat";
+ }
+ return rv;
+ }
+
+ enum class AtomicOp
+ {
+ Add,
+ Sub,
+ And,
+ Or,
+ Xor
+ };
+
class CodeGenerator_C:
public CodeGenerator
{
@@ -100,6 +126,9 @@ namespace {
const ::MIR::TypeResolve* m_mir_res;
Compiler m_compiler = Compiler::Gcc;
+ struct {
+ bool emulated_i128 = false;
+ } m_options;
::std::map<::HIR::GenericPath, ::std::vector<unsigned>> m_enum_repr_cache;
@@ -116,9 +145,11 @@ namespace {
{
case CodegenMode::Gnu11:
m_compiler = Compiler::Gcc;
+ m_options.emulated_i128 = false;
break;
case CodegenMode::Msvc:
m_compiler = Compiler::Msvc;
+ m_options.emulated_i128 = true;
break;
}
@@ -167,12 +198,60 @@ namespace {
case Compiler::Msvc:
m_of << "__declspec(noreturn) extern void _Unwind_Resume(void);\n";
//case Compilter::Std11:
+ break;
+ }
+
+ if( m_options.emulated_i128 )
+ {
m_of
- << "typedef unsigned _int128 uint128_t;\n"
- << "typedef signed _int128 int128_t;\n"
+ << "typedef struct { uint64_t lo, hi; } uint128_t;\n"
+ << "typedef struct { uint64_t lo, hi; } int128_t;\n"
+ << "int128_t make128s(int64_t v) { int128_t rv = { v, (v < 0 ? -1 : 0) }; return rv; }\n"
+ << "int128_t add128s(int128_t a, int128_t b) { int128_t v; v.lo = a.lo + b.lo; v.hi = a.hi + b.hi + (v.lo < a.lo ? 1 : 0); return v; }\n"
+ << "int128_t sub128s(int128_t a, int128_t b) { int128_t v; v.lo = a.lo - b.lo; v.hi = a.hi - b.hi - (v.lo > a.lo ? 1 : 0); return v; }\n"
+ << "int128_t mul128s(int128_t a, int128_t b) { abort(); }\n"
+ << "int128_t div128s(int128_t a, int128_t b) { abort(); }\n"
+ << "int128_t mod128s(int128_t a, int128_t b) { abort(); }\n"
+ << "int128_t and128s(int128_t a, int128_t b) { int128_t v = { a.lo & b.lo, a.hi & b.hi }; return v; }\n"
+ << "int128_t or128s (int128_t a, int128_t b) { int128_t v = { a.lo | b.lo, a.hi | b.hi }; return v; }\n"
+ << "int128_t xor128s(int128_t a, int128_t b) { int128_t v = { a.lo ^ b.lo, a.hi ^ b.hi }; return v; }\n"
+ << "int128_t shl128s(int128_t a, uint32_t b) { int128_t v; if(b < 64) { v.lo = a.lo << b; v.hi = (a.hi << b) | (a.lo >> (64 - b)); } else { v.hi = a.lo << (b - 64); v.lo = 0; } return v; }\n"
+ << "int128_t shr128s(int128_t a, uint32_t b) { int128_t v; if(b < 64) { v.lo = (a.lo >> b)|(a.hi << (64 - b)); v.hi = a.hi >> b; } else { v.lo = a.hi >> (b - 64); v.hi = 0; } return v; }\n"
+ << "uint128_t make128(uint64_t v) { uint128_t rv = { v, 0 }; return rv; }\n"
+ << "uint128_t add128(uint128_t a, uint128_t b) { uint128_t v; v.lo = a.lo + b.lo; v.hi = a.hi + b.hi + (v.lo < a.lo ? 1 : 0); return v; }\n"
+ << "uint128_t sub128(uint128_t a, uint128_t b) { uint128_t v; v.lo = a.lo - b.lo; v.hi = a.hi - b.hi - (v.lo > a.lo ? 1 : 0); return v; }\n"
+ << "uint128_t mul128(uint128_t a, uint128_t b) { abort(); }\n"
+ << "uint128_t div128(uint128_t a, uint128_t b) { abort(); }\n"
+ << "uint128_t mod128(uint128_t a, uint128_t b) { abort(); }\n"
+ << "uint128_t and128(uint128_t a, uint128_t b) { uint128_t v = { a.lo & b.lo, a.hi & b.hi }; return v; }\n"
+ << "uint128_t or128 (uint128_t a, uint128_t b) { uint128_t v = { a.lo | b.lo, a.hi | b.hi }; return v; }\n"
+ << "uint128_t xor128(uint128_t a, uint128_t b) { uint128_t v = { a.lo ^ b.lo, a.hi ^ b.hi }; return v; }\n"
+ << "uint128_t shl128(uint128_t a, uint32_t b) { uint128_t v; if(b < 64) { v.lo = a.lo << b; v.hi = (a.hi << b) | (a.lo >> (64 - b)); } else { v.hi = a.lo << (b - 64); v.lo = 0; } return v; }\n"
+ << "uint128_t shr128(uint128_t a, uint32_t b) { uint128_t v; if(b < 64) { v.lo = (a.lo >> b)|(a.hi << (64 - b)); v.hi = a.hi >> b; } else { v.lo = a.hi >> (b - 64); v.hi = 0; } return v; }\n"
+ << "uint128_t popcount128(uint128_t a) { uint128_t v = { __builtin_popcount(a.lo) + __builtin_popcount(a.hi), 0 }; return v; }"
+ << "static inline uint128_t __builtin_bswap128(uint128_t v) { uint128_t rv = { __builtin_bswap64(v.hi), __builtin_bswap64(v.lo) }; return rv; }\n"
+ << "static inline uint128_t intrinsic_ctlz_u128(uint128_t v) {\n"
+ << "\tuint128_t rv = { (v.hi != 0 ? __builtin_clz64(v.hi) : (v.lo != 0 ? 64 + __builtin_clz64(v.lo) : 128)), 0 };\n"
+ << "\treturn rv;\n"
+ << "}\n"
+ << "static inline uint128_t intrinsic_cttz_u128(uint128_t v) {\n"
+ << "\tuint128_t rv = { (v.lo == 0 ? (v.hi == 0 ? 128 : __builtin_ctz64(v.hi) + 64) : __builtin_ctz64(v.lo)), 0 };\n"
+ << "\treturn rv;\n"
+ << "}\n"
;
- break;
}
+ else
+ {
+ m_of
+ << "static inline uint128_t intrinsic_ctlz_u128(uint128_t v) {\n"
+ << "\treturn (v == 0 ? 128 : (v >> 64 != 0 ? __builtin_clz64(v>>64) : 64 + __builtin_clz64(v)));\n"
+ << "}\n"
+ << "static inline uint128_t intrinsic_cttz_u128(uint128_t v) {\n"
+ << "\treturn (v == 0 ? 128 : ((v&0xFFFFFFFFFFFFFFFF) == 0 ? __builtin_ctz64(v>>64) + 64 : __builtin_ctz64(v)));\n"
+ << "}\n"
+ ;
+ }
+
// Common helpers
m_of
<< "\n"
@@ -186,7 +265,7 @@ namespace {
<< "static inline SLICE_PTR make_sliceptr(void* ptr, size_t s) { SLICE_PTR rv = { ptr, s }; return rv; }\n"
<< "static inline TRAITOBJ_PTR make_traitobjptr(void* ptr, void* vt) { TRAITOBJ_PTR rv = { ptr, vt }; return rv; }\n"
<< "\n"
- << "static inline size_t max(size_t a, size_t b) { return a < b ? b : a; }\n"
+ << "static inline size_t mrustc_max(size_t a, size_t b) { return a < b ? b : a; }\n"
<< "static inline void noop_drop(void *p) {}\n"
<< "\n"
;
@@ -204,7 +283,7 @@ namespace {
;
// u128/i128 ops (gcc intrinsics)
m_of
- << "static inline unsigned __int128 __builtin_bswap128(uint128_t v) {\n"
+ << "static inline uint128_t __builtin_bswap128(uint128_t v) {\n"
<< "\tuint64_t lo = __builtin_bswap64((uint64_t)v);\n"
<< "\tuint64_t hi = __builtin_bswap64((uint64_t)(v>>64));\n"
<< "\treturn ((uint128_t)lo << 64) | (uint128_t)hi;\n"
@@ -315,7 +394,7 @@ namespace {
break;
case Compiler::Msvc:
is_windows = true;
- args.push_back("C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\vcvarsall.bat");
+ args.push_back(cache_str( detect_msvc().path_vcvarsall ));
args.push_back("&");
args.push_back("cl.exe");
args.push_back(m_outfile_path_c.c_str());
@@ -1040,12 +1119,17 @@ namespace {
{
::MIR::TypeResolve top_mir_res { sp, m_resolve, FMT_CB(ss, ss << "extern static " << p;), ::HIR::TypeRef(), {}, *(::MIR::Function*)nullptr };
m_mir_res = &top_mir_res;
-
TRACE_FUNCTION_F(p);
+
+ if( item.m_linkage.name != "" && m_compiler != Compiler::Gcc )
+ {
+ m_of << "#define " << Trans_Mangle(p) << " " << item.m_linkage.name << "\n";
+ }
+
auto type = params.monomorph(m_resolve, item.m_type);
m_of << "extern ";
emit_ctype( type, FMT_CB(ss, ss << Trans_Mangle(p);) );
- if( item.m_linkage.name != "" )
+ if( item.m_linkage.name != "" && m_compiler == Compiler::Gcc)
{
m_of << " asm(\"" << item.m_linkage.name << "\")";
}
@@ -1228,10 +1312,12 @@ namespace {
m_of << ::std::hex << "0x" << (e & 0xFFFFFFFF) << ::std::dec;
break;
case ::HIR::CoreType::U64:
- case ::HIR::CoreType::U128:
case ::HIR::CoreType::Usize:
m_of << ::std::hex << "0x" << e << ::std::dec;
break;
+ case ::HIR::CoreType::U128:
+ m_of << ::std::hex << "0x" << e << ::std::dec;
+ break;
case ::HIR::CoreType::I8:
m_of << static_cast<uint16_t>( static_cast<int8_t>(e) );
break;
@@ -1448,12 +1534,17 @@ namespace {
{
::MIR::TypeResolve top_mir_res { sp, m_resolve, FMT_CB(ss, ss << "extern fn " << p;), ::HIR::TypeRef(), {}, *(::MIR::Function*)nullptr };
m_mir_res = &top_mir_res;
-
TRACE_FUNCTION_F(p);
+
+ if (item.m_linkage.name != "" && m_compiler != Compiler::Gcc)
+ {
+ m_of << "#define " << Trans_Mangle(p) << " " << item.m_linkage.name << "\n";
+ }
+
m_of << "// extern \"" << item.m_abi << "\" " << p << "\n";
m_of << "extern ";
emit_function_header(p, item, params);
- if( item.m_linkage.name != "" )
+ if( item.m_linkage.name != "" && m_compiler == Compiler::Gcc)
{
m_of << " asm(\"" << item.m_linkage.name << "\")";
}
@@ -1711,6 +1802,11 @@ namespace {
)
}
+ bool type_is_emulated_i128(const ::HIR::TypeRef& ty) const
+ {
+ return m_options.emulated_i128 && (ty == ::HIR::CoreType::I128 || ty == ::HIR::CoreType::U128);
+ }
+
void emit_statement(const ::MIR::TypeResolve& mir_res, const ::MIR::Statement& stmt, unsigned indent_level=1)
{
auto indent = RepeatLitStr { "\t", static_cast<int>(indent_level) };
@@ -1892,68 +1988,14 @@ namespace {
}
),
(Cast,
- if( m_resolve.is_type_phantom_data(ve.type) ) {
- m_of << "/* PhandomData cast */\n";
- return ;
- }
-
- ::HIR::TypeRef tmp;
- const auto& ty = mir_res.get_lvalue_type(tmp, ve.val);
-
- // A cast to a fat pointer doesn't actually change the C type.
- if( (ve.type.m_data.is_Pointer() && is_dst(*ve.type.m_data.as_Pointer().inner))
- || (ve.type.m_data.is_Borrow() && is_dst(*ve.type.m_data.as_Borrow().inner))
- // OR: If it's a no-op cast
- || ve.type == ty
- )
- {
- emit_lvalue(e.dst);
- m_of << " = ";
- emit_lvalue(ve.val);
- break;
- }
- //if( m_emulated_i128 && (
- // ve.type == ::HIR::CoreType::U128 || ve.type == ::HIR::CoreType::I128
- // || ty == ::HIR::CoreType::U128 || ty == ::HIR::CoreType::I128
- // ) )
- //{
- // if( ty == ::HIR::CoreType::U128
- //}
-
- emit_lvalue(e.dst);
- m_of << " = ";
- m_of << "("; emit_ctype(ve.type); m_of << ")";
- // TODO: If the source is an unsized borrow, then extract the pointer
- bool special = false;
- // If the destination is a thin pointer
- if( ve.type.m_data.is_Pointer() && !is_dst( *ve.type.m_data.as_Pointer().inner ) )
- {
- // NOTE: Checks the result of the deref
- if( (ty.m_data.is_Borrow() && is_dst(*ty.m_data.as_Borrow().inner))
- || (ty.m_data.is_Pointer() && is_dst(*ty.m_data.as_Pointer().inner))
- )
- {
- emit_lvalue(ve.val);
- m_of << ".PTR";
- special = true;
- }
- }
- if( ve.type.m_data.is_Primitive() && ty.m_data.is_Path() && ty.m_data.as_Path().binding.is_Enum() )
- {
- emit_lvalue(ve.val);
- m_of << ".TAG";
- special = true;
- }
- if( !special )
- {
- emit_lvalue(ve.val);
- }
+ emit_rvalue_cast(mir_res, e.dst, ve);
),
(BinOp,
emit_lvalue(e.dst);
m_of << " = ";
- ::HIR::TypeRef tmp;
- const auto& ty = ve.val_l.is_LValue() ? mir_res.get_lvalue_type(tmp, ve.val_l.as_LValue()) : tmp = mir_res.get_const_type(ve.val_l.as_Constant());
+ ::HIR::TypeRef tmp, tmp_r;
+ const auto& ty = mir_res.get_param_type(tmp, ve.val_l);
+ const auto& ty_r = mir_res.get_param_type(tmp_r, ve.val_r);
if( ty.m_data.is_Borrow() ) {
m_of << "(slice_cmp("; emit_param(ve.val_l); m_of << ", "; emit_param(ve.val_r); m_of << ")";
switch(ve.op)
@@ -2013,6 +2055,49 @@ namespace {
m_of << "("; emit_param(ve.val_l); m_of << ", "; emit_param(ve.val_r); m_of << ")";
break;
}
+ else if( type_is_emulated_i128(ty) )
+ {
+ switch (ve.op)
+ {
+ case ::MIR::eBinOp::ADD: m_of << "add128"; if(0)
+ case ::MIR::eBinOp::SUB: m_of << "sub128"; if(0)
+ case ::MIR::eBinOp::MUL: m_of << "mul128"; if(0)
+ case ::MIR::eBinOp::DIV: m_of << "div128"; if(0)
+ case ::MIR::eBinOp::MOD: m_of << "mod128"; if(0)
+ case ::MIR::eBinOp::BIT_OR: m_of << "or128"; if(0)
+ case ::MIR::eBinOp::BIT_AND: m_of << "and128"; if(0)
+ case ::MIR::eBinOp::BIT_XOR: m_of << "xor128";
+ if( ty == ::HIR::CoreType::I128 )
+ m_of << "s";
+ m_of << "("; emit_param(ve.val_l); m_of << ", "; emit_param(ve.val_r); m_of << ")";
+ break;
+ case ::MIR::eBinOp::BIT_SHR: m_of << "shr128"; if (0)
+ case ::MIR::eBinOp::BIT_SHL: m_of << "shl128";
+ if( ty == ::HIR::CoreType::I128 )
+ m_of << "s";
+ m_of << "("; emit_param(ve.val_l); m_of << ", "; emit_param(ve.val_r);
+ if( (ty_r == ::HIR::CoreType::I128 || ty_r == ::HIR::CoreType::U128) )
+ {
+ m_of << ".lo";
+ }
+ m_of << ")";
+ break;
+
+ case ::MIR::eBinOp::EQ: m_of << "0 == "; if(0)
+ case ::MIR::eBinOp::NE: m_of << "0 != "; if(0)
+ case ::MIR::eBinOp::GT: m_of << "0 > "; if(0)
+ case ::MIR::eBinOp::GE: m_of << "0 >= "; if(0)
+ case ::MIR::eBinOp::LT: m_of << "0 < "; if(0)
+ case ::MIR::eBinOp::LE: m_of << "0 <= ";
+ // NOTE: Reversed order due to reversed logic above
+ m_of << "cmp128";
+ if (ty == ::HIR::CoreType::I128)
+ m_of << "s";
+ m_of << "("; emit_param(ve.val_r); m_of << ", "; emit_param(ve.val_l); m_of << ")";
+ break;
+ }
+ break;
+ }
else {
}
@@ -2045,16 +2130,43 @@ namespace {
break;
}
emit_param(ve.val_r);
+ if( type_is_emulated_i128(ty_r) )
+ {
+ m_of << ".lo";
+ }
),
(UniOp,
::HIR::TypeRef tmp;
+ const auto& ty = mir_res.get_lvalue_type(tmp, e.dst);
+
+ if( type_is_emulated_i128(ty) )
+ {
+ switch (ve.op)
+ {
+ case ::MIR::eUniOp::NEG:
+ emit_lvalue(e.dst);
+ m_of << ".lo = -"; emit_lvalue(ve.val); m_of << ".lo; ";
+ emit_lvalue(e.dst);
+ m_of << ".hi = -"; emit_lvalue(ve.val); m_of << ".hi";
+ break;
+ case ::MIR::eUniOp::INV:
+ emit_lvalue(e.dst);
+ m_of << ".lo = ~"; emit_lvalue(ve.val); m_of << ".lo; ";
+ emit_lvalue(e.dst);
+ m_of << ".hi = ~"; emit_lvalue(ve.val); m_of << ".hi";
+ break;
+ }
+ break ;
+ }
+
+
emit_lvalue(e.dst);
m_of << " = ";
switch(ve.op)
{
case ::MIR::eUniOp::NEG: m_of << "-"; break;
case ::MIR::eUniOp::INV:
- if( mir_res.get_lvalue_type(tmp, e.dst) == ::HIR::CoreType::Bool )
+ if( ty == ::HIR::CoreType::Bool )
m_of << "!";
else
m_of << "~";
@@ -2179,6 +2291,163 @@ namespace {
break; }
}
}
+ void emit_rvalue_cast(const ::MIR::TypeResolve& mir_res, const ::MIR::LValue& dst, const ::MIR::RValue::Data_Cast& ve)
+ {
+ if (m_resolve.is_type_phantom_data(ve.type)) {
+ m_of << "/* PhandomData cast */\n";
+ return;
+ }
+
+ ::HIR::TypeRef tmp;
+ const auto& ty = mir_res.get_lvalue_type(tmp, ve.val);
+
+ // A cast to a fat pointer doesn't actually change the C type.
+ if ((ve.type.m_data.is_Pointer() && is_dst(*ve.type.m_data.as_Pointer().inner))
+ || (ve.type.m_data.is_Borrow() && is_dst(*ve.type.m_data.as_Borrow().inner))
+ // OR: If it's a no-op cast
+ || ve.type == ty
+ )
+ {
+ emit_lvalue(dst);
+ m_of << " = ";
+ emit_lvalue(ve.val);
+ return;
+ }
+
+ // Emulated i128/u128 support
+ if (m_options.emulated_i128 && (
+ ve.type == ::HIR::CoreType::U128 || ve.type == ::HIR::CoreType::I128
+ || ty == ::HIR::CoreType::U128 || ty == ::HIR::CoreType::I128
+ ))
+ {
+ // Destination
+ MIR_ASSERT(mir_res, ve.type.m_data.is_Primitive(), "i128/u128 cast to non-primitive");
+ MIR_ASSERT(mir_res, ty.m_data.is_Primitive(), "i128/u128 cast from non-primitive");
+ switch (ve.type.m_data.as_Primitive())
+ {
+ case ::HIR::CoreType::U128:
+ if (ty == ::HIR::CoreType::I128) {
+ // Cast from i128 to u128
+ emit_lvalue(dst);
+ m_of << ".lo = ";
+ emit_lvalue(ve.val);
+ m_of << ".lo; ";
+ emit_lvalue(dst);
+ m_of << ".hi = ";
+ emit_lvalue(ve.val);
+ m_of << ".hi";
+ }
+ else {
+ // Cast from small to u128
+ emit_lvalue(dst);
+ m_of << ".lo = ";
+ emit_lvalue(ve.val);
+ m_of << "; ";
+ emit_lvalue(dst);
+ m_of << ".hi = 0";
+ }
+ break;
+ case ::HIR::CoreType::I128:
+ if (ty == ::HIR::CoreType::U128) {
+ // Cast from u128 to i128
+ emit_lvalue(dst);
+ m_of << ".lo = ";
+ emit_lvalue(ve.val);
+ m_of << ".lo; ";
+ emit_lvalue(dst);
+ m_of << ".hi = ";
+ emit_lvalue(ve.val);
+ m_of << ".hi";
+ }
+ else {
+ // Cast from small to i128
+ emit_lvalue(dst);
+ m_of << ".lo = ";
+ emit_lvalue(ve.val);
+ m_of << "; ";
+ emit_lvalue(dst);
+ m_of << ".hi = 0"; // TODO: Sign
+ }
+ break;
+ case ::HIR::CoreType::I8:
+ case ::HIR::CoreType::I16:
+ case ::HIR::CoreType::I32:
+ case ::HIR::CoreType::I64:
+ case ::HIR::CoreType::Isize:
+ emit_lvalue(dst);
+ m_of << " = ";
+ switch (ty.m_data.as_Primitive())
+ {
+ case ::HIR::CoreType::U128:
+ emit_lvalue(ve.val);
+ m_of << ".lo";
+ break;
+ case ::HIR::CoreType::I128:
+ // TODO: Maintain sign
+ emit_lvalue(ve.val);
+ m_of << ".lo";
+ break;
+ default:
+ MIR_BUG(mir_res, "Unreachable");
+ }
+ break;
+ case ::HIR::CoreType::U8:
+ case ::HIR::CoreType::U16:
+ case ::HIR::CoreType::U32:
+ case ::HIR::CoreType::U64:
+ case ::HIR::CoreType::Usize:
+ emit_lvalue(dst);
+ m_of << " = ";
+ switch (ty.m_data.as_Primitive())
+ {
+ case ::HIR::CoreType::U128:
+ emit_lvalue(ve.val);
+ m_of << ".lo";
+ break;
+ case ::HIR::CoreType::I128:
+ emit_lvalue(ve.val);
+ m_of << ".lo";
+ break;
+ default:
+ MIR_BUG(mir_res, "Unreachable");
+ }
+ break;
+ default:
+ MIR_BUG(mir_res, "Bad i128/u128 cast");
+ }
+ return;
+ }
+
+ // Standard cast
+ emit_lvalue(dst);
+ m_of << " = ";
+ m_of << "("; emit_ctype(ve.type); m_of << ")";
+ // TODO: If the source is an unsized borrow, then extract the pointer
+ bool special = false;
+ // If the destination is a thin pointer
+ if (ve.type.m_data.is_Pointer() && !is_dst(*ve.type.m_data.as_Pointer().inner))
+ {
+ // NOTE: Checks the result of the deref
+ if ((ty.m_data.is_Borrow() && is_dst(*ty.m_data.as_Borrow().inner))
+ || (ty.m_data.is_Pointer() && is_dst(*ty.m_data.as_Pointer().inner))
+ )
+ {
+ emit_lvalue(ve.val);
+ m_of << ".PTR";
+ special = true;
+ }
+ }
+ if (ve.type.m_data.is_Primitive() && ty.m_data.is_Path() && ty.m_data.as_Path().binding.is_Enum())
+ {
+ emit_lvalue(ve.val);
+ m_of << ".TAG";
+ special = true;
+ }
+ if (!special)
+ {
+ emit_lvalue(ve.val);
+ }
+ }
void emit_term_switch(const ::MIR::TypeResolve& mir_res, const ::MIR::LValue& val, size_t n_arms, unsigned indent_level, ::std::function<void(size_t)> cb)
{
auto indent = RepeatLitStr { "\t", static_cast<int>(indent_level) };
@@ -2354,41 +2623,129 @@ namespace {
void emit_intrinsic_call(const ::std::string& name, const ::HIR::PathParams& params, const ::MIR::Terminator::Data_Call& e)
{
const auto& mir_res = *m_mir_res;
- struct H {
- static const char* get_atomic_ordering(const ::MIR::TypeResolve& mir_res, const ::std::string& name, size_t prefix_len) {
+ auto get_atomic_ordering = [&](const ::std::string& name, size_t prefix_len)->const char* {
if( name.size() < prefix_len )
- return "memory_order_seq_cst";
+ {
+ switch(m_compiler)
+ {
+ case Compiler::Gcc: return "memory_order_seq_cst";
+ case Compiler::Msvc: return "";
+ }
+ }
const char* suffix = name.c_str() + prefix_len;
if( ::std::strcmp(suffix, "acq") == 0 ) {
- return "memory_order_acquire";
+ switch (m_compiler)
+ {
+ case Compiler::Gcc: return "memory_order_acquire";
+ case Compiler::Msvc: return "Acquire";
+ }
}
else if( ::std::strcmp(suffix, "rel") == 0 ) {
- return "memory_order_release";
+ switch (m_compiler)
+ {
+ case Compiler::Gcc: return "memory_order_release";
+ case Compiler::Msvc: return "Release";
+ }
}
else if( ::std::strcmp(suffix, "relaxed") == 0 ) {
- return "memory_order_relaxed";
+ switch (m_compiler)
+ {
+ case Compiler::Gcc: return "memory_order_relaxed";
+ case Compiler::Msvc: return "NoFence";
+ }
}
else if( ::std::strcmp(suffix, "acqrel") == 0 ) {
- return "memory_order_acq_rel";
+ switch (m_compiler)
+ {
+ case Compiler::Gcc: return "memory_order_acq_rel";
+ case Compiler::Msvc: return ""; // TODO: This is either Acquire or Release
+ }
}
else {
MIR_BUG(mir_res, "Unknown atomic ordering suffix - '" << suffix << "'");
}
+ throw "";
+ };
+ auto emit_msvc_atomic_op = [&](const char* name, const char* ordering) {
+ switch (params.m_types.at(0).m_data.as_Primitive())
+ {
+ case ::HIR::CoreType::U16:
+ m_of << name << "16" << ordering << "(";
+ break;
+ case ::HIR::CoreType::U32:
+ m_of << name << ordering << "(";
+ break;
+ case ::HIR::CoreType::U64:
+ //case ::HIR::CoreType::I64:
+ m_of << name << "64" << ordering << "(";
+ break;
+ case ::HIR::CoreType::Usize:
+ case ::HIR::CoreType::Isize:
+ m_of << "(uintptr_t)" << name << "Pointer" << ordering << "((void**)";
+ break;
+ default:
+ MIR_BUG(mir_res, "Unsupported atomic type - " << params.m_types.at(0));
}
- };
+ };
+ auto emit_atomic_cast = [&]() {
+ m_of << "(_Atomic "; emit_ctype(params.m_types.at(0)); m_of << "*)";
+ };
auto emit_atomic_cxchg = [&](const auto& e, const char* o_succ, const char* o_fail, bool is_weak) {
- emit_lvalue(e.ret_val); m_of << "._0 = "; emit_param(e.args.at(1)); m_of << ";\n\t";
- emit_lvalue(e.ret_val); m_of << "._1 = atomic_compare_exchange_" << (is_weak ? "weak" : "strong") << "_explicit(";
- m_of << "(_Atomic "; emit_ctype(params.m_types.at(0)); m_of << "*)"; emit_param(e.args.at(0));
- m_of << ", &"; emit_lvalue(e.ret_val); m_of << "._0";
- m_of << ", "; emit_param(e.args.at(2));
- m_of << ", "<<o_succ<<", "<<o_fail<<")";
+ switch(m_compiler)
+ {
+ case Compiler::Gcc:
+ emit_lvalue(e.ret_val); m_of << "._0 = "; emit_param(e.args.at(1)); m_of << ";\n\t";
+ emit_lvalue(e.ret_val); m_of << "._1 = atomic_compare_exchange_" << (is_weak ? "weak" : "strong") << "_explicit(";
+ emit_atomic_cast(); emit_param(e.args.at(0));
+ m_of << ", &"; emit_lvalue(e.ret_val); m_of << "._0";
+ m_of << ", "; emit_param(e.args.at(2));
+ m_of << ", "<<o_succ<<", "<<o_fail<<")";
+ break;
+ case Compiler::Msvc:
+ emit_msvc_atomic_op("InterlockedCompareExchange", ""); // TODO: Use ordering
+ if(params.m_types.at(0) == ::HIR::CoreType::Usize || params.m_types.at(0) == ::HIR::CoreType::Isize)
+ {
+ emit_param(e.args.at(0)); m_of << ", (void*)"; emit_param(e.args.at(1)); m_of << ", (void*)"; emit_param(e.args.at(2)); m_of << ")";
+ }
+ else
+ {
+ emit_param(e.args.at(0)); m_of << ", "; emit_param(e.args.at(1)); m_of << ", "; emit_param(e.args.at(2)); m_of << ")";
+ }
+ break;
+ }
};
- auto emit_atomic_arith = [&](const char* name, const char* ordering) {
- emit_lvalue(e.ret_val); m_of << " = atomic_" << name << "_explicit";
- m_of <<"((_Atomic "; emit_ctype(params.m_types.at(0)); m_of << "*)"; emit_param(e.args.at(0));
- m_of << ", "; emit_param(e.args.at(1));
- m_of << ", " << ordering << ")";
+ auto emit_atomic_arith = [&](AtomicOp op, const char* ordering) {
+ emit_lvalue(e.ret_val); m_of << " = ";
+ switch(m_compiler)
+ {
+ case Compiler::Gcc:
+ switch(op)
+ {
+ case AtomicOp::Add: m_of << "atomic_fetch_add_explicit"; break;
+ case AtomicOp::Sub: m_of << "atomic_fetch_sub_explicit"; break;
+ case AtomicOp::And: m_of << "atomic_fetch_and_explicit"; break;
+ case AtomicOp::Or: m_of << "atomic_fetch_or_explicit"; break;
+ case AtomicOp::Xor: m_of << "atomic_fetch_xor_explicit"; break;
+ }
+ m_of << "("; emit_atomic_cast(); emit_param(e.args.at(0)); m_of << ", "; emit_param(e.args.at(1)); m_of << ", " << ordering << ")";
+ break;
+ case Compiler::Msvc:
+ switch(op)
+ {
+ case AtomicOp::Add: emit_msvc_atomic_op("InterlockedExchangeAdd", ordering); break;
+ case AtomicOp::Sub: emit_msvc_atomic_op("InterlockedExchangeSub", ordering); break;
+ case AtomicOp::And: emit_msvc_atomic_op("InterlockedExchangeAnd", ordering); break;
+ case AtomicOp::Or: emit_msvc_atomic_op("InterlockedExchangeOr", ordering); break;
+ case AtomicOp::Xor: emit_msvc_atomic_op("InterlockedExchangeXor", ordering); break;
+ }
+ emit_param(e.args.at(0)); m_of << ", ";
+ if (params.m_types.at(0) == ::HIR::CoreType::Usize || params.m_types.at(0) == ::HIR::CoreType::Isize)
+ {
+ m_of << "(void*)";
+ }
+ emit_param(e.args.at(1)); m_of << ")";
+ break;
+ }
};
if( name == "size_of" ) {
emit_lvalue(e.ret_val); m_of << " = sizeof("; emit_ctype(params.m_types.at(0)); m_of << ")";
@@ -2454,7 +2811,7 @@ namespace {
}
else if( const auto* te = inner_ty.m_data.opt_Slice() ) {
if( ! ty.m_data.is_Slice() ) {
- m_of << "max( __alignof__("; emit_ctype(ty); m_of << "), ";
+ m_of << "mrustc_max( __alignof__("; emit_ctype(ty); m_of << "), ";
}
m_of << "__alignof__("; emit_ctype(*te->inner); m_of << ")";
if( ! ty.m_data.is_Slice() ) {
@@ -2471,7 +2828,7 @@ namespace {
}
else if( inner_ty.m_data.is_TraitObject() ) {
if( ! ty.m_data.is_TraitObject() ) {
- m_of << "max( __alignof__("; emit_ctype(ty); m_of << "), ";
+ m_of << "mrustc_max( __alignof__("; emit_ctype(ty); m_of << "), ";
}
m_of << "((VTABLE_HDR*)"; emit_param(e.args.at(0)); m_of << ".META)->align";
if( ! ty.m_data.is_TraitObject() ) {
@@ -2674,16 +3031,56 @@ namespace {
}
// Unchecked Arithmatic
else if( name == "unchecked_div" ) {
- emit_lvalue(e.ret_val); m_of << " = "; emit_param(e.args.at(0)); m_of << " / "; emit_param(e.args.at(1));
+ emit_lvalue(e.ret_val); m_of << " = ";
+ if( type_is_emulated_i128(params.m_types.at(0)) )
+ {
+ m_of << "div128";
+ if(params.m_types.at(0) == ::HIR::CoreType::I128) m_of << "s";
+ m_of << "("; emit_param(e.args.at(0)); m_of << ", "; emit_param(e.args.at(1)); m_of << ")";
+ }
+ else
+ {
+ emit_param(e.args.at(0)); m_of << " / "; emit_param(e.args.at(1));
+ }
}
else if( name == "unchecked_rem" ) {
- emit_lvalue(e.ret_val); m_of << " = "; emit_param(e.args.at(0)); m_of << " % "; emit_param(e.args.at(1));
+ emit_lvalue(e.ret_val); m_of << " = ";
+ if (type_is_emulated_i128(params.m_types.at(0)))
+ {
+ m_of << "mod128";
+ if(params.m_types.at(0) == ::HIR::CoreType::I128) m_of << "s";
+ m_of << "("; emit_param(e.args.at(0)); m_of << ", "; emit_param(e.args.at(1)); m_of << ")";
+ }
+ else
+ {
+ emit_param(e.args.at(0)); m_of << " % "; emit_param(e.args.at(1));
+ }
}
else if( name == "unchecked_shl" ) {
- emit_lvalue(e.ret_val); m_of << " = "; emit_param(e.args.at(0)); m_of << " << "; emit_param(e.args.at(1));
+ emit_lvalue(e.ret_val); m_of << " = ";
+ if (type_is_emulated_i128(params.m_types.at(0)))
+ {
+ m_of << "shl128";
+ if(params.m_types.at(0) == ::HIR::CoreType::I128) m_of << "s";
+ m_of << "("; emit_param(e.args.at(0)); m_of << ", "; emit_param(e.args.at(1)); m_of << ")";
+ }
+ else
+ {
+ emit_param(e.args.at(0)); m_of << " << "; emit_param(e.args.at(1));
+ }
}
else if( name == "unchecked_shr" ) {
- emit_lvalue(e.ret_val); m_of << " = "; emit_param(e.args.at(0)); m_of << " >> "; emit_param(e.args.at(1));
+ emit_lvalue(e.ret_val); m_of << " = ";
+ if (type_is_emulated_i128(params.m_types.at(0)))
+ {
+ m_of << "shr128";
+ if (params.m_types.at(0) == ::HIR::CoreType::I128) m_of << "s";
+ m_of << "("; emit_param(e.args.at(0)); m_of << ", "; emit_param(e.args.at(1)); m_of << ")";
+ }
+ else
+ {
+ emit_param(e.args.at(0)); m_of << " >> "; emit_param(e.args.at(1));
+ }
}
// Bit Twiddling
// - CounT Leading Zeroes
@@ -2691,18 +3088,21 @@ namespace {
else if( name == "ctlz" || name == "cttz" ) {
auto emit_arg0 = [&](){ emit_param(e.args.at(0)); };
const auto& ty = params.m_types.at(0);
- emit_lvalue(e.ret_val); m_of << " = ("; emit_param(e.args.at(0)); m_of << " != 0 ? ";
+ emit_lvalue(e.ret_val); m_of << " = (";
if( ty == ::HIR::CoreType::U128 )
{
if( name == "ctlz" ) {
- m_of << "__builtin_clz128("; emit_param(e.args.at(0)); m_of << ")";
+ m_of << "intrinsic_ctlz_u128("; emit_param(e.args.at(0)); m_of << ")";
}
else {
- m_of << "__builtin_ctz128("; emit_param(e.args.at(0)); m_of << ")";
+ m_of << "intrinsic_cttz_u128("; emit_param(e.args.at(0)); m_of << ")";
}
+ m_of << ");";
+ return ;
}
else if( ty == ::HIR::CoreType::U64 || (ty == ::HIR::CoreType::Usize /*&& target_is_64_bit */) )
{
+ emit_param(e.args.at(0)); m_of << " != 0 ? ";
if( name == "ctlz" ) {
m_of << "__builtin_clz64("; emit_arg0(); m_of << ")";
}
@@ -2712,6 +3112,7 @@ namespace {
}
else
{
+ emit_param(e.args.at(0)); m_of << " != 0 ? ";
if( name == "ctlz" ) {
m_of << "__builtin_clz("; emit_param(e.args.at(0)); m_of << ")";
}
@@ -2723,7 +3124,19 @@ namespace {
}
// - CounT POPulated
else if( name == "ctpop" ) {
- emit_lvalue(e.ret_val); m_of << " = __builtin_popcount("; emit_param(e.args.at(0)); m_of << ")";
+ emit_lvalue(e.ret_val); m_of << " = ";
+
+ if( type_is_emulated_i128(params.m_types.at(0)) )
+ {
+ m_of << "popcount128";
+ if(params.m_types.at(0) == ::HIR::CoreType::I128)
+ m_of << "s";
+ }
+ else
+ {
+ m_of << "__builtin_popcount";
+ }
+ m_of << "("; emit_param(e.args.at(0)); m_of << ")";
}
// --- Floating Point
// > Round to nearest integer, half-way rounds away from zero
@@ -2792,32 +3205,54 @@ namespace {
// --- Atomics!
// > Single-ordering atomics
else if( name == "atomic_xadd" || name.compare(0, 7+4+1, "atomic_xadd_") == 0 ) {
- auto ordering = H::get_atomic_ordering(mir_res, name, 7+4+1);
- emit_atomic_arith("fetch_add", ordering);
+ auto ordering = get_atomic_ordering(name, 7+4+1);
+ emit_atomic_arith(AtomicOp::Add, ordering);
}
else if( name == "atomic_xsub" || name.compare(0, 7+4+1, "atomic_xsub_") == 0 ) {
- auto ordering = H::get_atomic_ordering(mir_res, name, 7+4+1);
- emit_atomic_arith("fetch_sub", ordering);
+ auto ordering = get_atomic_ordering(name, 7+4+1);
+ emit_atomic_arith(AtomicOp::Sub, ordering);
}
else if( name == "atomic_and" || name.compare(0, 7+3+1, "atomic_and_") == 0 ) {
- auto ordering = H::get_atomic_ordering(mir_res, name, 7+3+1);
- emit_atomic_arith("fetch_and", ordering);
+ auto ordering = get_atomic_ordering(name, 7+3+1);
+ emit_atomic_arith(AtomicOp::And, ordering);
}
else if( name == "atomic_or" || name.compare(0, 7+2+1, "atomic_or_") == 0 ) {
- auto ordering = H::get_atomic_ordering(mir_res, name, 7+2+1);
- emit_atomic_arith("fetch_or", ordering);
+ auto ordering = get_atomic_ordering(name, 7+2+1);
+ emit_atomic_arith(AtomicOp::Or, ordering);
}
else if( name == "atomic_xor" || name.compare(0, 7+3+1, "atomic_xor_") == 0 ) {
- auto ordering = H::get_atomic_ordering(mir_res, name, 7+3+1);
- emit_atomic_arith("fetch_xor", ordering);
+ auto ordering = get_atomic_ordering(name, 7+3+1);
+ emit_atomic_arith(AtomicOp::Xor, ordering);
}
else if( name == "atomic_load" || name.compare(0, 7+4+1, "atomic_load_") == 0 ) {
- auto ordering = H::get_atomic_ordering(mir_res, name, 7+4+1);
- emit_lvalue(e.ret_val); m_of << " = atomic_load_explicit((_Atomic "; emit_ctype(params.m_types.at(0)); m_of << "*)"; emit_param(e.args.at(0)); m_of << ", " << ordering << ")";
+ auto ordering = get_atomic_ordering(name, 7+4+1);
+ emit_lvalue(e.ret_val); m_of << " = ";
+ switch(m_compiler)
+ {
+ case Compiler::Gcc:
+ m_of << "atomic_load_explicit("; emit_atomic_cast(); emit_param(e.args.at(0)); m_of << ", " << ordering << ")";
+ break;
+ case Compiler::Msvc:
+ emit_msvc_atomic_op("InterlockedRead", ordering); emit_param(e.args.at(0)); m_of << ")";
+ break;
+ }
}
else if( name == "atomic_store" || name.compare(0, 7+5+1, "atomic_store_") == 0 ) {
- auto ordering = H::get_atomic_ordering(mir_res, name, 7+5+1);
- m_of << "atomic_store_explicit((_Atomic "; emit_ctype(params.m_types.at(0)); m_of << "*)"; emit_param(e.args.at(0)); m_of << ", "; emit_param(e.args.at(1)); m_of << ", " << ordering << ")";
+ auto ordering = get_atomic_ordering(name, 7+5+1);
+ switch (m_compiler)
+ {
+ case Compiler::Gcc:
+ m_of << "atomic_store_explicit("; emit_atomic_cast(); emit_param(e.args.at(0)); m_of << ", "; emit_param(e.args.at(1)); m_of << ", " << ordering << ")";
+ break;
+ case Compiler::Msvc:
+ emit_msvc_atomic_op("InterlockedStore", ordering); emit_param(e.args.at(0)); m_of << ", ";
+ if (params.m_types.at(0) == ::HIR::CoreType::Usize || params.m_types.at(0) == ::HIR::CoreType::Isize)
+ {
+ m_of << "(void*)";
+ }
+ emit_param(e.args.at(1)); m_of << ")";
+ break;
+ }
}
// Comare+Exchange (has two orderings)
else if( name == "atomic_cxchg_acq_failrelaxed" ) {
@@ -2835,11 +3270,11 @@ namespace {
emit_atomic_cxchg(e, "memory_order_acq_rel", "memory_order_acquire", false);
}
else if( name.compare(0, 7+6+4, "atomic_cxchg_fail") == 0 ) {
- auto fail_ordering = H::get_atomic_ordering(mir_res, name, 7+6+4);
+ auto fail_ordering = get_atomic_ordering(name, 7+6+4);
emit_atomic_cxchg(e, "memory_order_seq_cst", fail_ordering, false);
}
else if( name == "atomic_cxchg" || name.compare(0, 7+6, "atomic_cxchg_") == 0 ) {
- auto ordering = H::get_atomic_ordering(mir_res, name, 7+6);
+ auto ordering = get_atomic_ordering(name, 7+6);
emit_atomic_cxchg(e, ordering, ordering, false);
}
else if( name == "atomic_cxchgweak_acq_failrelaxed" ) {
@@ -2849,7 +3284,7 @@ namespace {
emit_atomic_cxchg(e, "memory_order_acq_rel", "memory_order_relaxed", true);
}
else if( name.compare(0, 7+10+4, "atomic_cxchgweak_fail") == 0 ) {
- auto fail_ordering = H::get_atomic_ordering(mir_res, name, 7+10+4);
+ auto fail_ordering = get_atomic_ordering(name, 7+10+4);
emit_atomic_cxchg(e, "memory_order_seq_cst", fail_ordering, true);
}
else if( name == "atomic_cxchgweak" ) {
@@ -2868,12 +3303,34 @@ namespace {
emit_atomic_cxchg(e, "memory_order_relaxed", "memory_order_relaxed", true);
}
else if( name == "atomic_xchg" || name.compare(0, 7+5, "atomic_xchg_") == 0 ) {
- auto ordering = H::get_atomic_ordering(mir_res, name, 7+5);
- emit_lvalue(e.ret_val); m_of << " = atomic_exchange_explicit((_Atomic "; emit_ctype(params.m_types.at(0)); m_of << "*)"; emit_param(e.args.at(0)); m_of << ", "; emit_param(e.args.at(1)); m_of << ", " << ordering << ")";
+ auto ordering = get_atomic_ordering(name, 7+5);
+ emit_lvalue(e.ret_val); m_of << " = ";
+ switch(m_compiler)
+ {
+ case Compiler::Gcc:
+ m_of << "atomic_exchange_explicit("; emit_atomic_cast(); emit_param(e.args.at(0)); m_of << ", "; emit_param(e.args.at(1)); m_of << ", " << ordering << ")";
+ break;
+ case Compiler::Msvc:
+ emit_msvc_atomic_op("InterlockedExchange", ordering);
+ emit_param(e.args.at(0)); m_of << ", ";
+ if (params.m_types.at(0) == ::HIR::CoreType::Usize || params.m_types.at(0) == ::HIR::CoreType::Isize)
+ {
+ m_of << "(void*)";
+ }
+ emit_param(e.args.at(1)); m_of << ")";
+ break;
+ }
}
else if( name == "atomic_fence" || name.compare(0, 7+6, "atomic_fence_") == 0 ) {
- auto ordering = H::get_atomic_ordering(mir_res, name, 7+6);
- m_of << "atomic_thread_fence(" << ordering << ")";
+ auto ordering = get_atomic_ordering(name, 7+6);
+ switch(m_compiler)
+ {
+ case Compiler::Gcc:
+ m_of << "atomic_thread_fence(" << ordering << ")";
+ break;
+ case Compiler::Msvc:
+ break;
+ }
}
else if( name == "atomic_singlethreadfence" || name.compare(0, 7+18, "atomic_singlethreadfence_") == 0 ) {
// TODO: Does this matter?
@@ -3318,14 +3775,26 @@ namespace {
m_of << "INT64_MIN";
else
{
- m_of << c.v;
switch(c.t)
{
case ::HIR::CoreType::I64:
- case ::HIR::CoreType::I128:
case ::HIR::CoreType::Isize:
+ m_of << c.v;
m_of << "ll";
+ break;
+ case ::HIR::CoreType::I128:
+ if( m_options.emulated_i128 )
+ {
+ m_of << "make128s(" << c.v << "ll)";
+ }
+ else
+ {
+ m_of << c.v;
+ m_of << "ll";
+ }
+ break;
default:
+ m_of << c.v;
break;
}
}
@@ -3343,10 +3812,19 @@ namespace {
m_of << ::std::hex << "0x" << (c.v & 0xFFFFFFFF) << ::std::dec;
break;
case ::HIR::CoreType::U64:
- case ::HIR::CoreType::U128:
case ::HIR::CoreType::Usize:
m_of << ::std::hex << "0x" << c.v << "ull" << ::std::dec;
break;
+ case ::HIR::CoreType::U128:
+ if( m_options.emulated_i128 )
+ {
+ m_of << "make128(" << ::std::hex << "0x" << c.v << "ull)" << ::std::dec;
+ }
+ else
+ {
+ m_of << ::std::hex << "0x" << c.v << "ull" << ::std::dec;
+ }
+ break;
case ::HIR::CoreType::Char:
assert(0 <= c.v && c.v <= 0x10FFFF);
if( c.v < 256 ) {
diff --git a/src/trans/target.cpp b/src/trans/target.cpp
index 43b63822..5b77d848 100644
--- a/src/trans/target.cpp
+++ b/src/trans/target.cpp
@@ -13,7 +13,7 @@
TargetArch ARCH_X86_64 = {
"x86_64",
64, false,
- { true, false, true, true, true }
+ { false /*true*/, false, true, true, true }
};
TargetSpec g_target;