gigatron-rom
gigatron-rom copied to clipboard
lcc: not promoting unsigned short to int when sizes are equal
From http://www.homebrewcpu.com/retargeting_lcc.htm:
7/4/2007 - Fixed what I believe to be a bug in the handling of ANSI integral promotion. There are some odd rules about promoting unsigned integer types to signed in ANSI C that are somewhat different than standard C. When an unsigned short type is widened to an int, it is changed from unsigned to signed. LCC does this - but when the sizeof(short) is the same as sizeof(int), the change of sign should not happen. LCC made this change anyway, which broke some code in Minix (and pretty much rendered unsigned short useless). My fix was to add an if clause to binary() that allows an unsigned short to remain unsigned iff short and int widths are the same.
The actual fix to binary() in src/expr.c is not listed on the page.
- We have to consider if we want the same treatment.
- Also consider the other types for as long as their sizes are equal to their own higher ranking type.
- The fix for unsigned short can be restricted to the &IR == >1IR condition.
- This should work, at the end of binary():
+ if (xty->size == yty->size)
+ if (xty == unsignedshort || yty == unsignedshort)
+ return unsignedtype;
return inttype;
- These cases seem to be handled ok already
- Better not restrict. This looks like a genuine LCC bug
We shouldn't fix this without a test, so keep on hold for now
Low priority
Feedback from Bill Buzbee (Magic-1) in the comment section of "Magic-1 at 16 years old" https://www.youtube.com/watch?v=qOcSnaK0yBw
13 hours ago I suspect there is a more general way to do this, but here is my post-hack binary(). If I recall, this is an issue that only arose because I declared Magic-1's integer type to be 16 bits - the same width as short.
For those following along, here's the webpage on my lcc retargeting: http://www.homebrewcpu.com/retargeting_lcc.htm
The biggest trick I used with lcc was to lie to it and tell it I had 4 32-bit integer registers, 4 32-bit float registers and 4 64-bit double registers. These were actually mapped to frame memory. At the end of one of the passes, I looked to see if any were used. If so, I allocated space on the stack and then changed the name of the register to the stack offset. It worked surprisingly well.
Anyway, here's my binary() hack:
Type binary(Type xty, Type yty) { #define xx(t) if (xty == t || yty == t) return t xx(longdouble); xx(doubletype); xx(floattype); xx(unsignedlonglong); xx(longlong); xx(unsignedlong); if (xty == longtype && yty == unsignedtype || xty == unsignedtype && yty == longtype) if (longtype->size > unsignedtype->size) return longtype; else return unsignedlong; xx(longtype); xx(unsignedtype); // WBB fix - integral promotion rules allow // unsigned to stay unsigned when // width of short is same as width of int if (inttype->size == shorttype->size) { xx(unsignedshort); } // WBB end fix return inttype; #undef xx }
This issue should be closed since glcc fixes it.