Make type-system more consistent
Currently types of constants are guessed purely based on the values resulting from the calculation.
The result is an inconsistent type system. As an example byte a=250, b=250;
. If a and b are variables then a+b will be a byte with value 244 - however if a and b are both constant then a+b will be a word with value 500.The type system should be modified so the types of calculation results is the same for typed constants and variables.
The new type system will work as follows
-
Integer Literal Type Postfix (ub/uc: unsigned byte, sb/sc: signed byte, uw/ui/us: unsigned word, sw/si/ss: signed word, ud/ul: unsigned dword, sd/sl/l: signed dword).
-
No Integer Promotion. To achieve performance 8-bit types (byte, char) are not promoted to 16-bits in calculations.
-
Normal Type Conversion. When two typed integer values are combined using a binary operator including assignment) the result type follows C99 Standard Conversion Rules.
- If both are unsigned the result is the largest of the two types.
- If both are signed the result is the largest of the two types.
- If one type is unsigned and the other signed
- If the signed type can contain all values of the unsigned type the result is the same as the signed type.
- Otherwise the result is the same as the unsigned type (which must be at least the same size as the signed type)
-
Operand Casting Implementation / Optimization When operands of different types are combined using a binary operator (including assignment) the operands are converted to the same type before being combined. The type is defined by Normal Type Conversion as described above. However in most cases the KickC compiler will not explicitly perform this cast in the generated assembler code. Instead the language attempts to contain implementations for most combinations of types.
This improves performance significantly over explicit casting. For instance bitwise AND of a byte and a word can be performed significantly faster than first explicitly casting the byte to a word and then bitwise anding the resulting word with the other word-operand:
- vwuz1=_word_vbuz2_and_vwuz3: LDA z2 AND z3 STA z1 LDA #0 STA z1+1
- vwuz1=_word_vbuz2, vwuz1=vwuz2_and_vwuz3: LDA z2 STA z1 LDA #0 STA z1+1 LDA z2 AND z3 STA z1 LDA z2+1 AND z3+1 STA z1+1
-
Special Number Type A special type "number" is assigned to integer constants without a literal postfix. Numbers are flexible and will take a type based on their actual value when they are combined with a typed integer using a binary operator (including assignment).
- If one operand is a signed type and the other a number the number is converted to the smallest signed type that can hold its values.
- If one operand is a signed type and the other a number the number is converted to the smallest unsigned type that can hold its values. If the number value is negative it is converted to unsigned using two's complement.
Number types will always be resolved to actual fixed size types during the compilation.
-
Number Type Resolving Implementation
- All integer constants without a type postfix receives the type number.
- All temporary result resulting from combining a number with another integer value also receives the type number.
- When a binary operation (inclusing assignment) involves an integer type where the signedness is known and a "number" the number type is converted to one of the types "snumber" (signed number) or "unumber" (unsigned number) depending on the sign of the fixed integer type.
- Any constant integer that has type "snumber" is converted to the smallest signed type that can hold the value.
- Similarly any constant integer value that has type "unumber" is converted to the smallest unsigned integer type that can hold the value. If the value is negative it is converted to unsigned using twos complement.