On Wed, Sep 12, 2012 at 12:27 PM, Ouriel, Boaz <span dir="ltr"><<a href="mailto:boaz.ouriel@intel.com" target="_blank">boaz.ouriel@intel.com</a>></span> wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hey All,<br>
<br>
This is a very big topic in SPIR and probably a very controversial one as well. It includes dealing with 32 vs. 64 bit architectures and OpenCL "C" endianness.<br>
We have written down some of the aspects, but of course did not cover everything - let's start a discussion on the portability and see where it takes us.<br>
I suggest we start with the 32 vs. 64 bits discussion and then move to the Endianness part.<br>
<br>
****Introduction****<br>
As a reminder, portability is one of SPIR's goals.<br>
However, SPIR does not attempt to solve inherent portability issues, which exist in OpenCL "C" or in C99.<br>
It is clear that OpenCL programs could be written in a way which make them non portable and very device specific.<br>
Such programs will never be portable. In addition, some corner case scenario's which have been identified by Khronos members have been disallowed in SPIR.<br>
So, SPIR aims at being portable but not for every scenario.<br>
<br>
1) ****Portability between Devices with different address width (32 vs. 64 bits)****<br>
During the design stages, Khronos members needed to decide on its philosophy when it comes to dealing with the address width of devices (32 vs. 64bits).<br>
During internal discussions, two alternatives came up. The first alternative was to split SPIR into two sub-cases: SPIR 32bits and SPIR 64bits.<br>
The second alternative was to try and abstract this information at SPIR level.<br>
<br>
Splitting SPIR into 32bit and 64bit is simpler to implement. However, it is less portable.<br>
This will require OpenCL developers to pre-compile two versions of their code one for 32bit and another for 64bit devices and make their application aware at runtime to the underlying device architecture.<br>
OpenCL applications would need to load the proper SPIR binary based on the device architecture.<br>
An option that was raised during the discussions was to have a fat binary that contains both 32bit and 64bit versions of SPIR binaries.<br>
However, this option was controversial inside Khronos and eventually was not accepted.<br>
The decision was to pursue the second alternative. Khronos members understand that this is a more complex alternative and does not guarantee 100% percent coverage to all cases.<br>
However, as stated before, SPIR attempts to solve the important cases. Those particular cases which SPIR will not be able to address are explicitly documented in the specification.<br>
<br>
         ****Pointers****<br>
During SPIR generation, the size, and the alignment of pointers is unknown (32 vs. 64 bits).<br>
The SPIR representation shouldn't assume anything about the size and the alignment of pointers,<br>
but it might use pointers in the usual way (except from using GEP when the pointed type has unknown size - this one is illegal in SPIR and will fail the SPIR verification pass which was written by Khronos members)<br>
<br>
         *****Sizeof******<br>
Most valid built-in and user specific types in OpenCL have known non device-specific size.<br>
However, for some types (pointers, size_t, ptrdiff_t) the size is unknown during compilation.<br>
To overcome this issue, SPIR provides functions to substitute the constant values of the sizeof operator.<br>
These functions should be resolved by the device backend compiler when producing the final machine code of the OpenCL program.<br></blockquote><div><br></div><div>OpenCL 1.2 (6.3)/k says the result of sizeof is an ICE. So these are valid:</div>
<div><br></div><div>int does_this_compile[sizeof(void*) - 3];</div><div><br></div><div>struct how_do_you_represent_this_in_IR {</div><div>  int a : 1;</div><div>  int b : sizeof(void*) * 4;</div><div>};</div><div><br></div>
<div>Is OpenCL going to be changed to reject these cases?</div><div><br></div><div><br></div><div>How do you perform record layout if the size of a pointer is unknown? For instance:</div><div><br></div><div>struct A {</div>
<div>  int *p;</div><div>  int n;</div><div>} a;</div><div>int arr[offsetof(A, n) - 3]; // or, int arr[(char*)&a.n - (char*)&a.p - 3];</div><div><br></div><div>-- Richard</div></div>