|
Revision tags: llvmorg-20.1.0, llvmorg-20.1.0-rc3, llvmorg-20.1.0-rc2, llvmorg-20.1.0-rc1, llvmorg-21-init, llvmorg-19.1.7, llvmorg-19.1.6, llvmorg-19.1.5, llvmorg-19.1.4, llvmorg-19.1.3, llvmorg-19.1.2, llvmorg-19.1.1, llvmorg-19.1.0, llvmorg-19.1.0-rc4, llvmorg-19.1.0-rc3, llvmorg-19.1.0-rc2, llvmorg-19.1.0-rc1, llvmorg-20-init, llvmorg-18.1.8, llvmorg-18.1.7, llvmorg-18.1.6, llvmorg-18.1.5, llvmorg-18.1.4, llvmorg-18.1.3, llvmorg-18.1.2, llvmorg-18.1.1, llvmorg-18.1.0, llvmorg-18.1.0-rc4, llvmorg-18.1.0-rc3, llvmorg-18.1.0-rc2, llvmorg-18.1.0-rc1, llvmorg-19-init, llvmorg-17.0.6, llvmorg-17.0.5, llvmorg-17.0.4, llvmorg-17.0.3, llvmorg-17.0.2, llvmorg-17.0.1, llvmorg-17.0.0, llvmorg-17.0.0-rc4, llvmorg-17.0.0-rc3, llvmorg-17.0.0-rc2, llvmorg-17.0.0-rc1, llvmorg-18-init, llvmorg-16.0.6, llvmorg-16.0.5, llvmorg-16.0.4, llvmorg-16.0.3, llvmorg-16.0.2, llvmorg-16.0.1, llvmorg-16.0.0, llvmorg-16.0.0-rc4, llvmorg-16.0.0-rc3, llvmorg-16.0.0-rc2, llvmorg-16.0.0-rc1, llvmorg-17-init, llvmorg-15.0.7, llvmorg-15.0.6, llvmorg-15.0.5, llvmorg-15.0.4, llvmorg-15.0.3, llvmorg-15.0.2, llvmorg-15.0.1, llvmorg-15.0.0, llvmorg-15.0.0-rc3, llvmorg-15.0.0-rc2 |
|
| #
786a4f42 |
| 02-Aug-2022 |
Chuanqi Xu <[email protected]> |
[C++20] [Modules] Handle initializer for Header Units
Previously when we add module initializer, we forget to handle header units. This results that we couldn't compile a Hello World Example with He
[C++20] [Modules] Handle initializer for Header Units
Previously when we add module initializer, we forget to handle header units. This results that we couldn't compile a Hello World Example with Header Units. This patch tries to fix this.
Reviewed By: iains
Differential Revision: https://reviews.llvm.org/D130871
(cherry picked from commit 6d10733d445506c02ebec9faa54658431857bb49)
show more ...
|
|
Revision tags: llvmorg-15.0.0-rc1, llvmorg-16-init, llvmorg-14.0.6, llvmorg-14.0.5, llvmorg-14.0.4 |
|
| #
afda39a5 |
| 15-May-2022 |
Iain Sandoe <[email protected]> |
re-land [C++20][Modules] Build module static initializers per P1874R1.
The re-land fixes module map module dependencies seen on Greendragon, but not in the clang test suite.
---
Currently we only
re-land [C++20][Modules] Build module static initializers per P1874R1.
The re-land fixes module map module dependencies seen on Greendragon, but not in the clang test suite.
---
Currently we only implement this for the Itanium ABI since the correct mangling for the initializers in other ABIs is not yet known.
Intended result:
For a module interface [which includes partition interface and implementation units] (instead of the generic CXX initializer) we emit a module init that:
- wraps the contained initializations in a control variable to ensure that the inits only happen once, even if a module is imported many times by imports of the main unit.
- calls module initializers for imported modules first. Note that the order of module import is not significant, and therefore neither is the order of imported module initializers.
- We then call initializers for the Global Module Fragment (if present) - We then call initializers for the current module. - We then call initializers for the Private Module Fragment (if present)
For a module implementation unit, or a non-module TU that imports at least one module we emit a regular CXX init that:
- Calls the initializers for any imported modules first. - Then proceeds as normal with remaining inits.
For all module unit kinds we include a global constructor entry, this allows for the (in most cases unusual) possibility that a module object could be included in a final binary without a specific call to its initializer.
Implementation:
- We provide the module pointer in the AST Context so that CodeGen can act on it and its sub-modules.
- We need to account for module build lines like this: ` clang -cc1 -std=c++20 Foo.pcm -emit-obj -o Foo.o` or ` clang -cc1 -std=c++20 -xc++-module Foo.cpp -emit-obj -o Foo.o`
- in order to do this, we add to ParseAST to set the module pointer in the ASTContext, once we establish that this is a module build and we know the module pointer. To be able to do this, we make the query for current module public in Sema.
- In CodeGen, we determine if the current build requires a CXX20-style module init and, if so, we defer any module initializers during the "Eagerly Emitted" phase.
- We then walk the module initializers at the end of the TU but before emitting deferred inits (which adds any hidden and static ones, fixing https://github.com/llvm/llvm-project/issues/51873 ).
- We then proceed to emit the deferred inits and continue to emit the CXX init function.
Differential Revision: https://reviews.llvm.org/D126189
show more ...
|
| #
b19d3ee7 |
| 11-Jul-2022 |
Iain Sandoe <[email protected]> |
Revert "[C++20][Modules] Build module static initializers per P1874R1."
This reverts commit ac507102d258b6fc0cb57eb60c9dfabd57ff562f.
reverting while we figuere out why one of the green dragon lldb
Revert "[C++20][Modules] Build module static initializers per P1874R1."
This reverts commit ac507102d258b6fc0cb57eb60c9dfabd57ff562f.
reverting while we figuere out why one of the green dragon lldb test fails.
show more ...
|
| #
ac507102 |
| 15-May-2022 |
Iain Sandoe <[email protected]> |
[C++20][Modules] Build module static initializers per P1874R1.
Currently we only implement this for the Itanium ABI since the correct mangling for the initializers in other ABIs is not yet known.
I
[C++20][Modules] Build module static initializers per P1874R1.
Currently we only implement this for the Itanium ABI since the correct mangling for the initializers in other ABIs is not yet known.
Intended result:
For a module interface [which includes partition interface and implementation units] (instead of the generic CXX initializer) we emit a module init that:
- wraps the contained initializations in a control variable to ensure that the inits only happen once, even if a module is imported many times by imports of the main unit.
- calls module initializers for imported modules first. Note that the order of module import is not significant, and therefore neither is the order of imported module initializers.
- We then call initializers for the Global Module Fragment (if present) - We then call initializers for the current module. - We then call initializers for the Private Module Fragment (if present)
For a module implementation unit, or a non-module TU that imports at least one module we emit a regular CXX init that:
- Calls the initializers for any imported modules first. - Then proceeds as normal with remaining inits.
For all module unit kinds we include a global constructor entry, this allows for the (in most cases unusual) possibility that a module object could be included in a final binary without a specific call to its initializer.
Implementation:
- We provide the module pointer in the AST Context so that CodeGen can act on it and its sub-modules.
- We need to account for module build lines like this: ` clang -cc1 -std=c++20 Foo.pcm -emit-obj -o Foo.o` or ` clang -cc1 -std=c++20 -xc++-module Foo.cpp -emit-obj -o Foo.o`
- in order to do this, we add to ParseAST to set the module pointer in the ASTContext, once we establish that this is a module build and we know the module pointer. To be able to do this, we make the query for current module public in Sema.
- In CodeGen, we determine if the current build requires a CXX20-style module init and, if so, we defer any module initializers during the "Eagerly Emitted" phase.
- We then walk the module initializers at the end of the TU but before emitting deferred inits (which adds any hidden and static ones, fixing https://github.com/llvm/llvm-project/issues/51873 ).
- We then proceed to emit the deferred inits and continue to emit the CXX init function.
Differential Revision: https://reviews.llvm.org/D126189
show more ...
|
| #
8ad4c6e4 |
| 17-Jun-2022 |
Yaxun (Sam) Liu <[email protected]> |
[HIP] add -fhip-kernel-arg-name
Add option -fhip-kernel-arg-name to emit kernel argument name metadata, which is needed for certain HIP applications.
Reviewed by: Artem Belevich, Fangrui Song, Bria
[HIP] add -fhip-kernel-arg-name
Add option -fhip-kernel-arg-name to emit kernel argument name metadata, which is needed for certain HIP applications.
Reviewed by: Artem Belevich, Fangrui Song, Brian Sumner
Differential Revision: https://reviews.llvm.org/D128022
show more ...
|
|
Revision tags: llvmorg-14.0.3, llvmorg-14.0.2, llvmorg-14.0.1 |
|
| #
fa34951f |
| 08-Apr-2022 |
Mitch Phillips <[email protected]> |
Reland "[MTE] Add -fsanitize=memtag* and friends."
Differential Revision: https://reviews.llvm.org/D118948
|
| #
4aaf25b4 |
| 08-Apr-2022 |
Aaron Ballman <[email protected]> |
Revert "[MTE] Add -fsanitize=memtag* and friends."
This reverts commit 8aa1490513f111afd407d87c3f07d26f65c8a686.
Broke testing: https://lab.llvm.org/buildbot/#/builders/109/builds/36233
|
| #
8aa14905 |
| 01-Apr-2022 |
Mitch Phillips <[email protected]> |
[MTE] Add -fsanitize=memtag* and friends.
Currently, enablement of heap MTE on Android is specified by an ELF note, which signals to the linker to enable heap MTE. This change allows -fsanitize=memt
[MTE] Add -fsanitize=memtag* and friends.
Currently, enablement of heap MTE on Android is specified by an ELF note, which signals to the linker to enable heap MTE. This change allows -fsanitize=memtag-heap to synthesize these notes, rather than adding them through the build system. We need to extend this feature to also signal the linker to do special work for MTE globals (in future) and MTE stack (currently implemented in the toolchain, but not implemented in the loader).
Current Android uses a non-backwards-compatible ELF note, called ".note.android.memtag". Stack MTE is an ABI break anyway, so we don't mind that we won't be able to run executables with stack MTE on Android 11/12 devices.
The current expectation is to support the verbiage used by Android, in that "SYNC" means MTE Synchronous mode, and "ASYNC" effectively means "fast", using the Kernel auto-upgrade feature that allows hardware-specific and core-specific configuration as to whether "ASYNC" would end up being Asynchronous, Asymmetric, or Synchronous on that particular core, whichever has a reasonable performance delta. Of course, this is platform and loader-specific.
Differential Revision: https://reviews.llvm.org/D118948
show more ...
|
| #
3c6d32ec |
| 25-Mar-2022 |
Joseph Huber <[email protected]> |
[OpenMP] Make Ctor / Dtor functions have external visibility
The default construction of constructor functions by LLVM tends to make them have internal linkage. When we call a ctor / dtor function i
[OpenMP] Make Ctor / Dtor functions have external visibility
The default construction of constructor functions by LLVM tends to make them have internal linkage. When we call a ctor / dtor function in the target region we are actually creating a kernel that is called at registration. Because the ctor is a kernel we need to make sure it's externally visible so we can actually call it. This prevented AMDGPU from correctly using constructors while NVPTX could use them simply because it ignored internal visibility.
Reviewed By: JonChesterfield
Differential Revision: https://reviews.llvm.org/D122504
show more ...
|
|
Revision tags: llvmorg-14.0.0, llvmorg-14.0.0-rc4, llvmorg-14.0.0-rc3, llvmorg-14.0.0-rc2, llvmorg-14.0.0-rc1, llvmorg-15-init, llvmorg-13.0.1, llvmorg-13.0.1-rc3, llvmorg-13.0.1-rc2 |
|
| #
2d1b55eb |
| 04-Jan-2022 |
Nikita Popov <[email protected]> |
[CodeGen] Make element type in emitArrayDestroy() predictable
When calling emitArrayDestroy(), the pointer will usually have ConvertTypeForMem(EltType) as the element type, as one would expect. Howe
[CodeGen] Make element type in emitArrayDestroy() predictable
When calling emitArrayDestroy(), the pointer will usually have ConvertTypeForMem(EltType) as the element type, as one would expect. However, globals with initializers sometimes don't use the same types as values normally would, e.g. here the global uses { double, i32 } rather than %struct.T as element type.
Add an early cast to the global destruction path to avoid this special case. The cast would happen lateron anyway, it only gets moved to an earlier point.
Differential Revision: https://reviews.llvm.org/D116219
show more ...
|
| #
55d7a12b |
| 21-Dec-2021 |
Nikita Popov <[email protected]> |
[CodeGen] Avoid pointee type access during global var declaration
All callers pass in a GlobalVariable, so we can conveniently fetch the type from there.
|
| #
c3b624a1 |
| 15-Dec-2021 |
Nikita Popov <[email protected]> |
[CodeGen] Avoid deprecated ConstantAddress constructor
Change all uses of the deprecated constructor to pass the element type explicitly and drop it.
For cases where the correct element type was no
[CodeGen] Avoid deprecated ConstantAddress constructor
Change all uses of the deprecated constructor to pass the element type explicitly and drop it.
For cases where the correct element type was not immediately obvious to me or would require a slightly larger change I'm falling back to explicitly calling getPointerElementType() for now.
show more ...
|
|
Revision tags: llvmorg-13.0.1-rc1, llvmorg-13.0.0, llvmorg-13.0.0-rc4, llvmorg-13.0.0-rc3, llvmorg-13.0.0-rc2 |
|
| #
cd4d6d71 |
| 25-Aug-2021 |
Richard Smith <[email protected]> |
PR48030: Fix COMDAT-related linking problem with C++ thread_local static data members.
Previously when emitting a C++ guarded initializer, we tried to work out what the enclosing function would be u
PR48030: Fix COMDAT-related linking problem with C++ thread_local static data members.
Previously when emitting a C++ guarded initializer, we tried to work out what the enclosing function would be used for and added it to the COMDAT containing the variable if we thought that doing so would be correct. But this was done from a context in which we didn't -- and realistically couldn't -- correctly infer how the enclosing function would be used.
Instead, add the initialization function to a COMDAT from the code that creates it, in the case where it makes sense to do so: when we know that the one and only reference to the initialization function is in @llvm.global.ctors and that reference is in the same COMDAT.
Reviewed By: rjmccall
Differential Revision: https://reviews.llvm.org/D108680
show more ...
|
|
Revision tags: llvmorg-13.0.0-rc1 |
|
| #
828767f3 |
| 28-Jul-2021 |
Fangrui Song <[email protected]> |
COFF/ELF: Place llvm.global_ctors elements in llvm.used if comdat is used
On ELF, an SHT_INIT_ARRAY outside a section group is a GC root. The current codegen abuses SHT_INIT_ARRAY in a section group
COFF/ELF: Place llvm.global_ctors elements in llvm.used if comdat is used
On ELF, an SHT_INIT_ARRAY outside a section group is a GC root. The current codegen abuses SHT_INIT_ARRAY in a section group to mean a GC root.
On PE/COFF, the dynamic initialization for `__declspec(selectany)` in a comdat can be garbage collected by `-opt:ref`.
Call `addUsedGlobal` for the two cases to fix the abuse/bug.
Reviewed By: rnk
Differential Revision: https://reviews.llvm.org/D106925
show more ...
|
|
Revision tags: llvmorg-14-init |
|
| #
73840f9f |
| 19-Jul-2021 |
Jamie Schmeiser <[email protected]> |
thread_local support for AIX
Summary: The AIX linker will produce errors on unresolved weak symbols. Change the generated code to not check for the initialization function but just call it and ensu
thread_local support for AIX
Summary: The AIX linker will produce errors on unresolved weak symbols. Change the generated code to not check for the initialization function but just call it and ensure that it always exists. Also, the AIX atexit routine has a different name (and signature) so call it correctly. Update the lit tests to test on AIX appropriately.
Author: Jamie Schmeiser <[email protected]> Reviewed By: hubert.reinterpretcast (Hubert Tong) Differential Revision: https://reviews.llvm.org/D104420
show more ...
|
|
Revision tags: llvmorg-12.0.1, llvmorg-12.0.1-rc4, llvmorg-12.0.1-rc3, llvmorg-12.0.1-rc2, llvmorg-12.0.1-rc1 |
|
| #
4cb42564 |
| 19-May-2021 |
Yaxun (Sam) Liu <[email protected]> |
[CUDA][HIP] Fix device variables used by host
variables emitted on both host and device side with different addresses when ODR-used by host function should not cause device side counter-part to be f
[CUDA][HIP] Fix device variables used by host
variables emitted on both host and device side with different addresses when ODR-used by host function should not cause device side counter-part to be force emitted.
This fixes the regression caused by https://reviews.llvm.org/D102237
Reviewed by: Artem Belevich
Differential Revision: https://reviews.llvm.org/D102801
show more ...
|
| #
d5085617 |
| 08-Apr-2021 |
Xiangling Liao <[email protected]> |
[AIX] Support init priority attribute
Differential Revision: https://reviews.llvm.org/D99291
|
|
Revision tags: llvmorg-12.0.0, llvmorg-12.0.0-rc5, llvmorg-12.0.0-rc4, llvmorg-12.0.0-rc3, llvmorg-12.0.0-rc2 |
|
| #
e64fcdf8 |
| 22-Feb-2021 |
Melanie Blower <[email protected]> |
[clang][patch] Inclusive language, modify filename SanitizerBlacklist.h to NoSanitizeList.h
This patch responds to a comment from @vitalybuka in D96203: suggestion to do the change incrementally, an
[clang][patch] Inclusive language, modify filename SanitizerBlacklist.h to NoSanitizeList.h
This patch responds to a comment from @vitalybuka in D96203: suggestion to do the change incrementally, and start by modifying this file name. I modified the file name and made the other changes that follow from that rename.
Reviewers: vitalybuka, echristo, MaskRay, jansvoboda11, aaron.ballman
Differential Revision: https://reviews.llvm.org/D96974
show more ...
|
|
Revision tags: llvmorg-11.1.0, llvmorg-11.1.0-rc3, llvmorg-12.0.0-rc1, llvmorg-13-init, llvmorg-11.1.0-rc2, llvmorg-11.1.0-rc1, llvmorg-11.0.1, llvmorg-11.0.1-rc2, llvmorg-11.0.1-rc1 |
|
| #
17497ec5 |
| 19-Nov-2020 |
Xiangling Liao <[email protected]> |
[AIX][FE] Support constructor/destructor attribute
Support attribute((constructor)) and attribute((destructor)) on AIX
Differential Revision: https://reviews.llvm.org/D90892
|
| #
66face6a |
| 09-Oct-2020 |
Alexandre Ganea <[email protected]> |
Re-land [DebugInfo] Add debug location to stubs generated by CGDeclCXX and mark them as artificial
Previously, when clang was compiled with -DLLVM_ENABLE_ASSERTIONS=ON, the added tests were displayi
Re-land [DebugInfo] Add debug location to stubs generated by CGDeclCXX and mark them as artificial
Previously, when clang was compiled with -DLLVM_ENABLE_ASSERTIONS=ON, the added tests were displaying:
inlinable function call in a function with debug info must have a !dbg location call void @"??1?$c@UB@@@@QEAA@XZ"(%struct.c* @"?f@?1??d@@YAPEAU?$c@UB@@@@XZ@4U2@A") fatal error: error in backend: Broken module found, compilation aborted! Stack dump: 0. Program arguments: <f:\svn\buildninja\bin\clang -cc1 -emit-llvm debug-info-no-location.cpp> -gcodeview -debug-info-kind=limited 1. <eof> parser at end of file 2. Per-function optimization
Fixes PR43012
Differential Revision: https://reviews.llvm.org/D66328
show more ...
|
|
Revision tags: llvmorg-11.0.0, llvmorg-11.0.0-rc6, llvmorg-11.0.0-rc5, llvmorg-11.0.0-rc4 |
|
| #
a88c722e |
| 25-Sep-2020 |
Momchil Velikov <[email protected]> |
[AArch64] PAC/BTI code generation for LLVM generated functions
PAC/BTI-related codegen in the AArch64 backend is controlled by a set of LLVM IR function attributes, added to the function by Clang, b
[AArch64] PAC/BTI code generation for LLVM generated functions
PAC/BTI-related codegen in the AArch64 backend is controlled by a set of LLVM IR function attributes, added to the function by Clang, based on command-line options and GCC-style function attributes. However, functions, generated in the LLVM middle end (for example, asan.module.ctor or __llvm_gcov_write_out) do not get any attributes and the backend incorrectly does not do any PAC/BTI code generation.
This patch record the default state of PAC/BTI codegen in a set of LLVM IR module-level attributes, based on command-line options:
* "sign-return-address", with non-zero value means generate code to sign return addresses (PAC-RET), zero value means disable PAC-RET.
* "sign-return-address-all", with non-zero value means enable PAC-RET for all functions, zero value means enable PAC-RET only for functions, which spill LR.
* "sign-return-address-with-bkey", with non-zero value means use B-key for signing, zero value mean use A-key.
This set of attributes are always added for AArch64 targets (as opposed, for example, to interpreting a missing attribute as having a value 0) in order to be able to check for conflicts when combining module attributed during LTO.
Module-level attributes are overridden by function level attributes. All the decision making about whether to not to generate PAC and/or BTI code is factored out into AArch64FunctionInfo, there shouldn't be any places left, other than AArch64FunctionInfo, which directly examine PAC/BTI attributes, except AArch64AsmPrinter.cpp, which is/will-be handled by a separate patch.
Differential Revision: https://reviews.llvm.org/D85649
show more ...
|
|
Revision tags: llvmorg-11.0.0-rc3, llvmorg-11.0.0-rc2, llvmorg-11.0.0-rc1 |
|
| #
6ef801aa |
| 15-Jul-2020 |
Xiangling Liao <[email protected]> |
[AIX] Static init frontend recovery and backend support
On the frontend side, this patch recovers AIX static init implementation to use the linkage type and function names Clang chooses for sinit re
[AIX] Static init frontend recovery and backend support
On the frontend side, this patch recovers AIX static init implementation to use the linkage type and function names Clang chooses for sinit related function.
On the backend side, this patch sets correct linkage and function names on aliases created for sinit/sterm functions.
Differential Revision: https://reviews.llvm.org/D84534
show more ...
|
|
Revision tags: llvmorg-12-init |
|
| #
69f3378a |
| 11-Jul-2020 |
Xiangling Liao <[email protected]> |
[AIX]Generate debug info for static init related functions
Set the debug location for static init related functions(__dtor and __finalize) so we can generate valid debug info on AIX by invoking -g w
[AIX]Generate debug info for static init related functions
Set the debug location for static init related functions(__dtor and __finalize) so we can generate valid debug info on AIX by invoking -g with clang or -debug-info-kind=limited with clang_cc1.
This also works for any other future targets who may use sinit and sterm functions for static initialization, where a direct call to dtor will be generated within finalize function body.
This patch also aims at validating that the debug info generated is correct for AIX sinit related functions.
Differential Revision: https://reviews.llvm.org/D83702
show more ...
|
|
Revision tags: llvmorg-10.0.1, llvmorg-10.0.1-rc4, llvmorg-10.0.1-rc3, llvmorg-10.0.1-rc2 |
|
| #
22337bfe |
| 27-May-2020 |
Xiangling Liao <[email protected]> |
[AIX][Frontend] Static init implementation for AIX considering no priority
1. Provides no piroirity supoort && disables three priority related attributes: init_priority, ctor attr, dtor attr; 2.
[AIX][Frontend] Static init implementation for AIX considering no priority
1. Provides no piroirity supoort && disables three priority related attributes: init_priority, ctor attr, dtor attr; 2. '-qunique' in XL compiler equivalent behavior of emitting sinit and sterm functions name using getUniqueModuleId() util function in LLVM (currently no support for InternalLinkage and WeakODRLinkage symbols); 3. Add testcases to emit IR sample with __sinit80000000, __dtor, and __sterm80000000; 4. Temporarily side-steps the need to implement the functionality of llvm.global_ctors and llvm.global_dtors arrays. The uses of that functionality in this patch (with respect to the name of the functions involved) are not representative of how the functionality will be used once implemented.
Differential Revision: https://reviews.llvm.org/D74166
show more ...
|
| #
ed1b5569 |
| 16-Jun-2020 |
Xiangling Liao <[email protected]> |
[NFC] Cleanup of EmitCXXGlobalInitFunc() and EmitCXXGlobalDtorFunc()
Tidy up some code of EmitCXXGlobalInitFunc() and EmitCXXGlobalDtorFunc() as the pre-work of D74166 patch.
Differential Revision:
[NFC] Cleanup of EmitCXXGlobalInitFunc() and EmitCXXGlobalDtorFunc()
Tidy up some code of EmitCXXGlobalInitFunc() and EmitCXXGlobalDtorFunc() as the pre-work of D74166 patch.
Differential Revision: https://reviews.llvm.org/D81972
show more ...
|