diff options
Diffstat (limited to 'runtime/GCCLibraries/crtend')
-rw-r--r-- | runtime/GCCLibraries/crtend/Exception.cpp | 54 | ||||
-rw-r--r-- | runtime/GCCLibraries/crtend/Exception.h | 71 | ||||
-rw-r--r-- | runtime/GCCLibraries/crtend/Makefile | 83 | ||||
-rw-r--r-- | runtime/GCCLibraries/crtend/README.txt | 15 | ||||
-rw-r--r-- | runtime/GCCLibraries/crtend/SJLJ-Exception.cpp | 146 | ||||
-rw-r--r-- | runtime/GCCLibraries/crtend/SJLJ-Exception.h | 80 | ||||
-rw-r--r-- | runtime/GCCLibraries/crtend/comp_genericeh.lst | 9 | ||||
-rw-r--r-- | runtime/GCCLibraries/crtend/comp_main.lst | 3 | ||||
-rw-r--r-- | runtime/GCCLibraries/crtend/comp_sjljeh.lst | 7 | ||||
-rw-r--r-- | runtime/GCCLibraries/crtend/crtend.c | 16 |
10 files changed, 484 insertions, 0 deletions
diff --git a/runtime/GCCLibraries/crtend/Exception.cpp b/runtime/GCCLibraries/crtend/Exception.cpp new file mode 100644 index 0000000000..d4ac290122 --- /dev/null +++ b/runtime/GCCLibraries/crtend/Exception.cpp @@ -0,0 +1,54 @@ +//===- Exception.cpp - Generic language-independent exceptions ------------===// +// +// This file defines the the shared data structures used by all language +// specific exception handling runtime libraries. +// +//===----------------------------------------------------------------------===// + +#include "Exception.h" + +// Thread local state for exception handling. FIXME: This should really be made +// thread-local! + +// UncaughtExceptionStack - The stack of exceptions currently being thrown. +static llvm_exception *UncaughtExceptionStack = 0; + +// __llvm_eh_has_uncaught_exception - This is used to implement +// std::uncaught_exception. +// +bool __llvm_eh_has_uncaught_exception() throw() { + return UncaughtExceptionStack != 0; +} + +// __llvm_eh_current_uncaught_exception - This function checks to see if the +// current uncaught exception is of the specified language type. If so, it +// returns a pointer to the exception area data. +// +void *__llvm_eh_current_uncaught_exception_type(unsigned HandlerType) throw() { + if (UncaughtExceptionStack->ExceptionType == HandlerType) + return UncaughtExceptionStack+1; + return 0; +} + +// __llvm_eh_add_uncaught_exception - This adds the specified exception to the +// top of the uncaught exception stack. The exception should not already be on +// the stack! +void __llvm_eh_add_uncaught_exception(llvm_exception *E) throw() { + E->Next = UncaughtExceptionStack; + UncaughtExceptionStack = E; +} + + +// __llvm_eh_get_uncaught_exception - Returns the current uncaught exception. +// There must be an uncaught exception for this to work! +llvm_exception *__llvm_eh_get_uncaught_exception() throw() { + return UncaughtExceptionStack; +} + +// __llvm_eh_pop_from_uncaught_stack - Remove the current uncaught exception +// from the top of the stack. +llvm_exception *__llvm_eh_pop_from_uncaught_stack() throw() { + llvm_exception *E = __llvm_eh_get_uncaught_exception(); + UncaughtExceptionStack = E->Next; + return E; +} diff --git a/runtime/GCCLibraries/crtend/Exception.h b/runtime/GCCLibraries/crtend/Exception.h new file mode 100644 index 0000000000..dc4d3a5f2c --- /dev/null +++ b/runtime/GCCLibraries/crtend/Exception.h @@ -0,0 +1,71 @@ +//===- Exception.h - Generic language-independent exceptions ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the the shared data structures used by all language +// specific exception handling runtime libraries. +// +// NOTE NOTE NOTE: A copy of this file lives in llvmgcc/libstdc++-v3/libsupc++/ +// Any modifications to this file must keep it in sync! +// +//===----------------------------------------------------------------------===// + +#ifndef EXCEPTION_H +#define EXCEPTION_H + +struct llvm_exception { + // ExceptionDestructor - This call-back function is used to destroy the + // current exception, without requiring the caller to know what the concrete + // exception type is. + // + void (*ExceptionDestructor)(llvm_exception *); + + // ExceptionType - This field identifies what runtime library this exception + // came from. Currently defined values are: + // 0 - Error + // 1 - longjmp exception (see longjmp-exception.c) + // 2 - C++ exception (see c++-exception.c) + // + unsigned ExceptionType; + + // Next - This points to the next exception in the current stack. + llvm_exception *Next; + + // HandlerCount - This is a count of the number of handlers which have + // currently caught this exception. If the handler is caught and this number + // falls to zero, the exception is destroyed. + // + unsigned HandlerCount; + + // isRethrown - This field is set on an exception if it has been 'throw;'n. + // This is needed because the exception might exit through a number of the + // end_catch statements matching the number of begin_catch statements that + // have been processed. When this happens, the exception should become + // uncaught, not dead. + // + int isRethrown; +}; + +enum { + ErrorException = 0, + SJLJException = 1, + CXXException = 2 +}; + +// Language independent exception handling API... +// +extern "C" { + bool __llvm_eh_has_uncaught_exception() throw(); + void *__llvm_eh_current_uncaught_exception_type(unsigned HandlerType) throw(); + void __llvm_eh_add_uncaught_exception(llvm_exception *E) throw(); + + llvm_exception *__llvm_eh_get_uncaught_exception() throw(); + llvm_exception *__llvm_eh_pop_from_uncaught_stack() throw(); +} + +#endif diff --git a/runtime/GCCLibraries/crtend/Makefile b/runtime/GCCLibraries/crtend/Makefile new file mode 100644 index 0000000000..1fd3167246 --- /dev/null +++ b/runtime/GCCLibraries/crtend/Makefile @@ -0,0 +1,83 @@ +##===- runtime/GCCLibraries/crtend/Makefile ----------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file was developed by the LLVM research group and is distributed under +# the University of Illinois Open Source License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This directory contains the C and C++ runtime libraries for the LLVM GCC +# front-ends. See the README.txt file for more details. +# +# Since this archive has strange requirements, we use some custom rules for +# building it. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +DONT_BUILD_RELINKED = 1 +LIBRARYNAME = crtend +BYTECODE_DESTINATION = $(CFERuntimeLibDir) + +MainSrc := crtend.c +GenericEHSrc := Exception.cpp +SJLJEHSrc := SJLJ-Exception.cpp + +EXTRA_DIST := $(MainSrc) $(GenericEHSrc) $(SJLJEHSrc) \ + comp_main.lst comp_genericeh.lst comp_sjljeh.lst + +include $(LEVEL)/Makefile.common + +MainObj := $(ObjDir)/crtend.bc +GenericEHObj := $(ObjDir)/Exception.bc +SJLJEHObj := $(ObjDir)/SJLJ-Exception.bc + +# __main and ctor/dtor support component +$(ObjDir)/comp_main.bc: $(MainObj) + $(Echo) Linking $(notdir $@) component... + $(Verb) $(GCCLD) -link-as-library \ + -internalize-public-api-file=$(PROJ_SRC_DIR)/comp_main.lst \ + $(MainObj) -o $@ + +# Generic exception handling support runtime. +$(ObjDir)/comp_genericeh.bc: $(GenericEHObj) + $(Echo) Linking $(notdir $@) component... + $(Verb) $(GCCLD) -link-as-library \ + -internalize-public-api-file=$(PROJ_SRC_DIR)/comp_genericeh.lst \ + $(GenericEHObj) -o $@ + +# setjmp/longjmp exception handling support runtime. +$(ObjDir)/comp_sjljeh.bc: $(SJLJEHObj) + $(Echo) Linking $(notdir $@) component... + $(Verb) $(GCCLD) -link-as-library \ + -internalize-public-api-file=$(PROJ_SRC_DIR)/comp_sjljeh.lst \ + $(SJLJEHObj) -o $@ + +SYMBOLHACKEDOBJS := $(ObjDir)/comp_main.bc $(ObjDir)/comp_genericeh.bc \ + $(ObjDir)/comp_sjljeh.bc + +all-local:: $(LibName.BCA) + +ifdef BYTECODE_DESTINATION +BytecodeDestDir := $(BYTECODE_DESTINATION) +else +BytecodeDestDir := $(PROJ_libdir) +endif + +DestBytecodeLib = $(BytecodeDestDir)/lib$(LIBRARYNAME).a +install-bytecode-local:: $(DestBytecodeLib) +install-local:: $(DestBytecodeLib) + +$(LibName.BCA): $(SYMBOLHACKEDOBJS) $(LibDir)/.dir $(LLVMToolDir)/llvm-ar + $(Echo) Building $(BuildMode) Bytecode Archive $(notdir $@) + $(Verb) $(RM) -f $@ + $(Verb) $(LArchive) $@ $(SYMBOLHACKEDOBJS) + +$(DestBytecodeLib): $(BytecodeDestDir) $(LibName.BCA) + $(Echo) Installing $(BuildMode) Bytecode Archive $(DestBytecodeLib) + $(Verb) $(DataInstall) $(LibName.BCA) $(DestBytecodeLib) + +uninstall-local:: + $(Echo) Uninstalling $(BuildMode) Bytecode Archive $(DestBytecodeLib) + -$(Verb) $(RM) -f $(DestBytecodeLib) diff --git a/runtime/GCCLibraries/crtend/README.txt b/runtime/GCCLibraries/crtend/README.txt new file mode 100644 index 0000000000..a763cb26dd --- /dev/null +++ b/runtime/GCCLibraries/crtend/README.txt @@ -0,0 +1,15 @@ +This directory contains the C and C++ runtime libraries for the LLVM GCC +front-ends. It is composed of four distinct pieces: + +1. __main: now dead, but provided for compatibility. + +2. Generic EH support routines. This is used by C/C++ programs that use + setjmp/longjmp, and by C++ programs that make use of exceptions. + +3. setjmp/longjmp EH support. This is used by C/C++ programs that call SJLJ. + +4. C++ exception handling runtime support. + +These four components are compiled together into an archive file, so that +applications using a subset of the four do not pull in unnecessary code and +dependencies. diff --git a/runtime/GCCLibraries/crtend/SJLJ-Exception.cpp b/runtime/GCCLibraries/crtend/SJLJ-Exception.cpp new file mode 100644 index 0000000000..6a3e4724ae --- /dev/null +++ b/runtime/GCCLibraries/crtend/SJLJ-Exception.cpp @@ -0,0 +1,146 @@ +//===- SJLJ-Exception.cpp - SetJmp/LongJmp Exception Handling -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the API used by the Setjmp/Longjmp exception handling +// runtime library. +// +//===----------------------------------------------------------------------===// + +#include "SJLJ-Exception.h" +#include <cstdlib> +#include <cassert> + +// Assert should only be used for debugging the runtime library. Enabling it in +// CVS will break some platforms! +#undef assert +#define assert(X) + +// get_sjlj_exception - Adjust the llvm_exception pointer to be an appropriate +// llvm_sjlj_exception pointer. +inline llvm_sjlj_exception *get_sjlj_exception(llvm_exception *E) { + assert(E->ExceptionType == SJLJException); + return (llvm_sjlj_exception*)(E+1) - 1; +} + +// SetJmpMapEntry - One entry in a linked list of setjmps for the current +// function. +struct SetJmpMapEntry { + void *JmpBuf; + unsigned SetJmpID; + SetJmpMapEntry *Next; +}; + +// SJLJDestructor - This function is used to free the exception when +// language-indent code needs to destroy the exception without knowing exactly +// what type it is. +static void SJLJDestructor(llvm_exception *E) { + free(get_sjlj_exception(E)); +} + + +// __llvm_sjljeh_throw_longjmp - This function creates the longjmp exception and +// returns. It takes care of mapping the longjmp value from 0 -> 1 as +// appropriate. The caller should immediately call llvm.unwind after this +// function call. +void __llvm_sjljeh_throw_longjmp(void *JmpBuffer, int Val) throw() { + llvm_sjlj_exception *E = + (llvm_sjlj_exception *)malloc(sizeof(llvm_sjlj_exception)); + E->BaseException.ExceptionDestructor = SJLJDestructor; + E->BaseException.ExceptionType = SJLJException; + E->BaseException.HandlerCount = 0; + E->BaseException.isRethrown = 0; + E->JmpBuffer = JmpBuffer; + E->LongJmpValue = Val ? Val : 1; + + __llvm_eh_add_uncaught_exception(&E->BaseException); +} + +// __llvm_sjljeh_init_setjmpmap - This funciton initializes the pointer provided +// to an empty setjmp map, and should be called on entry to a function which +// calls setjmp. +void __llvm_sjljeh_init_setjmpmap(void **SetJmpMap) throw() { + *SetJmpMap = 0; +} + +// __llvm_sjljeh_destroy_setjmpmap - This function frees all memory associated +// with the specified setjmpmap structure. It should be called on all exits +// (returns or unwinds) from the function which calls ...init_setjmpmap. +void __llvm_sjljeh_destroy_setjmpmap(void **SetJmpMap) throw() { + SetJmpMapEntry *Next; + for (SetJmpMapEntry *SJE = *(SetJmpMapEntry**)SetJmpMap; SJE; SJE = Next) { + Next = SJE->Next; + free(SJE); + } +} + +// __llvm_sjljeh_add_setjmp_to_map - This function adds or updates an entry to +// the map, to indicate which setjmp should be returned to if a longjmp happens. +void __llvm_sjljeh_add_setjmp_to_map(void **SetJmpMap, void *JmpBuf, + unsigned SetJmpID) throw() { + SetJmpMapEntry **SJE = (SetJmpMapEntry**)SetJmpMap; + + // Scan for a pre-existing entry... + for (; *SJE; SJE = &(*SJE)->Next) + if ((*SJE)->JmpBuf == JmpBuf) { + (*SJE)->SetJmpID = SetJmpID; + return; + } + + // No prexisting entry found, append to the end of the list... + SetJmpMapEntry *New = (SetJmpMapEntry *)malloc(sizeof(SetJmpMapEntry)); + *SJE = New; + New->JmpBuf = JmpBuf; + New->SetJmpID = SetJmpID; + New->Next = 0; +} + +// __llvm_sjljeh_is_longjmp_exception - This function returns true if the +// current uncaught exception is a longjmp exception. This is the first step of +// catching a sjlj exception. +bool __llvm_sjljeh_is_longjmp_exception() throw() { + return __llvm_eh_current_uncaught_exception_type(SJLJException) != 0; +} + +// __llvm_sjljeh_get_longjmp_value - This function returns the value that the +// setjmp call should "return". This requires that the current uncaught +// exception be a sjlj exception, though it does not require the exception to be +// caught by this function. +int __llvm_sjljeh_get_longjmp_value() throw() { + llvm_sjlj_exception *E = + get_sjlj_exception(__llvm_eh_get_uncaught_exception()); + return E->LongJmpValue; +} + +// __llvm_sjljeh_try_catching_longjmp_exception - This function checks to see if +// the current uncaught longjmp exception matches any of the setjmps collected +// in the setjmpmap structure. If so, it catches and destroys the exception, +// returning the index of the setjmp which caught the exception. If not, it +// leaves the exception uncaught and returns a value of ~0. +unsigned __llvm_sjljeh_try_catching_longjmp_exception(void **SetJmpMap) throw(){ + llvm_sjlj_exception *E = + get_sjlj_exception(__llvm_eh_get_uncaught_exception()); + + // Scan for a matching entry in the SetJmpMap... + SetJmpMapEntry *SJE = *(SetJmpMapEntry**)SetJmpMap; + for (; SJE; SJE = SJE->Next) + if (SJE->JmpBuf == E->JmpBuffer) { + // "Catch" and destroy the exception... + __llvm_eh_pop_from_uncaught_stack(); + + // We know it's a longjmp exception, so we can just free it instead of + // calling the destructor. + free(E); + + // Return the setjmp ID which we should branch to... + return SJE->SetJmpID; + } + + // No setjmp in this function catches the exception! + return ~0; +} diff --git a/runtime/GCCLibraries/crtend/SJLJ-Exception.h b/runtime/GCCLibraries/crtend/SJLJ-Exception.h new file mode 100644 index 0000000000..ac27cbed7f --- /dev/null +++ b/runtime/GCCLibraries/crtend/SJLJ-Exception.h @@ -0,0 +1,80 @@ +//===- SJLJ-Exception.h - SetJmp/LongJmp Exception Handling -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the data structures and API used by the Setjmp/Longjmp +// exception handling runtime library. +// +//===----------------------------------------------------------------------===// + +#ifndef SJLJ_EXCEPTION_H +#define SJLJ_EXCEPTION_H + +#include "Exception.h" + +struct llvm_sjlj_exception { + // JmpBuffer - This is the buffer which was longjmp'd with. + // + void *JmpBuffer; + + // LongJmpValue - The value passed into longjmp, which the corresponding + // setjmp should return. Note that this value will never be equal to 0. + // + int LongJmpValue; + + // BaseException - The language independent portion of the exception state. + // This is at the end of the record so that we can add additional members to + // this structure without breaking binary compatibility. + // + llvm_exception BaseException; +}; + +extern "C" { + // __llvm_sjljeh_throw_longjmp - This function creates the longjmp exception + // and returns. It takes care of mapping the longjmp value from 0 -> 1 as + // appropriate. The caller should immediately call llvm.unwind after this + // function call. + void __llvm_sjljeh_throw_longjmp(void *JmpBuffer, int Val) throw(); + + // __llvm_sjljeh_init_setjmpmap - This funciton initializes the pointer + // provided to an empty setjmp map, and should be called on entry to a + // function which calls setjmp. + void __llvm_sjljeh_init_setjmpmap(void **SetJmpMap) throw(); + + // __llvm_sjljeh_destroy_setjmpmap - This function frees all memory associated + // with the specified setjmpmap structure. It should be called on all exits + // (returns or unwinds) from the function which calls ...init_setjmpmap. + void __llvm_sjljeh_destroy_setjmpmap(void **SetJmpMap) throw(); + + // __llvm_sjljeh_add_setjmp_to_map - This function adds or updates an entry to + // the map, to indicate which setjmp should be returned to if a longjmp + // happens. + void __llvm_sjljeh_add_setjmp_to_map(void **SetJmpMap, void *JmpBuf, + unsigned SetJmpID) throw(); + + // __llvm_sjljeh_is_longjmp_exception - This function returns true if the + // current uncaught exception is a longjmp exception. This is the first step + // of catching a sjlj exception. + bool __llvm_sjljeh_is_longjmp_exception() throw(); + + // __llvm_sjljeh_get_longjmp_value - This function returns the value that the + // setjmp call should "return". This requires that the current uncaught + // exception be a sjlj exception, though it does not require the exception to + // be caught by this function. + int __llvm_sjljeh_get_longjmp_value() throw(); + + // __llvm_sjljeh_try_catching_longjmp_exception - This function checks to see + // if the current uncaught longjmp exception matches any of the setjmps + // collected in the setjmpmap structure. If so, it catches and destroys the + // exception, returning the index of the setjmp which caught the exception. + // If not, it leaves the exception uncaught and returns a value of ~0. + unsigned __llvm_sjljeh_try_catching_longjmp_exception(void **SetJmpMap) + throw(); +} + +#endif diff --git a/runtime/GCCLibraries/crtend/comp_genericeh.lst b/runtime/GCCLibraries/crtend/comp_genericeh.lst new file mode 100644 index 0000000000..9270648b03 --- /dev/null +++ b/runtime/GCCLibraries/crtend/comp_genericeh.lst @@ -0,0 +1,9 @@ +__main +llvm.global_ctors +llvm.global_dtors + +__llvm_eh_has_uncaught_exception +__llvm_eh_current_uncaught_exception_type +__llvm_eh_add_uncaught_exception +__llvm_eh_get_uncaught_exception +__llvm_eh_pop_from_uncaught_stack diff --git a/runtime/GCCLibraries/crtend/comp_main.lst b/runtime/GCCLibraries/crtend/comp_main.lst new file mode 100644 index 0000000000..ea953b7f92 --- /dev/null +++ b/runtime/GCCLibraries/crtend/comp_main.lst @@ -0,0 +1,3 @@ +__main +llvm.global_ctors +llvm.global_dtors diff --git a/runtime/GCCLibraries/crtend/comp_sjljeh.lst b/runtime/GCCLibraries/crtend/comp_sjljeh.lst new file mode 100644 index 0000000000..afcaaf0d05 --- /dev/null +++ b/runtime/GCCLibraries/crtend/comp_sjljeh.lst @@ -0,0 +1,7 @@ +__llvm_sjljeh_throw_longjmp +__llvm_sjljeh_init_setjmpmap +__llvm_sjljeh_destroy_setjmpmap +__llvm_sjljeh_add_setjmp_to_map +__llvm_sjljeh_is_longjmp_exception +__llvm_sjljeh_get_longjmp_value +__llvm_sjljeh_try_catching_longjmp_exception diff --git a/runtime/GCCLibraries/crtend/crtend.c b/runtime/GCCLibraries/crtend/crtend.c new file mode 100644 index 0000000000..561b6fd241 --- /dev/null +++ b/runtime/GCCLibraries/crtend/crtend.c @@ -0,0 +1,16 @@ +/*===- crtend.c - Initialization code for programs ------------------------===*\ + * + * The LLVM Compiler Infrastructure + * + * This file was developed by the LLVM research group and is distributed under + * the University of Illinois Open Source License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===* + * + * This file defines the __main function, which we preserve for backwards + * compatibility. + * +\*===----------------------------------------------------------------------===*/ + +void __main(void) { +} |