brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.0 KiB · b4a7d23 Raw
287 lines · plain
1.. raw:: html2 3  <style type="text/css">4    .none { background-color: #FFCCCC }5    .partial { background-color: #FFFF99 }6    .good { background-color: #CCFF99 }7  </style>8 9.. role:: none10.. role:: partial11.. role:: good12 13==================14MSVC compatibility15==================16 17When Clang compiles C++ code for Windows, it attempts to be compatible with18MSVC.  There are multiple dimensions to compatibility.19 20First, Clang attempts to be ABI-compatible, meaning that Clang-compiled code21should be able to link against MSVC-compiled code successfully.  However, C++22ABIs are particularly large and complicated, and Clang's support for MSVC's C++23ABI is a work in progress.  If you don't require MSVC ABI compatibility or don't24want to use Microsoft's C and C++ runtimes, the mingw32 toolchain might be a25better fit for your project.26 27Second, Clang implements many MSVC language extensions, such as28``__declspec(dllexport)`` and a handful of pragmas.  These are typically29controlled by ``-fms-extensions``.30 31Third, MSVC accepts some C++ code that Clang will typically diagnose as32invalid.  When these constructs are present in widely included system headers,33Clang attempts to recover and continue compiling the user's program.  Most34parsing and semantic compatibility tweaks are controlled by35``-fms-compatibility`` and ``-fdelayed-template-parsing``, and they are a work36in progress.37 38Finally, there is :ref:`clang-cl`, a driver program for clang that attempts to39be compatible with MSVC's cl.exe.40 41ABI features42============43 44The status of major ABI-impacting C++ features:45 46* Record layout: :good:`Complete`.  We've tested this with a fuzzer and have47  fixed all known bugs.48 49* Class inheritance: :good:`Mostly complete`.  This covers all of the standard50  OO features you would expect: virtual method inheritance, multiple51  inheritance, and virtual inheritance.  Every so often we uncover a bug where52  our tables are incompatible, but this is pretty well in hand.  This feature53  has also been fuzz tested.54 55* Name mangling: :good:`Ongoing`.  Every new C++ feature generally needs its own56  mangling.  For example, member pointer template arguments have an interesting57  and distinct mangling.  Fortunately, incorrect manglings usually do not result58  in runtime errors.  Non-inline functions with incorrect manglings usually59  result in link errors, which are relatively easy to diagnose.  Incorrect60  manglings for inline functions and templates result in multiple copies in the61  final image.  The C++ standard requires that those addresses be equal, but few62  programs rely on this.63 64* Member pointers: :good:`Mostly complete`.  Standard C++ member pointers are65  fully implemented and should be ABI compatible.  Both `#pragma66  pointers_to_members`_ and the `/vm`_ flags are supported. However, MSVC67  supports an extension to allow creating a `pointer to a member of a virtual68  base class`_.  Clang does not yet support this.69 70.. _#pragma pointers_to_members:71  https://msdn.microsoft.com/en-us/library/83cch5a6.aspx72.. _/vm: https://msdn.microsoft.com/en-us/library/yad46a6z.aspx73.. _pointer to a member of a virtual base class: https://llvm.org/PR1571374 75* Debug info: :good:`Mostly complete`.  Clang emits relatively complete CodeView76  debug information if ``/Z7`` or ``/Zi`` is passed. Microsoft's link.exe will77  transform the CodeView debug information into a PDB that works in Windows78  debuggers and other tools that consume PDB files like ETW. Work to teach lld79  about CodeView and PDBs is ongoing.80 81* RTTI: :good:`Complete`.  Generation of RTTI data structures has been82  finished, along with support for the ``/GR`` flag.83 84* C++ Exceptions: :good:`Mostly complete`.  Support for85  C++ exceptions (``try`` / ``catch`` / ``throw``) have been implemented for86  x86 and x64.  Our implementation has been well tested but we still get the87  odd bug report now and again.88  C++ exception specifications are ignored, but this is `consistent with Visual89  C++`_.90 91.. _consistent with Visual C++:92  https://msdn.microsoft.com/en-us/library/wfa0edys.aspx93 94* Asynchronous Exceptions (SEH): :partial:`Partial`.95  Structured exceptions (``__try`` / ``__except`` / ``__finally``) mostly96  work on x86 and x64.97  LLVM does not model asynchronous exceptions, so it is currently impossible to98  catch an asynchronous exception generated in the same frame as the catching99  ``__try``.100 101* Thread-safe initialization of local statics: :good:`Complete`.  MSVC 2015102  added support for thread-safe initialization of such variables by taking an103  ABI break.104  We are ABI compatible with both the MSVC 2013 and 2015 ABI for static local105  variables.106 107* Lambdas: :good:`Mostly complete`.  Clang is compatible with Microsoft's108  implementation of lambdas except for providing overloads for conversion to109  function pointer for different calling conventions.  However, Microsoft's110  extension is non-conforming.111 112Template instantiation and name lookup113======================================114 115MSVC allows many invalid constructs in class templates that Clang has116historically rejected.  In order to parse widely distributed headers for117libraries such as the Active Template Library (ATL) and Windows Runtime Library118(WRL), some template rules have been relaxed or extended in Clang on Windows.119 120The first major semantic difference is that MSVC appears to defer all parsing121an analysis of inline method bodies in class templates until instantiation122time.  By default on Windows, Clang attempts to follow suit.  This behavior is123controlled by the ``-fdelayed-template-parsing`` flag.  While Clang delays124parsing of method bodies, it still parses the bodies *before* template argument125substitution, which is not what MSVC does.  The following compatibility tweaks126are necessary to parse the template in those cases.127 128MSVC allows some name lookup into dependent base classes.  Even on other129platforms, this has been a `frequently asked question`_ for Clang users.  A130dependent base class is a base class that depends on the value of a template131parameter.  Clang cannot see any of the names inside dependent bases while it132is parsing your template, so the user is sometimes required to use the133``typename`` keyword to assist the parser.  On Windows, Clang attempts to134follow the normal lookup rules, but if lookup fails, it will assume that the135user intended to find the name in a dependent base.  While parsing the136following program, Clang will recover as if the user had written the137commented-out code:138 139.. _frequently asked question:140  https://clang.llvm.org/compatibility.html#dep_lookup141 142.. code-block:: c++143 144  template <typename T>145  struct Foo : T {146    void f() {147      /*typename*/ T::UnknownType x =  /*this->*/unknownMember;148    }149  };150 151After recovery, Clang warns the user that this code is non-standard and issues152a hint suggesting how to fix the problem.153 154As of this writing, Clang is able to compile a simple ATL hello world155application.  There are still issues parsing WRL headers for modern Windows 8156apps, but they should be addressed soon.157 158__forceinline behavior159======================160 161``__forceinline`` behaves like ``[[clang::always_inline]]``.162Inlining is always attempted regardless of optimization level.163 164This differs from MSVC where ``__forceinline`` is only respected once inline expansion is enabled165which allows any function marked implicitly or explicitly ``inline`` or ``__forceinline`` to be expanded.166Therefore functions marked ``__forceinline`` will be expanded when the optimization level is ``/Od`` unlike167MSVC where ``__forceinline`` will not be expanded under ``/Od``.168 169SIMD and instruction set intrinsic behavior170===========================================171 172Clang follows the GCC model for intrinsics and not the MSVC model.173There are currently no plans to support the MSVC model.174 175MSVC intrinsics always emit the machine instruction the intrinsic models regardless of the compile time options specified.176For example ``__popcnt`` always emits the x86 popcnt instruction even if the compiler does not have the option enabled to emit popcnt on its own volition.177 178There are two common cases where code that compiles with MSVC will need reworking to build on clang.179Assume the examples are only built with `-msse2` so we do not have the intrinsics at compile time.180 181.. code-block:: c++182 183  unsigned PopCnt(unsigned v) {184    if (HavePopCnt)185      return __popcnt(v);186    else187      return GenericPopCnt(v);188  }189 190.. code-block:: c++191 192  __m128 dot4_sse3(__m128 v0, __m128 v1) {193    __m128 r = _mm_mul_ps(v0, v1);194    r = _mm_hadd_ps(r, r);195    r = _mm_hadd_ps(r, r);196    return r;197  }198 199Clang expects that either you have compile time support for the target features, `-msse3` and `-mpopcnt`, you mark the function with the expected target feature or use runtime detection with an indirect call.200 201.. code-block:: c++202 203  __attribute__((__target__("sse3"))) __m128 dot4_sse3(__m128 v0, __m128 v1) {204    __m128 r = _mm_mul_ps(v0, v1);205    r = _mm_hadd_ps(r, r);206    r = _mm_hadd_ps(r, r);207    return r;208  }209 210The SSE3 dot product can be easily fixed by either building the translation unit with SSE3 support or using `__target__` to compile that specific function with SSE3 support.211 212.. code-block:: c++213 214  unsigned PopCnt(unsigned v) {215    if (HavePopCnt)216      return __popcnt(v);217    else218      return GenericPopCnt(v);219  }220 221The above ``PopCnt`` example must be changed to work with clang. If we mark the function with `__target__("popcnt")` then the compiler is free to emit popcnt at will which we do not want. While this isn't a concern in our small example it is a concern in larger functions with surrounding code around the intrinsics. Similar reasoning for compiling the translation unit with `-mpopcnt`.222We must split each branch into its own function that can be called indirectly instead of using the intrinsic directly.223 224.. code-block:: c++225 226  __attribute__((__target__("popcnt"))) unsigned hwPopCnt(unsigned v) { return __popcnt(v); }227  unsigned (*PopCnt)(unsigned) = HavePopCnt ? hwPopCnt : GenericPopCnt;228 229.. code-block:: c++230 231  __attribute__((__target__("popcnt"))) unsigned hwPopCnt(unsigned v) { return __popcnt(v); }232  unsigned PopCnt(unsigned v) {233    if (HavePopCnt)234      return hwPopCnt(v);235    else236      return GenericPopCnt(v);237  }238 239In the above example ``hwPopCnt`` will not be inlined into ``PopCnt`` since ``PopCnt`` doesn't have the popcnt target feature.240With a larger function that does real work the function call overhead is negligible. However in our popcnt example there is the function call241overhead. There is no analog for this specific MSVC behavior in clang.242 243For clang we effectively have to create the dispatch function ourselves to each specific implementation.244 245SIMD vector types246=================247 248Clang's simd vector types are builtin types and not user defined types as in MSVC. This does have some observable behavior changes.249We will look at the x86 `__m128` type for the examples below but the statements apply to all vector types including ARM's `float32x4_t`.250 251There are no members that can be accessed on the vector types. Vector types are not structs in clang.252You cannot use ``__m128.m128_f32[0]`` to access the first element of the `__m128`.253This also means struct initialization like ``__m128{ { 0.0f, 0.0f, 0.0f, 0.0f } }`` will not compile with clang.254 255Since vector types are builtin types, clang implements operators on them natively.256 257.. code-block:: c++258 259  #ifdef _MSC_VER260  __m128 operator+(__m128 a, __m128 b) { return _mm_add_ps(a, b); }261  #endif262 263The above code will fail to compile since overloaded 'operator+' must have at least one parameter of class or enumeration type.264You will need to fix such code to have the check ``#if defined(_MSC_VER) && !defined(__clang__)``.265 266Since `__m128` is not a class type in clang any overloads after a template definition will not be considered.267 268.. code-block:: c++269 270  template<class T>271  void foo(T) {}272 273  template<class T>274  void bar(T t) {275    foo(t);276  }277 278  void foo(__m128) {}279 280  int main() {281    bar(_mm_setzero_ps());282  }283 284With MSVC ``foo(__m128)`` will be selected but with clang ``foo<__m128>()`` will be selected since on clang `__m128` is a builtin type.285 286In general the takeaway is `__m128` is a builtin type on clang while a class type on MSVC.287