| /* d-port.cc -- D frontend interface to the gcc back-end. |
| Copyright (C) 2013-2021 Free Software Foundation, Inc. |
| |
| GCC is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 3, or (at your option) |
| any later version. |
| |
| GCC is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GCC; see the file COPYING3. If not see |
| <http://www.gnu.org/licenses/>. */ |
| |
| #include "config.h" |
| #include "system.h" |
| #include "coretypes.h" |
| |
| #include "dmd/root/port.h" |
| #include "dmd/target.h" |
| |
| #include "tree.h" |
| |
| |
| /* Implements the Port interface defined by the frontend. |
| A mini library for doing compiler/system specific things. */ |
| |
| /* Compare the first N bytes of S1 and S2 without regard to the case. */ |
| |
| int |
| Port::memicmp (const char *s1, const char *s2, size_t n) |
| { |
| int result = 0; |
| |
| for (size_t i = 0; i < n; i++) |
| { |
| char c1 = s1[i]; |
| char c2 = s2[i]; |
| |
| result = c1 - c2; |
| if (result) |
| { |
| result = TOUPPER (c1) - TOUPPER (c2); |
| if (result) |
| break; |
| } |
| } |
| |
| return result; |
| } |
| |
| /* Convert all characters in S to uppercase. */ |
| |
| char * |
| Port::strupr (char *s) |
| { |
| char *t = s; |
| |
| while (*s) |
| { |
| *s = TOUPPER (*s); |
| s++; |
| } |
| |
| return t; |
| } |
| |
| /* Return true if the real_t value from string BUFFER overflows |
| as a result of rounding down to float mode. */ |
| |
| bool |
| Port::isFloat32LiteralOutOfRange (const char *buffer) |
| { |
| real_t r; |
| |
| real_from_string3 (&r.rv (), buffer, TYPE_MODE (float_type_node)); |
| |
| return r == target.RealProperties.infinity; |
| } |
| |
| /* Return true if the real_t value from string BUFFER overflows |
| as a result of rounding down to double mode. */ |
| |
| bool |
| Port::isFloat64LiteralOutOfRange (const char *buffer) |
| { |
| real_t r; |
| |
| real_from_string3 (&r.rv (), buffer, TYPE_MODE (double_type_node)); |
| |
| return r == target.RealProperties.infinity; |
| } |
| |
| /* Fetch a little-endian 16-bit value from BUFFER. */ |
| |
| unsigned |
| Port::readwordLE (const void *buffer) |
| { |
| const unsigned char *p = (const unsigned char *) buffer; |
| |
| return ((unsigned) p[1] << 8) | (unsigned) p[0]; |
| } |
| |
| /* Fetch a big-endian 16-bit value from BUFFER. */ |
| |
| unsigned |
| Port::readwordBE (const void *buffer) |
| { |
| const unsigned char *p = (const unsigned char *) buffer; |
| |
| return ((unsigned) p[0] << 8) | (unsigned) p[1]; |
| } |
| |
| /* Fetch a little-endian 32-bit value from BUFFER. */ |
| |
| unsigned |
| Port::readlongLE (const void *buffer) |
| { |
| const unsigned char *p = (const unsigned char *) buffer; |
| |
| return (((unsigned) p[3] << 24) |
| | ((unsigned) p[2] << 16) |
| | ((unsigned) p[1] << 8) |
| | (unsigned) p[0]); |
| } |
| |
| /* Fetch a big-endian 32-bit value from BUFFER. */ |
| |
| unsigned |
| Port::readlongBE (const void *buffer) |
| { |
| const unsigned char *p = (const unsigned char *) buffer; |
| |
| return (((unsigned) p[0] << 24) |
| | ((unsigned) p[1] << 16) |
| | ((unsigned) p[2] << 8) |
| | (unsigned) p[3]); |
| } |
| |
| /* Write an SZ-byte sized VALUE to BUFFER, ignoring endian-ness. */ |
| |
| void |
| Port::valcpy (void *buffer, uint64_t value, size_t sz) |
| { |
| switch (sz) |
| { |
| case 1: |
| *(uint8_t *) buffer = (uint8_t) value; |
| break; |
| |
| case 2: |
| *(uint16_t *) buffer = (uint16_t) value; |
| break; |
| |
| case 4: |
| *(uint32_t *) buffer = (uint32_t) value; |
| break; |
| |
| case 8: |
| *(uint64_t *) buffer = (uint64_t) value; |
| break; |
| |
| default: |
| gcc_unreachable (); |
| } |
| } |