From a098a18b95d2520ca9787cec9f0254caf0f1364e Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 3 Mar 2018 12:47:48 +0800 Subject: Codegen C - More work with MSVC support (darn atomics) --- src/trans/codegen_c.cpp | 141 ++++++++++++++++++++++++++++-------------------- 1 file changed, 82 insertions(+), 59 deletions(-) (limited to 'src/trans/codegen_c.cpp') diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index c59e1c79..acd54528 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -390,6 +390,14 @@ namespace { << "\t""return (a > b ? *o >= b : *o > a);\n" << "}\n" << "static inline uint64_t __builtin_bswap64(uint64_t v) { return _byteswap_uint64(v); }\n" + << "static inline uint8_t InterlockedCompareExchange8(volatile uint8_t* v, uint8_t n, uint8_t e){ return _InterlockedCompareExchange8(v, n, e); }\n" + << "static inline uint8_t InterlockedCompareExchangeNoFence8(volatile uint8_t* v, uint8_t n, uint8_t e){ return InterlockedCompareExchange8(v, n, e); }\n" + << "static inline uint8_t InterlockedCompareExchangeAcquire8(volatile uint8_t* v, uint8_t n, uint8_t e){ return InterlockedCompareExchange8(v, n, e); }\n" + << "static inline uint8_t InterlockedCompareExchangeRelease8(volatile uint8_t* v, uint8_t n, uint8_t e){ return InterlockedCompareExchange8(v, n, e); }\n" + //<< "static inline uint8_t InterlockedExchange8(volatile uint8_t* v, uint8_t n){ return _InterlockedExchange8((volatile char*)v, (char)n); }\n" + << "static inline uint8_t InterlockedExchangeNoFence8(volatile uint8_t* v, uint8_t n){ return InterlockedExchange8(v, n); }\n" + << "static inline uint8_t InterlockedExchangeAcquire8(volatile uint8_t* v, uint8_t n){ return InterlockedExchange8(v, n); }\n" + << "static inline uint8_t InterlockedExchangeRelease8(volatile uint8_t* v, uint8_t n){ return InterlockedExchange8(v, n); }\n" ; break; } @@ -3423,43 +3431,53 @@ 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; - auto get_atomic_ordering = [&](const ::std::string& name, size_t prefix_len)->const char* { + enum class Ordering + { + SeqCst, + Acquire, + Release, + Relaxed, + AcqRel, + }; + auto get_atomic_ty_gcc = [&](Ordering o)->const char* { + switch(o) + { + case Ordering::SeqCst: return "memory_order_seq_cst"; + case Ordering::Acquire: return "memory_order_acquire"; + case Ordering::Release: return "memory_order_release"; + case Ordering::Relaxed: return "memory_order_relaxed"; + case Ordering::AcqRel: return "memory_order_acq_rel"; + } + throw ""; + }; + auto get_atomic_suffix_msvc = [&](Ordering o)->const char* { + switch(o) + { + case Ordering::SeqCst: return ""; + case Ordering::Acquire: return "Acquire"; + case Ordering::Release: return "Release"; + case Ordering::Relaxed: return "NoFence"; + case Ordering::AcqRel: return ""; // this is either Acquire or Release + } + throw ""; + }; + auto get_atomic_ordering = [&](const ::std::string& name, size_t prefix_len)->Ordering { if( name.size() < prefix_len ) { - switch(m_compiler) - { - case Compiler::Gcc: return "memory_order_seq_cst"; - case Compiler::Msvc: return ""; - } + return Ordering::SeqCst; } const char* suffix = name.c_str() + prefix_len; if( ::std::strcmp(suffix, "acq") == 0 ) { - switch (m_compiler) - { - case Compiler::Gcc: return "memory_order_acquire"; - case Compiler::Msvc: return "Acquire"; - } + return Ordering::Acquire; } else if( ::std::strcmp(suffix, "rel") == 0 ) { - switch (m_compiler) - { - case Compiler::Gcc: return "memory_order_release"; - case Compiler::Msvc: return "Release"; - } + return Ordering::Release; } else if( ::std::strcmp(suffix, "relaxed") == 0 ) { - switch (m_compiler) - { - case Compiler::Gcc: return "memory_order_relaxed"; - case Compiler::Msvc: return "NoFence"; - } + return Ordering::Relaxed; } else if( ::std::strcmp(suffix, "acqrel") == 0 ) { - switch (m_compiler) - { - case Compiler::Gcc: return "memory_order_acq_rel"; - case Compiler::Msvc: return ""; // TODO: This is either Acquire or Release - } + return Ordering::AcqRel; } else { MIR_BUG(mir_res, "Unknown atomic ordering suffix - '" << suffix << "'"); @@ -3494,33 +3512,35 @@ namespace { MIR_BUG(mir_res, "Unknown primitive for getting size- " << ty); } }; - auto emit_msvc_atomic_op = [&](const char* name, const char* ordering) { + auto emit_msvc_atomic_op = [&](const char* name, Ordering ordering, bool is_before_size=false) { + const char* o_before = is_before_size ? get_atomic_suffix_msvc(ordering) : ""; + const char* o_after = is_before_size ? "" : get_atomic_suffix_msvc(ordering); switch (params.m_types.at(0).m_data.as_Primitive()) { case ::HIR::CoreType::U8: case ::HIR::CoreType::I8: - m_of << name << "8" << ordering << "("; + m_of << name << o_before << "8" << o_after << "("; break; case ::HIR::CoreType::U16: - m_of << name << "16" << ordering << "("; + m_of << name << o_before << "16" << o_after << "("; break; case ::HIR::CoreType::U32: - m_of << name << ordering << "("; + m_of << name << o_before << o_after << "("; break; case ::HIR::CoreType::U64: //case ::HIR::CoreType::I64: - m_of << name << "64" << ordering << "("; + m_of << name << o_before << "64" << o_after << "("; break; case ::HIR::CoreType::Usize: case ::HIR::CoreType::Isize: - m_of << name; + m_of << name << o_before; if( Target_GetCurSpec().m_arch.m_pointer_bits == 64 ) m_of << "64"; else if( Target_GetCurSpec().m_arch.m_pointer_bits == 32 ) m_of << ""; else MIR_TODO(mir_res, "Handle non 32/64 bit pointer types"); - m_of << ordering << "("; + m_of << o_after << "("; break; default: MIR_BUG(mir_res, "Unsupported atomic type - " << params.m_types.at(0)); @@ -3529,7 +3549,7 @@ namespace { 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) { + auto emit_atomic_cxchg = [&](const auto& e, Ordering o_succ, Ordering o_fail, bool is_weak) { switch(m_compiler) { case Compiler::Gcc: @@ -3538,18 +3558,18 @@ namespace { 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 << ", "<