1626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner//===-- ExceptionDemo.cpp - An example using llvm Exceptions --------------===// 2a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// 3a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// The LLVM Compiler Infrastructure 4a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// 5a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// This file is distributed under the University of Illinois Open Source 6a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// License. See LICENSE.TXT for details. 7a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// 8626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner//===----------------------------------------------------------------------===// 9a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// 10a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// Demo program which implements an example LLVM exception implementation, and 11a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// shows several test cases including the handling of foreign exceptions. 12a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// It is run with type info types arguments to throw. A test will 139f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi// be run for each given type info type. While type info types with the value 14a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// of -1 will trigger a foreign C++ exception to be thrown; type info types 159f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi// <= 6 and >= 1 will cause the associated generated exceptions to be thrown 16a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// and caught by generated test functions; and type info types > 6 17a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// will result in exceptions which pass through to the test harness. All other 18a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// type info types are not supported and could cause a crash. In all cases, 199f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi// the "finally" blocks of every generated test functions will executed 20a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// regardless of whether or not that test function ignores or catches the 21a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// thrown exception. 22a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// 23a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// examples: 24a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// 25a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// ExceptionDemo 26a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// 27a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// causes a usage to be printed to stderr 289f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi// 29a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// ExceptionDemo 2 3 7 -1 30a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// 31a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// results in the following cases: 329f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi// - Value 2 causes an exception with a type info type of 2 to be 33a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// thrown and caught by an inner generated test function. 349f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi// - Value 3 causes an exception with a type info type of 3 to be 35a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// thrown and caught by an outer generated test function. 369f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi// - Value 7 causes an exception with a type info type of 7 to be 37a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// thrown and NOT be caught by any generated function. 38a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// - Value -1 causes a foreign C++ exception to be thrown and not be 39a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// caught by any generated function 40a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// 41a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// Cases -1 and 7 are caught by a C++ test harness where the validity of 429f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi// of a C++ catch(...) clause catching a generated exception with a 439f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi// type info type of 7 is explained by: example in rules 1.6.4 in 44a6f10317bf2b90a16a931d0f5260cf3920a28d62Dmitri Gribenko// http://mentorembedded.github.com/cxx-abi/abi-eh.html (v1.22) 45a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// 469f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi// This code uses code from the llvm compiler-rt project and the llvm 47a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// Kaleidoscope project. 48a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// 49626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner//===----------------------------------------------------------------------===// 50a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 514ca7e09b7c1e41535f2a1bd86915375d023daf27Chandler Carruth#include "llvm/Analysis/Verifier.h" 52c8b9551a8fe52cefbefeac820c81996281fff4e5Rafael Espindola#include "llvm/ExecutionEngine/MCJIT.h" 53c8b9551a8fe52cefbefeac820c81996281fff4e5Rafael Espindola#include "llvm/ExecutionEngine/SectionMemoryManager.h" 540a08460599eed603e469e3e16d0cf6aa33b8ba93Chandler Carruth#include "llvm/IR/DataLayout.h" 550a08460599eed603e469e3e16d0cf6aa33b8ba93Chandler Carruth#include "llvm/IR/DerivedTypes.h" 560a08460599eed603e469e3e16d0cf6aa33b8ba93Chandler Carruth#include "llvm/IR/IRBuilder.h" 570a08460599eed603e469e3e16d0cf6aa33b8ba93Chandler Carruth#include "llvm/IR/Intrinsics.h" 580a08460599eed603e469e3e16d0cf6aa33b8ba93Chandler Carruth#include "llvm/IR/LLVMContext.h" 590a08460599eed603e469e3e16d0cf6aa33b8ba93Chandler Carruth#include "llvm/IR/Module.h" 60a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#include "llvm/PassManager.h" 61a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#include "llvm/Support/Dwarf.h" 623e74d6fdd248e20a280f1dff3da9a6c689c2c4c3Evan Cheng#include "llvm/Support/TargetSelect.h" 634ca7e09b7c1e41535f2a1bd86915375d023daf27Chandler Carruth#include "llvm/Target/TargetOptions.h" 644ca7e09b7c1e41535f2a1bd86915375d023daf27Chandler Carruth#include "llvm/Transforms/Scalar.h" 65a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 669f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi// FIXME: Although all systems tested with (Linux, OS X), do not need this 679f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi// header file included. A user on ubuntu reported, undefined symbols 6818bba84d7782e978caebddbd98b39e555c63b4dcGarrison Venn// for stderr, and fprintf, and the addition of this include fixed the 699f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi// issue for them. Given that LLVM's best practices include the goal 709f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi// of reducing the number of redundant header files included, the 719f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi// correct solution would be to find out why these symbols are not 7218bba84d7782e978caebddbd98b39e555c63b4dcGarrison Venn// defined for the system in question, and fix the issue by finding out 7318bba84d7782e978caebddbd98b39e555c63b4dcGarrison Venn// which LLVM header file, if any, would include these symbols. 742a7d4ad1f4f008ba4820782331464aedccd969d5Garrison Venn#include <cstdio> 7518bba84d7782e978caebddbd98b39e555c63b4dcGarrison Venn 76a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#include <sstream> 77a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#include <stdexcept> 78a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 79a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 80a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#ifndef USE_GLOBAL_STR_CONSTS 81a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#define USE_GLOBAL_STR_CONSTS true 82a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#endif 83a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 849f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi// System C++ ABI unwind types from: 85a6f10317bf2b90a16a931d0f5260cf3920a28d62Dmitri Gribenko// http://mentorembedded.github.com/cxx-abi/abi-eh.html (v1.22) 86a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 87a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennextern "C" { 889f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 89626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner typedef enum { 90a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn _URC_NO_REASON = 0, 91a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn _URC_FOREIGN_EXCEPTION_CAUGHT = 1, 92a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn _URC_FATAL_PHASE2_ERROR = 2, 93a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn _URC_FATAL_PHASE1_ERROR = 3, 94a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn _URC_NORMAL_STOP = 4, 95a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn _URC_END_OF_STACK = 5, 96a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn _URC_HANDLER_FOUND = 6, 97a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn _URC_INSTALL_CONTEXT = 7, 98a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn _URC_CONTINUE_UNWIND = 8 99626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } _Unwind_Reason_Code; 1009f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 101626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner typedef enum { 102a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn _UA_SEARCH_PHASE = 1, 103a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn _UA_CLEANUP_PHASE = 2, 104a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn _UA_HANDLER_FRAME = 4, 105a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn _UA_FORCE_UNWIND = 8, 106a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn _UA_END_OF_STACK = 16 107626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } _Unwind_Action; 1089f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 109626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner struct _Unwind_Exception; 1109f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 111626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner typedef void (*_Unwind_Exception_Cleanup_Fn) (_Unwind_Reason_Code, 112626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner struct _Unwind_Exception *); 1139f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 114626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner struct _Unwind_Exception { 115a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn uint64_t exception_class; 116a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn _Unwind_Exception_Cleanup_Fn exception_cleanup; 1179f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1189f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi uintptr_t private_1; 1199f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi uintptr_t private_2; 1209f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 121a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn // @@@ The IA-64 ABI says that this structure must be double-word aligned. 1229f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi // Taking that literally does not make much sense generically. Instead 123a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn // we provide the maximum alignment required by any type for the machine. 124626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } __attribute__((__aligned__)); 1259f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 126626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner struct _Unwind_Context; 12764cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn typedef struct _Unwind_Context *_Unwind_Context_t; 1289f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 12964cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn extern const uint8_t *_Unwind_GetLanguageSpecificData (_Unwind_Context_t c); 130626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner extern uintptr_t _Unwind_GetGR (_Unwind_Context_t c, int i); 131626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner extern void _Unwind_SetGR (_Unwind_Context_t c, int i, uintptr_t n); 132626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner extern void _Unwind_SetIP (_Unwind_Context_t, uintptr_t new_value); 133626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner extern uintptr_t _Unwind_GetIP (_Unwind_Context_t context); 134626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner extern uintptr_t _Unwind_GetRegionStart (_Unwind_Context_t context); 1359f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 136a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn} // extern "C" 137a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 138a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// 139a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// Example types 140a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// 141a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 142a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// This is our simplistic type info 143a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennstruct OurExceptionType_t { 144626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner /// type info type 145626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner int type; 146a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn}; 147a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 148a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 149a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// This is our Exception class which relies on a negative offset to calculate 150a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// pointers to its instances from pointers to its unwindException member. 1519f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// 152a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// Note: The above unwind.h defines struct _Unwind_Exception to be aligned 153a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// on a double word boundary. This is necessary to match the standard: 154a6f10317bf2b90a16a931d0f5260cf3920a28d62Dmitri Gribenko/// http://mentorembedded.github.com/cxx-abi/abi-eh.html 155a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennstruct OurBaseException_t { 156626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner struct OurExceptionType_t type; 1579f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 158626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Note: This is properly aligned in unwind.h 159626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner struct _Unwind_Exception unwindException; 160a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn}; 161a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 162a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 163a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// Note: Not needed since we are C++ 164a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venntypedef struct OurBaseException_t OurException; 165a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venntypedef struct _Unwind_Exception OurUnwindException; 166a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 167a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// 1689f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi// Various globals used to support typeinfo and generatted exceptions in 169a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// general 170a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// 171a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 172a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennstatic std::map<std::string, llvm::Value*> namedValues; 173a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 174a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennint64_t ourBaseFromUnwindOffset; 175a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 1769f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumiconst unsigned char ourBaseExcpClassChars[] = 177626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner{'o', 'b', 'j', '\0', 'b', 'a', 's', '\0'}; 178a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 179a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 180a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennstatic uint64_t ourBaseExceptionClass = 0; 181a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 182a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennstatic std::vector<std::string> ourTypeInfoNames; 183a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennstatic std::map<int, std::string> ourTypeInfoNamesIndex; 184a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 18564cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Vennstatic llvm::StructType *ourTypeInfoType; 18685500714c460be6452a96be1574d8676d062051cGarrison Vennstatic llvm::StructType *ourCaughtResultType; 18764cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Vennstatic llvm::StructType *ourExceptionType; 18864cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Vennstatic llvm::StructType *ourUnwindExceptionType; 189a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 19064cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Vennstatic llvm::ConstantInt *ourExceptionNotThrownState; 19164cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Vennstatic llvm::ConstantInt *ourExceptionThrownState; 19264cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Vennstatic llvm::ConstantInt *ourExceptionCaughtState; 193a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 194a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venntypedef std::vector<std::string> ArgNames; 1956e6cdd00aaca083779eb70dc238779935da6b9c8Garrison Venntypedef std::vector<llvm::Type*> ArgTypes; 196a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 197a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// 198a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// Code Generation Utilities 199a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// 200a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 201a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// Utility used to create a function, both declarations and definitions 202a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param module for module instance 203a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param retType function return type 204a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param theArgTypes function's ordered argument types 205a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param theArgNames function's ordered arguments needed if use of this 2069f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// function corresponds to a function definition. Use empty 207a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// aggregate for function declarations. 208a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param functName function name 209a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param linkage function linkage 210a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param declarationOnly for function declarations 211a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param isVarArg function uses vararg arguments 212a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @returns function instance 21364cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Vennllvm::Function *createFunction(llvm::Module &module, 21477613d4135d5fc8461d0583837b5b850c4a29ecdChris Lattner llvm::Type *retType, 21564cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn const ArgTypes &theArgTypes, 21664cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn const ArgNames &theArgNames, 21764cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn const std::string &functName, 218a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn llvm::GlobalValue::LinkageTypes linkage, 219a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn bool declarationOnly, 220a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn bool isVarArg) { 221626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner llvm::FunctionType *functType = 222626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner llvm::FunctionType::get(retType, theArgTypes, isVarArg); 223626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner llvm::Function *ret = 224626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner llvm::Function::Create(functType, linkage, functName, &module); 225626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner if (!ret || declarationOnly) 226a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn return(ret); 2279f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 228626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner namedValues.clear(); 2299f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi unsigned i = 0; 230626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner for (llvm::Function::arg_iterator argIndex = ret->arg_begin(); 231626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner i != theArgNames.size(); 232626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner ++argIndex, ++i) { 2339f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 234626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner argIndex->setName(theArgNames[i]); 235626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner namedValues[theArgNames[i]] = argIndex; 236626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 2379f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 238626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner return(ret); 239a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn} 240a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 241a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 242a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// Create an alloca instruction in the entry block of 243a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// the parent function. This is used for mutable variables etc. 244a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param function parent instance 245a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param varName stack variable name 246a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param type stack variable type 247a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param initWith optional constant initialization value 248a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @returns AllocaInst instance 24964cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Vennstatic llvm::AllocaInst *createEntryBlockAlloca(llvm::Function &function, 250626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner const std::string &varName, 25177613d4135d5fc8461d0583837b5b850c4a29ecdChris Lattner llvm::Type *type, 25264cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn llvm::Constant *initWith = 0) { 2539f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::BasicBlock &block = function.getEntryBlock(); 254626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner llvm::IRBuilder<> tmp(&block, block.begin()); 25564cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn llvm::AllocaInst *ret = tmp.CreateAlloca(type, 0, varName.c_str()); 2569f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 2579f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi if (initWith) 258626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner tmp.CreateStore(initWith, ret); 2599f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 260626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner return(ret); 261a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn} 262a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 263a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 264a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// 265a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// Code Generation Utilities End 266a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// 267a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 268a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// 2699f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi// Runtime C Library functions 270a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// 271a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 272a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// Note: using an extern "C" block so that static functions can be used 273a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennextern "C" { 274a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 275a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// Note: Better ways to decide on bit width 276a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// 277a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// Prints a 32 bit number, according to the format, to stderr. 2789f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// @param intToPrint integer to print 279a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param format printf like format to use when printing 28064cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Vennvoid print32Int(int intToPrint, const char *format) { 281626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner if (format) { 282626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Note: No NULL check 283626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fprintf(stderr, format, intToPrint); 284626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 285626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner else { 286626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Note: No NULL check 287626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fprintf(stderr, "::print32Int(...):NULL arg.\n"); 288626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 289a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn} 290a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 291a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 292a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// Note: Better ways to decide on bit width 293a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// 294a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// Prints a 64 bit number, according to the format, to stderr. 2959f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// @param intToPrint integer to print 296a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param format printf like format to use when printing 29764cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Vennvoid print64Int(long int intToPrint, const char *format) { 298626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner if (format) { 299626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Note: No NULL check 300626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fprintf(stderr, format, intToPrint); 301626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 302626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner else { 303626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Note: No NULL check 304626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fprintf(stderr, "::print64Int(...):NULL arg.\n"); 305626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 306a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn} 307a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 308a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 309a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// Prints a C string to stderr 310a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param toPrint string to print 31164cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Vennvoid printStr(char *toPrint) { 312626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner if (toPrint) { 313626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fprintf(stderr, "%s", toPrint); 314626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 315626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner else { 316626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fprintf(stderr, "::printStr(...):NULL arg.\n"); 317626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 318a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn} 319a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 320a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 321a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// Deletes the true previosly allocated exception whose address 322a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// is calculated from the supplied OurBaseException_t::unwindException 323a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// member address. Handles (ignores), NULL pointers. 324a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param expToDelete exception to delete 32564cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Vennvoid deleteOurException(OurUnwindException *expToDelete) { 326a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#ifdef DEBUG 327626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fprintf(stderr, 328626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner "deleteOurException(...).\n"); 329a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#endif 3309f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 331626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner if (expToDelete && 332626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner (expToDelete->exception_class == ourBaseExceptionClass)) { 3339f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 334626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner free(((char*) expToDelete) + ourBaseFromUnwindOffset); 335626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 336a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn} 337a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 338a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 3399f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// This function is the struct _Unwind_Exception API mandated delete function 3409f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// used by foreign exception handlers when deleting our exception 341a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// (OurException), instances. 342c16babf6939f9db05a8a81c4d530a2fd605b4236NAKAMURA Takumi/// @param reason See @link http://mentorembedded.github.com/cxx-abi/abi-eh.html 343a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @unlink 344a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param expToDelete exception instance to delete 345a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennvoid deleteFromUnwindOurException(_Unwind_Reason_Code reason, 34664cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn OurUnwindException *expToDelete) { 347a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#ifdef DEBUG 348626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fprintf(stderr, 349626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner "deleteFromUnwindOurException(...).\n"); 350a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#endif 3519f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 352626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner deleteOurException(expToDelete); 353a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn} 354a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 355a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 356a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// Creates (allocates on the heap), an exception (OurException instance), 357a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// of the supplied type info type. 358a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param type type info type 35964cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison VennOurUnwindException *createOurException(int type) { 360626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner size_t size = sizeof(OurException); 36164cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn OurException *ret = (OurException*) memset(malloc(size), 0, size); 362626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner (ret->type).type = type; 363626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner (ret->unwindException).exception_class = ourBaseExceptionClass; 364626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner (ret->unwindException).exception_cleanup = deleteFromUnwindOurException; 3659f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 366626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner return(&(ret->unwindException)); 367a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn} 368a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 369a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 3709f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// Read a uleb128 encoded value and advance pointer 3719f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// See Variable Length Data in: 372a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @link http://dwarfstd.org/Dwarf3.pdf @unlink 373a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param data reference variable holding memory pointer to decode from 374a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @returns decoded value 37564cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Vennstatic uintptr_t readULEB128(const uint8_t **data) { 376626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner uintptr_t result = 0; 377626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner uintptr_t shift = 0; 378626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner unsigned char byte; 37964cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn const uint8_t *p = *data; 3809f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 381626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner do { 382626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner byte = *p++; 383626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner result |= (byte & 0x7f) << shift; 384626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner shift += 7; 3859f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi } 386626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner while (byte & 0x80); 3879f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 388626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner *data = p; 3899f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 390626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner return result; 391a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn} 392a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 393a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 3949f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// Read a sleb128 encoded value and advance pointer 3959f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// See Variable Length Data in: 396a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @link http://dwarfstd.org/Dwarf3.pdf @unlink 397a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param data reference variable holding memory pointer to decode from 398a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @returns decoded value 39964cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Vennstatic uintptr_t readSLEB128(const uint8_t **data) { 400626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner uintptr_t result = 0; 401626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner uintptr_t shift = 0; 402626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner unsigned char byte; 40364cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn const uint8_t *p = *data; 4049f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 405626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner do { 406626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner byte = *p++; 407626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner result |= (byte & 0x7f) << shift; 408626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner shift += 7; 4099f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi } 410626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner while (byte & 0x80); 4119f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 412626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner *data = p; 4139f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 414626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner if ((byte & 0x40) && (shift < (sizeof(result) << 3))) { 415626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner result |= (~0 << shift); 416626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 4179f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 418626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner return result; 419a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn} 420a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 42158c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindolaunsigned getEncodingSize(uint8_t Encoding) { 42258c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola if (Encoding == llvm::dwarf::DW_EH_PE_omit) 42358c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola return 0; 42458c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola 42558c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola switch (Encoding & 0x0F) { 42658c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola case llvm::dwarf::DW_EH_PE_absptr: 42758c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola return sizeof(uintptr_t); 42858c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola case llvm::dwarf::DW_EH_PE_udata2: 42958c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola return sizeof(uint16_t); 43058c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola case llvm::dwarf::DW_EH_PE_udata4: 43158c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola return sizeof(uint32_t); 43258c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola case llvm::dwarf::DW_EH_PE_udata8: 43358c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola return sizeof(uint64_t); 43458c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola case llvm::dwarf::DW_EH_PE_sdata2: 43558c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola return sizeof(int16_t); 43658c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola case llvm::dwarf::DW_EH_PE_sdata4: 43758c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola return sizeof(int32_t); 43858c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola case llvm::dwarf::DW_EH_PE_sdata8: 43958c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola return sizeof(int64_t); 44058c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola default: 44158c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola // not supported 44258c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola abort(); 44358c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola } 44458c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola} 445a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 4469f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// Read a pointer encoded value and advance pointer 4479f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// See Variable Length Data in: 448a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @link http://dwarfstd.org/Dwarf3.pdf @unlink 449a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param data reference variable holding memory pointer to decode from 450a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param encoding dwarf encoding type 451a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @returns decoded value 45264cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Vennstatic uintptr_t readEncodedPointer(const uint8_t **data, uint8_t encoding) { 453626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner uintptr_t result = 0; 45464cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn const uint8_t *p = *data; 4559f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 4569f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi if (encoding == llvm::dwarf::DW_EH_PE_omit) 457626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner return(result); 4589f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 4599f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi // first get value 460626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner switch (encoding & 0x0F) { 461626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner case llvm::dwarf::DW_EH_PE_absptr: 462626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner result = *((uintptr_t*)p); 463626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner p += sizeof(uintptr_t); 464626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner break; 465626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner case llvm::dwarf::DW_EH_PE_uleb128: 466626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner result = readULEB128(&p); 467626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner break; 468626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Note: This case has not been tested 469626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner case llvm::dwarf::DW_EH_PE_sleb128: 470626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner result = readSLEB128(&p); 471626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner break; 472626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner case llvm::dwarf::DW_EH_PE_udata2: 473626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner result = *((uint16_t*)p); 474626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner p += sizeof(uint16_t); 475626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner break; 476626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner case llvm::dwarf::DW_EH_PE_udata4: 477626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner result = *((uint32_t*)p); 478626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner p += sizeof(uint32_t); 479626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner break; 480626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner case llvm::dwarf::DW_EH_PE_udata8: 481626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner result = *((uint64_t*)p); 482626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner p += sizeof(uint64_t); 483626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner break; 484626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner case llvm::dwarf::DW_EH_PE_sdata2: 485626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner result = *((int16_t*)p); 486626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner p += sizeof(int16_t); 487626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner break; 488626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner case llvm::dwarf::DW_EH_PE_sdata4: 489626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner result = *((int32_t*)p); 490626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner p += sizeof(int32_t); 491626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner break; 492626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner case llvm::dwarf::DW_EH_PE_sdata8: 493626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner result = *((int64_t*)p); 494626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner p += sizeof(int64_t); 495626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner break; 496626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner default: 4979f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi // not supported 498626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner abort(); 499626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner break; 500626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 5019f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 5029f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi // then add relative offset 503626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner switch (encoding & 0x70) { 504626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner case llvm::dwarf::DW_EH_PE_absptr: 5059f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi // do nothing 506626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner break; 507626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner case llvm::dwarf::DW_EH_PE_pcrel: 508626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner result += (uintptr_t)(*data); 509626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner break; 510626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner case llvm::dwarf::DW_EH_PE_textrel: 511626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner case llvm::dwarf::DW_EH_PE_datarel: 512626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner case llvm::dwarf::DW_EH_PE_funcrel: 513626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner case llvm::dwarf::DW_EH_PE_aligned: 514626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner default: 5159f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi // not supported 516626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner abort(); 517626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner break; 518626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 5199f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 5209f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi // then apply indirection 521626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner if (encoding & llvm::dwarf::DW_EH_PE_indirect) { 522626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner result = *((uintptr_t*)result); 523626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 5249f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 525626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner *data = p; 5269f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 527626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner return result; 528a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn} 529a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 530a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 5319f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// Deals with Dwarf actions matching our type infos 5329f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// (OurExceptionType_t instances). Returns whether or not a dwarf emitted 5339f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// action matches the supplied exception type. If such a match succeeds, 5349f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// the resultAction argument will be set with > 0 index value. Only 5359f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// corresponding llvm.eh.selector type info arguments, cleanup arguments 536a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// are supported. Filters are not supported. 5379f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// See Variable Length Data in: 538a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @link http://dwarfstd.org/Dwarf3.pdf @unlink 539a6f10317bf2b90a16a931d0f5260cf3920a28d62Dmitri Gribenko/// Also see @link http://mentorembedded.github.com/cxx-abi/abi-eh.html @unlink 540a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param resultAction reference variable which will be set with result 541a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param classInfo our array of type info pointers (to globals) 5429f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// @param actionEntry index into above type info array or 0 (clean up). 543a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// We do not support filters. 544a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param exceptionClass exception class (_Unwind_Exception::exception_class) 545a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// of thrown exception. 546a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param exceptionObject thrown _Unwind_Exception instance. 547a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @returns whether or not a type info was found. False is returned if only 548a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// a cleanup was found 549a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennstatic bool handleActionValue(int64_t *resultAction, 55058c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola uint8_t TTypeEncoding, 55158c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola const uint8_t *ClassInfo, 5529f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi uintptr_t actionEntry, 5539f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi uint64_t exceptionClass, 554a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn struct _Unwind_Exception *exceptionObject) { 555626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner bool ret = false; 5569f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 5579f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi if (!resultAction || 5589f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi !exceptionObject || 559626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner (exceptionClass != ourBaseExceptionClass)) 560626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner return(ret); 5619f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 56264cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn struct OurBaseException_t *excp = (struct OurBaseException_t*) 563626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner (((char*) exceptionObject) + ourBaseFromUnwindOffset); 564626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner struct OurExceptionType_t *excpType = &(excp->type); 565626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner int type = excpType->type; 5669f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 567a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#ifdef DEBUG 568626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fprintf(stderr, 569626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner "handleActionValue(...): exceptionObject = <%p>, " 570626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner "excp = <%p>.\n", 571626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner exceptionObject, 572626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner excp); 573a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#endif 5749f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 575626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner const uint8_t *actionPos = (uint8_t*) actionEntry, 576626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner *tempActionPos; 577626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner int64_t typeOffset = 0, 578626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner actionOffset; 5799f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 580626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner for (int i = 0; true; ++i) { 581626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Each emitted dwarf action corresponds to a 2 tuple of 582626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // type info address offset, and action offset to the next 583626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // emitted action. 584626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner typeOffset = readSLEB128(&actionPos); 585626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner tempActionPos = actionPos; 586626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner actionOffset = readSLEB128(&tempActionPos); 5879f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 588a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#ifdef DEBUG 589626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fprintf(stderr, 590626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner "handleActionValue(...):typeOffset: <%lld>, " 591626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner "actionOffset: <%lld>.\n", 592626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner typeOffset, 593626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner actionOffset); 594a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#endif 5959f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi assert((typeOffset >= 0) && 596626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner "handleActionValue(...):filters are not supported."); 5979f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 598626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Note: A typeOffset == 0 implies that a cleanup llvm.eh.selector 599626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // argument has been matched. 60058c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola if (typeOffset > 0) { 601a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#ifdef DEBUG 602626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fprintf(stderr, 603626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner "handleActionValue(...):actionValue <%d> found.\n", 604626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner i); 605a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#endif 60658c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola unsigned EncSize = getEncodingSize(TTypeEncoding); 60758c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola const uint8_t *EntryP = ClassInfo - typeOffset * EncSize; 60858c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola uintptr_t P = readEncodedPointer(&EntryP, TTypeEncoding); 60958c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola struct OurExceptionType_t *ThisClassInfo = 61058c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola reinterpret_cast<struct OurExceptionType_t *>(P); 61158c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola if (ThisClassInfo->type == type) { 61258c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola *resultAction = i + 1; 61358c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola ret = true; 61458c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola break; 61558c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola } 616626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 6179f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 618a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#ifdef DEBUG 619626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fprintf(stderr, 620626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner "handleActionValue(...):actionValue not found.\n"); 621a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#endif 622626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner if (!actionOffset) 623626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner break; 6249f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 625626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner actionPos += actionOffset; 626626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 6279f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 628626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner return(ret); 629a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn} 630a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 631a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 632a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// Deals with the Language specific data portion of the emitted dwarf code. 633a6f10317bf2b90a16a931d0f5260cf3920a28d62Dmitri Gribenko/// See @link http://mentorembedded.github.com/cxx-abi/abi-eh.html @unlink 634a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param version unsupported (ignored), unwind version 635a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param lsda language specific data area 6369f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// @param _Unwind_Action actions minimally supported unwind stage 637a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// (forced specifically not supported) 638a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param exceptionClass exception class (_Unwind_Exception::exception_class) 639a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// of thrown exception. 640a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param exceptionObject thrown _Unwind_Exception instance. 641a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param context unwind system context 6429f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// @returns minimally supported unwinding control indicator 6439f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumistatic _Unwind_Reason_Code handleLsda(int version, 64464cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn const uint8_t *lsda, 645626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner _Unwind_Action actions, 6469f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi uint64_t exceptionClass, 64764cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn struct _Unwind_Exception *exceptionObject, 648626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner _Unwind_Context_t context) { 649626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner _Unwind_Reason_Code ret = _URC_CONTINUE_UNWIND; 6509f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 651626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner if (!lsda) 652626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner return(ret); 6539f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 654a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#ifdef DEBUG 6559f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi fprintf(stderr, 656626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner "handleLsda(...):lsda is non-zero.\n"); 657a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#endif 6589f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 659626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Get the current instruction pointer and offset it before next 660626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // instruction in the current frame which threw the exception. 661626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner uintptr_t pc = _Unwind_GetIP(context)-1; 6629f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 6639f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi // Get beginning current frame's code (as defined by the 664626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // emitted dwarf code) 665626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner uintptr_t funcStart = _Unwind_GetRegionStart(context); 666626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner uintptr_t pcOffset = pc - funcStart; 66758c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola const uint8_t *ClassInfo = NULL; 6689f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 669626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding 670626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // dwarf emission 6719f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 672626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Parse LSDA header. 673626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner uint8_t lpStartEncoding = *lsda++; 6749f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 675626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner if (lpStartEncoding != llvm::dwarf::DW_EH_PE_omit) { 6769f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi readEncodedPointer(&lsda, lpStartEncoding); 677626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 6789f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 679626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner uint8_t ttypeEncoding = *lsda++; 680626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner uintptr_t classInfoOffset; 6819f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 682626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner if (ttypeEncoding != llvm::dwarf::DW_EH_PE_omit) { 683626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Calculate type info locations in emitted dwarf code which 684626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // were flagged by type info arguments to llvm.eh.selector 685626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // intrinsic 686626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner classInfoOffset = readULEB128(&lsda); 68758c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola ClassInfo = lsda + classInfoOffset; 688626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 6899f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 6909f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi // Walk call-site table looking for range that 6919f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi // includes current PC. 6929f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 693626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner uint8_t callSiteEncoding = *lsda++; 694626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner uint32_t callSiteTableLength = readULEB128(&lsda); 69564cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn const uint8_t *callSiteTableStart = lsda; 6969f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi const uint8_t *callSiteTableEnd = callSiteTableStart + 697626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner callSiteTableLength; 69864cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn const uint8_t *actionTableStart = callSiteTableEnd; 69964cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn const uint8_t *callSitePtr = callSiteTableStart; 7009f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 701626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner while (callSitePtr < callSiteTableEnd) { 7029f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi uintptr_t start = readEncodedPointer(&callSitePtr, 703626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner callSiteEncoding); 7049f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi uintptr_t length = readEncodedPointer(&callSitePtr, 705626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner callSiteEncoding); 7069f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi uintptr_t landingPad = readEncodedPointer(&callSitePtr, 707a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn callSiteEncoding); 7089f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 709626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Note: Action value 710626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner uintptr_t actionEntry = readULEB128(&callSitePtr); 7119f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 712626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner if (exceptionClass != ourBaseExceptionClass) { 713626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // We have been notified of a foreign exception being thrown, 714626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // and we therefore need to execute cleanup landing pads 715626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner actionEntry = 0; 716626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 7179f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 718626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner if (landingPad == 0) { 719a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#ifdef DEBUG 720626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fprintf(stderr, 721626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner "handleLsda(...): No landing pad found.\n"); 722a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#endif 7239f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 724626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner continue; // no landing pad for this entry 725626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 7269f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 727626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner if (actionEntry) { 728626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner actionEntry += ((uintptr_t) actionTableStart) - 1; 729626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 730626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner else { 731a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#ifdef DEBUG 732626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fprintf(stderr, 733626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner "handleLsda(...):No action table found.\n"); 734a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#endif 735626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 7369f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 737626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner bool exceptionMatched = false; 7389f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 739626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner if ((start <= pcOffset) && (pcOffset < (start + length))) { 740a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#ifdef DEBUG 741626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fprintf(stderr, 742626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner "handleLsda(...): Landing pad found.\n"); 743a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#endif 744626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner int64_t actionValue = 0; 7459f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 746626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner if (actionEntry) { 74764cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn exceptionMatched = handleActionValue(&actionValue, 74858c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola ttypeEncoding, 74958c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola ClassInfo, 7509f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi actionEntry, 7519f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi exceptionClass, 75264cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn exceptionObject); 753626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 7549f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 755626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner if (!(actions & _UA_SEARCH_PHASE)) { 756a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#ifdef DEBUG 757626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fprintf(stderr, 758626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner "handleLsda(...): installed landing pad " 759626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner "context.\n"); 760a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#endif 7619f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 762626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Found landing pad for the PC. 7639f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi // Set Instruction Pointer to so we re-enter function 7649f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi // at landing pad. The landing pad is created by the 765626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // compiler to take two parameters in registers. 7669f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi _Unwind_SetGR(context, 7679f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi __builtin_eh_return_data_regno(0), 768626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner (uintptr_t)exceptionObject); 7699f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 770626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Note: this virtual register directly corresponds 771626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // to the return of the llvm.eh.selector intrinsic 772626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner if (!actionEntry || !exceptionMatched) { 773626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // We indicate cleanup only 7749f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi _Unwind_SetGR(context, 7759f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi __builtin_eh_return_data_regno(1), 776626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner 0); 777626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 778626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner else { 779626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Matched type info index of llvm.eh.selector intrinsic 780626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // passed here. 7819f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi _Unwind_SetGR(context, 7829f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi __builtin_eh_return_data_regno(1), 783626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner actionValue); 784626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 7859f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 786626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // To execute landing pad set here 787626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner _Unwind_SetIP(context, funcStart + landingPad); 788626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner ret = _URC_INSTALL_CONTEXT; 789626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 790626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner else if (exceptionMatched) { 791a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#ifdef DEBUG 792626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fprintf(stderr, 793626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner "handleLsda(...): setting handler found.\n"); 794a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#endif 795626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner ret = _URC_HANDLER_FOUND; 796626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 797626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner else { 798626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Note: Only non-clean up handlers are marked as 7999f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi // found. Otherwise the clean up handlers will be 8009f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi // re-found and executed during the clean up 801626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // phase. 802a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#ifdef DEBUG 803626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fprintf(stderr, 804626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner "handleLsda(...): cleanup handler found.\n"); 805a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#endif 806626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 8079f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 808626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner break; 809a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn } 810626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 8119f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 812626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner return(ret); 813a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn} 814a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 815a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 816a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// This is the personality function which is embedded (dwarf emitted), in the 817a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// dwarf unwind info block. Again see: JITDwarfEmitter.cpp. 818a6f10317bf2b90a16a931d0f5260cf3920a28d62Dmitri Gribenko/// See @link http://mentorembedded.github.com/cxx-abi/abi-eh.html @unlink 819a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param version unsupported (ignored), unwind version 8209f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// @param _Unwind_Action actions minimally supported unwind stage 821a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// (forced specifically not supported) 822a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param exceptionClass exception class (_Unwind_Exception::exception_class) 823a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// of thrown exception. 824a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param exceptionObject thrown _Unwind_Exception instance. 825a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param context unwind system context 8269f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// @returns minimally supported unwinding control indicator 8279f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi_Unwind_Reason_Code ourPersonality(int version, 828626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner _Unwind_Action actions, 8299f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi uint64_t exceptionClass, 83064cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn struct _Unwind_Exception *exceptionObject, 831626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner _Unwind_Context_t context) { 832a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#ifdef DEBUG 8339f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi fprintf(stderr, 834626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner "We are in ourPersonality(...):actions is <%d>.\n", 835626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner actions); 8369f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 837626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner if (actions & _UA_SEARCH_PHASE) { 838626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fprintf(stderr, "ourPersonality(...):In search phase.\n"); 839626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 840626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner else { 841626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fprintf(stderr, "ourPersonality(...):In non-search phase.\n"); 842626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 843a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#endif 8449f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 84564cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn const uint8_t *lsda = _Unwind_GetLanguageSpecificData(context); 8469f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 847a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#ifdef DEBUG 8489f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi fprintf(stderr, 849626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner "ourPersonality(...):lsda = <%p>.\n", 850626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner lsda); 851a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#endif 8529f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 853626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // The real work of the personality function is captured here 854626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner return(handleLsda(version, 855626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner lsda, 856626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner actions, 857626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner exceptionClass, 858626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner exceptionObject, 859626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner context)); 860a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn} 861a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 862a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 863a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// Generates our _Unwind_Exception class from a given character array. 864a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// thereby handling arbitrary lengths (not in standard), and handling 865a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// embedded \0s. 866a6f10317bf2b90a16a931d0f5260cf3920a28d62Dmitri Gribenko/// See @link http://mentorembedded.github.com/cxx-abi/abi-eh.html @unlink 867a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param classChars char array to encode. NULL values not checkedf 868a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param classCharsSize number of chars in classChars. Value is not checked. 869a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @returns class value 870a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennuint64_t genClass(const unsigned char classChars[], size_t classCharsSize) 871a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn{ 872626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner uint64_t ret = classChars[0]; 8739f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 874626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner for (unsigned i = 1; i < classCharsSize; ++i) { 875626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner ret <<= 8; 876626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner ret += classChars[i]; 877626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 8789f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 879626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner return(ret); 880a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn} 881a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 882a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn} // extern "C" 883a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 884a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// 885a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// Runtime C Library functions End 886a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// 887a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 888a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// 889a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// Code generation functions 890a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// 891a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 892a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// Generates code to print given constant string 893a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param context llvm context 894a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param module code for module instance 895a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param builder builder instance 896a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param toPrint string to print 8979f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// @param useGlobal A value of true (default) indicates a GlobalValue is 8989f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// generated, and is used to hold the constant string. A value of 8999f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// false indicates that the constant string will be stored on the 900a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// stack. 9019f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumivoid generateStringPrint(llvm::LLVMContext &context, 90264cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn llvm::Module &module, 9039f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::IRBuilder<> &builder, 904a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn std::string toPrint, 905a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn bool useGlobal = true) { 906626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner llvm::Function *printFunct = module.getFunction("printStr"); 9079f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 908626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner llvm::Value *stringVar; 9099f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::Constant *stringConstant = 910793a32dfb643c2804b79d7d675cc614659debae7Peter Collingbourne llvm::ConstantDataArray::getString(context, toPrint); 9119f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 912626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner if (useGlobal) { 913626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Note: Does not work without allocation 9149f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi stringVar = 9159f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi new llvm::GlobalVariable(module, 916626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner stringConstant->getType(), 9179f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi true, 9189f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::GlobalValue::LinkerPrivateLinkage, 9199f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi stringConstant, 920626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner ""); 921626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 922626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner else { 923626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner stringVar = builder.CreateAlloca(stringConstant->getType()); 924626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner builder.CreateStore(stringConstant, stringVar); 925626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 9269f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 9279f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::Value *cast = builder.CreatePointerCast(stringVar, 9289cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn builder.getInt8PtrTy()); 929626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner builder.CreateCall(printFunct, cast); 930a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn} 931a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 932a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 933a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// Generates code to print given runtime integer according to constant 934a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// string format, and a given print function. 935a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param context llvm context 936a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param module code for module instance 937a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param builder builder instance 938a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param printFunct function used to "print" integer 939a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param toPrint string to print 940a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param format printf like formating string for print 9419f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// @param useGlobal A value of true (default) indicates a GlobalValue is 9429f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// generated, and is used to hold the constant string. A value of 9439f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// false indicates that the constant string will be stored on the 944a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// stack. 9459f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumivoid generateIntegerPrint(llvm::LLVMContext &context, 94664cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn llvm::Module &module, 9479f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::IRBuilder<> &builder, 94864cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn llvm::Function &printFunct, 94964cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn llvm::Value &toPrint, 9509f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi std::string format, 951a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn bool useGlobal = true) { 952793a32dfb643c2804b79d7d675cc614659debae7Peter Collingbourne llvm::Constant *stringConstant = 953793a32dfb643c2804b79d7d675cc614659debae7Peter Collingbourne llvm::ConstantDataArray::getString(context, format); 954626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner llvm::Value *stringVar; 9559f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 956626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner if (useGlobal) { 957626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Note: Does not seem to work without allocation 9589f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi stringVar = 9599f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi new llvm::GlobalVariable(module, 960626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner stringConstant->getType(), 9619f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi true, 9629f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::GlobalValue::LinkerPrivateLinkage, 9639f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi stringConstant, 964626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner ""); 965626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 966626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner else { 967626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner stringVar = builder.CreateAlloca(stringConstant->getType()); 968626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner builder.CreateStore(stringConstant, stringVar); 969626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 9709f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 9719f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::Value *cast = builder.CreateBitCast(stringVar, 9729cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn builder.getInt8PtrTy()); 973626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner builder.CreateCall2(&printFunct, &toPrint, cast); 974a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn} 975a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 976a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 9779f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// Generates code to handle finally block type semantics: always runs 9789f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// regardless of whether a thrown exception is passing through or the 9799f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// parent function is simply exiting. In addition to printing some state 9809f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// to stderr, this code will resume the exception handling--runs the 9819f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// unwind resume block, if the exception has not been previously caught 9829f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// by a catch clause, and will otherwise execute the end block (terminator 9839f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// block). In addition this function creates the corresponding function's 984a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// stack storage for the exception pointer and catch flag status. 985a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param context llvm context 986a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param module code for module instance 987a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param builder builder instance 988a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param toAddTo parent function to add block to 989a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param blockName block name of new "finally" block. 990a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param functionId output id used for printing 991a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param terminatorBlock terminator "end" block 992a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param unwindResumeBlock unwind resume block 993a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param exceptionCaughtFlag reference exception caught/thrown status storage 994a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param exceptionStorage reference to exception pointer storage 9959cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn/// @param caughtResultStorage reference to landingpad result storage 996a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @returns newly created block 9979f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumistatic llvm::BasicBlock *createFinallyBlock(llvm::LLVMContext &context, 9989f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::Module &module, 9999f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::IRBuilder<> &builder, 100064cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn llvm::Function &toAddTo, 100164cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn std::string &blockName, 100264cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn std::string &functionId, 100364cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn llvm::BasicBlock &terminatorBlock, 100464cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn llvm::BasicBlock &unwindResumeBlock, 100564cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn llvm::Value **exceptionCaughtFlag, 100608e8db423df938160bd611741da4c6dad40ce125Bill Wendling llvm::Value **exceptionStorage, 100708e8db423df938160bd611741da4c6dad40ce125Bill Wendling llvm::Value **caughtResultStorage) { 10089f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi assert(exceptionCaughtFlag && 1009626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner "ExceptionDemo::createFinallyBlock(...):exceptionCaughtFlag " 1010626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner "is NULL"); 10119f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi assert(exceptionStorage && 1012626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner "ExceptionDemo::createFinallyBlock(...):exceptionStorage " 1013626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner "is NULL"); 10149f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi assert(caughtResultStorage && 10159cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn "ExceptionDemo::createFinallyBlock(...):caughtResultStorage " 10169cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn "is NULL"); 10179f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 10189cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn *exceptionCaughtFlag = createEntryBlockAlloca(toAddTo, 10199cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn "exceptionCaught", 10209cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn ourExceptionNotThrownState->getType(), 10219cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn ourExceptionNotThrownState); 10229f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 102377613d4135d5fc8461d0583837b5b850c4a29ecdChris Lattner llvm::PointerType *exceptionStorageType = builder.getInt8PtrTy(); 10249cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn *exceptionStorage = createEntryBlockAlloca(toAddTo, 10259cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn "exceptionStorage", 10269cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn exceptionStorageType, 10279cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn llvm::ConstantPointerNull::get( 10289cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn exceptionStorageType)); 10299cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn *caughtResultStorage = createEntryBlockAlloca(toAddTo, 10309cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn "caughtResultStorage", 10319cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn ourCaughtResultType, 10329cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn llvm::ConstantAggregateZero::get( 10339cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn ourCaughtResultType)); 10349f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1035626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner llvm::BasicBlock *ret = llvm::BasicBlock::Create(context, 1036626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner blockName, 1037626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner &toAddTo); 10389f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1039626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner builder.SetInsertPoint(ret); 10409f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1041626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner std::ostringstream bufferToPrint; 1042626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner bufferToPrint << "Gen: Executing finally block " 1043626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner << blockName << " in " << functionId << "\n"; 10449f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi generateStringPrint(context, 10459f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi module, 10469f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi builder, 1047626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner bufferToPrint.str(), 1048626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner USE_GLOBAL_STR_CONSTS); 10499f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 10509cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn llvm::SwitchInst *theSwitch = builder.CreateSwitch(builder.CreateLoad( 10519f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi *exceptionCaughtFlag), 10529cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn &terminatorBlock, 10539cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn 2); 1054626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner theSwitch->addCase(ourExceptionCaughtState, &terminatorBlock); 1055626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner theSwitch->addCase(ourExceptionThrownState, &unwindResumeBlock); 10569f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1057626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner return(ret); 1058a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn} 1059a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 1060a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 1061a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// Generates catch block semantics which print a string to indicate type of 10629f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// catch executed, sets an exception caught flag, and executes passed in 1063a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// end block (terminator block). 1064a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param context llvm context 1065a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param module code for module instance 1066a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param builder builder instance 1067a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param toAddTo parent function to add block to 1068a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param blockName block name of new "catch" block. 1069a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param functionId output id used for printing 1070a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param terminatorBlock terminator "end" block 1071a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param exceptionCaughtFlag exception caught/thrown status 1072a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @returns newly created block 10739f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumistatic llvm::BasicBlock *createCatchBlock(llvm::LLVMContext &context, 10749f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::Module &module, 10759f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::IRBuilder<> &builder, 107664cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn llvm::Function &toAddTo, 107764cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn std::string &blockName, 107864cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn std::string &functionId, 107964cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn llvm::BasicBlock &terminatorBlock, 108064cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn llvm::Value &exceptionCaughtFlag) { 10819f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1082626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner llvm::BasicBlock *ret = llvm::BasicBlock::Create(context, 1083626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner blockName, 1084626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner &toAddTo); 10859f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1086626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner builder.SetInsertPoint(ret); 10879f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1088626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner std::ostringstream bufferToPrint; 1089626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner bufferToPrint << "Gen: Executing catch block " 1090626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner << blockName 1091626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner << " in " 1092626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner << functionId 1093626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner << std::endl; 10949f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi generateStringPrint(context, 10959f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi module, 10969f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi builder, 1097626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner bufferToPrint.str(), 1098626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner USE_GLOBAL_STR_CONSTS); 1099626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner builder.CreateStore(ourExceptionCaughtState, &exceptionCaughtFlag); 1100626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner builder.CreateBr(&terminatorBlock); 11019f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1102626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner return(ret); 1103a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn} 1104a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 1105a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 11069f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// Generates a function which invokes a function (toInvoke) and, whose 11079f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// unwind block will "catch" the type info types correspondingly held in the 11089f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// exceptionTypesToCatch argument. If the toInvoke function throws an 11099f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// exception which does not match any type info types contained in 11109f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// exceptionTypesToCatch, the generated code will call _Unwind_Resume 11119f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// with the raised exception. On the other hand the generated code will 1112a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// normally exit if the toInvoke function does not throw an exception. 11139f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// The generated "finally" block is always run regardless of the cause of 1114a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// the generated function exit. 1115a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// The generated function is returned after being verified. 1116a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param module code for module instance 1117a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param builder builder instance 11189f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// @param fpm a function pass manager holding optional IR to IR 1119a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// transformations 1120a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param toInvoke inner function to invoke 1121a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param ourId id used to printing purposes 1122a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param numExceptionsToCatch length of exceptionTypesToCatch array 1123a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param exceptionTypesToCatch array of type info types to "catch" 1124a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @returns generated function 1125a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennstatic 11269f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumillvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module, 11279f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::IRBuilder<> &builder, 112864cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn llvm::FunctionPassManager &fpm, 112964cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn llvm::Function &toInvoke, 113064cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn std::string ourId, 113164cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn unsigned numExceptionsToCatch, 113264cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn unsigned exceptionTypesToCatch[]) { 11339f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 113464cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn llvm::LLVMContext &context = module.getContext(); 1135626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner llvm::Function *toPrint32Int = module.getFunction("print32Int"); 11369f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1137626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner ArgTypes argTypes; 1138c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn argTypes.push_back(builder.getInt32Ty()); 11399f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1140626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner ArgNames argNames; 1141626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner argNames.push_back("exceptTypeToThrow"); 11429f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 11439f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::Function *ret = createFunction(module, 1144626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner builder.getVoidTy(), 11459f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi argTypes, 11469f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi argNames, 1147626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner ourId, 11489f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::Function::ExternalLinkage, 11499f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi false, 1150626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner false); 11519f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1152626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Block which calls invoke 1153626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner llvm::BasicBlock *entryBlock = llvm::BasicBlock::Create(context, 11549f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi "entry", 1155626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner ret); 1156626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Normal block for invoke 11579f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::BasicBlock *normalBlock = llvm::BasicBlock::Create(context, 11589f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi "normal", 1159626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner ret); 1160626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Unwind block for invoke 11619f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::BasicBlock *exceptionBlock = llvm::BasicBlock::Create(context, 11629f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi "exception", 11639cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn ret); 11649f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1165626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Block which routes exception to correct catch handler block 11669f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::BasicBlock *exceptionRouteBlock = llvm::BasicBlock::Create(context, 11679f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi "exceptionRoute", 11689cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn ret); 11699f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1170626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Foreign exception handler 11719f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::BasicBlock *externalExceptionBlock = llvm::BasicBlock::Create(context, 11729f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi "externalException", 11739cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn ret); 11749f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1175626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Block which calls _Unwind_Resume 11769f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::BasicBlock *unwindResumeBlock = llvm::BasicBlock::Create(context, 11779f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi "unwindResume", 11789cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn ret); 11799f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1180626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Clean up block which delete exception if needed 11819cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn llvm::BasicBlock *endBlock = llvm::BasicBlock::Create(context, "end", ret); 11829f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1183626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner std::string nextName; 1184626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner std::vector<llvm::BasicBlock*> catchBlocks(numExceptionsToCatch); 118564cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn llvm::Value *exceptionCaughtFlag = NULL; 118664cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn llvm::Value *exceptionStorage = NULL; 11879cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn llvm::Value *caughtResultStorage = NULL; 11889f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 11899f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi // Finally block which will branch to unwindResumeBlock if 1190626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // exception is not caught. Initializes/allocates stack locations. 11919f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::BasicBlock *finallyBlock = createFinallyBlock(context, 11929f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi module, 11939f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi builder, 11949f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi *ret, 11959f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi nextName = "finally", 1196626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner ourId, 1197626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner *endBlock, 1198626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner *unwindResumeBlock, 1199626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner &exceptionCaughtFlag, 120008e8db423df938160bd611741da4c6dad40ce125Bill Wendling &exceptionStorage, 120108e8db423df938160bd611741da4c6dad40ce125Bill Wendling &caughtResultStorage 12029cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn ); 12039f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1204626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner for (unsigned i = 0; i < numExceptionsToCatch; ++i) { 1205626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner nextName = ourTypeInfoNames[exceptionTypesToCatch[i]]; 12069f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1207626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // One catch block per type info to be caught 12089f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi catchBlocks[i] = createCatchBlock(context, 12099f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi module, 12109f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi builder, 1211626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner *ret, 12129f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi nextName, 1213626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner ourId, 1214626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner *finallyBlock, 1215626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner *exceptionCaughtFlag); 1216626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 12179f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1218626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Entry Block 12199f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1220626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner builder.SetInsertPoint(entryBlock); 12219f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1222626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner std::vector<llvm::Value*> args; 1223626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner args.push_back(namedValues["exceptTypeToThrow"]); 12249f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi builder.CreateInvoke(&toInvoke, 12259f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi normalBlock, 12269f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi exceptionBlock, 122777613d4135d5fc8461d0583837b5b850c4a29ecdChris Lattner args); 12289f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1229626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // End Block 12309f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1231626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner builder.SetInsertPoint(endBlock); 12329f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 12339f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi generateStringPrint(context, 1234626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner module, 12359f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi builder, 1236626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner "Gen: In end block: exiting in " + ourId + ".\n", 1237626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner USE_GLOBAL_STR_CONSTS); 12389cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn llvm::Function *deleteOurException = module.getFunction("deleteOurException"); 12399f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1240626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Note: function handles NULL exceptions 12419f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi builder.CreateCall(deleteOurException, 1242626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner builder.CreateLoad(exceptionStorage)); 1243626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner builder.CreateRetVoid(); 12449f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1245626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Normal Block 12469f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1247626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner builder.SetInsertPoint(normalBlock); 12489f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 12499f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi generateStringPrint(context, 1250626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner module, 12519f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi builder, 1252626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner "Gen: No exception in " + ourId + "!\n", 1253626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner USE_GLOBAL_STR_CONSTS); 12549f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1255626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Finally block is always called 1256626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner builder.CreateBr(finallyBlock); 12579f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1258626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Unwind Resume Block 12599f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1260626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner builder.SetInsertPoint(unwindResumeBlock); 12619f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 12629cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn builder.CreateResume(builder.CreateLoad(caughtResultStorage)); 12639f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1264626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Exception Block 12659f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1266626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner builder.SetInsertPoint(exceptionBlock); 12679f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 126885500714c460be6452a96be1574d8676d062051cGarrison Venn llvm::Function *personality = module.getFunction("ourPersonality"); 12699f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 12709f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::LandingPadInst *caughtResult = 127185500714c460be6452a96be1574d8676d062051cGarrison Venn builder.CreateLandingPad(ourCaughtResultType, 127285500714c460be6452a96be1574d8676d062051cGarrison Venn personality, 127385500714c460be6452a96be1574d8676d062051cGarrison Venn numExceptionsToCatch, 127485500714c460be6452a96be1574d8676d062051cGarrison Venn "landingPad"); 127585500714c460be6452a96be1574d8676d062051cGarrison Venn 127685500714c460be6452a96be1574d8676d062051cGarrison Venn caughtResult->setCleanup(true); 127785500714c460be6452a96be1574d8676d062051cGarrison Venn 127885500714c460be6452a96be1574d8676d062051cGarrison Venn for (unsigned i = 0; i < numExceptionsToCatch; ++i) { 127985500714c460be6452a96be1574d8676d062051cGarrison Venn // Set up type infos to be caught 128085500714c460be6452a96be1574d8676d062051cGarrison Venn caughtResult->addClause(module.getGlobalVariable( 128185500714c460be6452a96be1574d8676d062051cGarrison Venn ourTypeInfoNames[exceptionTypesToCatch[i]])); 128285500714c460be6452a96be1574d8676d062051cGarrison Venn } 128385500714c460be6452a96be1574d8676d062051cGarrison Venn 128485500714c460be6452a96be1574d8676d062051cGarrison Venn llvm::Value *unwindException = builder.CreateExtractValue(caughtResult, 0); 12859cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn llvm::Value *retTypeInfoIndex = builder.CreateExtractValue(caughtResult, 1); 128685500714c460be6452a96be1574d8676d062051cGarrison Venn 12879f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi // FIXME: Redundant storage which, beyond utilizing value of 12889f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi // caughtResultStore for unwindException storage, may be alleviated 1289d9b0b025612992a0b724eeca8bdf10b1d7a5c355Benjamin Kramer // altogether with a block rearrangement 12909cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn builder.CreateStore(caughtResult, caughtResultStorage); 129185500714c460be6452a96be1574d8676d062051cGarrison Venn builder.CreateStore(unwindException, exceptionStorage); 129285500714c460be6452a96be1574d8676d062051cGarrison Venn builder.CreateStore(ourExceptionThrownState, exceptionCaughtFlag); 12939f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 12949f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi // Retrieve exception_class member from thrown exception 1295626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // (_Unwind_Exception instance). This member tells us whether or not 1296626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // the exception is foreign. 12979f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::Value *unwindExceptionClass = 1298626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner builder.CreateLoad(builder.CreateStructGEP( 12999f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi builder.CreatePointerCast(unwindException, 1300b8bce928f4ffdf50eff69334f3e25b27848536b6Micah Villmow ourUnwindExceptionType->getPointerTo()), 1301626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner 0)); 13029f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1303626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Branch to the externalExceptionBlock if the exception is foreign or 1304626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // to a catch router if not. Either way the finally block will be run. 1305626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner builder.CreateCondBr(builder.CreateICmpEQ(unwindExceptionClass, 13069f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::ConstantInt::get(builder.getInt64Ty(), 1307626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner ourBaseExceptionClass)), 1308626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner exceptionRouteBlock, 1309626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner externalExceptionBlock); 13109f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1311626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // External Exception Block 13129f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1313626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner builder.SetInsertPoint(externalExceptionBlock); 13149f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 13159f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi generateStringPrint(context, 1316626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner module, 13179f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi builder, 1318626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner "Gen: Foreign exception received.\n", 1319626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner USE_GLOBAL_STR_CONSTS); 13209f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1321626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Branch to the finally block 1322626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner builder.CreateBr(finallyBlock); 13239f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1324626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Exception Route Block 13259f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1326626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner builder.SetInsertPoint(exceptionRouteBlock); 13279f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 13289f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi // Casts exception pointer (_Unwind_Exception instance) to parent 1329626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // (OurException instance). 1330626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // 1331626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Note: ourBaseFromUnwindOffset is usually negative 13329cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn llvm::Value *typeInfoThrown = builder.CreatePointerCast( 13339cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn builder.CreateConstGEP1_64(unwindException, 1334626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner ourBaseFromUnwindOffset), 13359cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn ourExceptionType->getPointerTo()); 13369f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1337626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Retrieve thrown exception type info type 1338626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // 1339626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Note: Index is not relative to pointer but instead to structure 1340626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // unlike a true getelementptr (GEP) instruction 1341626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner typeInfoThrown = builder.CreateStructGEP(typeInfoThrown, 0); 13429f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 13439f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::Value *typeInfoThrownType = 1344626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner builder.CreateStructGEP(typeInfoThrown, 0); 13459f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 13469f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi generateIntegerPrint(context, 1347626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner module, 13489f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi builder, 13499f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi *toPrint32Int, 1350626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner *(builder.CreateLoad(typeInfoThrownType)), 13519f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi "Gen: Exception type <%d> received (stack unwound) " 13529f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi " in " + 13539f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi ourId + 1354626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner ".\n", 1355626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner USE_GLOBAL_STR_CONSTS); 13569f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1357626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Route to matched type info catch block or run cleanup finally block 13589f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::SwitchInst *switchToCatchBlock = builder.CreateSwitch(retTypeInfoIndex, 13599f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi finallyBlock, 13609cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn numExceptionsToCatch); 13619f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1362626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner unsigned nextTypeToCatch; 13639f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1364626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner for (unsigned i = 1; i <= numExceptionsToCatch; ++i) { 1365626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner nextTypeToCatch = i - 1; 1366626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner switchToCatchBlock->addCase(llvm::ConstantInt::get( 1367626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner llvm::Type::getInt32Ty(context), i), 1368626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner catchBlocks[nextTypeToCatch]); 1369626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 137085500714c460be6452a96be1574d8676d062051cGarrison Venn 1371626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner llvm::verifyFunction(*ret); 1372626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fpm.run(*ret); 13739f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1374626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner return(ret); 1375626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner} 1376626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner 1377626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner 1378626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner/// Generates function which throws either an exception matched to a runtime 13799f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// determined type info type (argument to generated function), or if this 13809f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// runtime value matches nativeThrowType, throws a foreign exception by 1381626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner/// calling nativeThrowFunct. 1382626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner/// @param module code for module instance 1383626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner/// @param builder builder instance 13849f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// @param fpm a function pass manager holding optional IR to IR 1385a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// transformations 1386a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param ourId id used to printing purposes 1387a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param nativeThrowType a runtime argument of this value results in 1388a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// nativeThrowFunct being called to generate/throw exception. 1389a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param nativeThrowFunct function which will throw a foreign exception 1390a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// if the above nativeThrowType matches generated function's arg. 1391a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @returns generated function 1392a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennstatic 13939f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumillvm::Function *createThrowExceptionFunction(llvm::Module &module, 13949f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::IRBuilder<> &builder, 139564cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn llvm::FunctionPassManager &fpm, 1396626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner std::string ourId, 1397626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner int32_t nativeThrowType, 139864cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn llvm::Function &nativeThrowFunct) { 139964cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn llvm::LLVMContext &context = module.getContext(); 1400626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner namedValues.clear(); 1401626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner ArgTypes unwindArgTypes; 1402c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn unwindArgTypes.push_back(builder.getInt32Ty()); 1403626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner ArgNames unwindArgNames; 1404626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner unwindArgNames.push_back("exceptTypeToThrow"); 14059f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1406626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner llvm::Function *ret = createFunction(module, 1407626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner builder.getVoidTy(), 1408626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner unwindArgTypes, 1409626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner unwindArgNames, 1410626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner ourId, 1411626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner llvm::Function::ExternalLinkage, 1412626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner false, 1413626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner false); 14149f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1415626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Throws either one of our exception or a native C++ exception depending 1416626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // on a runtime argument value containing a type info type. 1417626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner llvm::BasicBlock *entryBlock = llvm::BasicBlock::Create(context, 14189f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi "entry", 1419626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner ret); 1420626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Throws a foreign exception 14219cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn llvm::BasicBlock *nativeThrowBlock = llvm::BasicBlock::Create(context, 14229f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi "nativeThrow", 14239cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn ret); 1424626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Throws one of our Exceptions 14259cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn llvm::BasicBlock *generatedThrowBlock = llvm::BasicBlock::Create(context, 14269f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi "generatedThrow", 14279cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn ret); 1428626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Retrieved runtime type info type to throw 142964cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn llvm::Value *exceptionType = namedValues["exceptTypeToThrow"]; 14309f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1431626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // nativeThrowBlock block 14329f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1433626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner builder.SetInsertPoint(nativeThrowBlock); 14349f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1435626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Throws foreign exception 1436626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner builder.CreateCall(&nativeThrowFunct, exceptionType); 1437626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner builder.CreateUnreachable(); 14389f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1439626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // entry block 14409f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1441626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner builder.SetInsertPoint(entryBlock); 14429f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1443626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner llvm::Function *toPrint32Int = module.getFunction("print32Int"); 14449f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi generateIntegerPrint(context, 1445626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner module, 14469f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi builder, 14479f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi *toPrint32Int, 14489f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi *exceptionType, 14499f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi "\nGen: About to throw exception type <%d> in " + 14509f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi ourId + 1451626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner ".\n", 1452626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner USE_GLOBAL_STR_CONSTS); 14539f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1454626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Switches on runtime type info type value to determine whether or not 14559f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi // a foreign exception is thrown. Defaults to throwing one of our 1456626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // generated exceptions. 145764cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn llvm::SwitchInst *theSwitch = builder.CreateSwitch(exceptionType, 1458626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner generatedThrowBlock, 1459626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner 1); 14609f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 14619f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi theSwitch->addCase(llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), 1462626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner nativeThrowType), 1463626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner nativeThrowBlock); 14649f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1465626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // generatedThrow block 14669f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1467626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner builder.SetInsertPoint(generatedThrowBlock); 14689f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 14699cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn llvm::Function *createOurException = module.getFunction("createOurException"); 14709cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn llvm::Function *raiseOurException = module.getFunction( 14719cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn "_Unwind_RaiseException"); 14729f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1473626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Creates exception to throw with runtime type info type. 14749f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::Value *exception = builder.CreateCall(createOurException, 14759cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn namedValues["exceptTypeToThrow"]); 14769f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1477626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Throw generated Exception 1478626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner builder.CreateCall(raiseOurException, exception); 1479626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner builder.CreateUnreachable(); 14809f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1481626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner llvm::verifyFunction(*ret); 1482626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fpm.run(*ret); 14839f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1484626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner return(ret); 1485a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn} 1486a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 1487a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennstatic void createStandardUtilityFunctions(unsigned numTypeInfos, 14889f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::Module &module, 148964cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn llvm::IRBuilder<> &builder); 1490a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 14919f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// Creates test code by generating and organizing these functions into the 1492a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// test case. The test case consists of an outer function setup to invoke 14939f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// an inner function within an environment having multiple catch and single 1494a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// finally blocks. This inner function is also setup to invoke a throw 14959f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// function within an evironment similar in nature to the outer function's 1496a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// catch and finally blocks. Each of these two functions catch mutually 1497a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// exclusive subsets (even or odd) of the type info types configured 1498a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// for this this. All generated functions have a runtime argument which 1499a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// holds a type info type to throw that each function takes and passes it 1500a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// to the inner one if such a inner function exists. This type info type is 1501a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// looked at by the generated throw function to see whether or not it should 1502a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// throw a generated exception with the same type info type, or instead call 1503a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// a supplied a function which in turn will throw a foreign exception. 1504a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param module code for module instance 1505a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param builder builder instance 15069f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// @param fpm a function pass manager holding optional IR to IR 1507a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// transformations 1508a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param nativeThrowFunctName name of external function which will throw 1509a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// a foreign exception 1510a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @returns outermost generated test function. 15119f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumillvm::Function *createUnwindExceptionTest(llvm::Module &module, 15129f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::IRBuilder<> &builder, 151364cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn llvm::FunctionPassManager &fpm, 1514a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn std::string nativeThrowFunctName) { 1515626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Number of type infos to generate 1516626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner unsigned numTypeInfos = 6; 15179f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1518626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Initialze intrisics and external functions to use along with exception 1519626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // and type info globals. 1520626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner createStandardUtilityFunctions(numTypeInfos, 1521626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner module, 1522626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner builder); 15239cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn llvm::Function *nativeThrowFunct = module.getFunction(nativeThrowFunctName); 15249f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 15259f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi // Create exception throw function using the value ~0 to cause 1526626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // foreign exceptions to be thrown. 15279cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn llvm::Function *throwFunct = createThrowExceptionFunction(module, 15289cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn builder, 15299cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn fpm, 15309cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn "throwFunct", 15319cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn ~0, 15329cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn *nativeThrowFunct); 1533626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Inner function will catch even type infos 1534626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner unsigned innerExceptionTypesToCatch[] = {6, 2, 4}; 15359f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi size_t numExceptionTypesToCatch = sizeof(innerExceptionTypesToCatch) / 15369cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn sizeof(unsigned); 15379f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1538626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Generate inner function. 15399cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn llvm::Function *innerCatchFunct = createCatchWrappedInvokeFunction(module, 15409cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn builder, 15419cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn fpm, 15429cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn *throwFunct, 15439cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn "innerCatchFunct", 15449cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn numExceptionTypesToCatch, 15459cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn innerExceptionTypesToCatch); 15469f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1547626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Outer function will catch odd type infos 1548626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner unsigned outerExceptionTypesToCatch[] = {3, 1, 5}; 15499f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi numExceptionTypesToCatch = sizeof(outerExceptionTypesToCatch) / 1550626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner sizeof(unsigned); 15519f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1552626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Generate outer function 15539cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn llvm::Function *outerCatchFunct = createCatchWrappedInvokeFunction(module, 15549cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn builder, 15559cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn fpm, 15569cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn *innerCatchFunct, 15579cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn "outerCatchFunct", 15589cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn numExceptionTypesToCatch, 15599cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn outerExceptionTypesToCatch); 15609f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1561626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Return outer function to run 1562626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner return(outerCatchFunct); 1563a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn} 1564a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 1565a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 1566a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// Represents our foreign exceptions 1567a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennclass OurCppRunException : public std::runtime_error { 1568a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennpublic: 1569626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner OurCppRunException(const std::string reason) : 1570626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner std::runtime_error(reason) {} 15719f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 157264cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn OurCppRunException (const OurCppRunException &toCopy) : 1573626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner std::runtime_error(toCopy) {} 15749f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 157564cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn OurCppRunException &operator = (const OurCppRunException &toCopy) { 1576626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner return(reinterpret_cast<OurCppRunException&>( 1577626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner std::runtime_error::operator=(toCopy))); 1578626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 15799f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1580626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner ~OurCppRunException (void) throw () {} 1581a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn}; 1582a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 1583a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 1584a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// Throws foreign C++ exception. 1585a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param ignoreIt unused parameter that allows function to match implied 1586a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// generated function contract. 1587a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennextern "C" 1588a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennvoid throwCppException (int32_t ignoreIt) { 1589626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner throw(OurCppRunException("thrown by throwCppException(...)")); 1590a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn} 1591a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 1592a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venntypedef void (*OurExceptionThrowFunctType) (int32_t typeToThrow); 1593a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 15949f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// This is a test harness which runs test by executing generated 15957a2bdde0a0eebcd2125055e0eacaca040f0b766cChris Lattner/// function with a type info type to throw. Harness wraps the execution 1596a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// of generated function in a C++ try catch clause. 1597a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param engine execution engine to use for executing generated function. 1598a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// This demo program expects this to be a JIT instance for demo 1599a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// purposes. 1600a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param function generated test function to run 1601a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param typeToThrow type info type of generated exception to throw, or 1602a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// indicator to cause foreign exception to be thrown. 1603a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennstatic 16049f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumivoid runExceptionThrow(llvm::ExecutionEngine *engine, 16059f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::Function *function, 1606a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn int32_t typeToThrow) { 16079f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1608626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Find test's function pointer 16099f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi OurExceptionThrowFunctType functPtr = 1610626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner reinterpret_cast<OurExceptionThrowFunctType>( 1611626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner reinterpret_cast<intptr_t>(engine->getPointerToFunction(function))); 16129f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1613626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner try { 1614626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Run test 1615626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner (*functPtr)(typeToThrow); 1616626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 1617626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner catch (OurCppRunException exc) { 1618626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Catch foreign C++ exception 1619626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fprintf(stderr, 1620626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner "\nrunExceptionThrow(...):In C++ catch OurCppRunException " 16219f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi "with reason: %s.\n", 1622626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner exc.what()); 1623626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 1624626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner catch (...) { 16259f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi // Catch all exceptions including our generated ones. This latter 1626113aa8612010434069fc5b5e09f6b2667e03e173Garrison Venn // functionality works according to the example in rules 1.6.4 of 1627a6f10317bf2b90a16a931d0f5260cf3920a28d62Dmitri Gribenko // http://mentorembedded.github.com/cxx-abi/abi-eh.html (v1.22), 16289f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi // given that these will be exceptions foreign to C++ 16299f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi // (the _Unwind_Exception::exception_class should be different from 1630113aa8612010434069fc5b5e09f6b2667e03e173Garrison Venn // the one used by C++). 1631626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fprintf(stderr, 1632626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner "\nrunExceptionThrow(...):In C++ catch all.\n"); 1633626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 1634a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn} 1635a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 1636a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// 1637a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// End test functions 1638a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// 1639a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 16406e6cdd00aaca083779eb70dc238779935da6b9c8Garrison Venntypedef llvm::ArrayRef<llvm::Type*> TypeArray; 1641cad3f77fa8618ac940aa519cd40c403800977273Chris Lattner 16429f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// This initialization routine creates type info globals and 1643a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// adds external function declarations to module. 1644a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param numTypeInfos number of linear type info associated type info types 1645a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// to create as GlobalVariable instances, starting with the value 1. 1646a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param module code for module instance 1647a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param builder builder instance 1648a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennstatic void createStandardUtilityFunctions(unsigned numTypeInfos, 16499f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::Module &module, 165064cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn llvm::IRBuilder<> &builder) { 16519f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 165264cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn llvm::LLVMContext &context = module.getContext(); 16539f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1654626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Exception initializations 16559f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1656626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Setup exception catch state 16579f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi ourExceptionNotThrownState = 16589cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 0), 16599f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi ourExceptionThrownState = 16609cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 1), 16619f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi ourExceptionCaughtState = 16629cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 2), 16639f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 16649f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 16659f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1666626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Create our type info type 16679f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi ourTypeInfoType = llvm::StructType::get(context, 16689cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn TypeArray(builder.getInt32Ty())); 166985500714c460be6452a96be1574d8676d062051cGarrison Venn 167085500714c460be6452a96be1574d8676d062051cGarrison Venn llvm::Type *caughtResultFieldTypes[] = { 167185500714c460be6452a96be1574d8676d062051cGarrison Venn builder.getInt8PtrTy(), 167285500714c460be6452a96be1574d8676d062051cGarrison Venn builder.getInt32Ty() 167385500714c460be6452a96be1574d8676d062051cGarrison Venn }; 167485500714c460be6452a96be1574d8676d062051cGarrison Venn 167585500714c460be6452a96be1574d8676d062051cGarrison Venn // Create our landingpad result type 167685500714c460be6452a96be1574d8676d062051cGarrison Venn ourCaughtResultType = llvm::StructType::get(context, 167785500714c460be6452a96be1574d8676d062051cGarrison Venn TypeArray(caughtResultFieldTypes)); 167885500714c460be6452a96be1574d8676d062051cGarrison Venn 1679626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Create OurException type 16809f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi ourExceptionType = llvm::StructType::get(context, 1681626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner TypeArray(ourTypeInfoType)); 16829f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1683626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Create portion of _Unwind_Exception type 1684626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // 1685626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Note: Declaring only a portion of the _Unwind_Exception struct. 1686626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Does this cause problems? 1687626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner ourUnwindExceptionType = 16889f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::StructType::get(context, 1689c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn TypeArray(builder.getInt64Ty())); 16906e6cdd00aaca083779eb70dc238779935da6b9c8Garrison Venn 1691626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner struct OurBaseException_t dummyException; 16929f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1693626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Calculate offset of OurException::unwindException member. 16949f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi ourBaseFromUnwindOffset = ((uintptr_t) &dummyException) - 16959cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn ((uintptr_t) &(dummyException.unwindException)); 16969f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1697a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#ifdef DEBUG 1698626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fprintf(stderr, 1699626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner "createStandardUtilityFunctions(...):ourBaseFromUnwindOffset " 1700626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner "= %lld, sizeof(struct OurBaseException_t) - " 1701626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner "sizeof(struct _Unwind_Exception) = %lu.\n", 1702626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner ourBaseFromUnwindOffset, 17039f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi sizeof(struct OurBaseException_t) - 1704626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner sizeof(struct _Unwind_Exception)); 1705a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#endif 17069f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1707626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner size_t numChars = sizeof(ourBaseExcpClassChars) / sizeof(char); 17089f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1709626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Create our _Unwind_Exception::exception_class value 1710626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner ourBaseExceptionClass = genClass(ourBaseExcpClassChars, numChars); 17119f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1712626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Type infos 17139f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1714626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner std::string baseStr = "typeInfo", typeInfoName; 1715626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner std::ostringstream typeInfoNameBuilder; 1716626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner std::vector<llvm::Constant*> structVals; 17179f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1718626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner llvm::Constant *nextStruct; 17199f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1720626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Generate each type info 1721626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // 1722626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Note: First type info is not used. 1723626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner for (unsigned i = 0; i <= numTypeInfos; ++i) { 1724626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner structVals.clear(); 1725626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner structVals.push_back(llvm::ConstantInt::get(builder.getInt32Ty(), i)); 1726626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner nextStruct = llvm::ConstantStruct::get(ourTypeInfoType, structVals); 17279f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1728626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner typeInfoNameBuilder.str(""); 1729626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner typeInfoNameBuilder << baseStr << i; 1730626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner typeInfoName = typeInfoNameBuilder.str(); 17319f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1732626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Note: Does not seem to work without allocation 17339f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi new llvm::GlobalVariable(module, 17349f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi ourTypeInfoType, 17359f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi true, 17369f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::GlobalValue::ExternalLinkage, 17379f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi nextStruct, 1738626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner typeInfoName); 17399f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1740626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner ourTypeInfoNames.push_back(typeInfoName); 1741626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner ourTypeInfoNamesIndex[i] = typeInfoName; 1742626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 17439f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1744626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner ArgNames argNames; 1745626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner ArgTypes argTypes; 174664cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn llvm::Function *funct = NULL; 17479f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1748626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // print32Int 17499f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 175077613d4135d5fc8461d0583837b5b850c4a29ecdChris Lattner llvm::Type *retType = builder.getVoidTy(); 17519f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1752626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner argTypes.clear(); 1753c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn argTypes.push_back(builder.getInt32Ty()); 1754c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn argTypes.push_back(builder.getInt8PtrTy()); 17559f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1756626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner argNames.clear(); 17579f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 17589f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi createFunction(module, 17599f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi retType, 17609f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi argTypes, 17619f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi argNames, 17629f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi "print32Int", 17639f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::Function::ExternalLinkage, 17649f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi true, 1765626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner false); 17669f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1767626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // print64Int 17689f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1769626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner retType = builder.getVoidTy(); 17709f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1771626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner argTypes.clear(); 1772c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn argTypes.push_back(builder.getInt64Ty()); 1773c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn argTypes.push_back(builder.getInt8PtrTy()); 17749f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1775626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner argNames.clear(); 17769f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 17779f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi createFunction(module, 17789f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi retType, 17799f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi argTypes, 17809f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi argNames, 17819f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi "print64Int", 17829f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::Function::ExternalLinkage, 17839f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi true, 1784626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner false); 17859f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1786626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // printStr 17879f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1788626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner retType = builder.getVoidTy(); 17899f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1790626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner argTypes.clear(); 1791c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn argTypes.push_back(builder.getInt8PtrTy()); 17929f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1793626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner argNames.clear(); 17949f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 17959f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi createFunction(module, 17969f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi retType, 17979f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi argTypes, 17989f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi argNames, 17999f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi "printStr", 18009f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::Function::ExternalLinkage, 18019f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi true, 1802626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner false); 18039f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1804626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // throwCppException 18059f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1806626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner retType = builder.getVoidTy(); 18079f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1808626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner argTypes.clear(); 1809c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn argTypes.push_back(builder.getInt32Ty()); 18109f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1811626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner argNames.clear(); 18129f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 18139f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi createFunction(module, 18149f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi retType, 18159f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi argTypes, 18169f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi argNames, 18179f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi "throwCppException", 18189f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::Function::ExternalLinkage, 18199f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi true, 1820626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner false); 18219f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1822626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // deleteOurException 18239f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1824626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner retType = builder.getVoidTy(); 18259f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1826626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner argTypes.clear(); 1827c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn argTypes.push_back(builder.getInt8PtrTy()); 18289f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1829626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner argNames.clear(); 18309f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 18319f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi createFunction(module, 18329f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi retType, 18339f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi argTypes, 18349f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi argNames, 18359f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi "deleteOurException", 18369f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::Function::ExternalLinkage, 18379f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi true, 1838626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner false); 18399f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1840626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // createOurException 18419f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1842c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn retType = builder.getInt8PtrTy(); 18439f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1844626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner argTypes.clear(); 1845c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn argTypes.push_back(builder.getInt32Ty()); 18469f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1847626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner argNames.clear(); 18489f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 18499f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi createFunction(module, 18509f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi retType, 18519f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi argTypes, 18529f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi argNames, 18539f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi "createOurException", 18549f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::Function::ExternalLinkage, 18559f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi true, 1856626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner false); 18579f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1858626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // _Unwind_RaiseException 18599f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1860626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner retType = builder.getInt32Ty(); 18619f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1862626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner argTypes.clear(); 1863c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn argTypes.push_back(builder.getInt8PtrTy()); 18649f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1865626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner argNames.clear(); 18669f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 18679f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi funct = createFunction(module, 18689f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi retType, 18699f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi argTypes, 18709f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi argNames, 18719f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi "_Unwind_RaiseException", 18729f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::Function::ExternalLinkage, 18739f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi true, 1874626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner false); 18759f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 18764c856ee1f8672de5da97d73c05687420eb0049e2NAKAMURA Takumi funct->setDoesNotReturn(); 18779f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1878626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // _Unwind_Resume 18799f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1880626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner retType = builder.getInt32Ty(); 18819f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1882626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner argTypes.clear(); 1883c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn argTypes.push_back(builder.getInt8PtrTy()); 18849f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1885626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner argNames.clear(); 18869f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 18879f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi funct = createFunction(module, 18889f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi retType, 18899f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi argTypes, 18909f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi argNames, 18919f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi "_Unwind_Resume", 18929f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::Function::ExternalLinkage, 18939f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi true, 1894626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner false); 18959f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 18964c856ee1f8672de5da97d73c05687420eb0049e2NAKAMURA Takumi funct->setDoesNotReturn(); 18979f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1898626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // ourPersonality 18999f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1900626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner retType = builder.getInt32Ty(); 19019f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1902626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner argTypes.clear(); 1903c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn argTypes.push_back(builder.getInt32Ty()); 1904c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn argTypes.push_back(builder.getInt32Ty()); 1905c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn argTypes.push_back(builder.getInt64Ty()); 1906c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn argTypes.push_back(builder.getInt8PtrTy()); 1907c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn argTypes.push_back(builder.getInt8PtrTy()); 19089f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1909626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner argNames.clear(); 19109f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 19119f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi createFunction(module, 19129f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi retType, 19139f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi argTypes, 19149f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi argNames, 19159f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi "ourPersonality", 19169f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::Function::ExternalLinkage, 19179f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi true, 1918626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner false); 19199f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1920626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // llvm.eh.typeid.for intrinsic 19219f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1922626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner getDeclaration(&module, llvm::Intrinsic::eh_typeid_for); 1923a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn} 1924a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 1925a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 1926626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner//===----------------------------------------------------------------------===// 1927a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// Main test driver code. 1928626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner//===----------------------------------------------------------------------===// 1929a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn 1930a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// Demo main routine which takes the type info types to throw. A test will 19319f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// be run for each given type info type. While type info types with the value 1932a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// of -1 will trigger a foreign C++ exception to be thrown; type info types 1933a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// <= 6 and >= 1 will be caught by test functions; and type info types > 6 1934a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// will result in exceptions which pass through to the test harness. All other 1935a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// type info types are not supported and could cause a crash. 193664cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Vennint main(int argc, char *argv[]) { 1937626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner if (argc == 1) { 1938626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fprintf(stderr, 1939626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner "\nUsage: ExceptionDemo <exception type to throw> " 1940626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner "[<type 2>...<type n>].\n" 1941626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner " Each type must have the value of 1 - 6 for " 1942626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner "generated exceptions to be caught;\n" 1943626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner " the value -1 for foreign C++ exceptions to be " 1944626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner "generated and thrown;\n" 1945626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner " or the values > 6 for exceptions to be ignored.\n" 1946626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner "\nTry: ExceptionDemo 2 3 7 -1\n" 1947626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner " for a full test.\n\n"); 1948626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner return(0); 1949626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 19509f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1951626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // If not set, exception handling will not be turned on 1952d40e103ea5bca8a223fc8261b3322b9454e9af12Peter Collingbourne llvm::TargetOptions Opts; 19539f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1954626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner llvm::InitializeNativeTarget(); 1955c8b9551a8fe52cefbefeac820c81996281fff4e5Rafael Espindola llvm::InitializeNativeTargetAsmPrinter(); 195664cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn llvm::LLVMContext &context = llvm::getGlobalContext(); 1957626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner llvm::IRBuilder<> theBuilder(context); 19589f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1959626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Make the module, which holds all the code. 196064cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn llvm::Module *module = new llvm::Module("my cool jit", context); 19619f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 19623c2b0e171f02f2bd0c2506101a1d6e66d7e9bdeeNAKAMURA Takumi llvm::RTDyldMemoryManager *MemMgr = new llvm::SectionMemoryManager(); 1963c8b9551a8fe52cefbefeac820c81996281fff4e5Rafael Espindola 1964626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Build engine with JIT 1965626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner llvm::EngineBuilder factory(module); 1966626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner factory.setEngineKind(llvm::EngineKind::JIT); 1967626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner factory.setAllocateGVsWithCode(false); 1968d40e103ea5bca8a223fc8261b3322b9454e9af12Peter Collingbourne factory.setTargetOptions(Opts); 19693c2b0e171f02f2bd0c2506101a1d6e66d7e9bdeeNAKAMURA Takumi factory.setMCJITMemoryManager(MemMgr); 1970c8b9551a8fe52cefbefeac820c81996281fff4e5Rafael Espindola factory.setUseMCJIT(true); 197164cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn llvm::ExecutionEngine *executionEngine = factory.create(); 19729f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1973626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner { 1974626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner llvm::FunctionPassManager fpm(module); 19759f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 19769f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi // Set up the optimizer pipeline. 1977626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Start with registering info about how the 1978626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // target lays out data structures. 19792b4b44e0d2e95fc695eafcc4d192fe1ae261e01eMicah Villmow fpm.add(new llvm::DataLayout(*executionEngine->getDataLayout())); 19809f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1981626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Optimizations turned on 1982a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#ifdef ADD_OPT_PASSES 19839f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1984626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Basic AliasAnslysis support for GVN. 1985626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fpm.add(llvm::createBasicAliasAnalysisPass()); 19869f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1987626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Promote allocas to registers. 1988626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fpm.add(llvm::createPromoteMemoryToRegisterPass()); 19899f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1990626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Do simple "peephole" optimizations and bit-twiddling optzns. 1991626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fpm.add(llvm::createInstructionCombiningPass()); 19929f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1993626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Reassociate expressions. 1994626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fpm.add(llvm::createReassociatePass()); 19959f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 1996626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Eliminate Common SubExpressions. 1997626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fpm.add(llvm::createGVNPass()); 19989f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 19999f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi // Simplify the control flow graph (deleting unreachable 2000626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // blocks, etc). 2001626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fpm.add(llvm::createCFGSimplificationPass()); 2002a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#endif // ADD_OPT_PASSES 20039f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 2004626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fpm.doInitialization(); 20059f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 2006626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Generate test code using function throwCppException(...) as 2007626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // the function which throws foreign exceptions. 20089f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi llvm::Function *toRun = 20099f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi createUnwindExceptionTest(*module, 20109f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi theBuilder, 201185500714c460be6452a96be1574d8676d062051cGarrison Venn fpm, 201285500714c460be6452a96be1574d8676d062051cGarrison Venn "throwCppException"); 20139f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 2014c8b9551a8fe52cefbefeac820c81996281fff4e5Rafael Espindola executionEngine->finalizeObject(); 2015c8b9551a8fe52cefbefeac820c81996281fff4e5Rafael Espindola 2016626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fprintf(stderr, "\nBegin module dump:\n\n"); 20179f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 2018626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner module->dump(); 20199f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 2020626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fprintf(stderr, "\nEnd module dump:\n"); 20219f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 2022626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fprintf(stderr, "\n\nBegin Test:\n"); 20239f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 2024626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner for (int i = 1; i < argc; ++i) { 2025626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // Run test for each argument whose value is the exception 2026626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner // type to throw. 20279f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi runExceptionThrow(executionEngine, 20289f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi toRun, 2029626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner (unsigned) strtoul(argv[i], NULL, 10)); 2030626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner } 20319f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 2032626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner fprintf(stderr, "\nEnd Test:\n\n"); 20339f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi } 20349f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 2035626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner delete executionEngine; 20369f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi 2037626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner return 0; 2038a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn} 2039