xref: /netbsd-src/external/gpl3/gcc.old/dist/include/leb128.h (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
11debfc3dSmrg /* Utilities for reading leb128 values.
2*8feb0f0bSmrg    Copyright (C) 2012-2020 Free Software Foundation, Inc.
31debfc3dSmrg 
41debfc3dSmrg This file is part of the libiberty library.
51debfc3dSmrg Libiberty is free software; you can redistribute it and/or
61debfc3dSmrg modify it under the terms of the GNU Library General Public
71debfc3dSmrg License as published by the Free Software Foundation; either
81debfc3dSmrg version 2 of the License, or (at your option) any later version.
91debfc3dSmrg 
101debfc3dSmrg Libiberty is distributed in the hope that it will be useful,
111debfc3dSmrg but WITHOUT ANY WARRANTY; without even the implied warranty of
121debfc3dSmrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
131debfc3dSmrg Library General Public License for more details.
141debfc3dSmrg 
151debfc3dSmrg You should have received a copy of the GNU Library General Public
161debfc3dSmrg License along with libiberty; see the file COPYING.LIB.  If not, write
171debfc3dSmrg to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
181debfc3dSmrg Boston, MA 02110-1301, USA.  */
191debfc3dSmrg 
201debfc3dSmrg /* The functions defined here can be speed critical.
211debfc3dSmrg    Since they are all pretty small we keep things simple and just define
221debfc3dSmrg    them all as "static inline".
231debfc3dSmrg 
241debfc3dSmrg    WARNING: This file is used by GDB which is stuck at C90. :-(
251debfc3dSmrg    Though it can use stdint.h, inttypes.h.
261debfc3dSmrg    Therefore if you want to add support for "long long" you need
271debfc3dSmrg    to wrap it in #ifdef CC_HAS_LONG_LONG.  */
281debfc3dSmrg 
291debfc3dSmrg #ifndef LEB128_H
301debfc3dSmrg #define LEB128_H
311debfc3dSmrg 
321debfc3dSmrg /* Get a definition for inline.  */
331debfc3dSmrg #include "ansidecl.h"
341debfc3dSmrg 
351debfc3dSmrg /* Get a definition for NULL, size_t.  */
361debfc3dSmrg #include <stddef.h>
371debfc3dSmrg 
381debfc3dSmrg #ifdef HAVE_STDINT_H
391debfc3dSmrg #include <stdint.h>
401debfc3dSmrg #endif
411debfc3dSmrg #ifdef HAVE_INTTYPES_H
421debfc3dSmrg #include <inttypes.h>
431debfc3dSmrg #endif
441debfc3dSmrg 
451debfc3dSmrg /* Decode the unsigned LEB128 constant at BUF into the variable pointed to
461debfc3dSmrg    by R, and return the number of bytes read.
471debfc3dSmrg    If we read off the end of the buffer, zero is returned,
481debfc3dSmrg    and nothing is stored in R.
491debfc3dSmrg 
501debfc3dSmrg    Note: The result is an int instead of a pointer to the next byte to be
511debfc3dSmrg    read to avoid const-vs-non-const problems.  */
521debfc3dSmrg 
531debfc3dSmrg static inline size_t
read_uleb128_to_uint64(const unsigned char * buf,const unsigned char * buf_end,uint64_t * r)541debfc3dSmrg read_uleb128_to_uint64 (const unsigned char *buf, const unsigned char *buf_end,
551debfc3dSmrg 			uint64_t *r)
561debfc3dSmrg {
571debfc3dSmrg   const unsigned char *p = buf;
581debfc3dSmrg   unsigned int shift = 0;
591debfc3dSmrg   uint64_t result = 0;
601debfc3dSmrg   unsigned char byte;
611debfc3dSmrg 
621debfc3dSmrg   while (1)
631debfc3dSmrg     {
641debfc3dSmrg       if (p >= buf_end)
651debfc3dSmrg 	return 0;
661debfc3dSmrg 
671debfc3dSmrg       byte = *p++;
681debfc3dSmrg       result |= ((uint64_t) (byte & 0x7f)) << shift;
691debfc3dSmrg       if ((byte & 0x80) == 0)
701debfc3dSmrg 	break;
711debfc3dSmrg       shift += 7;
721debfc3dSmrg     }
731debfc3dSmrg 
741debfc3dSmrg   *r = result;
751debfc3dSmrg   return p - buf;
761debfc3dSmrg }
771debfc3dSmrg 
781debfc3dSmrg /* Decode the signed LEB128 constant at BUF into the variable pointed to
791debfc3dSmrg    by R, and return the number of bytes read.
801debfc3dSmrg    If we read off the end of the buffer, zero is returned,
811debfc3dSmrg    and nothing is stored in R.
821debfc3dSmrg 
831debfc3dSmrg    Note: The result is an int instead of a pointer to the next byte to be
841debfc3dSmrg    read to avoid const-vs-non-const problems.  */
851debfc3dSmrg 
861debfc3dSmrg static inline size_t
read_sleb128_to_int64(const unsigned char * buf,const unsigned char * buf_end,int64_t * r)871debfc3dSmrg read_sleb128_to_int64 (const unsigned char *buf, const unsigned char *buf_end,
881debfc3dSmrg 		       int64_t *r)
891debfc3dSmrg {
901debfc3dSmrg   const unsigned char *p = buf;
911debfc3dSmrg   unsigned int shift = 0;
921debfc3dSmrg   int64_t result = 0;
931debfc3dSmrg   unsigned char byte;
941debfc3dSmrg 
951debfc3dSmrg   while (1)
961debfc3dSmrg     {
971debfc3dSmrg       if (p >= buf_end)
981debfc3dSmrg 	return 0;
991debfc3dSmrg 
1001debfc3dSmrg       byte = *p++;
1011debfc3dSmrg       result |= ((uint64_t) (byte & 0x7f)) << shift;
1021debfc3dSmrg       shift += 7;
1031debfc3dSmrg       if ((byte & 0x80) == 0)
1041debfc3dSmrg 	break;
1051debfc3dSmrg     }
1061debfc3dSmrg   if (shift < (sizeof (*r) * 8) && (byte & 0x40) != 0)
1071debfc3dSmrg     result |= -(((uint64_t) 1) << shift);
1081debfc3dSmrg 
1091debfc3dSmrg   *r = result;
1101debfc3dSmrg   return p - buf;
1111debfc3dSmrg }
1121debfc3dSmrg 
1131debfc3dSmrg /* Return the number of bytes to read to skip past an LEB128 number in BUF.
1141debfc3dSmrg    If the end isn't found before reaching BUF_END, return zero.
1151debfc3dSmrg 
1161debfc3dSmrg    Note: The result is an int instead of a pointer to the next byte to be
1171debfc3dSmrg    read to avoid const-vs-non-const problems.  */
1181debfc3dSmrg 
1191debfc3dSmrg static inline size_t
skip_leb128(const unsigned char * buf,const unsigned char * buf_end)1201debfc3dSmrg skip_leb128 (const unsigned char *buf, const unsigned char *buf_end)
1211debfc3dSmrg {
1221debfc3dSmrg   const unsigned char *p = buf;
1231debfc3dSmrg   unsigned char byte;
1241debfc3dSmrg 
1251debfc3dSmrg   while (1)
1261debfc3dSmrg     {
1271debfc3dSmrg       if (p == buf_end)
1281debfc3dSmrg 	return 0;
1291debfc3dSmrg 
1301debfc3dSmrg       byte = *p++;
1311debfc3dSmrg       if ((byte & 0x80) == 0)
1321debfc3dSmrg 	return p - buf;
1331debfc3dSmrg     }
1341debfc3dSmrg }
1351debfc3dSmrg 
1361debfc3dSmrg #endif /* LEB128_H */
137