Only decide the bitsize of an integer literal when interpreting, not when parsing #49252
Replies: 2 comments 1 reply
-
The "default" integer type also comes up when asking for the length of an Array or Tuple. |
Beta Was this translation helpful? Give feedback.
-
This discourse thread had me think a bit more about this, and there's a usecase that complicates this. Say you have a microcontroller like the ATmega328p with its word size of Now, if we were to make the compiler aware on the
is 16 bytes (an
I'm unsure of general solutions to this. To cover all cases, I suspect we'd have to not only write a type tag, but actively check that the expected layouts are the same in some sort of initialization handshake. Or we could write the layout before serializing the actual value. Alternatively, we'd have to not use As far as the original motivation for the discussion/issue is concerned - the type of integer literals should IMO still be flexible. That is, |
Beta Was this translation helpful? Give feedback.
-
Currently, the parser decides the numeric type of a literal integer like
1
to be the native integer type of the platform the parser runs on:This is an issue for cross compilation to e.g. AVR, where the native integer size is 8 bit. This has the consequence that code like
eachindex("foo")
or1:10
returns an iterable with eltypeInt64
when compiling on a 64 bit host, forcing code intended for AVR to emulate 64 bit integer semantics when it's not really necessary to do so, using 8 registers perInt64
instead of just one forInt8
. Likewise, cross compilation from 64 bit to 32 bit experiences the same issue, just with 2 registers.One possible solution to this is to move that decision point (i.e., that a parsed literal needs to be an
Int64
orInt32
on 32 bit platforms) from the parser to the interpreter/type inference, when we already know the target architecture. The idea is to have the parser emitInt 1
, without introducing an additional type, i.e. makeInt !== Int64
for the parser only, and resolve this to the native integer size of the target architecture before running type inference. This keeps the existing behavior thatInt === Int64
on 64 bit systems, as well asInt === Int32
on 32 bit systems, while simultaneously allowingInt === Int8
in cross compilation for AVR. Conceptually, no new types need to be introduced for this - type inference just sees a different type depending on the target architecture. This behavior should be the same that users on current 64 bit/32 bit platforms can already observe.This also preserves all existing promotion rules & behavior, i.e.
zero(Int32) + 1
still returnsone(Int64)
on 64 bit platforms andone(Int32)
on 32 bit platforms.zero(Int) + 1
would now returnone(Int)
, which will (for non-cross compilation) stay the same as it is now.It may be desirable to introduce this change as part of a broader cross compilation API in codegen, since it's not clear how the following would behave with just this change:
Semantically, we need to assign a value to
y
, but can't really do this without knowing the concrete runtime type ofx
. Having a dedicated cross compilation API would solve this, due to being able to ask the interpreter to evaluate the parsedmodule
expression in the context of a target machine different from the host machine (thereby replacing the occurences ofInt
in the parsed expression with the appropriate integer type before evaluating the expression). Similar issues exist with the use of macros on the top level, which may also need to be evaluated in the context of the target instead of the host, to account for differences insizeof(Int)
.Beta Was this translation helpful? Give feedback.
All reactions