Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
f6dadc0
Some Cpp Core Guidelines warning fixes (#2116)
AlexGuteniev Mar 30, 2023
f1206d8
P2374R4: `views::cartesian_product` (#3561)
JMazurkiewicz Mar 30, 2023
9231abe
Python cleanups (#3598)
StephanTLavavej Mar 30, 2023
5d4aa49
Revert the ppltasks change that introduced an `ole32.dll` dependency …
StephanTLavavej Apr 4, 2023
8a652e6
Document import library (#2141)
AlexGuteniev Apr 7, 2023
10f0c3a
Build the import lib with `_ENFORCE_ONLY_CORE_HEADERS` (#3621)
StephanTLavavej Apr 7, 2023
0461a50
`type_index::operator<=>` should not call the comparison function twi…
frederick-vs-ja Apr 7, 2023
97f5698
`<ranges>`: Explicitly specify the template parameters for `tuple` (#…
cpplearner Apr 7, 2023
b37ff31
Testing: Check new C++23 CPOs (#3610)
JMazurkiewicz Apr 7, 2023
adaf68c
Testing: Check `c(begin|end)` members of C++20 ranges (#3612)
JMazurkiewicz Apr 7, 2023
cb86d7e
Fix silent bad codegen for vectorized `meow_element()` above 4 GB (#3…
StephanTLavavej Apr 7, 2023
d494511
Don't include `<xmemory>` in `<optional>` and `<variant>` (#3624)
frederick-vs-ja Apr 7, 2023
2df667e
Move `_Char_traits_eq` and `_Char_traits_lt` from `<xstring>` to `<re…
frederick-vs-ja Apr 7, 2023
7eeef47
Don't include `<algorithm>` in `<chrono>` (#3626)
frederick-vs-ja Apr 7, 2023
b331f8d
Don't include `<bit>` in `<compare>` (#3627)
frederick-vs-ja Apr 7, 2023
e6a12f7
`vector_algorithms.cpp`: Add `vzeroupper`, so that it is there even i…
AlexGuteniev Apr 7, 2023
46124c7
Merge branch 'main' into unlimited-mdspan
StephanTLavavej Apr 7, 2023
34fce78
`<mdspan>` needs `<limits>` for `numeric_limits`.
StephanTLavavej Apr 7, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions docs/import_library.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<!-- Copyright (c) Microsoft Corporation. -->
<!-- SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -->

# Filenames

Mode | Import Library | DLL (VS) | DLL (GitHub) |
--------|----------------|-----------------|---------------------|
Release | `msvcprt.lib` | `msvcp140.dll` | `msvcp140_oss.dll` |
Debug | `msvcprtd.lib` | `msvcp140d.dll` | `msvcp140d_oss.dll` |

# Import Libraries

An import library is a `.lib` file that defines its symbols as imported from a DLL.

Usually there is one `.lib` file for one `.dll` file, with the same name.
The names are different for MSVC because it started encoding its ABI version into the DLL's filename,
but there was no reason to change the import library's filename.

Also, an import library usually only contains references to DLL symbols and doesn't define anything on its own.
However, this is purely a convention - nothing technically stops an import library
from containing object files that are effectively statically linked.

## Advantages of Injecting Additional Code

This is what the STL's import library does - it defines some functions and variables on its own.
This allows us to:

* Extend the STL implementation without altering the DLL export surface.
+ This has been critical in allowing us to implement C++17 `<filesystem>` and much more.
* Separately compile functions and constant data for improved throughput.
+ `<charconv>`'s lookup tables are a notable example.

## Limitations

The caveats of this technique are:

* It effectively defeats the purpose of the `/MD` and `/MDd` options by embedding part of
the STL implementation into the resulting user binaries, rather than staying in the STL's DLL.
* Due to the duplication in each user binary that links to the import library,
variables in the import library **cannot represent shared global state**.
+ This limitation is subtle (not readily apparent from the source code) and critical.
If shared global state is necessary, our only option while preserving bincompat is adding a satellite DLL.
* Due to having just two flavors of the import library (debug and release),
we cannot use anything that depends on `_CONTAINER_DEBUG_LEVEL` or `_ITERATOR_DEBUG_LEVEL`.

For these reasons, especially the last one, we need to strictly control what is used by the import library.
In particular, `basic_string` must not be used there.

## Core Headers

Restricting the import library to including core headers only is an effective way to avoid problems.
`locale0.cpp`'s inclusion of `<xfacet>` is currently a special case and should be treated with extreme caution.
4 changes: 2 additions & 2 deletions stl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -577,15 +577,15 @@ function(add_stl_dlls D_SUFFIX REL_OR_DBG)
target_stl_compile_options(msvcp${D_SUFFIX}_eha_objects ${REL_OR_DBG})

add_library(msvcp${D_SUFFIX} SHARED)
target_link_libraries(msvcp${D_SUFFIX} PRIVATE msvcp${D_SUFFIX}_eha_objects msvcp${D_SUFFIX}_objects msvcp${D_SUFFIX}_init_objects "${TOOLSET_LIB}/vcruntime${D_SUFFIX}.lib" "${TOOLSET_LIB}/msvcrt${D_SUFFIX}.lib" "ucrt${D_SUFFIX}.lib" "ole32.lib")
target_link_libraries(msvcp${D_SUFFIX} PRIVATE msvcp${D_SUFFIX}_eha_objects msvcp${D_SUFFIX}_objects msvcp${D_SUFFIX}_init_objects "${TOOLSET_LIB}/vcruntime${D_SUFFIX}.lib" "${TOOLSET_LIB}/msvcrt${D_SUFFIX}.lib" "ucrt${D_SUFFIX}.lib")
set_target_properties(msvcp${D_SUFFIX} PROPERTIES ARCHIVE_OUTPUT_NAME "msvcp140_base${D_SUFFIX}${VCLIBS_SUFFIX}")
set_target_properties(msvcp${D_SUFFIX} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
set_target_properties(msvcp${D_SUFFIX} PROPERTIES OUTPUT_NAME "msvcp140${D_SUFFIX}${VCLIBS_SUFFIX}")
target_link_options(msvcp${D_SUFFIX} PRIVATE ${link_options_${REL_OR_DBG}})

# import library 'statics'
add_library(msvcp${D_SUFFIX}_implib_objects OBJECT ${IMPLIB_SOURCES})
target_compile_definitions(msvcp${D_SUFFIX}_implib_objects PRIVATE _DLL)
target_compile_definitions(msvcp${D_SUFFIX}_implib_objects PRIVATE _DLL _ENFORCE_ONLY_CORE_HEADERS)
target_compile_options(msvcp${D_SUFFIX}_implib_objects PRIVATE /EHsc) # No /GL!
target_stl_compile_options(msvcp${D_SUFFIX}_implib_objects ${REL_OR_DBG})

Expand Down
4 changes: 2 additions & 2 deletions stl/inc/atomic
Original file line number Diff line number Diff line change
Expand Up @@ -524,8 +524,8 @@ inline void _Atomic_lock_acquire(long& _Spinlock) noexcept {
// Algorithm from Intel(R) 64 and IA-32 Architectures Optimization Reference Manual, May 2020
// Example 2-4. Contended Locks with Increasing Back-off Example - Improved Version, page 2-22
// The code in mentioned manual is covered by the 0BSD license.
int _Current_backoff = 1;
const int _Max_backoff = 64;
int _Current_backoff = 1;
constexpr int _Max_backoff = 64;
while (_InterlockedExchange(&_Spinlock, 1) != 0) {
while (__iso_volatile_load32(&reinterpret_cast<int&>(_Spinlock)) != 0) {
for (int _Count_down = _Current_backoff; _Count_down != 0; --_Count_down) {
Expand Down
10 changes: 5 additions & 5 deletions stl/inc/charconv
Original file line number Diff line number Diff line change
Expand Up @@ -980,7 +980,7 @@ void _Assemble_floating_point_infinity(const bool _Is_negative, _FloatingType& _
_Uint_type _Sign_component = _Is_negative;
_Sign_component <<= _Floating_traits::_Sign_shift;

const _Uint_type _Exponent_component = _Floating_traits::_Shifted_exponent_mask;
constexpr _Uint_type _Exponent_component = _Floating_traits::_Shifted_exponent_mask;

_Result = _Bit_cast<_FloatingType>(_Sign_component | _Exponent_component);
}
Expand Down Expand Up @@ -1227,12 +1227,12 @@ _NODISCARD errc _Assemble_floating_point_value_from_big_integer_flt(const _Big_i
_FloatingType& _Result) noexcept {
using _Traits = _Floating_type_traits<_FloatingType>;

const int32_t _Base_exponent = _Traits::_Mantissa_bits - 1;
constexpr int32_t _Base_exponent = _Traits::_Mantissa_bits - 1;

// Very fast case: If we have 64 bits of precision or fewer,
// we can just take the two low order elements from the _Big_integer_flt:
if (_Integer_bits_of_precision <= 64) {
const int32_t _Exponent = _Base_exponent;
constexpr int32_t _Exponent = _Base_exponent;

const uint32_t _Mantissa_low = _Integer_value._Myused > 0 ? _Integer_value._Mydata[0] : 0;
const uint32_t _Mantissa_high = _Integer_value._Myused > 1 ? _Integer_value._Mydata[1] : 0;
Expand Down Expand Up @@ -1335,7 +1335,7 @@ _NODISCARD errc _Convert_decimal_string_to_floating_type(
// To generate an N bit mantissa we require N + 1 bits of precision. The extra bit is used to correctly round
// the mantissa (if there are fewer bits than this available, then that's totally okay;
// in that case we use what we have and we don't need to round).
const uint32_t _Required_bits_of_precision = static_cast<uint32_t>(_Traits::_Mantissa_bits + 1);
constexpr uint32_t _Required_bits_of_precision = static_cast<uint32_t>(_Traits::_Mantissa_bits + 1);

// The input is of the form 0.mantissa * 10^exponent, where 'mantissa' are the decimal digits of the mantissa
// and 'exponent' is the decimal exponent. We decompose the mantissa into two parts: an integer part and a
Expand Down Expand Up @@ -2167,7 +2167,7 @@ _NODISCARD to_chars_result _Floating_to_chars_hex_shortest(
// C11 7.21.6.1 "The fprintf function"/8: "If the value is zero, the exponent is zero."
// Special-casing zero is necessary because of the exponent.
const char* const _Str = "0p+0";
const size_t _Len = 4;
constexpr size_t _Len = 4;

if (_Last - _First < static_cast<ptrdiff_t>(_Len)) {
return {_Last, errc::value_too_large};
Expand Down
18 changes: 11 additions & 7 deletions stl/inc/chrono
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

#if _HAS_CXX20
#include <__msvc_tzdb.hpp>
#include <algorithm>
#include <atomic>
#include <cmath>
#include <compare>
Expand Down Expand Up @@ -2250,14 +2249,19 @@ namespace chrono {
auto [_Leap_sec, _All_ls_positive] = _Tzdb_generate_leap_seconds(_Tzdb_list.front().leap_seconds.size());
if (!_Leap_sec.empty()) {
const auto& _Tzdb = _Tzdb_list.front();

vector<time_zone> _Zones;
_STD transform(_Tzdb.zones.begin(), _Tzdb.zones.end(), _STD back_inserter(_Zones),
[](const auto& _Tz) { return time_zone{_Tz.name()}; });
_Zones.reserve(_Tzdb.zones.size());
for (const auto& _Tz : _Tzdb.zones) {
_Zones.emplace_back(_Tz.name());
}

vector<time_zone_link> _Links;
_STD transform(
_Tzdb.links.begin(), _Tzdb.links.end(), _STD back_inserter(_Links), [](const auto& _Link) {
return time_zone_link{_Link.name(), _Link.target()};
});
_Links.reserve(_Tzdb.links.size());
for (const auto& _Link : _Tzdb.links) {
_Links.emplace_back(_Link.name(), _Link.target());
}

auto _Version = _Tzdb_update_version(_Tzdb.version, _Leap_sec.size());
_Tzdb_list.emplace_front(tzdb{
_STD move(_Version), _STD move(_Zones), _STD move(_Links), _STD move(_Leap_sec), _All_ls_positive});
Expand Down
9 changes: 4 additions & 5 deletions stl/inc/compare
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
_EMIT_STL_WARNING(STL4038, "The contents of <compare> are available only with C++20 or later.");
#else // ^^^ !_HAS_CXX20 / _HAS_CXX20 vvv
#ifdef __cpp_lib_concepts
#include <bit>
#include <concepts>
#else // ^^^ __cpp_lib_concepts / !__cpp_lib_concepts vvv
#include <xtr1common>
Expand Down Expand Up @@ -427,8 +426,8 @@ namespace _Strong_order {
using _Uint_type = typename _Traits::_Uint_type;
using _Sint_type = make_signed_t<_Uint_type>;

const auto _Left_uint = _STD bit_cast<_Uint_type>(_Left);
const auto _Right_uint = _STD bit_cast<_Uint_type>(_Right);
const auto _Left_uint = _Bit_cast<_Uint_type>(_Left);
const auto _Right_uint = _Bit_cast<_Uint_type>(_Right);

// 1. Ultra-fast path: equal representations are equal.
if (_Left_uint == _Right_uint) {
Expand Down Expand Up @@ -534,8 +533,8 @@ namespace _Weak_order {
using _Uint_type = typename _Traits::_Uint_type;
using _Sint_type = make_signed_t<_Uint_type>;

auto _Left_uint = _STD bit_cast<_Uint_type>(_Left);
auto _Right_uint = _STD bit_cast<_Uint_type>(_Right);
auto _Left_uint = _Bit_cast<_Uint_type>(_Left);
auto _Right_uint = _Bit_cast<_Uint_type>(_Right);

// 1. Ultra-fast path: equal representations are equivalent.
if (_Left_uint == _Right_uint) {
Expand Down
2 changes: 1 addition & 1 deletion stl/inc/coroutine
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ struct coroutine_handle<noop_coroutine_promise> {

_NODISCARD noop_coroutine_promise& promise() const noexcept {
// Returns a reference to the associated promise
return *reinterpret_cast<noop_coroutine_promise*>(__builtin_coro_promise(_Ptr, 0, false));
return *static_cast<noop_coroutine_promise*>(__builtin_coro_promise(_Ptr, 0, false));
}

_NODISCARD constexpr void* address() const noexcept {
Expand Down
4 changes: 2 additions & 2 deletions stl/inc/execution
Original file line number Diff line number Diff line change
Expand Up @@ -2813,9 +2813,9 @@ inline size_t _Get_stable_sort_tree_height(const size_t _Count, const size_t _Hw
const auto _Ideal_chunks = _Hw_threads * _Oversubscription_multiplier;
const size_t _Log_ideal_chunks = _Floor_of_log_2(_Ideal_chunks);
#ifdef _WIN64
const size_t _Max_tree_height = 62; // to avoid ptrdiff_t overflow
constexpr size_t _Max_tree_height = 62; // to avoid ptrdiff_t overflow
#else // ^^^ _WIN64 / !_WIN64 vvv
const size_t _Max_tree_height = 30;
constexpr size_t _Max_tree_height = 30;
#endif // _WIN64
const size_t _Clamped_ideal_chunks = (_STD min)(_Max_tree_height, _Log_ideal_chunks);

Expand Down
3 changes: 2 additions & 1 deletion stl/inc/format
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ _EMIT_STL_WARNING(STL4038, "The contents of <format> are available only with C++
#else // ^^^ !defined(__cpp_lib_concepts) / defined(__cpp_lib_concepts) vvv

#include <__msvc_format_ucd_tables.hpp>
#include <bit>
#include <charconv>
#include <concepts>
#include <cstdint>
Expand Down Expand Up @@ -1982,7 +1983,7 @@ private:
template <class _Ty>
_NODISCARD static auto _Get_value_from_memory(const unsigned char* const _Val) noexcept {
auto& _Temp = *reinterpret_cast<const unsigned char(*)[sizeof(_Ty)]>(_Val);
return _Bit_cast<_Ty>(_Temp);
return _STD bit_cast<_Ty>(_Temp);
}

size_t _Num_args = 0;
Expand Down
1 change: 1 addition & 0 deletions stl/inc/mdspan
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
_EMIT_STL_WARNING(STL4038, "The contents of <mdspan> are available only with C++23 or later.");
#else // ^^^ not supported / supported language mode vvv
#include <array>
#include <limits>
#include <span>
#include <type_traits>

Expand Down
2 changes: 1 addition & 1 deletion stl/inc/memory_resource
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ namespace pmr {
#endif // _DEBUG
}

_Oversized_header* _Hdr = reinterpret_cast<_Oversized_header*>(reinterpret_cast<char*>(_Ptr) + _Bytes) - 1;
_Oversized_header* _Hdr = reinterpret_cast<_Oversized_header*>(static_cast<char*>(_Ptr) + _Bytes) - 1;

_STL_ASSERT(_Hdr->_Size == _Bytes && _Hdr->_Align == _Align,
"Cannot deallocate memory not allocated by this memory pool.");
Expand Down
6 changes: 3 additions & 3 deletions stl/inc/optional
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ _EMIT_STL_WARNING(STL4038, "The contents of <optional> are available only with C
#include <initializer_list>
#include <type_traits>
#include <utility>
#include <xmemory>
#include <xsmf_control.h>
#include <xutility>

#pragma pack(push, _CRT_PACKING)
#pragma warning(push, _STL_WARNING_LEVEL)
Expand Down Expand Up @@ -104,7 +104,7 @@ struct _Optional_destruct_base<_Ty, false> { // either contains a value of _Ty o

_CONSTEXPR20 ~_Optional_destruct_base() noexcept {
if (_Has_value) {
_Destroy_in_place(_Value);
_Value.~_Ty();
}
}

Expand All @@ -129,7 +129,7 @@ struct _Optional_destruct_base<_Ty, false> { // either contains a value of _Ty o

_CONSTEXPR20 void reset() noexcept {
if (_Has_value) {
_Destroy_in_place(_Value);
_Value.~_Ty();
_Has_value = false;
}
}
Expand Down
Loading