Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use custom function to format TRIL code #5587

Open
wants to merge 22 commits into
base: master
Choose a base branch
from

Conversation

janvrany
Copy link
Contributor

This commit introduces new template function Tril::format() that
is to be used to format TRIL code in tests designed as drop-in
replacement for std::snprintf() except that:

  1. supports limited number of arguments (up to 10, this limit
    can/will be removed with allowed use of variadic templates),
  2. support only a (used) subset of *printf-like conversion flags and
  3. the conversion depends on a static type of a value rather than
    on specified conversion (different conversion flags are supported
    for std::snprintf() compatibility)

Use of a template function and static types rather than *printf-like
conversion flags allows Tril::format() to be used in another templates
and thus will allow to further simplify test creation.

Moreover, this makes TRIL formatting independent on std::snprintf()
which is known to behave differently on different systems. Therefore,
this commit introduces indirection required to fix #5183 and #5308 .

@janvrany
Copy link
Contributor Author

@genie-omr build all

Copy link
Contributor

@Leonardo2718 Leonardo2718 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for doing this @janvrany! This will simplify things for sure. A few general comments:

  1. Using fixed width integer types to overload functions (literal() in this case) can sometimes cause ambiguity problems because multiple primitive types can have the same size. For example, both long int and long long int can be 64-bits wide, but are required to be distinct types. int64_t can only be a typedef for one of the two. Because long int (and unsigned long int for that matter) can be implicitly converted to either long long int or unsigned long long int, overloading with int64_t and uint64_t can cause an ambiguity if the latter are typedefs for long long int and unsigned long long int, respectively. See the osx failure [1] and Compiler Explorer example [2].
  2. I think Tril already uses variadic templates for some things (see [3]) so I believe you should be able to use one for Tril::format.
  3. Can you add some tests for this new tool? 🙂

[1] https://ci.eclipse.org/omr/job/PullRequest-osx_x86-64/2021/console

[2] https://godbolt.org/z/x49ffq

[3] https://github.com/eclipse/omr/blob/9d20fb28330885a22ecef2e4b225144d6004b7fd/fvtest/compilertriltest/OpCodeTest.hpp#L81-L82


inline size_t literal(char* dst, const size_t size, const void* value)
{
return std::snprintf(dst, size, "%" OMR_PRIXPTR, value);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe PRIXPTR is technically for intptr_t and clang is reporting a warning about this. Might need to add a reinterpret_cast.

Suggested change
return std::snprintf(dst, size, "%" OMR_PRIXPTR, value);
return std::snprintf(dst, size, "%" OMR_PRIXPTR, reinterpret_cast<intptr_t>(value));

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I've seen that. Will fix as suggested.

{
if (*fmt == '%')
{
throw std::runtime_error("found conversion specifier but no value given");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should there be a special case for %%?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed. Thanks!

fvtest/tril/tril/format.hpp Outdated Show resolved Hide resolved
const auto format_string = "(method return=Int32 args=[Int32] (block (ireturn (icall address=0x%jX args=[Int32] (iload parm=0)) ) ))";
std::snprintf(inputTrees, 200, format_string, reinterpret_cast<uintmax_t>(&oracleBoracle));
const auto format_string = "(method return=Int32 args=[Int32] (block (ireturn (icall address=0x%X args=[Int32] (iload parm=0)) ) ))";
Tril::format(inputTrees, 200, format_string, reinterpret_cast<void*>(&oracleBoracle));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this can become a static_cast now?

Suggested change
Tril::format(inputTrees, 200, format_string, reinterpret_cast<void*>(&oracleBoracle));
Tril::format(inputTrees, 200, format_string, static_cast<void*>(&oracleBoracle));

@janvrany
Copy link
Contributor Author

janvrany commented Oct 1, 2020

Thanks for this review, @Leonardo2718 - and for all that will follow as this would - I'm afraid - take a couple of iterations!

Can you add some tests for this new tool?

Yeah, I guess so. I was afraid somebody would ask for them. :-)

I think Tril already uses variadic templates for some things

Brilliant, I was put off by explicit mentioning in Unsupported C++11 Features

Just to double check, is the syntax for conversion specifiers being kept just to maintain compatibility with the existing tests? Given that the correct conversion specifier is derived from the type T and that the explicit specifiers are ignored,...

I'm actually thinking of using them. The idea is to have %s that would actually derive "best-bet" specifier from T (as it is now) and for everything else use them to make sure they're "correct". something like (after skipping modifiers like ll or j):

if (*fmt == 'd') {
    assert( std::is_integral<T>::value && "%d used but value is of an integral type" );
    std::snprintf(buf, size, "%" PRId64, static_cast<int64_t>(value)); 
} else if (...)

This may provide more flexbility (removes "one formatting rules them all" for any given type), may provide more
"type safety" (if desired) and also should address

Using fixed width integer types to overload functions (literal() in this case) can sometimes cause ambiguity problems
I believe - I have to try.

I'll make a second pass next week. Thanks for having a look!

@Leonardo2718
Copy link
Contributor

[...] and for all that will follow as this would - I'm afraid - take a couple of iterations!

Yeah..... sorry about that 😅

Brilliant, I was put off by explicit mentioning in Unsupported C++11 Features

Hm, we've upgraded some of our compilers since the last time that document was revised. I've opened #5592 to revisit that list and bring it up to date.

I'm actually thinking of using them. The idea is to have %s that would actually derive "best-bet" specifier from T (as it is now) and for everything else use them to make sure they're "correct". something like (after skipping modifiers like ll or j):

   if (*fmt == 'd') {
       assert( std::is_integral<T>::value && "%d used but value is of an integral type" );
       std::snprintf(buf, size, "%" PRId64, static_cast<int64_t>(value)); 
   } else if (...)

This may provide more flexbility (removes "one formatting rules them all" for any given type), may provide more
"type safety" (if desired) and also should address

Oh, interesting! 👍

@janvrany janvrany force-pushed the pr/use-custom-tril-format branch 3 times, most recently from 21f8a89 to 5370ed3 Compare October 12, 2020 10:17
@janvrany
Copy link
Contributor Author

@genie-omr build all

@0xdaryl
Copy link
Contributor

0xdaryl commented Mar 5, 2021

@genie-omr build all

Re-running CI to see if there are any failures.

@janvrany
Copy link
Contributor Author

janvrany commented Mar 5, 2021

Just to let you know I still plan to finish this, but got distracted by all the J9, CI, linkage...will get back to it.

@0xdaryl
Copy link
Contributor

0xdaryl commented Mar 5, 2021

Just to let you know I still plan to finish this, but got distracted by all the J9, CI, linkage...will get back to it.

Cool. Thanks @janvrany.

@janvrany
Copy link
Contributor Author

jenkins build all

@janvrany
Copy link
Contributor Author

jenkins build all

@janvrany
Copy link
Contributor Author

jenkins build zos aix

1 similar comment
@janvrany
Copy link
Contributor Author

jenkins build zos aix

@janvrany
Copy link
Contributor Author

jenkins build zos

@janvrany janvrany force-pushed the pr/use-custom-tril-format branch 5 times, most recently from 0e8a93b to 7f9b99c Compare December 14, 2023 18:54
@janvrany
Copy link
Contributor Author

jenkins build zos aix

This commit introduces new template function `Tril::format()` that
is to be used to format TRIL code in tests designed as drop-in
replacement for `std::snprintf()` except that:

  1. support only a (used) subset of *printf-like conversion specifiers,
  2. "modifiers" like l, ll, h, hh, j, I, I32 and I64 are ignored and
  3. used conversion specifier and a static type of actual parameter must
     match (it is not possible to format `double` using `%X`
     conversion)

Use of a template function and static types rather than *printf-like
conversion flags allows `Tril::format()` to be used in another templates
and thus will allow to further simplify test creation.

Moreover, this makes TRIL formatting independent on `std::snprintf()`
which is known to behave differently on different systems. Therefore,
this commit introduces indirection required to fix eclipse-omr#5183 and eclipse-omr#5324.
Since XLC compiler used at a time on AIX and ZOS does not support
std::make_signed, this commit provides simplified drop-in replacement
for use in reinterpret_as_signed().

Once XLC compiler on AIX and ZOS is upgraded to support std::make_signed,
this simplified version can be removed in favour of standard version.
@janvrany
Copy link
Contributor Author

jenkins build all

@janvrany
Copy link
Contributor Author

I finally got back to it hoping that over time compilers would be bumped to newer versions which would solve some mysterious template-related error messages I've got couple years ago.

After a lot of trial and error on platforms I have no access to I thing I've got it working. The failure on macOS seems unrelated (jitbuilder API generator test), the failure on RISC-V seems to be #6905. On my RISC-V systems, comptest passes.

FYI @0xdaryl as I'm not sure who maintains TRIL these days.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Review creation of TRIL code in tests
3 participants