[SystemSafety] Critical systems Linux

Olwen Morgan olwen at phaedsys.com
Fri Nov 23 03:57:00 CET 2018


Rod,

That depends on your degree of confidence in the preservation of 
semantics. With C as the target language and a C compiler as the back 
end, you are translating into something whose standard gives so much 
latitude to the implementor that it's anyone's guess whether or not 
you've introduced ambiguity.Although one can guard against ambiguity to 
a substantial extent by ultra-strict sub-setting and usage rules, I 
don't have and I've not yet seen a convincing demonstration that 
ambiguities can be entirely avoided even by draconian sub-setting - 
especially given the latitude that the C standard permits to optimisers. 
The C standard permits an implementation to omit any evaluation provided 
that it can deduce that no needed side effect is thereby omitted - but 
since the standard does not actually define what constitutes a "needed 
side effect", one ends up in a no-man's land where implementations 
generally appear to behave sensibly but none is actually obliged to.

Although I usually program in a paranoiacally strict subset of C - and 
I've not yet come unstuck with it - I wouldn't be first in the queue to 
claim it's foolproof. When programming for bare-metal targets, you 
sometimes have to examine generated code manually to ensure that nothing 
silly has happened. One example of this is an idle loop at the end of a 
cycle in a cyclic executive with a timed interrupt triggering each 
cycle. You might code the loop as:

     i = 1;

     while (i) { i = 1-i; i = 1-i };

but the standard does not forbid a C implementation from generating no 
code at all for this. I've never known this to happen in C but I've been 
told on good authority that some FORTRAN compilers have been known to 
optimise such loops away to nothing.

One could try:

     volatile int i = 2;

     while (3 != i) { i = (i+i)%7; }

in a two-prong attack to defeat an optimiser. If it ignores the volatile 
qualifier, you hope that it cannot deduce that i cycles through only 
quadratic residues mod 7 and therefore can never be equal to 3. Yet, in 
a really adverse case you might have to code such a loop using gotos to 
avoid stack problems.

On the other hand, a lot of embedded programmers might simply avoid the 
faffing and resort to embedding in-line assembler in the C giving a 
self-looping instruction such as:IDLE: JMP IDLE

where this instruction simply jumps to itself - and there are some 
circumstances in which this may be technically preferable.

With C there can never be the solidity of technical guarantee that one 
might like. You might recall my earlier-posted piece of C mischief:

#include <stdio.h>

void PrintEvalOrder( int p1, int p2, int p3)
{
     printf("\np1, p2, p3 evaluated in order: p%i, p%i, p%i\n", p1, p2, p3);
     return;
}

int main(void)
{
     int i = 0;

     /* next line tests order of eval. of args to a function call */

     PrintEvalOrder((++i), (++i), (++i));

     return 0;
}

Compiled under gcc version 5 and then run, this outputs: "p1, p2, p3 
evaluated in order: p3, p3, p3" - thereby revealing over-agressive 
optimisation even in a simple program.

One hopes that CCG steers clear of such problems but I'd challenge 
anyone to give a rock-solid proof that that is the case.


Olwen


On 22/11/2018 22:41, Roderick Chapman wrote:
> On 22/11/2018 14:44, Olwen Morgan wrote:
>
>> Of course, CCG will still face the same problems that I mentioned in 
>> previous postings. 
>
> I don't understand that... the compiler should be semantics-preserving,
>
> so verified, unambiguous SPARK becomes C with the same semantics.
>
> Why would a compiler _introduce_ ambiguity when there's no need to do so?
>
>  - Rod
>
>
> _______________________________________________
> The System Safety Mailing List
> systemsafety at TechFak.Uni-Bielefeld.DE
> Manage your subscription: 
> https://lists.techfak.uni-bielefeld.de/mailman/listinfo/systemsafety


More information about the systemsafety mailing list