[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [bug-mes] MesCC assigns incorrect types to arithmetic expressions
From: |
Mark H Weaver |
Subject: |
Re: [bug-mes] MesCC assigns incorrect types to arithmetic expressions |
Date: |
Thu, 18 Jul 2019 15:52:31 -0400 |
Hi Jan,
> Mark H Weaver writes:
>
>> Currently, if I understand the code correctly, MesCC simply assigns the
>> type of the first operand as the type of most (all?) binary expressions.
>> For example, the type of (a + b) is the type of a, with no regard to b.
>> Ditto for the relational operators. In particular, I'm looking at
>> 'ast->type' in compile.scm.
>
> Ah, that could be; good catch.
>
> Do you have a suggestion for a failing test (as this was something
> you're aware of?).
I don't know enough about MesCC to predict a specific test that will
fail off-hand, but here's a likely avenue to search for one: unsigned
integer arithmetic has fully specified behavior in case of overflows,
namely to take the true mathematical result modulo MAX+1. In order for
this to work properly, the compiler needs to choose the correct type for
the operation, so that it will wrap around in the way the programmer
expected.
For binary arithmetic operations such as (A + B), the scalar type used
for the addition operation is determined by the integer promotions and
usual arithmetic conversions (see below).
For example, consider this:
#include <stdint.h>
uint64_t foo (void)
{
uint32_t a = 0xffffffff;
uint64_t b = 0xffffffff;
return a + b;
}
C99 specifies that (a + b) should be performed as a 64-bit operation,
and therefore the result should be 0x1fffffffe. However, if you use a
32-bit operation, the result will be 0xfffffffe, which is incorrect.
Based on my guess that MesCC is assigning the type uint32_t to (a + b),
and perhaps therefore emitting a 32-bit unsigned addition, I guess that
it might miscompile this example. Or perhaps it works because of some
other misbehavior elsewhere that I don't yet know about.
>> From an admittedly quick search, I didn't see anything about the
>> usual arithmetic conversions, or the integer promotions. Did I miss
>> them?
>
> I'm not sure what is usual;
The "integer promotions" and "usual arithmetic conversions" are
technical terms defined in sections 6.3.1.1 and 6.3.1.8 of C99,
respectively.
> this is my first C compiler and I never
> thought it would work so well. As you have seen, it could do with
> some refactoring; as soon as MesCC procuded a working tcc I paused
> development and started on integrating mes/mescc into the guix
> bootstrap...
>
> Promotion-wise, I think that is handled in some individual cases,
> like here
>
> --8<---------------cut here---------------start------------->8---
> ((ge ,a ,b)
> (let* ((type-a (ast->type a info))
> (type-b (ast->type b info))
> (info ((binop->r info) a b 'r0-r1))
> (test->r (if (or (unsigned? type-a) (unsigned? type-b))
> 'ae?->r 'ge?->r))
> (info (append-text info (wrap-as (as info test->r))))
> (info (append-text info (wrap-as (as info 'test-r)))))
> info))
> --8<---------------cut here---------------end--------------->8---
Admittedly, I don't really understand what the code above is doing, but
I don't see anything that looks like integer promotion here.
> These tests (WIP branch) currently fail
>
> --8<---------------cut here---------------start------------->8---
> 17-compare-unsigned-char-le
> 17-compare-unsigned-short-le
> --8<---------------cut here---------------end--------------->8---
>
> which may be what you're aiming at?
Yes, I guess that those tests are likely failing due to the problems
I've raised here.
Thanks,
Mark