Commit Graph

315 Commits

Author SHA1 Message Date
Duncan P. N. Exon Smith 8d536973a2 IR: Update references to temporaries before deleting
During `MDNode::deleteTemporary()`, call `replaceAllUsesWith(nullptr)`
to update all tracking references to `nullptr`.

This fixes PR22280, where inverted destruction order between tracking
references and the temporaries themselves caused a use-after-free in
`LLParser`.

An alternative fix would be to add an assertion that there are no users,
and continue to fix inverted destruction order in clients (like
`LLParser`), but instead I decided to make getting-teardown-right easy.
(If someone disagrees let me know.)

llvm-svn: 226866
2015-01-22 21:36:45 +00:00
Duncan P. N. Exon Smith 13890af51c AsmParser: Fix error location for missing fields
llvm-svn: 226524
2015-01-19 23:32:36 +00:00
Duncan P. N. Exon Smith 2f5bb31302 IR: Allow 16-bits for column info
Raise the limit for column information from 8 bits to 16 bits.

llvm-svn: 226291
2015-01-16 17:33:08 +00:00
Duncan P. N. Exon Smith 9885469922 IR: Move MDLocation into place
This commit moves `MDLocation`, finishing off PR21433.  There's an
accompanying clang commit for frontend testcases.  I'll attach the
testcase upgrade script I used to PR21433 to help out-of-tree
frontends/backends.

This changes the schema for `DebugLoc` and `DILocation` from:

    !{i32 3, i32 7, !7, !8}

to:

    !MDLocation(line: 3, column: 7, scope: !7, inlinedAt: !8)

Note that empty fields (line/column: 0 and inlinedAt: null) don't get
printed by the assembly writer.

llvm-svn: 226048
2015-01-14 22:27:36 +00:00
Duncan P. N. Exon Smith 503cf3bff9 IR: Always print MDLocation line
Print `MDLocation`'s `line` field even when it's 0.

llvm-svn: 226046
2015-01-14 22:14:26 +00:00
Rafael Espindola 4e74d3be35 Add support for comdats with names larger than 256 characters.
llvm-svn: 226012
2015-01-14 18:25:45 +00:00
Duncan P. N. Exon Smith 6a4848324b AsmParser/Bitcode: Add support for MDLocation
This adds assembly and bitcode support for `MDLocation`.  The assembly
side is rather big, since this is the first `MDNode` subclass (that
isn't `MDTuple`).  Part of PR21433.

(If you're wondering where the mountains of testcase updates are, we
don't need them until I update `DILocation` and `DebugLoc` to actually
use this class.)

llvm-svn: 225830
2015-01-13 21:10:44 +00:00
Duncan P. N. Exon Smith 090a19bd3c IR: Add 'distinct' MDNodes to bitcode and assembly
Propagate whether `MDNode`s are 'distinct' through the other types of IR
(assembly and bitcode).  This adds the `distinct` keyword to assembly.

Currently, no one actually calls `MDNode::getDistinct()`, so these nodes
only get created for:

  - self-references, which are never uniqued, and
  - nodes whose operands are replaced that hit a uniquing collision.

The concept of distinct nodes is still not quite first-class, since
distinct-ness doesn't yet survive across `MapMetadata()`.

Part of PR22111.

llvm-svn: 225474
2015-01-08 22:38:29 +00:00
Rafael Espindola 83a362cde8 Change the .ll syntax for comdats and add a syntactic sugar.
In order to make comdats always explicit in the IR, we decided to make
the syntax a bit more compact for the case of a GlobalObject in a
comdat with the same name.

Just dropping the $name causes problems for

@foo = globabl i32 0, comdat
$bar = comdat ...

and

declare void @foo() comdat
$bar = comdat ...

So the syntax is changed to

@g1 = globabl i32 0, comdat($c1)
@g2 = globabl i32 0, comdat

and

declare void @foo() comdat($c1)
declare void @foo() comdat

llvm-svn: 225302
2015-01-06 22:55:16 +00:00
Duncan P. N. Exon Smith 68c37245d3 DebugInfo: Update testcase to actually check something
This test was missing a `Debug Info Version` so it's `not grep` was
passing vacuously.  Update it to CHECK for something useful at the same
time so it doesn't bitrot quite so easily in the future.

llvm-svn: 224324
2014-12-16 07:08:19 +00:00
Duncan P. N. Exon Smith be7ea19b58 IR: Make metadata typeless in assembly
Now that `Metadata` is typeless, reflect that in the assembly.  These
are the matching assembly changes for the metadata/value split in
r223802.

  - Only use the `metadata` type when referencing metadata from a call
    intrinsic -- i.e., only when it's used as a `Value`.

  - Stop pretending that `ValueAsMetadata` is wrapped in an `MDNode`
    when referencing it from call intrinsics.

So, assembly like this:

    define @foo(i32 %v) {
      call void @llvm.foo(metadata !{i32 %v}, metadata !0)
      call void @llvm.foo(metadata !{i32 7}, metadata !0)
      call void @llvm.foo(metadata !1, metadata !0)
      call void @llvm.foo(metadata !3, metadata !0)
      call void @llvm.foo(metadata !{metadata !3}, metadata !0)
      ret void, !bar !2
    }
    !0 = metadata !{metadata !2}
    !1 = metadata !{i32* @global}
    !2 = metadata !{metadata !3}
    !3 = metadata !{}

turns into this:

    define @foo(i32 %v) {
      call void @llvm.foo(metadata i32 %v, metadata !0)
      call void @llvm.foo(metadata i32 7, metadata !0)
      call void @llvm.foo(metadata i32* @global, metadata !0)
      call void @llvm.foo(metadata !3, metadata !0)
      call void @llvm.foo(metadata !{!3}, metadata !0)
      ret void, !bar !2
    }
    !0 = !{!2}
    !1 = !{i32* @global}
    !2 = !{!3}
    !3 = !{}

I wrote an upgrade script that handled almost all of the tests in llvm
and many of the tests in cfe (even handling many `CHECK` lines).  I've
attached it (or will attach it in a moment if you're speedy) to PR21532
to help everyone update their out-of-tree testcases.

This is part of PR21532.

llvm-svn: 224257
2014-12-15 19:07:53 +00:00
David Majnemer 0a14c0ec9d AsmParser: Don't crash on an ill-formed MDNodeVector
llvm-svn: 224056
2014-12-11 20:51:54 +00:00
David Majnemer 06f960d5d3 AsmParser: Don't crash on an ill-formed MDNodeVector
llvm-svn: 224053
2014-12-11 20:44:09 +00:00
Duncan P. N. Exon Smith f910e8a04d IR: Add 'invalid-' to test names for invalid assembly
Take the opportunity to sort these by `metadata`.

llvm-svn: 223993
2014-12-11 01:34:46 +00:00
David Majnemer 612f31284e DataLayout: Provide nicer diagnostics for malformed strings
llvm-svn: 223911
2014-12-10 02:36:41 +00:00
David Majnemer 6f3be2e155 AsmParser: Don't allow null bytes in BB labels
Since Value objects can't have null bytes in their name, we shouldn't
allow them in the labels of basic blocks.

llvm-svn: 223907
2014-12-10 02:10:35 +00:00
David Majnemer 2dc1b0f514 DataLayout: Be more verbose when diagnosing problems in pointer specs
llvm-svn: 223903
2014-12-10 01:38:28 +00:00
David Majnemer 84f798f0eb I didn't intend to commit this with r223898
llvm-svn: 223899
2014-12-10 01:17:48 +00:00
David Majnemer 5330c69bd1 DataLayout: Move asserts over to report_fatal_error
As indicated by the tests, it is possible to feed the AsmParser an
invalid datalayout string.  We should verify the result of parsing this
string regardless of whether or not we have assertions enabled.

llvm-svn: 223898
2014-12-10 01:17:08 +00:00
David Majnemer 1d681aa0ba AsmParser: Don't crash if a null byte is inside a quoted string
We don't allow Value* to have names which contain null bytes.  The
AsmParser should reject .ll files that try to do this.

llvm-svn: 223869
2014-12-10 00:43:17 +00:00
David Majnemer 4cea5b4954 Forgot to add test for r223856
llvm-svn: 223857
2014-12-09 23:51:14 +00:00
David Majnemer 2defbada38 AsmParser: Don't crash on short hex constants for fp128 types
If we see 0xL01, treat it like 0xL00000000000000000000000000000001
instead of crashing.

llvm-svn: 223811
2014-12-09 19:10:03 +00:00
Duncan P. N. Exon Smith 5bf8fef580 IR: Split Metadata from Value
Split `Metadata` away from the `Value` class hierarchy, as part of
PR21532.  Assembly and bitcode changes are in the wings, but this is the
bulk of the change for the IR C++ API.

I have a follow-up patch prepared for `clang`.  If this breaks other
sub-projects, I apologize in advance :(.  Help me compile it on Darwin
I'll try to fix it.  FWIW, the errors should be easy to fix, so it may
be simpler to just fix it yourself.

This breaks the build for all metadata-related code that's out-of-tree.
Rest assured the transition is mechanical and the compiler should catch
almost all of the problems.

Here's a quick guide for updating your code:

  - `Metadata` is the root of a class hierarchy with three main classes:
    `MDNode`, `MDString`, and `ValueAsMetadata`.  It is distinct from
    the `Value` class hierarchy.  It is typeless -- i.e., instances do
    *not* have a `Type`.

  - `MDNode`'s operands are all `Metadata *` (instead of `Value *`).

  - `TrackingVH<MDNode>` and `WeakVH` referring to metadata can be
    replaced with `TrackingMDNodeRef` and `TrackingMDRef`, respectively.

    If you're referring solely to resolved `MDNode`s -- post graph
    construction -- just use `MDNode*`.

  - `MDNode` (and the rest of `Metadata`) have only limited support for
    `replaceAllUsesWith()`.

    As long as an `MDNode` is pointing at a forward declaration -- the
    result of `MDNode::getTemporary()` -- it maintains a side map of its
    uses and can RAUW itself.  Once the forward declarations are fully
    resolved RAUW support is dropped on the ground.  This means that
    uniquing collisions on changing operands cause nodes to become
    "distinct".  (This already happened fairly commonly, whenever an
    operand went to null.)

    If you're constructing complex (non self-reference) `MDNode` cycles,
    you need to call `MDNode::resolveCycles()` on each node (or on a
    top-level node that somehow references all of the nodes).  Also,
    don't do that.  Metadata cycles (and the RAUW machinery needed to
    construct them) are expensive.

  - An `MDNode` can only refer to a `Constant` through a bridge called
    `ConstantAsMetadata` (one of the subclasses of `ValueAsMetadata`).

    As a side effect, accessing an operand of an `MDNode` that is known
    to be, e.g., `ConstantInt`, takes three steps: first, cast from
    `Metadata` to `ConstantAsMetadata`; second, extract the `Constant`;
    third, cast down to `ConstantInt`.

    The eventual goal is to introduce `MDInt`/`MDFloat`/etc. and have
    metadata schema owners transition away from using `Constant`s when
    the type isn't important (and they don't care about referring to
    `GlobalValue`s).

    In the meantime, I've added transitional API to the `mdconst`
    namespace that matches semantics with the old code, in order to
    avoid adding the error-prone three-step equivalent to every call
    site.  If your old code was:

        MDNode *N = foo();
        bar(isa             <ConstantInt>(N->getOperand(0)));
        baz(cast            <ConstantInt>(N->getOperand(1)));
        bak(cast_or_null    <ConstantInt>(N->getOperand(2)));
        bat(dyn_cast        <ConstantInt>(N->getOperand(3)));
        bay(dyn_cast_or_null<ConstantInt>(N->getOperand(4)));

    you can trivially match its semantics with:

        MDNode *N = foo();
        bar(mdconst::hasa               <ConstantInt>(N->getOperand(0)));
        baz(mdconst::extract            <ConstantInt>(N->getOperand(1)));
        bak(mdconst::extract_or_null    <ConstantInt>(N->getOperand(2)));
        bat(mdconst::dyn_extract        <ConstantInt>(N->getOperand(3)));
        bay(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(4)));

    and when you transition your metadata schema to `MDInt`:

        MDNode *N = foo();
        bar(isa             <MDInt>(N->getOperand(0)));
        baz(cast            <MDInt>(N->getOperand(1)));
        bak(cast_or_null    <MDInt>(N->getOperand(2)));
        bat(dyn_cast        <MDInt>(N->getOperand(3)));
        bay(dyn_cast_or_null<MDInt>(N->getOperand(4)));

  - A `CallInst` -- specifically, intrinsic instructions -- can refer to
    metadata through a bridge called `MetadataAsValue`.  This is a
    subclass of `Value` where `getType()->isMetadataTy()`.

    `MetadataAsValue` is the *only* class that can legally refer to a
    `LocalAsMetadata`, which is a bridged form of non-`Constant` values
    like `Argument` and `Instruction`.  It can also refer to any other
    `Metadata` subclass.

(I'll break all your testcases in a follow-up commit, when I propagate
this change to assembly.)

llvm-svn: 223802
2014-12-09 18:38:53 +00:00
David Majnemer b39e22bdc5 AsmParser: Don't crash on malformed attribute groups
This fixes PR21785.

llvm-svn: 223801
2014-12-09 18:33:57 +00:00
David Majnemer 598bd05bd7 Reland r223754
The commit is identical except a reference to `GV' should have been to
`GVal'.

llvm-svn: 223756
2014-12-09 05:56:09 +00:00
David Majnemer 8d3e580cc7 Revert "AsmParser: Reject invalid mismatch between forward ref and def"
This reverts commit r223754.  I've upset the buildbots.

llvm-svn: 223755
2014-12-09 05:50:11 +00:00
David Majnemer e9efecaa52 AsmParser: Reject invalid mismatch between forward ref and def
Don't assume that the forward referenced entity was of the same
global-kind as the new entity.

This fixes PR21779.

llvm-svn: 223754
2014-12-09 05:43:56 +00:00
David Majnemer 770fd82f39 ConstantFold: Zero-sized globals might land on top of another global
A zero sized array is zero sized and might share its address with
another global.

llvm-svn: 223684
2014-12-08 19:35:31 +00:00
Duncan P. N. Exon Smith 545a9b0f51 IR: Add missing tests for function-local metadata
Add assembly and bitcode tests that I neglected to add in r223564 (IR:
Disallow complicated function-local metadata) and r223574 (IR: Disallow
function-local metadata attachments).

Found a couple of bugs:

  - The error message for function-local attachments gave the wrong line
    number -- it indicated the next token (typically on the next line)
    instead of the token that started the attachment.  Fixed.

  - Metadata arguments of the form `!{i32 0, i32 %v}` (or with the
    arguments reversed) fired an assertion in `ValueEnumerator` in LLVM
    v3.5, so I suppose this never really worked.  I suppose this was
    "fixed" by r223564.

(Thanks to dblaikie for pointing out my omission.)

Part of PR21532.

llvm-svn: 223616
2014-12-07 17:56:16 +00:00
David Majnemer 64ba326b1e ConstantFold: Don't optimize comparisons with weak linkage objects
Consider:
void f() {}
void __attribute__((weak)) g() {}
bool b = &f != &g;

It's possble for g to resolve to f if --defsym=g=f is passed on to the
linker.

llvm-svn: 223585
2014-12-06 11:58:33 +00:00
Duncan P. N. Exon Smith da41af9e94 IR: Disallow complicated function-local metadata
Disallow complex types of function-local metadata.  The only valid
function-local metadata is an `MDNode` whose sole argument is a
non-metadata function-local value.

Part of PR21532.

llvm-svn: 223564
2014-12-06 01:26:49 +00:00
Rafael Espindola 1c99344156 Use FileCheck in a few tests.
llvm-svn: 221459
2014-11-06 15:05:51 +00:00
Rafael Espindola 11aaaeebe0 Delete -std-compile-opts.
These days -std-compile-opts was just a silly alias for -O3.

llvm-svn: 219951
2014-10-16 20:00:02 +00:00
Duncan P. N. Exon Smith 176b691d32 Revert "Revert "DI: Fold constant arguments into a single MDString""
This reverts commit r218918, effectively reapplying r218914 after fixing
an Ocaml bindings test and an Asan crash.  The root cause of the latter
was a tightened-up check in `DILexicalBlock::Verify()`, so I'll file a
PR to investigate who requires the loose check (and why).

Original commit message follows.

--

This patch addresses the first stage of PR17891 by folding constant
arguments together into a single MDString.  Integers are stringified and
a `\0` character is used as a separator.

Part of PR17891.

Note: I've attached my testcases upgrade scripts to the PR.  If I've
just broken your out-of-tree testcases, they might help.

llvm-svn: 219010
2014-10-03 20:01:09 +00:00
Duncan P. N. Exon Smith 786cd049fc Revert "DI: Fold constant arguments into a single MDString"
This reverts commit r218914 while I investigate some bots.

llvm-svn: 218918
2014-10-02 22:15:31 +00:00
Duncan P. N. Exon Smith 571f97bd90 DI: Fold constant arguments into a single MDString
This patch addresses the first stage of PR17891 by folding constant
arguments together into a single MDString.  Integers are stringified and
a `\0` character is used as a separator.

Part of PR17891.

Note: I've attached my testcases upgrade scripts to the PR.  If I've
just broken your out-of-tree testcases, they might help.

llvm-svn: 218914
2014-10-02 21:56:57 +00:00
Adrian Prantl 87b7eb9d0f Move the complex address expression out of DIVariable and into an extra
argument of the llvm.dbg.declare/llvm.dbg.value intrinsics.

Previously, DIVariable was a variable-length field that has an optional
reference to a Metadata array consisting of a variable number of
complex address expressions. In the case of OpPiece expressions this is
wasting a lot of storage in IR, because when an aggregate type is, e.g.,
SROA'd into all of its n individual members, the IR will contain n copies
of the DIVariable, all alike, only differing in the complex address
reference at the end.

By making the complex address into an extra argument of the
dbg.value/dbg.declare intrinsics, all of the pieces can reference the
same variable and the complex address expressions can be uniqued across
the CU, too.
Down the road, this will allow us to move other flags, such as
"indirection" out of the DIVariable, too.

The new intrinsics look like this:
declare void @llvm.dbg.declare(metadata %storage, metadata %var, metadata %expr)
declare void @llvm.dbg.value(metadata %storage, i64 %offset, metadata %var, metadata %expr)

This patch adds a new LLVM-local tag to DIExpressions, so we can detect
and pretty-print DIExpression metadata nodes.

What this patch doesn't do:

This patch does not touch the "Indirect" field in DIVariable; but moving
that into the expression would be a natural next step.

http://reviews.llvm.org/D4919
rdar://problem/17994491

Thanks to dblaikie and dexonsmith for reviewing this patch!

Note: I accidentally committed a bogus older version of this patch previously.
llvm-svn: 218787
2014-10-01 18:55:02 +00:00
Adrian Prantl b458dc2eee Revert r218778 while investigating buldbot breakage.
"Move the complex address expression out of DIVariable and into an extra"

llvm-svn: 218782
2014-10-01 18:10:54 +00:00
Adrian Prantl 25a7174e7a Move the complex address expression out of DIVariable and into an extra
argument of the llvm.dbg.declare/llvm.dbg.value intrinsics.

Previously, DIVariable was a variable-length field that has an optional
reference to a Metadata array consisting of a variable number of
complex address expressions. In the case of OpPiece expressions this is
wasting a lot of storage in IR, because when an aggregate type is, e.g.,
SROA'd into all of its n individual members, the IR will contain n copies
of the DIVariable, all alike, only differing in the complex address
reference at the end.

By making the complex address into an extra argument of the
dbg.value/dbg.declare intrinsics, all of the pieces can reference the
same variable and the complex address expressions can be uniqued across
the CU, too.
Down the road, this will allow us to move other flags, such as
"indirection" out of the DIVariable, too.

The new intrinsics look like this:
declare void @llvm.dbg.declare(metadata %storage, metadata %var, metadata %expr)
declare void @llvm.dbg.value(metadata %storage, i64 %offset, metadata %var, metadata %expr)

This patch adds a new LLVM-local tag to DIExpressions, so we can detect
and pretty-print DIExpression metadata nodes.

What this patch doesn't do:

This patch does not touch the "Indirect" field in DIVariable; but moving
that into the expression would be a natural next step.

http://reviews.llvm.org/D4919
rdar://problem/17994491

Thanks to dblaikie and dexonsmith for reviewing this patch!

llvm-svn: 218778
2014-10-01 17:55:39 +00:00
Akira Hatanaka 489decec67 [inline asm] Add a check in InlineAsm::ConstraintInfo::Parse to make sure '{'
follows '~' in a clobber constraint string.

Previously llc would hit an llvm_unreachable when compiling an inline-asm
instruction with malformed constraint string "~x{21}". This commit enables
LLParser to catch the error earlier and print a more helpful diagnostic.

rdar://problem/14206559

llvm-svn: 217288
2014-09-05 22:30:32 +00:00
Reid Kleckner 8349864dbd Declare that musttail calls in variadic functions forward the ellipsis
Summary:
There is no functionality change here except in the way we assemble and
dump musttail calls in variadic functions. There's really no need to
separate out the bits for musttail and "is forwarding varargs" on call
instructions. A musttail call by definition has to forward the ellipsis
or it would fail verification.

Reviewers: chandlerc, nlewycky

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D4892

llvm-svn: 216423
2014-08-26 00:33:28 +00:00
Duncan P. N. Exon Smith 0a448fbca3 IR: Implement uselistorder assembly directives
Implement `uselistorder` and `uselistorder_bb` assembly directives,
which allow the use-list order to be recovered when round-tripping to
assembly.

This is the bulk of PR20515.

llvm-svn: 216025
2014-08-19 21:30:15 +00:00
Duncan P. N. Exon Smith c8eccd1147 verify-uselistorder: Force -preserve-bc-use-list-order
llvm-svn: 216022
2014-08-19 21:08:27 +00:00
Duncan P. N. Exon Smith 0c39d40c8b IR: Don't add inbounds to GEPs of extern_weak variables
Global variables that have `extern_weak` linkage may be null, so it's
incorrect to add `inbounds` when constant folding.

This also fixes a bug when parsing global aliases, whose forward
reference placeholders are global variables with `extern_weak` linkage.
If GEPs to these aliases are encountered before the alias itself, the
GEPs would incorrectly gain the `inbounds` keyword as well.

llvm-svn: 215803
2014-08-16 01:54:32 +00:00
Duncan P. N. Exon Smith 852e00e3d1 verify-uselistorder: Change the default -num-shuffles=5
Change the default for `-num-shuffles` to 5 and better document the
algorithm in the header docs of `verify-uselistorder`.

llvm-svn: 214419
2014-07-31 18:46:24 +00:00
Duncan P. N. Exon Smith ab6adeb8a1 UseListOrder: Handle self-users
Correctly sort self-users (such as PHI nodes).  I added a targeted test
in `test/Bitcode/use-list-order.ll` and the final missing RUN line to
tests in `test/Assembly`.

This is part of PR5680.

llvm-svn: 214417
2014-07-31 18:33:12 +00:00
Duncan P. N. Exon Smith 9177867b24 UseListOrder: Don't give constant IDs to GlobalValues
Since initializers of GlobalValues are being assigned IDs before
GlobalValues themselves, explicitly exclude GlobalValues from the
constant pool.  Added targeted test in `test/Bitcode/use-list-order.ll`
and added two more RUN lines in `test/Assembly`.

This is part of PR5680.

llvm-svn: 214368
2014-07-31 00:13:28 +00:00
Duncan P. N. Exon Smith 5faa6225ad verify-uselistorder: Add RUN lines to cases in test/Assembly
Add RUN line for `verify-uselistorder` to every test in `test/Assembly`,
unless it's a negative check (assembler rejects it) or verification
fails.

There are three files that verification fails on (so I've left out the
RUN lines):

  - 2002-08-22-DominanceProblem.ll
  - ConstantExprFold.ll
  - ConstantExprFoldCast.ll

This is part of PR5680.

llvm-svn: 214365
2014-07-31 00:10:27 +00:00
Rafael Espindola 464fe024c5 Use "weak alias" instead of "alias weak"
Before this patch we had

@a = weak global ...
but
@b = alias weak ...

The patch changes aliases to look more like global variables.

Looking at some really old code suggests that the reason was that the old
bison based parser had a reduction for alias linkages and another one for
global variable linkages. Putting the alias first avoided the reduce/reduce
conflict.

The days of the old .ll parser are long gone. The new one parses just "linkage"
and a later check is responsible for deciding if a linkage is valid in a
given context.

llvm-svn: 214355
2014-07-30 22:51:54 +00:00
Mark Heffernan 9d20e42765 Rename metadata llvm.loop.vectorize.unroll to llvm.loop.vectorize.interleave.
llvm-svn: 213588
2014-07-21 23:11:03 +00:00