Finite list of things that vary with CPU-type

  • Thread starter Tomás Ó hÉilidhe
  • Start date
T

Tomás Ó hÉilidhe

I would like to draw up a finite list of things you have to "watch out
for" when compiling a C program for a different kind of CPU than it
was originally intended for. For instance, let's say you have a C
program that was intended to run on an x86 processor, but you want to
run it on an Apple Mac that has a PowerPC processor.

Well the obvious ones are:
 
J

jameskuyper

Tomás Ó hÉilidhe said:
I would like to draw up a finite list of things you have to "watch out
for" when compiling a C program for a different kind of CPU than it
was originally intended for. For instance, let's say you have a C
program that was intended to run on an x86 processor, but you want to
run it on an Apple Mac that has a PowerPC processor.

Well the obvious ones are:

The entirety of Annex J to the C standard is a good starting point.
I'm not sure whether it's comprehensive, though - it's only 27 pages
long, which doesn't seem sufficient to provide complete coverage.
 
D

dj3vande

I would like to draw up a finite list of things you have to "watch out
for" when compiling a C program for a different kind of CPU than it
was originally intended for.

Draw up your finite list.
Show it to a CPU designer with a contrarian streak.
The next version of the CPU architecture will have a difference not
accounted for on your list.

Therefore, no such finite list can exist.


The solution, of course, is to write to the interface defined by the
standard instead of making assumptions about the CPU; making it work
with a different CPU then becomes the compiler implementor's problem.


dave

--
Dave Vandervies dj3vande at eskimo dot com
Is it me or is the intelligence in here dropping like a stone?
It's just you. Unless the stone is made of Neutronium.
--Dave Brown and Shmuel (Seymour J.) Metz in the scary devil monastery
 
J

John Bode

I would like to draw up a finite list of things you have to "watch out
for" when compiling a C program for a different kind of CPU than it
was originally intended for. For instance, let's say you have a C
program that was intended to run on an x86 processor, but you want to
run it on an Apple Mac that has a PowerPC processor.

Well the obvious ones are:

Byte sex (endianess)
Alignment restrictions
Type sizes
 
F

Flash Gordon

John Bode wrote, On 04/12/08 16:55:
Byte sex (endianess)
Alignment restrictions
Type sizes

With floating point there is a lot more than just the type size!
CHAR_BIT (and everything else in limits.h)
Division of negative values
Timings (if they matter)
Extensions (ones used by the SW you are porting)
Availability of a compiler for the version of the C standard the code
conforms to (especially if it is C99 code)
Legal paths/filenames
Limits on program/data sizes
Whether it uses text/binary streams correctly
Anything the standard says in implementation defined
Use of anything the standard leave as unspecified or undefined

It goes on and on if you are talking about some random program. Writing
a program to be portable in the first place can be rather easier.
 
W

Walter Banks

Tomás Ó hÉilidhe said:
I would like to draw up a finite list of things you have to "watch out
for" when compiling a C program for a different kind of CPU

Well the obvious ones are:

My two cents worth

1) There are a ton of things that are related to function argument passing.
Stack frames, compile time local allocation, register passing.

2) The misra list is worth looking through. It raises a lot of implementation
defined points.

3) Variable packing, union and struct allocation.

4) Language symbol representation.

Regards,
 
C

CBFalconer

Tomás Ó hÉilidhe said:
I would like to draw up a finite list of things you have to "watch
out for" when compiling a C program for a different kind of CPU
than it was originally intended for. For instance, let's say you
have a C program that was intended to run on an x86 processor, but
you want to run it on an Apple Mac that has a PowerPC processor.

If you simply pay attention to the C standard and write properly
compliant code, you will have nothing to "watch for".
 
K

Keith Thompson

CBFalconer said:
If you simply pay attention to the C standard and write properly
compliant code, you will have nothing to "watch for".

That's not always possible, especially if you're working with code
that somebody else wrote or that's deliberately non-portable (there
are often good reasons for the latter).
 
L

litchie

If you simply pay attention to the C standard and write properly
compliant code, you will have nothing to  "watch for".

For example,

short *p;
char *q;
*p = *(short*)q;

this type of code works on some platforms, but will break on some
others.
 
J

jameskuyper

litchie wrote:
....
For example,

short *p;
char *q;
*p = *(short*)q;

this type of code works on some platforms, but will break on some
others.

What does "works" mean in this context? The behavior is undefined for
several different reasons, and will typically fail for at least one of
those reasons on every platform I normally work on. However, even if
the behavior were defined, what would you expect that behavior to be?
 
C

CBFalconer

litchie said:
.... snip ...


For example,

short *p;
char *q;
*p = *(short*)q;

this type of code works on some platforms, but will break on some
others.

That is NOT compliant code. However:

short *p;
char *q;

/* code initializing p */
q = (char*)p;

is compliant, and can be trusted.
 
K

Keith Thompson

CBFalconer said:
That is NOT compliant code.

That depends on what you mean by "compliant". The standard goes to a
great deal of trouble to list the various ways that code can be
something other than correct.

The code violates no constraints or syntax rules (assuming it appears
within a function definition). It invokes undefined behavior *if* q
has not been initialized (I assumed the initialization was meant to be
implicit), or if q contains an address that's not properly aligned for
storing an object of type short.

But this:

short *p = malloc(sizeof *p);
char *q = malloc(sizeof(short));
if (p == NULL || q == NULL) exit(EXIT_FAILURE);
*(short*)q = 42;
*p = *(short*)q;

is perfectly valid (assuming the proper surrounding context).
However:

short *p;
char *q;

/* code initializing p */
q = (char*)p;

is compliant, and can be trusted.

printf("hello, world\n");

is also compliant, and about equally relevant.
 
L

litchie

litchie wrote:

...




What does "works" mean in this context? The behavior is undefined for
several different reasons, and will typically fail for at least one of
those reasons on every platform I normally work on. However, even if
the behavior were defined, what would you expect that behavior to be?

At least it won't fail on x86. In fact, I have seen this kind of code
in many projects... I guess they have a quite self-evident behavior
though not defined in standard.
 
H

Harald van Dijk

Keith Thompson said:

Presumably he means "conforming", but how can we tell? The Standard
doesn't mention the word "compliant".

Quoting the index:
"compliance, /see/ conformance"

It seems like a reasonable assumption that compliant means conforming,
from that.
 
J

James Kuyper

litchie said:
At least it won't fail on x86. In fact, I have seen this kind of code
in many projects... I guess they have a quite self-evident behavior
though not defined in standard.

So it takes a pointer to char that has not been set to point to
anything, and converts it into a pointer to a short integer. Which short
integer should it "self-evidently" point at? If you don't know where it
points (and I can see how you possibly could), what possible use could
the result of the conversion be?
 
L

litchie

So it takes a pointer to char that has not been set to point to

Now I must apologize for the confusing code I provided. Another
example might be better:

void do_something(char* pbuf, int n)
{
int i;
for (i = 0; i < n; i+=2)
{
short a;

a = *(short*)pbuf;
...
}
}
 
B

Ben Bacarisse

litchie said:
Now I must apologize for the confusing code I provided. Another
example might be better:

This always happens -- when you try for more clarity another error
creeps in!
void do_something(char* pbuf, int n)
{
int i;
for (i = 0; i < n; i+=2)
{
short a;

a = *(short*)pbuf;


You probably meant *(short *)(pbuf + i) or *(short *)&buf.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,763
Messages
2,569,562
Members
45,038
Latest member
OrderProperKetocapsules

Latest Threads

Top