Chris Lattner | 6563768 | 2003-05-14 13:09:41 +0000 | [diff] [blame] | 1 | /*===- crtend.c - Initialization code for programs ------------------------===*\ |
Chris Lattner | 0f2aeea | 2004-08-05 00:20:51 +0000 | [diff] [blame] | 2 | * |
| 3 | * The LLVM Compiler Infrastructure |
| 4 | * |
| 5 | * This file was developed by the LLVM research group and is distributed under |
| 6 | * the University of Illinois Open Source License. See LICENSE.TXT for details. |
| 7 | * |
| 8 | *===----------------------------------------------------------------------===* |
Chris Lattner | 6563768 | 2003-05-14 13:09:41 +0000 | [diff] [blame] | 9 | * |
| 10 | * This file defines the __main function, which is used to run static |
| 11 | * constructors and destructors in C++ programs, or with C programs that use GCC |
| 12 | * extensions to accomplish the same effect. |
| 13 | * |
| 14 | * The main data structures used to implement this functionality is the |
| 15 | * llvm.global_ctors and llvm.global_dtors lists, which are null terminated |
| 16 | * lists of TorRec (defined below) structures. |
| 17 | * |
| 18 | \*===----------------------------------------------------------------------===*/ |
| 19 | |
| 20 | #include <stdlib.h> |
| 21 | |
| 22 | /* TorRec - The record type for each element of the ctor/dtor list */ |
| 23 | typedef struct TorRec { |
| 24 | int Priority; |
| 25 | void (*FP)(void); |
| 26 | } TorRec; |
| 27 | |
| 28 | /* __llvm_getGlobalCtors, __llvm_getGlobalDtors - Interface to the LLVM |
| 29 | * listend.ll file to get access to the start of the ctor and dtor lists... |
| 30 | */ |
| 31 | TorRec *__llvm_getGlobalCtors(void); |
| 32 | TorRec *__llvm_getGlobalDtors(void); |
| 33 | |
| 34 | static void run_destructors(void); |
| 35 | |
| 36 | /* __main - A call to this function is automatically inserted into the top of |
| 37 | * the "main" function in the program compiled. This function is responsible |
| 38 | * for calling static constructors before the program starts executing. |
| 39 | */ |
| 40 | void __main(void) { |
| 41 | /* Loop over all of the constructor records, calling each function pointer. */ |
| 42 | TorRec *R = __llvm_getGlobalCtors(); |
| 43 | |
Chris Lattner | 86dd6d8 | 2003-12-19 07:51:46 +0000 | [diff] [blame] | 44 | /* Recursively calling main is not legal C, but lots of people do it for |
| 45 | * testing stuff. We might as well work for them. |
| 46 | */ |
| 47 | static _Bool Initialized = 0; |
| 48 | if (Initialized) return; |
| 49 | Initialized = 1; |
| 50 | |
Chris Lattner | 0fe5e45 | 2003-06-26 04:20:38 +0000 | [diff] [blame] | 51 | /* Only register the global dtor handler if there is at least one global |
| 52 | * dtor! |
| 53 | */ |
| 54 | if (__llvm_getGlobalDtors()[0].FP) |
| 55 | if (atexit(run_destructors)) |
| 56 | abort(); /* Should be able to install ONE atexit handler! */ |
Chris Lattner | 6563768 | 2003-05-14 13:09:41 +0000 | [diff] [blame] | 57 | |
| 58 | /* FIXME: This should sort the list by priority! */ |
Chris Lattner | 2b6d3c8 | 2004-02-17 18:45:06 +0000 | [diff] [blame] | 59 | if (R->FP) |
| 60 | for (; R->FP; ++R) |
| 61 | R->FP(); |
Chris Lattner | 6563768 | 2003-05-14 13:09:41 +0000 | [diff] [blame] | 62 | } |
| 63 | |
| 64 | static void run_destructors(void) { |
| 65 | /* Loop over all of the destructor records, calling each function pointer. */ |
| 66 | TorRec *R = __llvm_getGlobalDtors(); |
| 67 | |
| 68 | /* FIXME: This should sort the list by priority! */ |
| 69 | for (; R->FP; ++R) |
| 70 | R->FP(); |
| 71 | } |