Commit Graph

1027 Commits

Author SHA1 Message Date
Louis Dionne bc556e5685 [libc++/abi] Re-remove unnecessary null pointer checks from operator delete
In 7cd67904f7, we removed the unnecessary nullptr checks from the libc++abi
definition of operator delete, but we forgot to update the definition in
libc++ (damn code duplication!). Then, in d4a1e03c5f, I synced the
definitions across libc++ and libc++abi, but I did it the wrong way around.
I re-added the if() checks to libc++abi instead of removing them from libc++.

In ef74f0fdc3, we re-removed the if() check from operator delete, but
only in libc++abi. This patch corrects this mess and removes it
consistently in libc++ and libc++abi.

Differential Revision: https://reviews.llvm.org/D93473
2021-01-08 17:03:50 -05:00
Fangrui Song 85f86e8a3c [libc++abi] Simplify __gxx_personality_v0
In three cases we call `scan_eh_tab` to parse LSDA:

* `actions & _UA_SEARCH_PHASE`
* `actions & _UA_CLEANUP_PHASE && actions & _UA_HANDLER_FRAME && !native_exception`
* `actions & _UA_CLEANUP_PHASE && !(actions & _UA_HANDLER_FRAME)`

Check
`actions & _UA_CLEANUP_PHASE && actions & _UA_HANDLER_FRAME && native_exception` first,
then we can move three `scan_eh_tab` into one place.

Another simplification is that we can check whether the result of `scan_eh_tab`
is `_UA_CONTINUE_UNWIND` or `_UA_FATAL_PHASE1_ERROR` first. Then many of the
original checks will be dead and can thus be deleted.

Reviewed By: #libc_abi, ldionne

Differential Revision: https://reviews.llvm.org/D93186
2021-01-07 14:05:46 -08:00
Fangrui Song ef74f0fdc3 [libc++abi] Remove redundant null pointer check in operator delete
Similar to D52401. Normally operator delete is defined in libc++abi
(LIBCPP_DISABLE_NEW_DELETE_DEFINITIONS is off by default).

C89 4.10.3.2 The free function
C99 7.20.3.2 The free function
C11 7.22.3.3 The free function

    If ptr is a null pointer, no action shall occur.

free on MSDN:

    If memblock is NULL, the pointer is ignored and free immediately returns.

Reviewed By: #libc_abi, ldionne

Differential Revision: https://reviews.llvm.org/D93339
2020-12-16 13:29:40 -08:00
Louis Dionne d67e58f23a [libc++abi] Don't try calling __libcpp_aligned_free when aligned allocation is disabled
See https://reviews.llvm.org/rGa78aaa1ad512#962077 for details.
2020-12-01 17:45:14 -05:00
Leonard Chan 61aec69a65 [libcxxabi] Add macro for changing functions to support the relative vtables ABI
Under the relative vtables ABI, __dynamic_cast will not work since it assumes
the vtable pointer is 2 ptrdiff_ts away from the start of the vtable (8-byte
offset to top + 8-byte pointer to typeinfo) when it is actually 8 bytes away
(4-byte offset to top + 4-byte offset to typeinfo). This adjusts the logic under
__dynamic_cast and other areas vtable calculations are done to support this ABI
when it's used.

Differential Revision: https://reviews.llvm.org/D77606
2020-11-30 10:50:05 -08:00
Louis Dionne 564628014c [libc++] Introduce an indirection to create threads in the test suite
We create threads using std::thread in various places in the test suite.
However, the usual std::thread constructor may not work on all platforms,
e.g. on platforms where passing a stack size is required to create a thread.

This commit introduces a simple indirection that makes it easier to tweak
how threads are created inside the test suite on various platforms. Note
that tests that are purposefully calling std::thread's constructor directly
(e.g. because that is what they're testing) were not modified.
2020-11-27 11:54:19 -05:00
Bruce Mitchener 527a7fdfbd [libc++] Replace several uses of 0 by nullptr
Differential Revision: https://reviews.llvm.org/D43159
2020-11-27 10:00:21 -05:00
Marek Kurdej 5641b1dfdd [libc++] Mark a few more tests as unsupported on gcc-8/9.
This will fix remaining failures on gcc-9 buildbot: http://lab.llvm.org:8011/#/builders/101.
gcc-8 and gcc-9 do not support constexpr destructors nor constexpr allocation.

Fix gcc warnings: -Wconversion, -Wpragmas.
2020-11-26 12:40:50 +01:00
Marek Kurdej dde0fcd7a7 [libc++] [libc++abi] Mark a few tests as unsupported/xfail on gcc-7/8/9.
This should make the builder http://lab.llvm.org:8011/#/builders/101/ happy.
It uses gcc-9 and not Tip-Of-Trunk as its name indicates BTW.
GCC-10 passes all these tests.

Fix gcc warnings: -Wsign-compare, -Wparentheses, -Wpragmas.

Reviewed By: ldionne, #libc, #libc_abi

Differential Revision: https://reviews.llvm.org/D92099
2020-11-26 08:59:52 +01:00
Louis Dionne a78aaa1ad5 [libc++] Factor out common logic for calling aligned allocation
There were a couple of places where we needed to call the underlying
platform's aligned allocation/deallocation function. Instead of having
the same logic all over the place, extract the logic into a pair of
helper functions __libcpp_aligned_alloc and __libcpp_aligned_free.

The code in libcxxabi/src/fallback_malloc.cpp looks like it could be
simplified after this change -- I purposefully did not simplify it
further to keep this change as straightforward as possible, since it
is touching very important parts of the library.

Also, the changes in libcxx/src/new.cpp and libcxxabi/src/stdlib_new_delete.cpp
are basically the same -- I just kept both source files in sync.

The underlying reason for this refactoring is to make it easier to support
platforms that provide aligned allocation through C11's aligned_alloc
function instead of posix_memalign. After this change, we'll only have
to add support for that in a single place.

Differential Revision: https://reviews.llvm.org/D91379
2020-11-25 15:44:50 -05:00
Marek Kurdej 3b625060fc [libc++] [libc++abi] Use C++20 standard.
This change is needed to use char8_t when building libc++.
Using the same standard in libc++abi for coherence.

See https://reviews.llvm.org/D91517.

Reviewed By: ldionne, #libc, #libc_abi

Differential Revision: https://reviews.llvm.org/D91691
2020-11-22 15:57:25 +01:00
Richard Smith bec968cbb3 Demangling support for class type non-type template parameter extensions.
The extensions in question are described in:
https://github.com/itanium-cxx-abi/cxx-abi/issues/47
https://github.com/itanium-cxx-abi/cxx-abi/issues/63

Differential Revision: https://reviews.llvm.org/D90003
2020-11-20 13:45:08 -08:00
Louis Dionne a7b6574144 [libc++abi] Reuse libc++'s refstring.h header instead of copying it
This has been a long-standing TODO item, however we have now been requiring
a monorepo layout to build libc++ and libc++abi for a while now. Hence,
we can fix this code duplication issue now.

Note that it's still not super pretty to reach into libc++ to include
headers, but it's better than having duplicated code which can get out
of sync.
2020-11-11 16:58:32 -05:00
Louis Dionne 8d51969bd4 [runtimes] Avoid overwriting the rpath unconditionally
When building the runtimes, it's very important not to add rpaths unless
the user explicitly asks for them (the standard way being CMAKE_INSTALL_RPATH),
or to change the install name dir unless the user requests it (via
CMAKE_INSTALL_NAME_DIR).

llvm_setup_rpath() would override the install_name_dir of the runtimes
even if CMAKE_INSTALL_NAME_DIR was specified to something, which is wrong
and in fact even "dangerous" for the runtimes.

This issue was discovered when trying to build libc++ and libc++abi as
system libraries for Apple, where we set the install name dir to /usr/lib
explicitly. llvm_setup_rpath() would cause libc++ to have the wrong install
name dir, and for basically everything on the system to fail to load.
This was discovered just now because we previously used something closer
to a standalone build, where llvm_setup_rpath() wouldn't exist, and hence
not be used.

This is a revert of the following commits:

  libunwind: 3a667b9bd8
  libc++abi: 4877063e19
  libc++: 88434fe05f

Those added llvm_setup_rpath() for consistency, so it seems reasonable
to revert.

Differential Revision: https://reviews.llvm.org/D91099
2020-11-09 16:56:03 -05:00
Louis Dionne c1887e3f15 Revert "Allow running back-deployment testing against libc++abi"
This reverts commit 4d79ef814a, which broke a few build bots.
I'm reverting until I have time to investigate.
2020-11-06 17:26:42 -05:00
Louis Dionne 4d79ef814a Allow running back-deployment testing against libc++abi
Summary:
Before this patch, we could only link against the back-deployment libc++abi
dylib. This patch allows linking against the just-built libc++abi, but
running against the back-deployment one -- just like we do for libc++.

Also, add XFAIL markup to flag expected errors.
2020-11-06 08:12:46 -05:00
Martin Storsjö 8a73aa8c4c [libcxx] [libcxxabi] Set flags for visibility when statically linking libcxxabi into libcxx for windows
Previously, these had to be set manually when building each of the
projects standalone, in order to get proper symbol visibility when
combining the two libraries.

Differential Revision: https://reviews.llvm.org/D90021
2020-11-03 17:13:48 +02:00
Martin Storsjö 9c30bafd59 [libcxxabi] Build all of libcxxabi with _LIBCPP_BUILDING_LIBRARY defined
Various definitions from libcxx need to be set in the same way
as if building libcxx itself.

Differential Revision: https://reviews.llvm.org/D90476
2020-11-03 09:32:52 +02:00
Louis Dionne 1b2fa6e46e [libc++/libc++abi] Use Python3_EXECUTABLE consistently to run utilities 2020-11-02 11:07:31 -05:00
Louis Dionne 8d31392753 [libc++abi] Get rid of warnings when running the tests with GCC 2020-11-02 10:19:39 -05:00
Louis Dionne b888463f8d [libc++abi] Make sure we can run the tests in Standalone mode
The tests would previously fail if the `python` executable wasn't found,
because we were missing the mandatory find_package.
2020-10-26 14:26:44 -04:00
Louis Dionne 2f8dd2687f [libc++] Refactor the run-buildbot script to make it more modular, and run the benchmarks
As a fly-by fix, unbreak the benchmarks on Apple platforms.

Differential Revision: https://reviews.llvm.org/D90043
2020-10-23 15:11:41 -04:00
Louis Dionne 48e4b0fd3a [runtimes] Revert the libc++ __config_site change
This is a massive revert of the following commits (from most revent to oldest):

	2b9b7b5775.
	529ac33197
	28270234f1
	69c2087283
	b5aa67446e
	5d796645d6

After checking-in the __config_site change, a lot of things started breaking
due to widespread reliance on various aspects of libc++'s build, notably the
fact that we can include the headers from the source tree, but also reliance
on various "internal" CMake variables used by the runtimes build and compiler-rt.

These were unintended consequences of the change, and after two days, we
still haven't restored all the bots to being green. Instead, now that I
understand what specific areas this will blow up in, I should be able to
chop up the patch into smaller ones that are easier to digest.

See https://reviews.llvm.org/D89041 for more details on this adventure.
2020-10-23 09:41:48 -04:00
Louis Dionne 529ac33197 [libc++abi] Fix the standalone build after the __config_site change
In 5d796645, we stopped looking at the LIBCXXABI_LIBCXX_INCLUDES variable,
which broke users of the Standalone build. This patch reinstates that
variable, however it must point to the *installed* path of the libc++
headers, not the libc++ headers in the source tree (which has always
been the case, but wasn't enforced before).

If LIBCXXABI_LIBCXX_INCLUDES points to the libc++ headers in the source
tree, the `__config_site` header will fail to be found.
2020-10-22 19:17:20 -04:00
Martin Storsjö 5449ea9f90 [libcxxabi] Define _LIBCXXABI_WEAK properly for mingw compilers
Copy over the compiler detection structure from libcxx, and set
_LIBCXXABI_WEAK like _LIBCPP_WEAK is set in libcxx.

This allows users to override operator new/delete, if using those
operators from libcxxabi instead of from libcxx.

Differential Revision: https://reviews.llvm.org/D89863
2020-10-22 09:00:57 +03:00
Louis Dionne 69c2087283 [libc++] Fix compiler-rt build by copying libc++ headers to <build>/include
This commit should really be named "Workaround external projects depending
on libc++ build system implementation details". It seems that the compiler-rt
build (and perhaps other projects) is relying on the fact that we copy libc++
and libc++abi headers to `<build-root>/include/c++/v1`. This was changed
by 5d796645, which moved the headers to `<build-root>/projects/libcxx/include/c++/v1`
and broke the compiler-rt build.

I'm committing this workaround to fix the compiler-rt build, but we should
remove reliance on implementation details like that. The correct way to
setup the compiler-rt build would be to "link" against the `cxx-headers`
target in CMake, or to run `install-cxx-headers` using an appropriate
installation prefix, and then manually add a `-I` path to that location.
2020-10-21 16:56:33 -04:00
Hafiz Abid Qadeer 272279a1c0 [libcxxabi] Stub out 'sleep' call when _LIBCXXABI_HAS_NO_THREADS is defined.
While running this test on a bare metal target, I got an error as 'sleep' was not available on that system. As 'sleep' call is not doing anything useful for cases when _LIBCXXABI_HAS_NO_THREADS is defined. This patch puts it under this check.

Reviewed By: ldionne

Differential Revision: https://reviews.llvm.org/D89871
2020-10-21 20:56:24 +01:00
Louis Dionne 5d796645d6 [take 2] [libc++] Include <__config_site> from <__config>
Prior to this patch, we would generate a fancy <__config> header by
concatenating <__config_site> and <__config>. This complexifies the
build system and also increases the difference between what's tested
and what's actually installed.

This patch removes that complexity and instead simply installs <__config_site>
alongside the libc++ headers. <__config_site> is then included by <__config>,
which is much simpler. Doing this also opens the door to having different
<__config_site> headers depending on the target, which was impossible before.

It does change the workflow for testing header-only changes to libc++.
Previously, we would run `lit` against the headers in libcxx/include.
After this patch, we run it against a fake installation root of the
headers (containing a proper <__config_site> header). This makes use
closer to testing what we actually install, which is good, however it
does mean that we have to update that root before testing header changes.
Thus, we now need to run `ninja check-cxx-deps` before running `lit` by
hand.

This commit was originally applied in 1e46d1aa3 and reverted in eb60c487
because it broke the libc++abi and libunwind test suites. This has now
been fixed.

Differential Revision: https://reviews.llvm.org/D89041
2020-10-21 10:40:33 -04:00
Louis Dionne eb60c48744 [libc++] Revert "Include <__config_site> from <__config>"
This temporarily reverts commit 1e46d1aa until I find a solution to fix
the libc++abi and libunwind test suites with that change.
2020-10-21 09:18:29 -04:00
Louis Dionne 1e46d1aa3f [libc++] Include <__config_site> from <__config>
Prior to this patch, we would generate a fancy <__config> header by
concatenating <__config_site> and <__config>. This complexifies the
build system and also increases the difference between what's tested
and what's actually installed.

This patch removes that complexity and instead simply installs <__config_site>
alongside the libc++ headers. <__config_site> is then included by <__config>,
which is much simpler. Doing this also opens the door to having different
<__config_site> headers depending on the target, which was impossible before.

It does change the workflow for testing header-only changes to libc++.
Previously, we would run `lit` against the headers in libcxx/include.
After this patch, we run it against a fake installation root of the
headers (containing a proper <__config_site> header). This makes use
closer to testing what we actually install, which is good, however it
does mean that we have to update that root before testing header changes.
Thus, we now need to run `ninja check-cxx-deps` before running `lit` by
hand.

Differential Revision: https://reviews.llvm.org/D89041
2020-10-21 08:46:57 -04:00
Eric Fiselier 229db36474 [libc++] Make __shared_weak_count vtable consistent across all build configurations
This patch ensures that __shared_weak_count provides a consistent vtable
regardless of if RTTI is enabled or if we are targeting a static or shared
libc++ build.

This patch is technically ABI breaking, but only for a very specific
configuration that no vendor should be shipping.

Note that _LIBCPP_BUILD_STATIC is not normally defined when building
libc++.a, but instead it must be manually provided by the user or the
__config_site.

Differential Revision: https://reviews.llvm.org/D32838
2020-10-20 08:19:43 -04:00
Louis Dionne 9b40ee8eb0 [libc++] Define new/delete in libc++abi only by default
Previously, we would define new/delete in both libc++ and libc++abi.
Not only does this cause code bloat, but also it's technically an ODR
violation since we don't know which operator will be selected. Furthermore,
since those are weak definitions, we should strive to have as few of them
as possible (to improve load times).

My preferred choice would have been to put the operators in libc++ only
by default, however that would create a circular dependency between
libc++ and libc++abi, which GNU linkers don't handle.

Folks who want to ship new/delete in libc++ instead of libc++abi are
free to do so by turning on LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS at
CMake configure time.

On Apple platforms, this shouldn't be an ABI break because we re-export
the new/delete symbols from libc++abi. This change actually makes libc++
behave closer to the system libc++ shipped on Apple platforms.

On other platforms, this is an ABI break for people linking against libc++
but not libc++abi. However, vendors have been consulted in D68269 and no
objection was raised. Furthermore, the definitions can be controlled to
appear in libc++ instead with the CMake option.

Differential Revision: https://reviews.llvm.org/D68269
2020-10-19 11:35:01 -04:00
Simon Tatham bcb7b87706 [libcxxabi] Fix printf formats in a test.
This is the libcxxabi counterpart of D89545, and would have been part
of that patch if I'd spotted it soon enough (oops). One test in
libcxxabi is using the `%lu` printf format to refer to `size_t`, which
should be `%zu`.

Reviewed By: ldionne, #libc_abi

Differential Revision: https://reviews.llvm.org/D89547
2020-10-16 13:59:11 +01:00
Dominik Montada 8c03fdf34a [libcxxabi,libunwind] support running tests in standalone mode
Remove check for standalone and shared library mode in libcxxabi to
allow including tests in said mode. This check prevented running the
tests in standalone mode with static libraries, which is the case for
baremetal targets.

Fix check-unwind target trying to use a non-existent llvm-lit executable
in standalone mode. Copy the HandleOutOfTreeLLVM logic from libcxxabi to
libunwind in order to make the tests work in standalone mode.

Reviewed By: ldionne, #libc_abi, #libc

Differential Revision: https://reviews.llvm.org/D86540
2020-10-14 09:10:20 +02:00
Louis Dionne cc69d211d0 [libc++/abi] Clean up uses of <iostream> in the test suite
We used <iostream> in several places where we don't actually need the
full power of <iostream>, and where using basic `std::printf` is enough.
This is better, since `std::printf` can be supported on systems that don't
have a notion of locales, while <iostream> can't.
2020-10-13 20:25:33 -04:00
Raphael Isemann 6b7a49bb43 Fix all the CMake code that can only handle -stdlib= but not --stdlib=
There are several places in LLVM's CMake setup that try to remove the
`stdlib=...` flag from the CMake flags. All this code however only considered
the `-stdlib=` variant of the flag but not the alternative spelling with a
double dash. This causes that when one adds `--stdlib=...` to the user-provided
CMake flags that this gets transformed into just `-` which ends up causing the
build system to think it should read the source from stdin (which then lead to
very confusing build errors).

This just adds the alternative spelling before the`-stdlib=` variant in all
these places

Reviewed By: ldionne

Differential Revision: https://reviews.llvm.org/D87133
2020-10-13 16:05:21 +02:00
Louis Dionne 504bc07d1a [runtimes] Use int main(int, char**) consistently in tests
This is needed when running the tests in Freestanding mode, where main()
isn't treated specially. In Freestanding, main() doesn't get mangled as
extern "C", so whatever runtime we're using fails to find the entry point.

One way to solve this problem is to define a symbol alias from __Z4mainiPPc
to _main, however this requires all definitions of main() to have the same
mangling. Hence this commit.
2020-10-08 14:28:13 -04:00
Louis Dionne d5a6da84a3 [libc++/abi] Revert "[libc++] Move the weak symbols list to libc++abi"
This reverts commit c7d4aa711a. I am still investigating the issue,
but it looks like that commit has an interaction with ld64 that causes
new/delete weak re-exports not to work properly anymore. This is weird
because this commit did not touch the exports of new/delete -- I am
still investigating.
2020-10-05 11:42:13 -04:00
Louis Dionne c7d4aa711a [libc++] Move the weak symbols list to libc++abi
Those symbols are exported from libc++abi in the first place, so it
makes more sense to have them there.
2020-10-02 09:22:23 -04:00
Louis Dionne 8654a0f8bb [libc++] Don't re-export new/delete from libc++abi when they are defined in libc++
This is a temporary workaround until the new/delete situation is made
better (i.e. we don't include new/delete in both libc++ and libc++abi
by default).
2020-10-01 13:31:55 -04:00
Louis Dionne 4f13b99929 [libc++] Simplify how we re-export symbols from libc++abi
Instead of managing two copies of the symbol lists, reuse the same list
in libc++abi and libc++.

Differential Revision: https://reviews.llvm.org/D88623
2020-10-01 08:30:27 -04:00
Louis Dionne f9e70fa546 [libc++] Rename the -fno-rtti Lit feature to just no-rtti
This is consistent to the way we name other Lit features, and it removes
the possibility for confusing the Lit feature with the actual compiler
flag.
2020-09-29 16:29:44 -04:00
Louis Dionne d0667562e1 [libc++] Fix some test failures in unusual configurations 2020-09-29 16:22:56 -04:00
Louis Dionne da104444fa [libc++] Allow building without threads in standalone builds
Setting _LIBCPP_HAS_NO_THREADS is needed when building libcxxabi without
threads in standalone mode. This is useful when target WASM. Otherwise,
you get an error like "No thread API" when building libcxxabi.

It would be better to link against a properly-configured libc++ headers
CMake target when building libc++abi instead, but we don't generate such
targets yet.

Thanks to Matthew Bauer for the patch.

Differential Revision: https://reviews.llvm.org/D60743
2020-09-15 08:44:48 -04:00
Louis Dionne 8bd0dc5bfe [libc++abi] Do not declare __cxa_finalize and __cxa_atexit in <cxxabi.h>
These functions are not defined by libc++abi, so they don't belong in <cxxabi.h>.

Differential Revision: https://reviews.llvm.org/D75795
2020-09-14 20:10:29 -04:00
Louis Dionne ec46cfefe8 [libcxx] Simplify back-deployment testing
The needs of back-deployment testing currently require two different
ways of running the test suite: one based on the deployment target,
and one based on the target triple. Since the triple includes all the
information we need, it's better to have just one way of doing things.

Furthermore, `--param platform=XXX` is also supersedded by using the
target triple. Previously, this parameter would serve the purpose of
controling XFAILs for availability markup errors, however it is possible
to achieve the same thing by using with_system_cxx_lib only and using
.verify.cpp tests instead, as explained in the documentation changes.

The motivation for this change is twofold:
1. This part of the Lit config has always been really confusing and
   complicated, and it has been a source of bugs in the past. I have
   simplified it iteratively in the past, but the complexity is still
   there.
2. The deployment-target detection started failing in weird ways in
   recent Clangs, breaking our CI. Instead of band-aid patching the
   issue, I decided to remove the complexity altogether by using target
   triples even on Apple platforms.

A follow-up to this commit will bring the test suite in line with
the recommended way of handling availability markup tests.
2020-09-10 08:17:26 -04:00
Elliott Hughes 96a979c0c2 Fix test for D77924.
The trailing 'L' was missing in the expectation.

Differential Revision: https://reviews.llvm.org/D86321
2020-08-24 15:32:58 -07:00
Elliott Hughes a7d0b7a786 ld128 demangle: allow space for 'L' suffix.
Summary:
Caught by HWASAN on arm64 Android (which uses ld128 for long double). This
was running the existing fuzzer.

The specific minimized fuzz input to reproduce this is:

  __cxa_demangle("1\006ILeeeEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE", 0, 0, 0);

Reviewers: eugenis, srhines, #libc_abi!

Subscribers: kristof.beyls, danielkiss, libcxx-commits

Tags: #libc_abi

Differential Revision: https://reviews.llvm.org/D77924
2020-08-18 16:14:05 -07:00
Aditya Kumar d54f5979bb Add cold attribute to one time construction APIs
_cxa_guard_acquire is used for only one purpose,
namely guarding local static variable initialization,
and since that purpose is definitionally cold,
it should be attributed as cold

Reviewed By: ldionne

Reviewers: mclow.lists, ldionne, jfb, yfeldblum

Differential Revision: https://reviews.llvm.org/D85873
2020-08-13 09:28:04 -07:00
Louis Dionne d0ad9e93ce [libc++abi] Make sure we use a 32 bit guard on 32 bit Aarch64 2020-08-04 15:12:03 -04:00