128 Commits

Author SHA1 Message Date
David Neto
a4f49d91dc spirv-reader: support OpDot, OpOuterProduct
Change-Id: I39f2369572a340be1c4c7c6e4a2c8e0e9347d792
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/32200
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: David Neto <dneto@google.com>
2020-11-11 13:59:24 +00:00
Ben Clayton
34a2eb1999 Add Source parameter to decoration constructors
Once a `Decoration` has been parsed, it'll be placed into a `DecorationList` and validated later in the parse. In order to create error diagnostics that refer back to the decoration, we need to know its source.

Bug: tint:282
Bug: tint:291
Change-Id: I38de708adbd041601b61d7e0a4d0402e9a2fe526
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/31722
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
2020-11-03 21:48:20 +00:00
David Neto
0a06243a70 spirv-reader: support scalar spec constants
Translate OpSpecConstantTrue, OpSpecConstantFalse, and OpSpecConstant.
The latter only can be used with integer or float scalars.

If the constant has a SpecId decoration, then generate a module-scope
decorated constant.  Otherwise generate a module-scope constant without
decorations.

Register the ID so we know to use the declared const identifier in
expressions later in the module.

Bug: tint:156
Change-Id: Icd6e9b60225ced7ee99963c4f85cec1eb0e3ae6b
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/31541
Commit-Queue: David Neto <dneto@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
2020-11-02 15:44:27 +00:00
David Neto
74023424da Remove stale TODO
Change-Id: I1b7dbbc0290c48309c9cbf00a432e3beccd27bcf
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/31540
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
2020-11-02 14:56:47 +00:00
Ben Clayton
5bee67fced Add File & Range information to tint::Source
This is the first step in improving the error messages produced while parsing.

The `line` and `column` information of `Source` has been moved to `Source::Location`.

`Source::Range` has been added that contains a `Location` interval - allowing error messages to highlight the full region of the error.

The `File` information provides an optional file path, and pre-splits the content into lines. These lines can be used to print the full line containing an error.

This CL contains a few temporary changes that help split up this work, and to ease integration with Tint.

Bug: tint:282
Change-Id: I7aa501b0a9631f286e8e93fd7396bdbe38175727
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/31420
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Reviewed-by: David Neto <dneto@google.com>
Commit-Queue: David Neto <dneto@google.com>
2020-10-30 20:44:53 +00:00
David Neto
9ab6e8b9eb spirv-reader: treat function parameters as const declarations
Change-Id: I5e5f35be15737c6dc46bb2e9dc1319f7c403eab8
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/30921
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Commit-Queue: David Neto <dneto@google.com>
2020-10-23 18:19:10 +00:00
dan sinclair
3c02592718 Remove cast operator.
This CL removes the cast operator and converts the tests over to using
type constructors.

Bug: tint:241
Change-Id: I2526acb61f5624b2e1c068612a2ddcc748c92aed
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/28860
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: Ryan Harrison <rharrison@chromium.org>
2020-09-24 14:38:44 +00:00
dan sinclair
a7d498e060 Rename 'as' to 'bitcast'
This CL updates Tint to use 'bitcast' instead of 'as' for the OpBitcast
conversions.

Bug: tint:241
Change-Id: I53a80de10421b2d9cc009527eebe5ff07e1285c2
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/28801
Commit-Queue: David Neto <dneto@google.com>
Reviewed-by: David Neto <dneto@google.com>
2020-09-22 22:07:13 +00:00
dan sinclair
b4fee2f824 Update builtin methods.
This CL removes the import mechanism, the identifier paths and updates
all of the standard library methods to be builtins.

Bug: tint:242
Change-Id: If09b98a155ae49ced3986ba2c9b517a060693006
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/28720
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: Ryan Harrison <rharrison@chromium.org>
2020-09-22 19:42:13 +00:00
dan sinclair
de2a019a7f [spirv-reader] Emit StageDecoration when building the functions
This CL adds the emission of StageDecoration to entry point functions.
EntryPoint nodes are still emitted. We duplicate the function emission
if there are multiple entry points pointing to the same function.

Change-Id: Icb48a063f5c6a30948bbe2c37c7fce7431af5864
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/28665
Reviewed-by: David Neto <dneto@google.com>
Reviewed-by: Sarah Mashayekhi <sarahmashay@google.com>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
2020-09-22 14:22:12 +00:00
David Neto
7653485162 [spirv-reader] Set some source locations
Set source location on function variable declarations, const
declarations, and most normal instructions.

Bug: tint:3
Change-Id: I469afcdf1b7d8f6d1e64617189a6fa329056737f
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/27700
Commit-Queue: David Neto <dneto@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
2020-08-31 18:52:54 +00:00
David Neto
5a75a174d6 [spirv-reader] Uses in phis count as uses
This is required so we actually emit values that are only used
in phis.

Bug: tint:3, tint:215
Change-Id: I9d957a697839b8d09246905c3f28064f0bc01731
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/27701
Commit-Queue: David Neto <dneto@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
2020-08-31 14:05:51 +00:00
David Neto
c5d65cc917 [spirv-reader] Don't hoist pointers that are already in scope.
Bug: tint:3, tint:213
Change-Id: I79410c670b8690c1f1ea86b7b9427f272a4ebbbb
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/27720
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
2020-08-29 16:11:02 +00:00
David Neto
25b856aa64 [spirv-reader] Avoid certain hoisting cases
If a definition occurs in the first block of an IfSelection or
SwitchSelection, then it should count as belonging to the scope of the
parent of that if or switch selection.  This prevents some bad hoisting
decisions.

Bug: tint:3, tint:213
Change-Id: I89df5e8cbc163577e19e78c2bf393eb1eec4a0aa
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/27660
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Commit-Queue: David Neto <dneto@google.com>
2020-08-28 19:58:12 +00:00
David Neto
fed63103f5 [spirv-reader] Follow non-canonicalized SPIR-V type for composite extract
Follow the actual SPIR-V type when computing a composite extract
instad of the canonicalized view in the optimizer's type manager.
Do this so we can generate the correct member name for a struct,
rather than using the member name for the other representative
struct type. The optimizer's type canonicalizer is insensitive to
struct member names.

Prompted by tint:213, for which the original case was an
access chain.

Bug: tint:3, tint:213
Change-Id: I8705c7ee655fe47c8b7a3658db524fe18833efdb
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/27603
Commit-Queue: David Neto <dneto@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
2020-08-28 16:28:42 +00:00
David Neto
53b1c39036 [spirv-reader] Follow non-canonicalized SPIR-V type for access chains
Follow the actual SPIR-V type when computing an access chain expression,
instead of the canonicalized view in the optimizer's type manager.
Do this so we can generate the correct member name for a struct,
rather than using the member name for the other representative
struct type. The optimizer's type canonicalizer is insensitive to
struct member names.

Fixes tint:213

Bug: tint:3, tint:213
Change-Id: I88ec42a4cb049b011a59d5522e4cb39bc181a4fb
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/27602
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
2020-08-28 15:49:31 +00:00
dan sinclair
bf4614e252 Update some language usage.
This CL updates a few bits of language to be inline with the Android
respectful code rules [1].

1- https://source.android.com/setup/contribute/respectful-code

Change-Id: Ia35b58d9003df64eeb1e9196c9c194f8955c11c1
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/25941
Reviewed-by: David Neto <dneto@google.com>
2020-07-29 17:49:01 +00:00
dan sinclair
cfdc5995ec [spirv-reader] Update to create BlockStatements
This CL updates the SPIR-V Reader to create BlockStatements instead of
StatementLists.

Bug: tint:136
Change-Id: I957019446ca00306187de701f86ae3e0dd5c5eb8
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/25740
Reviewed-by: Sarah Mashayekhi <sarahmashay@google.com>
2020-07-27 15:25:00 +00:00
dan sinclair
8f3c6356d4 Remove KillStatement
This CL removes the KillStatement from the AST and replaces all test
usage with DiscardStatement.

Bug: tint:169
Change-Id: Ie68dd3cdd54056f144d10506f05cc1f6903d1cda
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/25605
Reviewed-by: David Neto <dneto@google.com>
2020-07-25 14:33:50 +00:00
dan sinclair
23508f4339 [spirv-reader] Convert from KillStatement to DiscardStatement
This CL changes the SPIRV-Reader to generate DiscardStatements instead
of KillStatements for an OpKill.

Bug: tint:168
Change-Id: Ic4223b614c822c6ad449f61aedaddc9605c42535
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/25642
Reviewed-by: David Neto <dneto@google.com>
2020-07-25 14:33:35 +00:00
Ryan Harrison
7a0b734864 Fix BUILD.gn builds
Change-Id: I4e54b30497e064061baff2dcc205b68db87bee2c
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/25540
Reviewed-by: dan sinclair <dsinclair@chromium.org>
2020-07-22 20:41:12 +00:00
David Neto
b6f0299964 [spirv-reader] Support OpAny, OpAll, OpIsInf, OpIsNan
Bug: tint:3, tint:121
Change-Id: I1a6a2d45684c28a0e03ad4b208dc6b2f737da694
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/25422
Reviewed-by: dan sinclair <dsinclair@chromium.org>
2020-07-22 12:58:31 +00:00
David Neto
28d0f4b905 [spirv-reader] Support function call returning void
Bug: tint:3, tint:99
Change-Id: I6fe6d06d79115e6b3b0adb800f21c4704795dc15
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/25360
Reviewed-by: dan sinclair <dsinclair@chromium.org>
2020-07-21 16:08:56 +00:00
David Neto
0a56a103be [spirv-reader] Support select over scalars and vectors
Still TODO: OpSelect over arrays and structures, as permitted in SPIR-V 1.4

Bug: tint:3, tint:99
Change-Id: I70f6c8a43ea3339cd715813c6eb0128d66ff0df8
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/25301
Reviewed-by: dan sinclair <dsinclair@chromium.org>
2020-07-21 13:36:25 +00:00
David Neto
c29bad28ad [spirv-reader] Support function calls, except returning void
Functions returning void are blocked on https://crbug.com/tint/45

Change-Id: I15ec9cf0e267571bbfab921c678a59e25d0e3619
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/25280
Reviewed-by: dan sinclair <dsinclair@chromium.org>
2020-07-20 22:19:01 +00:00
dan sinclair
f1c3fb7670 [msl-writer] Handle uniform buffers.
This CL adds support for handling uniform data. Currently the uniform is
added to a buffer where the number is the binding value. This will need
to be updated to accept the correct mapping from the embedder.

Bug: tint:8
Change-Id: Icccccbe599a9555defa6136e384745f4093df020
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/25104
Reviewed-by: David Neto <dneto@google.com>
2020-07-20 13:46:32 +00:00
David Neto
6982c22eee [spirv-reader] Handle old-style storage buffers
Old way:
  - struct decorated with BufferBlock
  - Uniform storage class

New way
  - struct decorated with Block
  - StorageBuffer storage class

Also fixes the result type for an access chain.

Bug: tint:99
Change-Id: I2324ba94bb19b369d206313de798bdfec6099fe0
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/24605
Reviewed-by: dan sinclair <dsinclair@chromium.org>
2020-07-20 13:24:26 +00:00
David Neto
5f43fedcdd [spirv-reader] Handle gl_Position
Emits it as a module-level variable.  Deconstruct and throw away
the gl_PerVertex struct.

Not handled: unusual patterns that are technically valid but
which don't occur in practice:
- loading, storing, or producing intermediate values of the whole structure.
- multiple definitions of the per-vertex structure (e.g. if someone had
  put both a vertex shader and a tessellation shader in the same
  module.)

Bug: tint:3, tint:99
Change-Id: I3ad9ff6ab780a002367f01f385bfa7d6ddba6db9
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/24880
Reviewed-by: dan sinclair <dsinclair@chromium.org>
2020-07-16 20:15:22 +00:00
David Neto
919011af0a [spirv-reader] Refactor how we emit const definitions
Take the type of a const-definition (or a write to a hoisted variable)
from the generated expression rather than the directly-converted type
from the SPIR-V ID.

This prepares the way for remapping storage buffers from
Uniform/BufferBlock to StorageBuffer/Block representation.

Bug: tint:99
Change-Id: I6104d8ad96312053562468a3cdb247932c1cb6cb
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/24604
Reviewed-by: dan sinclair <dsinclair@chromium.org>
2020-07-13 14:16:12 +00:00
David Neto
6453bee795 [spirv-reader] Even better hoisted variables
Use the fact that in WGSL the scope corresponding to the loop construct
encloses the scope for its associated continue construct.
In our construct data structure, the two are adjacent but not
overlapping.

This improvement means that when a definition is in a loop construct,
but used only in the loop or associated continue construct, then no
hoisting is required.

Bug: tint:3
Change-Id: I8d33b8f76303ab2868306847e846b4c26899e746
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/24420
Reviewed-by: dan sinclair <dsinclair@google.com>
2020-07-07 17:25:48 +00:00
David Neto
91cb60f2ec [spirv-reader] Improve placement of hoisted vars
When we hoist a variable out of a continue construct, put it
in associated loop construct, if it exists.  This reduces its
lifetime in WGSL, and easier to understand as a code reader.

Change-Id: I8f0cc37640bfe67874cbc27b55029e79e9a8992c
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/24321
Reviewed-by: dan sinclair <dsinclair@google.com>
2020-07-06 18:10:52 +00:00
David Neto
4c48622aa1 [spirv-reader] Allow multi-block continue construct being the entire loop
The special case is not "single-block-loop" but rather the
case where a continue target is also its own loop header.
This can occur for single-block loops and multi-block loops.

Bug: tint:3
Change-Id: I4af1410793caf8b26a1f781e221fc0b395f07aa3
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/24320
Reviewed-by: dan sinclair <dsinclair@google.com>
2020-07-06 16:13:54 +00:00
David Neto
9b9a0b07da [spirv-reader] Support OpPhi
For each OpPhi, make a variable to carry values from predecessor blocks
to the OpPhi.  Declare the variable at the smallest scope enclosing all
the predecessor blocks (where we write to it), and the OpPhi (where we
read from it).

Bug: tint:3
Change-Id: I7898b4b903d9ee1a25a7466e3c5aaf6840550e2d
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/24181
Reviewed-by: dan sinclair <dsinclair@google.com>
2020-07-06 16:08:17 +00:00
David Neto
2c11bd6b68 [spirv-reader] Refactor bookkeeping for localy defined values
Bug: tint:3
Change-Id: Ibe26b802ae61c6271f8a75e641ac31db36df6000
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/24124
Reviewed-by: dan sinclair <dsinclair@google.com>
2020-06-30 19:03:17 +00:00
David Neto
e91325956d [spirv-reader] Hoist definitions as needed
Compensate for the fact that dominance does not correspond
exactly to scoping. A definition can dominate a use, but when mapped
in a naive way to constant definitiion and its use, the definition
name goes out of scope by the time you reach the use.

This is correct for storable types.

Bug: tint:3
Change-Id: I03e6c5ba68393151485ed4cdbe6b2b3d7773d1ad
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/24141
Reviewed-by: dan sinclair <dsinclair@google.com>
2020-06-30 15:16:18 +00:00
David Neto
de7b15ebb9 [spirv-reader] Don't move combinatorial values across control flow
Avoid sinking expensive operations into control flow such as loops.
The heuristic way to achieve that is to avoid moving combinatorial
values across *any* structured construct boundaries.

Bug: tint:3
Change-Id: I91502b01166a0db64c0e652331591850df75f9d4
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/24140
Reviewed-by: dan sinclair <dsinclair@google.com>
2020-06-30 13:59:43 +00:00
David Neto
194e0cca3b [spirv-reader] Support OpNop
An OpNop maps to nothing

Bug: tint:3
Change-Id: Id73601d481971954dd4de706202b5229dcf39871
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/23561
Reviewed-by: dan sinclair <dsinclair@google.com>
2020-06-22 20:49:34 +00:00
David Neto
fd3700c0a7 [spirv-reader] Support Undef, mapping to null
Bug: tint:3
Change-Id: I1549f0445c92312b0d20292ff9d60736300d5378
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/23600
Reviewed-by: dan sinclair <dsinclair@google.com>
2020-06-22 20:48:59 +00:00
David Neto
6b6e6a16ea [spirv-reader] Remove orphaned TODOs
TODOs in the test file are or were in the function_arithmetic_test.cc

Change-Id: I679dbf0019e12e26488ccc310dfb03a535628e0b
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/23462
Reviewed-by: dan sinclair <dsinclair@google.com>
2020-06-18 19:42:24 +00:00
David Neto
d7868e34c2 [spirv-reader] Add ConvertFToU, ConvertFToS
Bug: tint:3
Change-Id: I9f3188e0aac64e98da785c4df2e8b2aa42b71cf8
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/23402
Reviewed-by: dan sinclair <dsinclair@google.com>
2020-06-18 17:57:23 +00:00
David Neto
e12c5ff42e [spirv-reader] Add mixed scalar/vector/matrix multiply
Bug: tint:3
Change-Id: I5875bf453b05c5d5c96f90122206da04f6799976
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/23401
Reviewed-by: dan sinclair <dsinclair@google.com>
2020-06-17 23:33:35 +00:00
David Neto
b961e0069b [spirv-reader] Add ConvertSToF, ConvertUToF
Bug: tint:3
Change-Id: I28bcc109a207ef6f5225b9ea707bff11b1b6fd50
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/23420
Reviewed-by: dan sinclair <dsinclair@google.com>
2020-06-17 20:48:56 +00:00
David Neto
7df946d7aa [spirv-reader] Add vector shuffle
Use composite-construct from decomposed singly-named operands.

Bug: tint:3
Change-Id: I8536c5f8e87de312460c3d5c6164e090d79bb4a9
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/23380
Reviewed-by: dan sinclair <dsinclair@google.com>
2020-06-17 20:07:49 +00:00
David Neto
1650af2c86 [spirv-reader] Add OpCopyObject
Bug: tint:3
Change-Id: Ie389c825ddcc8ea6f110997e9b8f39ebbb1e1e0d
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/23340
Reviewed-by: dan sinclair <dsinclair@google.com>
2020-06-17 17:46:23 +00:00
dan sinclair
c7b66da6ad Cleanup formatting and linter.
This CL cleans up various formatting and lint errors.

Change-Id: Ieee14db90e36acc8b469d58abb84fcf3595321bb
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/23224
Reviewed-by: David Neto <dneto@google.com>
2020-06-16 15:02:50 +00:00
David Neto
93e39b451b [spirv-reader] Support ifbreak with other forward edge
Add a guard variable for flow control within that if-selection.

Also, the premerge blocks are always surrounded by an if-selection,
to ensure we cause reconvergence at the end of the original if-selection
construct, just like in the original SPIR-V.

Bug: tint:3
Change-Id: I614c6840e539bf9a338058beb5b6f70484e3320a
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/23182
Reviewed-by: dan sinclair <dsinclair@google.com>
2020-06-16 01:03:39 +00:00
David Neto
b2b0dfefa9 [spirv-reader] Add OpCompositeExtract
Bug: tint:3
Change-Id: I9d8c1cf2545e28ef0ddf89e55ce45ec19c50022a
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/23161
Reviewed-by: dan sinclair <dsinclair@google.com>
2020-06-16 01:02:21 +00:00
David Neto
c7d1ac3361 [spirv-reader] Add OpCompositeConstruct
Bug: tint:3
Change-Id: Ibb1a4124e7e7b7a5b95bdd4e7c7e7f1c570e641c
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/23127
Reviewed-by: dan sinclair <dsinclair@google.com>
2020-06-12 15:09:56 +00:00
David Neto
0335adbc9a [spirv-reader] First GLSL.std.450 instructions
This supports the extended instructions used by the compute_boids
example.

Bug: tint:3
Change-Id: I364c343217139e489377dd2a9330058114023caa
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/23126
Reviewed-by: dan sinclair <dsinclair@google.com>
2020-06-12 15:09:14 +00:00
David Neto
709b62528c [spirv-reader] Add fallthrough
Bug: tint:3
Change-Id: Ib2d337156d419ed13ef9c67aa94ac3ee90f79548
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/23041
Reviewed-by: dan sinclair <dsinclair@google.com>
2020-06-11 20:53:39 +00:00