From f45d23308a29f90253329b100d4952fe99adb993 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Tue, 21 Nov 2000 22:59:13 +0000 Subject: [PATCH] * porting.texi: New file. From-SVN: r37630 --- libstdc++-v3/ChangeLog | 4 + libstdc++-v3/porting.texi | 443 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 447 insertions(+) create mode 100644 libstdc++-v3/porting.texi diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 00679719871..bc93dd86ea2 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,7 @@ +2000-11-21 Mark Mitchell + + * porting.texi: New file. + 2000-11-21 Branko Cibej * config/os/solaris/solaris2.6/bits/os_defines.h: Define diff --git a/libstdc++-v3/porting.texi b/libstdc++-v3/porting.texi new file mode 100644 index 00000000000..6cd1c48b636 --- /dev/null +++ b/libstdc++-v3/porting.texi @@ -0,0 +1,443 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% File: porting.texi +% Author: Mark Mitchell +% Date: 11/21/2000 +% +% Contents: +% +% Copyright (c) 2000 by CodeSourcery, LLC. All rights reserved. +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\input texinfo + +@c --------------------------------------------------------------------- +@c Prologue +@c --------------------------------------------------------------------- + +@setfilename porting.info +@settitle Porting libstdc++-v3 +@setchapternewpage odd + +@ifinfo +This file explains how to port libstdc++-v3 (the GNU C++ library) to +a new target. + +Copyright (c) 2000 Free Software Foundation, Inc. +@end ifinfo + +@c --------------------------------------------------------------------- +@c Titlepage +@c --------------------------------------------------------------------- + +@titlepage +@title Porting libstdc++-v3 +@author Mark Mitchell +@page +@vskip 0pt plus 1filll +Copyright @copyright{} 2000 Free Software Foundation, Inc. +@end titlepage + +@c --------------------------------------------------------------------- +@c Top +@c --------------------------------------------------------------------- + +@node Top +@top Porting libstdc++-v3 + +This document explains how to port libstdc++-v3 (the GNU C++ library) to +a new target. + +In order to make the GNU C++ library (libstdc++-v3) work with a new +target, you must edit some configuration files and provide some new +header files. + +Before you get started, make sure that you have a working C library on +your target. The C library need not precisely comply with any +particular standard, but should generally conform to the requirements +imposed by the ANSI/ISO standard. + +In addition, you should try to verify that the C++ compiler generally +works. It is difficult to test the C++ compiler without a working +library, but you should at least try some minimal test cases. + +Here are the primary steps required to port the library: + +@menu +* Operating system:: Configuring for your operating system. +* Character types:: Implementing character classification. +* Thread safety:: Implementing atomic operations. +* Libtool:: Using libtool. +@end menu + +@c --------------------------------------------------------------------- +@c Operating system +@c --------------------------------------------------------------------- + +@node Operating system +@chapter Operating system + +If you are porting to a new operating-system (as opposed to a new chip +using an existing operating system), you will need to create a new +directory in the @file{config/os} hierarchy. For example, the IRIX +configuration files are all in @file{config/os/irix}. There is no set +way to organize the OS configuration directory. For example, +@file{config/os/solaris/solaris-2.6} and +@file{config/os/solaris/solaris-2.7} are used as configuration +directories for these two versions of Solaris. On the other hand, both +Solaris 2.7 and Solaris 2.8 use the @file{config/os/solaris/solaris-2.7} +directory. The important information is that there needs to be a +directory under @file{config/os} to store the files for your operating +system. + +You'll have to change the @file{configure.target} file to ensure that +your new directory is activated. Look for the switch statement that +sets @code{os_include_dir}, and add a pattern to handle your operating +system. The switch statement switches on only the OS portion of the +standard target triplet; e.g., the @code{solaris2.8} in +@code{sparc-sun-solaris2.8}. + +The first file to create in this directory, should be called +@file{bits/os_defines.h}. This file contains basic macro definitions +that are required to allow the C++ library to work with your C library. +This file should provide macro definitions for @code{__off_t}, +@code{__off64_t}, and @code{__ssize_t}. Typically, this just looks +like: + +@example +#define __off_t off_t +#define __off64_t off64_t +#define __ssize_t ssize_t +@end example + +@noindent +You don't have to provide these definitions if your system library +already defines these types -- but the only library known to provide +these types is the GNU C Library, so you will almost certainly have to +provide these macros. Note that this file does not have to include a +header file that defines @code{off_t}, or the other types; you simply +have to provide the macros. + +In addition, several V3 source files unconditionally define the macro +@code{_POSIX_SOURCE}. On many systems, defining this macro causes large +portions of the C library header files to be eliminated at preprocessing +time. Therefore, you may have to @code{#undef} this macro, or define +other macros (like @code{_LARGEFILE_SOURCE} or @code{__EXTENSIONS__}). +You won't know what macros to define or undefine at this point; you'll +have to try compiling the library and seeing what goes wrong. If you +see errors about calling functions that have not been declared, look in +your C library headers to see if the functions are declared there, and +then figure out what macros you should but in @file{bits/os_defines.h} +to make these declarations available. + +Finally, you should bracket the entire file in an include-guard, like +this: + +@example +#ifndef _GLIBCPP_OS_DEFINES +#define _GLIBCPP_OS_DEFINES +... +#endif +@end example + +@c --------------------------------------------------------------------- +@c Character types +@c --------------------------------------------------------------------- + +@node Character types +@chapter Character types + +The library requires that you provide three header files to implement +character classification, analagous to that provided by the C libraries +@file{} header. You can model these on the files provided in +@file{config/os/generic/bits}. However, these files will almost +certainly need some modification. + +The first file to write is @file{bits/ctype_base.h}. This file provides +some very basic information about character classification. The V3 +library assumes that your C library implements @file{} by using +a table (indexed by character code) containing integers, where each of +these integers is a bit-mask indicating whether the charcter is +upper-case, lower-case, alphabetic, etc. The @file{bits/ctype_base.h} +file gives the type of the integer, and the values of the various bit +masks. You will have to peer at your own @file{} to figure out +how to define the values required by this file. + +The @file{bits/ctype_base.h} header file does not need include guards. +It should contain a single @code{struct} definition called +@code{ctype_base}. This @code{struct} should contain two type +declarations, and one enumeration declaration, like this example, taken +from the IRIX configuration: + +@example +struct ctype_base +@{ + typedef unsigned int mask; + typedef int* __to_type; + + enum + @{ + space = _ISspace, + print = _ISprint, + cntrl = _IScntrl, + upper = _ISupper, + lower = _ISlower, + alpha = _ISalpha, + digit = _ISdigit, + punct = _ISpunct, + xdigit = _ISxdigit, + alnum = _ISalnum, + graph = _ISgraph + @}; +@}; +@end example + +@noindent +The @code{mask} type is the type of the elements in the table. If your +C library uses a table to map lower-case numbers to upper-case numbers, +and vice versa, you should define @code{__to_type} to be the type of the +elements in that table. If you don't mind taking a minor performance +penalty, or if your library doesn't implement @code{toupper} and +@code{tolower} in this way, you can pick any pointer-to-integer type, +but you must still define the type. + +The enumeration should give definitions for all the values in the above +example, using the values from your native @file{}. They can +be given symbolically (as above), or numerically, if you prefer. You do +not have to include @file{} in this header; it will always be +included before @file{bits/ctype_base.h} is included. + +The next file to write is @file{bits/ctype_noninline.h}, which also does +not require include guards. This file defines a few member functions +that will be included in @file{include/bits/locale_facets.h}. The first +function that must be written is the @code{ctype::ctype} +constructor. Here is the IRIX example: + +@example +ctype::ctype(const mask* __table = 0, bool __del = false, + size_t __refs = 0) + : _Ctype_nois(__refs), _M_del(__table != 0 && __del), + _M_toupper(NULL), + _M_tolower(NULL), + _M_ctable(NULL), + _M_table(!__table + ? (const mask*) (__libc_attr._ctype_tbl->_class + 1) + : __table) + @{ @} +@end example + +@noindent +There are two parts of this that you might choose to alter. The first, +and most important, is the line involving @code{__libc_attr}. That is +IRIX system-dependent code that gets the base of the table mapping +character codes to attributes. You need to substitute code that obtains +the address of this table on your system. If you want to use your +operating system's tables to map upper-case letters to lower-case, and +vice versa, you should initialize @code{_M_toupper} and +@code{_M_tolower} with those tables, in similar fashion. + +Now, you have to write two functions to convert from upper-case to +lower-case, and vice versa. Here are the IRIX versions: + +@example +char +ctype::do_toupper(char __c) const +@{ return _toupper(__c); @} + +char +ctype::do_tolower(char __c) const +@{ return _tolower(__c); @} +@end example + +@noindent +Your C library provides equivalents to IRIX's @code{_toupper} and +@code{_tolower}. If you initialized @code{_M_toupper} and +@code{_M_tolower} above, then you could use those tables instead. + +Finally, you have to provide two utility functions that convert strings +of characters. The versions provided here will always work -- but you +could use specialized routines for greater performance if you have +machinery to do that on your system: + +@example +const char* +ctype::do_toupper(char* __low, const char* __high) const +@{ + while (__low < __high) + @{ + *__low = do_toupper(*__low); + ++__low; + @} + return __high; +@} + +const char* +ctype::do_tolower(char* __low, const char* __high) const +@{ + while (__low < __high) + @{ + *__low = do_tolower(*__low); + ++__low; + @} + return __high; +@} +@end example + +You must also provide the @file{bits/ctype_inline.h} file, which +contains a few more functions. On most systems, you can just copy +@file{config/os/generic/ctype_inline.h} and use it on your system. + +In detail, the functions provided test characters for particular +properties; they are analagous to the functions like @code{isalpha} and +@code{islower} provided by the C library. + +The first function is implemented like this on IRIX: + +@example +bool +ctype:: +is(mask __m, char __c) const throw() +@{ return (_M_table)[(unsigned char)(__c)] & __m; @} +@end example + +@noindent +The @code{_M_table} is the table passed in above, in the constructor. +This is the table that contains the bitmasks for each character. The +implementation here should work on all systems. + +The next function is: + +@example +const char* +ctype:: +is(const char* __low, const char* __high, mask* __vec) const throw() +@{ + while (__low < __high) + *__vec++ = (_M_table)[(unsigned char)(*__low++)]; + return __high; +@} +@end example + +@noindent +This function is similar; it copies the masks for all the characters +from @code{__low} up until @code{__high} into the vector given by +@code{__vec}. + +The last two functions again are entirely generic: + +@example +const char* +ctype:: +scan_is(mask __m, const char* __low, const char* __high) const throw() +@{ + while (__low < __high && !this->is(__m, *__low)) + ++__low; + return __low; +@} + +const char* +ctype:: +scan_not(mask __m, const char* __low, const char* __high) const throw() +@{ + while (__low < __high && this->is(__m, *__low)) + ++__low; + return __low; +@} +@end example + +@c --------------------------------------------------------------------- +@c Thread safety +@c --------------------------------------------------------------------- + +@node Thread safety +@chapter Thread safety + +The C++ library string functionality requires a couple of atomic +operations to provide thread-safety. If you don't take any special +action, the library will use stub versions of these functions that are +not thread-safe. They will work fine, unless your applications are +multi-threaded. + +If you want to provide custom, safe, versions of these functions, there +are two distinct approaches. One is to provide a version for your CPU, +using assembly language constructs. The other is to use the +thread-safety primitives in your operating system. In either case, you +make a file called @file{bits/atomicity.h}. + +If you are using the assembly-language approach, put this code in +@file{config/cpu//bits/atomicity.h}, where chip is the name of +your chip. In that case, edit the switch statement in +@file{configure.target} to set the @code{cpu_include_dir}. In either +case, set the switch statement that sets @code{ATOMICITYH} to be the +directory containing @file{bits/atomicity.h}. + +With those bits out of the way, you have to actually write +@file{bits/atomicity.h} itself. This file should be wrapped in an +include guard named @code{_BITS_ATOMICITY_H}. It should define one +type, and two functions. + +The type is @code{_Atomic_word}. Here is the version used on IRIX: + +@example +typedef long _Atomic_word; +@end example + +@noindent +This type must be a signed integral type supporting atomic operations. +If you're using the OS approach, use the same type used by your system's +primitives. Otherwise, use the type for which your CPU provides atomic +primitives. + +Then, you must provide two functions. The bodies of these functions +must be equivalent to those provided here, but using atomic operations: + +@example +static inline _Atomic_word +__attribute__ ((__unused__)) +__exchange_and_add (_Atomic_word* __mem, int __val) +@{ + _Atomic_word __result = *__mem; + *__mem += __val; + return __result; +@} + +static inline void +__attribute__ ((__unused__)) +__atomic_add (_Atomic_word* __mem, int __val) +@{ + *__mem += __val; +@} +@end example + +@c --------------------------------------------------------------------- +@c Libtool +@c --------------------------------------------------------------------- + +@node Libtool +@chapter Libtool + +The C++ library is linked with libtool. Explaining the full workings of +libtool is beyond the scope of this document, but there is one +particular bit that should be explained here. The C++ run-time library +contains initialization code that needs to be run as the library is +loaded. Often, that requires linking in special object files when the +C++ library is built as a shared library, or taking other +system-specific actions. + +The V3 library is linked with the C version of libtool, even though it +is a C++ library. Therefore, the C version of libtool needs to ensure +that the run-time library initializers are run. The usual way to do +this is to build the library using @code{gcc -shared}. + +If you need to change how the library is linked, look at +@file{ltcf-c.sh} in the top-level directory. Find the switch statement +that sets @code{archive_cmds}. Here, adjust the setting for your +operating system. + +@c --------------------------------------------------------------------- +@c Epilogue +@c --------------------------------------------------------------------- + +@contents +@bye