Home | History | Annotate | Download | only in source
      1 // Copyright (c) 2015-2016 The Khronos Group Inc.
      2 //
      3 // Permission is hereby granted, free of charge, to any person obtaining a
      4 // copy of this software and/or associated documentation files (the
      5 // "Materials"), to deal in the Materials without restriction, including
      6 // without limitation the rights to use, copy, modify, merge, publish,
      7 // distribute, sublicense, and/or sell copies of the Materials, and to
      8 // permit persons to whom the Materials are furnished to do so, subject to
      9 // the following conditions:
     10 //
     11 // The above copyright notice and this permission notice shall be included
     12 // in all copies or substantial portions of the Materials.
     13 //
     14 // MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
     15 // KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
     16 // SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
     17 //    https://www.khronos.org/registry/
     18 //
     19 // THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     20 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     21 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     22 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
     23 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     24 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     25 // MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
     26 
     27 #include "spirv_endian.h"
     28 
     29 #include <cstring>
     30 
     31 enum {
     32   I32_ENDIAN_LITTLE = 0x03020100ul,
     33   I32_ENDIAN_BIG = 0x00010203ul,
     34 };
     35 
     36 // This constant value allows the detection of the host machine's endianness.
     37 // Accessing it through the "value" member is valid due to C++11 section 3.10
     38 // paragraph 10.
     39 static const union {
     40   unsigned char bytes[4];
     41   uint32_t value;
     42 } o32_host_order = {{0, 1, 2, 3}};
     43 
     44 #define I32_ENDIAN_HOST (o32_host_order.value)
     45 
     46 uint32_t spvFixWord(const uint32_t word, const spv_endianness_t endian) {
     47   if ((SPV_ENDIANNESS_LITTLE == endian && I32_ENDIAN_HOST == I32_ENDIAN_BIG) ||
     48       (SPV_ENDIANNESS_BIG == endian && I32_ENDIAN_HOST == I32_ENDIAN_LITTLE)) {
     49     return (word & 0x000000ff) << 24 | (word & 0x0000ff00) << 8 |
     50            (word & 0x00ff0000) >> 8 | (word & 0xff000000) >> 24;
     51   }
     52 
     53   return word;
     54 }
     55 
     56 uint64_t spvFixDoubleWord(const uint32_t low, const uint32_t high,
     57                           const spv_endianness_t endian) {
     58   return (uint64_t(spvFixWord(high, endian)) << 32) | spvFixWord(low, endian);
     59 }
     60 
     61 spv_result_t spvBinaryEndianness(spv_const_binary binary,
     62                                  spv_endianness_t* pEndian) {
     63   if (!binary->code || !binary->wordCount) return SPV_ERROR_INVALID_BINARY;
     64   if (!pEndian) return SPV_ERROR_INVALID_POINTER;
     65 
     66   uint8_t bytes[4];
     67   memcpy(bytes, binary->code, sizeof(uint32_t));
     68 
     69   if (0x03 == bytes[0] && 0x02 == bytes[1] && 0x23 == bytes[2] &&
     70       0x07 == bytes[3]) {
     71     *pEndian = SPV_ENDIANNESS_LITTLE;
     72     return SPV_SUCCESS;
     73   }
     74 
     75   if (0x07 == bytes[0] && 0x23 == bytes[1] && 0x02 == bytes[2] &&
     76       0x03 == bytes[3]) {
     77     *pEndian = SPV_ENDIANNESS_BIG;
     78     return SPV_SUCCESS;
     79   }
     80 
     81   return SPV_ERROR_INVALID_BINARY;
     82 }
     83 
     84 bool spvIsHostEndian(spv_endianness_t endian) {
     85   return ((SPV_ENDIANNESS_LITTLE == endian) &&
     86           (I32_ENDIAN_LITTLE == I32_ENDIAN_HOST)) ||
     87          ((SPV_ENDIANNESS_BIG == endian) &&
     88           (I32_ENDIAN_BIG == I32_ENDIAN_HOST));
     89 }
     90