xref: /aosp_15_r20/external/llvm/examples/ExceptionDemo/ExceptionDemo.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- ExceptionDemo.cpp - An example using llvm Exceptions --------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // Demo program which implements an example LLVM exception implementation, and
11*9880d681SAndroid Build Coastguard Worker // shows several test cases including the handling of foreign exceptions.
12*9880d681SAndroid Build Coastguard Worker // It is run with type info types arguments to throw. A test will
13*9880d681SAndroid Build Coastguard Worker // be run for each given type info type. While type info types with the value
14*9880d681SAndroid Build Coastguard Worker // of -1 will trigger a foreign C++ exception to be thrown; type info types
15*9880d681SAndroid Build Coastguard Worker // <= 6 and >= 1 will cause the associated generated exceptions to be thrown
16*9880d681SAndroid Build Coastguard Worker // and caught by generated test functions; and type info types > 6
17*9880d681SAndroid Build Coastguard Worker // will result in exceptions which pass through to the test harness. All other
18*9880d681SAndroid Build Coastguard Worker // type info types are not supported and could cause a crash. In all cases,
19*9880d681SAndroid Build Coastguard Worker // the "finally" blocks of every generated test functions will executed
20*9880d681SAndroid Build Coastguard Worker // regardless of whether or not that test function ignores or catches the
21*9880d681SAndroid Build Coastguard Worker // thrown exception.
22*9880d681SAndroid Build Coastguard Worker //
23*9880d681SAndroid Build Coastguard Worker // examples:
24*9880d681SAndroid Build Coastguard Worker //
25*9880d681SAndroid Build Coastguard Worker // ExceptionDemo
26*9880d681SAndroid Build Coastguard Worker //
27*9880d681SAndroid Build Coastguard Worker //     causes a usage to be printed to stderr
28*9880d681SAndroid Build Coastguard Worker //
29*9880d681SAndroid Build Coastguard Worker // ExceptionDemo 2 3 7 -1
30*9880d681SAndroid Build Coastguard Worker //
31*9880d681SAndroid Build Coastguard Worker //     results in the following cases:
32*9880d681SAndroid Build Coastguard Worker //         - Value 2 causes an exception with a type info type of 2 to be
33*9880d681SAndroid Build Coastguard Worker //           thrown and caught by an inner generated test function.
34*9880d681SAndroid Build Coastguard Worker //         - Value 3 causes an exception with a type info type of 3 to be
35*9880d681SAndroid Build Coastguard Worker //           thrown and caught by an outer generated test function.
36*9880d681SAndroid Build Coastguard Worker //         - Value 7 causes an exception with a type info type of 7 to be
37*9880d681SAndroid Build Coastguard Worker //           thrown and NOT be caught by any generated function.
38*9880d681SAndroid Build Coastguard Worker //         - Value -1 causes a foreign C++ exception to be thrown and not be
39*9880d681SAndroid Build Coastguard Worker //           caught by any generated function
40*9880d681SAndroid Build Coastguard Worker //
41*9880d681SAndroid Build Coastguard Worker //     Cases -1 and 7 are caught by a C++ test harness where the validity of
42*9880d681SAndroid Build Coastguard Worker //         of a C++ catch(...) clause catching a generated exception with a
43*9880d681SAndroid Build Coastguard Worker //         type info type of 7 is explained by: example in rules 1.6.4 in
44*9880d681SAndroid Build Coastguard Worker //         http://mentorembedded.github.com/cxx-abi/abi-eh.html (v1.22)
45*9880d681SAndroid Build Coastguard Worker //
46*9880d681SAndroid Build Coastguard Worker // This code uses code from the llvm compiler-rt project and the llvm
47*9880d681SAndroid Build Coastguard Worker // Kaleidoscope project.
48*9880d681SAndroid Build Coastguard Worker //
49*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
50*9880d681SAndroid Build Coastguard Worker 
51*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/STLExtras.h"
52*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Verifier.h"
53*9880d681SAndroid Build Coastguard Worker #include "llvm/ExecutionEngine/MCJIT.h"
54*9880d681SAndroid Build Coastguard Worker #include "llvm/ExecutionEngine/SectionMemoryManager.h"
55*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/DataLayout.h"
56*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/DerivedTypes.h"
57*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/IRBuilder.h"
58*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Intrinsics.h"
59*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/LLVMContext.h"
60*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/LegacyPassManager.h"
61*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Module.h"
62*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Dwarf.h"
63*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/TargetSelect.h"
64*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetOptions.h"
65*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/Scalar.h"
66*9880d681SAndroid Build Coastguard Worker 
67*9880d681SAndroid Build Coastguard Worker // FIXME: Although all systems tested with (Linux, OS X), do not need this
68*9880d681SAndroid Build Coastguard Worker //        header file included. A user on ubuntu reported, undefined symbols
69*9880d681SAndroid Build Coastguard Worker //        for stderr, and fprintf, and the addition of this include fixed the
70*9880d681SAndroid Build Coastguard Worker //        issue for them. Given that LLVM's best practices include the goal
71*9880d681SAndroid Build Coastguard Worker //        of reducing the number of redundant header files included, the
72*9880d681SAndroid Build Coastguard Worker //        correct solution would be to find out why these symbols are not
73*9880d681SAndroid Build Coastguard Worker //        defined for the system in question, and fix the issue by finding out
74*9880d681SAndroid Build Coastguard Worker //        which LLVM header file, if any, would include these symbols.
75*9880d681SAndroid Build Coastguard Worker #include <cstdio>
76*9880d681SAndroid Build Coastguard Worker 
77*9880d681SAndroid Build Coastguard Worker #include <sstream>
78*9880d681SAndroid Build Coastguard Worker #include <stdexcept>
79*9880d681SAndroid Build Coastguard Worker 
80*9880d681SAndroid Build Coastguard Worker #include <inttypes.h>
81*9880d681SAndroid Build Coastguard Worker 
82*9880d681SAndroid Build Coastguard Worker #ifndef USE_GLOBAL_STR_CONSTS
83*9880d681SAndroid Build Coastguard Worker #define USE_GLOBAL_STR_CONSTS true
84*9880d681SAndroid Build Coastguard Worker #endif
85*9880d681SAndroid Build Coastguard Worker 
86*9880d681SAndroid Build Coastguard Worker // System C++ ABI unwind types from:
87*9880d681SAndroid Build Coastguard Worker //     http://mentorembedded.github.com/cxx-abi/abi-eh.html (v1.22)
88*9880d681SAndroid Build Coastguard Worker 
89*9880d681SAndroid Build Coastguard Worker extern "C" {
90*9880d681SAndroid Build Coastguard Worker 
91*9880d681SAndroid Build Coastguard Worker   typedef enum {
92*9880d681SAndroid Build Coastguard Worker     _URC_NO_REASON = 0,
93*9880d681SAndroid Build Coastguard Worker     _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
94*9880d681SAndroid Build Coastguard Worker     _URC_FATAL_PHASE2_ERROR = 2,
95*9880d681SAndroid Build Coastguard Worker     _URC_FATAL_PHASE1_ERROR = 3,
96*9880d681SAndroid Build Coastguard Worker     _URC_NORMAL_STOP = 4,
97*9880d681SAndroid Build Coastguard Worker     _URC_END_OF_STACK = 5,
98*9880d681SAndroid Build Coastguard Worker     _URC_HANDLER_FOUND = 6,
99*9880d681SAndroid Build Coastguard Worker     _URC_INSTALL_CONTEXT = 7,
100*9880d681SAndroid Build Coastguard Worker     _URC_CONTINUE_UNWIND = 8
101*9880d681SAndroid Build Coastguard Worker   } _Unwind_Reason_Code;
102*9880d681SAndroid Build Coastguard Worker 
103*9880d681SAndroid Build Coastguard Worker   typedef enum {
104*9880d681SAndroid Build Coastguard Worker     _UA_SEARCH_PHASE = 1,
105*9880d681SAndroid Build Coastguard Worker     _UA_CLEANUP_PHASE = 2,
106*9880d681SAndroid Build Coastguard Worker     _UA_HANDLER_FRAME = 4,
107*9880d681SAndroid Build Coastguard Worker     _UA_FORCE_UNWIND = 8,
108*9880d681SAndroid Build Coastguard Worker     _UA_END_OF_STACK = 16
109*9880d681SAndroid Build Coastguard Worker   } _Unwind_Action;
110*9880d681SAndroid Build Coastguard Worker 
111*9880d681SAndroid Build Coastguard Worker   struct _Unwind_Exception;
112*9880d681SAndroid Build Coastguard Worker 
113*9880d681SAndroid Build Coastguard Worker   typedef void (*_Unwind_Exception_Cleanup_Fn) (_Unwind_Reason_Code,
114*9880d681SAndroid Build Coastguard Worker                                                 struct _Unwind_Exception *);
115*9880d681SAndroid Build Coastguard Worker 
116*9880d681SAndroid Build Coastguard Worker   struct _Unwind_Exception {
117*9880d681SAndroid Build Coastguard Worker     uint64_t exception_class;
118*9880d681SAndroid Build Coastguard Worker     _Unwind_Exception_Cleanup_Fn exception_cleanup;
119*9880d681SAndroid Build Coastguard Worker 
120*9880d681SAndroid Build Coastguard Worker     uintptr_t private_1;
121*9880d681SAndroid Build Coastguard Worker     uintptr_t private_2;
122*9880d681SAndroid Build Coastguard Worker 
123*9880d681SAndroid Build Coastguard Worker     // @@@ The IA-64 ABI says that this structure must be double-word aligned.
124*9880d681SAndroid Build Coastguard Worker     //  Taking that literally does not make much sense generically.  Instead
125*9880d681SAndroid Build Coastguard Worker     //  we provide the maximum alignment required by any type for the machine.
126*9880d681SAndroid Build Coastguard Worker   } __attribute__((__aligned__));
127*9880d681SAndroid Build Coastguard Worker 
128*9880d681SAndroid Build Coastguard Worker   struct _Unwind_Context;
129*9880d681SAndroid Build Coastguard Worker   typedef struct _Unwind_Context *_Unwind_Context_t;
130*9880d681SAndroid Build Coastguard Worker 
131*9880d681SAndroid Build Coastguard Worker   extern const uint8_t *_Unwind_GetLanguageSpecificData (_Unwind_Context_t c);
132*9880d681SAndroid Build Coastguard Worker   extern uintptr_t _Unwind_GetGR (_Unwind_Context_t c, int i);
133*9880d681SAndroid Build Coastguard Worker   extern void _Unwind_SetGR (_Unwind_Context_t c, int i, uintptr_t n);
134*9880d681SAndroid Build Coastguard Worker   extern void _Unwind_SetIP (_Unwind_Context_t, uintptr_t new_value);
135*9880d681SAndroid Build Coastguard Worker   extern uintptr_t _Unwind_GetIP (_Unwind_Context_t context);
136*9880d681SAndroid Build Coastguard Worker   extern uintptr_t _Unwind_GetRegionStart (_Unwind_Context_t context);
137*9880d681SAndroid Build Coastguard Worker 
138*9880d681SAndroid Build Coastguard Worker } // extern "C"
139*9880d681SAndroid Build Coastguard Worker 
140*9880d681SAndroid Build Coastguard Worker //
141*9880d681SAndroid Build Coastguard Worker // Example types
142*9880d681SAndroid Build Coastguard Worker //
143*9880d681SAndroid Build Coastguard Worker 
144*9880d681SAndroid Build Coastguard Worker /// This is our simplistic type info
145*9880d681SAndroid Build Coastguard Worker struct OurExceptionType_t {
146*9880d681SAndroid Build Coastguard Worker   /// type info type
147*9880d681SAndroid Build Coastguard Worker   int type;
148*9880d681SAndroid Build Coastguard Worker };
149*9880d681SAndroid Build Coastguard Worker 
150*9880d681SAndroid Build Coastguard Worker 
151*9880d681SAndroid Build Coastguard Worker /// This is our Exception class which relies on a negative offset to calculate
152*9880d681SAndroid Build Coastguard Worker /// pointers to its instances from pointers to its unwindException member.
153*9880d681SAndroid Build Coastguard Worker ///
154*9880d681SAndroid Build Coastguard Worker /// Note: The above unwind.h defines struct _Unwind_Exception to be aligned
155*9880d681SAndroid Build Coastguard Worker ///       on a double word boundary. This is necessary to match the standard:
156*9880d681SAndroid Build Coastguard Worker ///       http://mentorembedded.github.com/cxx-abi/abi-eh.html
157*9880d681SAndroid Build Coastguard Worker struct OurBaseException_t {
158*9880d681SAndroid Build Coastguard Worker   struct OurExceptionType_t type;
159*9880d681SAndroid Build Coastguard Worker 
160*9880d681SAndroid Build Coastguard Worker   // Note: This is properly aligned in unwind.h
161*9880d681SAndroid Build Coastguard Worker   struct _Unwind_Exception unwindException;
162*9880d681SAndroid Build Coastguard Worker };
163*9880d681SAndroid Build Coastguard Worker 
164*9880d681SAndroid Build Coastguard Worker 
165*9880d681SAndroid Build Coastguard Worker // Note: Not needed since we are C++
166*9880d681SAndroid Build Coastguard Worker typedef struct OurBaseException_t OurException;
167*9880d681SAndroid Build Coastguard Worker typedef struct _Unwind_Exception OurUnwindException;
168*9880d681SAndroid Build Coastguard Worker 
169*9880d681SAndroid Build Coastguard Worker //
170*9880d681SAndroid Build Coastguard Worker // Various globals used to support typeinfo and generatted exceptions in
171*9880d681SAndroid Build Coastguard Worker // general
172*9880d681SAndroid Build Coastguard Worker //
173*9880d681SAndroid Build Coastguard Worker 
174*9880d681SAndroid Build Coastguard Worker static std::map<std::string, llvm::Value*> namedValues;
175*9880d681SAndroid Build Coastguard Worker 
176*9880d681SAndroid Build Coastguard Worker int64_t ourBaseFromUnwindOffset;
177*9880d681SAndroid Build Coastguard Worker 
178*9880d681SAndroid Build Coastguard Worker const unsigned char ourBaseExcpClassChars[] =
179*9880d681SAndroid Build Coastguard Worker {'o', 'b', 'j', '\0', 'b', 'a', 's', '\0'};
180*9880d681SAndroid Build Coastguard Worker 
181*9880d681SAndroid Build Coastguard Worker 
182*9880d681SAndroid Build Coastguard Worker static uint64_t ourBaseExceptionClass = 0;
183*9880d681SAndroid Build Coastguard Worker 
184*9880d681SAndroid Build Coastguard Worker static std::vector<std::string> ourTypeInfoNames;
185*9880d681SAndroid Build Coastguard Worker static std::map<int, std::string> ourTypeInfoNamesIndex;
186*9880d681SAndroid Build Coastguard Worker 
187*9880d681SAndroid Build Coastguard Worker static llvm::StructType *ourTypeInfoType;
188*9880d681SAndroid Build Coastguard Worker static llvm::StructType *ourCaughtResultType;
189*9880d681SAndroid Build Coastguard Worker static llvm::StructType *ourExceptionType;
190*9880d681SAndroid Build Coastguard Worker static llvm::StructType *ourUnwindExceptionType;
191*9880d681SAndroid Build Coastguard Worker 
192*9880d681SAndroid Build Coastguard Worker static llvm::ConstantInt *ourExceptionNotThrownState;
193*9880d681SAndroid Build Coastguard Worker static llvm::ConstantInt *ourExceptionThrownState;
194*9880d681SAndroid Build Coastguard Worker static llvm::ConstantInt *ourExceptionCaughtState;
195*9880d681SAndroid Build Coastguard Worker 
196*9880d681SAndroid Build Coastguard Worker typedef std::vector<std::string> ArgNames;
197*9880d681SAndroid Build Coastguard Worker typedef std::vector<llvm::Type*> ArgTypes;
198*9880d681SAndroid Build Coastguard Worker 
199*9880d681SAndroid Build Coastguard Worker //
200*9880d681SAndroid Build Coastguard Worker // Code Generation Utilities
201*9880d681SAndroid Build Coastguard Worker //
202*9880d681SAndroid Build Coastguard Worker 
203*9880d681SAndroid Build Coastguard Worker /// Utility used to create a function, both declarations and definitions
204*9880d681SAndroid Build Coastguard Worker /// @param module for module instance
205*9880d681SAndroid Build Coastguard Worker /// @param retType function return type
206*9880d681SAndroid Build Coastguard Worker /// @param theArgTypes function's ordered argument types
207*9880d681SAndroid Build Coastguard Worker /// @param theArgNames function's ordered arguments needed if use of this
208*9880d681SAndroid Build Coastguard Worker ///        function corresponds to a function definition. Use empty
209*9880d681SAndroid Build Coastguard Worker ///        aggregate for function declarations.
210*9880d681SAndroid Build Coastguard Worker /// @param functName function name
211*9880d681SAndroid Build Coastguard Worker /// @param linkage function linkage
212*9880d681SAndroid Build Coastguard Worker /// @param declarationOnly for function declarations
213*9880d681SAndroid Build Coastguard Worker /// @param isVarArg function uses vararg arguments
214*9880d681SAndroid Build Coastguard Worker /// @returns function instance
createFunction(llvm::Module & module,llvm::Type * retType,const ArgTypes & theArgTypes,const ArgNames & theArgNames,const std::string & functName,llvm::GlobalValue::LinkageTypes linkage,bool declarationOnly,bool isVarArg)215*9880d681SAndroid Build Coastguard Worker llvm::Function *createFunction(llvm::Module &module,
216*9880d681SAndroid Build Coastguard Worker                                llvm::Type *retType,
217*9880d681SAndroid Build Coastguard Worker                                const ArgTypes &theArgTypes,
218*9880d681SAndroid Build Coastguard Worker                                const ArgNames &theArgNames,
219*9880d681SAndroid Build Coastguard Worker                                const std::string &functName,
220*9880d681SAndroid Build Coastguard Worker                                llvm::GlobalValue::LinkageTypes linkage,
221*9880d681SAndroid Build Coastguard Worker                                bool declarationOnly,
222*9880d681SAndroid Build Coastguard Worker                                bool isVarArg) {
223*9880d681SAndroid Build Coastguard Worker   llvm::FunctionType *functType =
224*9880d681SAndroid Build Coastguard Worker     llvm::FunctionType::get(retType, theArgTypes, isVarArg);
225*9880d681SAndroid Build Coastguard Worker   llvm::Function *ret =
226*9880d681SAndroid Build Coastguard Worker     llvm::Function::Create(functType, linkage, functName, &module);
227*9880d681SAndroid Build Coastguard Worker   if (!ret || declarationOnly)
228*9880d681SAndroid Build Coastguard Worker     return(ret);
229*9880d681SAndroid Build Coastguard Worker 
230*9880d681SAndroid Build Coastguard Worker   namedValues.clear();
231*9880d681SAndroid Build Coastguard Worker   unsigned i = 0;
232*9880d681SAndroid Build Coastguard Worker   for (llvm::Function::arg_iterator argIndex = ret->arg_begin();
233*9880d681SAndroid Build Coastguard Worker        i != theArgNames.size();
234*9880d681SAndroid Build Coastguard Worker        ++argIndex, ++i) {
235*9880d681SAndroid Build Coastguard Worker 
236*9880d681SAndroid Build Coastguard Worker     argIndex->setName(theArgNames[i]);
237*9880d681SAndroid Build Coastguard Worker     namedValues[theArgNames[i]] = argIndex;
238*9880d681SAndroid Build Coastguard Worker   }
239*9880d681SAndroid Build Coastguard Worker 
240*9880d681SAndroid Build Coastguard Worker   return(ret);
241*9880d681SAndroid Build Coastguard Worker }
242*9880d681SAndroid Build Coastguard Worker 
243*9880d681SAndroid Build Coastguard Worker 
244*9880d681SAndroid Build Coastguard Worker /// Create an alloca instruction in the entry block of
245*9880d681SAndroid Build Coastguard Worker /// the parent function.  This is used for mutable variables etc.
246*9880d681SAndroid Build Coastguard Worker /// @param function parent instance
247*9880d681SAndroid Build Coastguard Worker /// @param varName stack variable name
248*9880d681SAndroid Build Coastguard Worker /// @param type stack variable type
249*9880d681SAndroid Build Coastguard Worker /// @param initWith optional constant initialization value
250*9880d681SAndroid Build Coastguard Worker /// @returns AllocaInst instance
createEntryBlockAlloca(llvm::Function & function,const std::string & varName,llvm::Type * type,llvm::Constant * initWith=0)251*9880d681SAndroid Build Coastguard Worker static llvm::AllocaInst *createEntryBlockAlloca(llvm::Function &function,
252*9880d681SAndroid Build Coastguard Worker                                                 const std::string &varName,
253*9880d681SAndroid Build Coastguard Worker                                                 llvm::Type *type,
254*9880d681SAndroid Build Coastguard Worker                                                 llvm::Constant *initWith = 0) {
255*9880d681SAndroid Build Coastguard Worker   llvm::BasicBlock &block = function.getEntryBlock();
256*9880d681SAndroid Build Coastguard Worker   llvm::IRBuilder<> tmp(&block, block.begin());
257*9880d681SAndroid Build Coastguard Worker   llvm::AllocaInst *ret = tmp.CreateAlloca(type, 0, varName.c_str());
258*9880d681SAndroid Build Coastguard Worker 
259*9880d681SAndroid Build Coastguard Worker   if (initWith)
260*9880d681SAndroid Build Coastguard Worker     tmp.CreateStore(initWith, ret);
261*9880d681SAndroid Build Coastguard Worker 
262*9880d681SAndroid Build Coastguard Worker   return(ret);
263*9880d681SAndroid Build Coastguard Worker }
264*9880d681SAndroid Build Coastguard Worker 
265*9880d681SAndroid Build Coastguard Worker 
266*9880d681SAndroid Build Coastguard Worker //
267*9880d681SAndroid Build Coastguard Worker // Code Generation Utilities End
268*9880d681SAndroid Build Coastguard Worker //
269*9880d681SAndroid Build Coastguard Worker 
270*9880d681SAndroid Build Coastguard Worker //
271*9880d681SAndroid Build Coastguard Worker // Runtime C Library functions
272*9880d681SAndroid Build Coastguard Worker //
273*9880d681SAndroid Build Coastguard Worker 
274*9880d681SAndroid Build Coastguard Worker // Note: using an extern "C" block so that static functions can be used
275*9880d681SAndroid Build Coastguard Worker extern "C" {
276*9880d681SAndroid Build Coastguard Worker 
277*9880d681SAndroid Build Coastguard Worker // Note: Better ways to decide on bit width
278*9880d681SAndroid Build Coastguard Worker //
279*9880d681SAndroid Build Coastguard Worker /// Prints a 32 bit number, according to the format, to stderr.
280*9880d681SAndroid Build Coastguard Worker /// @param intToPrint integer to print
281*9880d681SAndroid Build Coastguard Worker /// @param format printf like format to use when printing
print32Int(int intToPrint,const char * format)282*9880d681SAndroid Build Coastguard Worker void print32Int(int intToPrint, const char *format) {
283*9880d681SAndroid Build Coastguard Worker   if (format) {
284*9880d681SAndroid Build Coastguard Worker     // Note: No NULL check
285*9880d681SAndroid Build Coastguard Worker     fprintf(stderr, format, intToPrint);
286*9880d681SAndroid Build Coastguard Worker   }
287*9880d681SAndroid Build Coastguard Worker   else {
288*9880d681SAndroid Build Coastguard Worker     // Note: No NULL check
289*9880d681SAndroid Build Coastguard Worker     fprintf(stderr, "::print32Int(...):NULL arg.\n");
290*9880d681SAndroid Build Coastguard Worker   }
291*9880d681SAndroid Build Coastguard Worker }
292*9880d681SAndroid Build Coastguard Worker 
293*9880d681SAndroid Build Coastguard Worker 
294*9880d681SAndroid Build Coastguard Worker // Note: Better ways to decide on bit width
295*9880d681SAndroid Build Coastguard Worker //
296*9880d681SAndroid Build Coastguard Worker /// Prints a 64 bit number, according to the format, to stderr.
297*9880d681SAndroid Build Coastguard Worker /// @param intToPrint integer to print
298*9880d681SAndroid Build Coastguard Worker /// @param format printf like format to use when printing
print64Int(long int intToPrint,const char * format)299*9880d681SAndroid Build Coastguard Worker void print64Int(long int intToPrint, const char *format) {
300*9880d681SAndroid Build Coastguard Worker   if (format) {
301*9880d681SAndroid Build Coastguard Worker     // Note: No NULL check
302*9880d681SAndroid Build Coastguard Worker     fprintf(stderr, format, intToPrint);
303*9880d681SAndroid Build Coastguard Worker   }
304*9880d681SAndroid Build Coastguard Worker   else {
305*9880d681SAndroid Build Coastguard Worker     // Note: No NULL check
306*9880d681SAndroid Build Coastguard Worker     fprintf(stderr, "::print64Int(...):NULL arg.\n");
307*9880d681SAndroid Build Coastguard Worker   }
308*9880d681SAndroid Build Coastguard Worker }
309*9880d681SAndroid Build Coastguard Worker 
310*9880d681SAndroid Build Coastguard Worker 
311*9880d681SAndroid Build Coastguard Worker /// Prints a C string to stderr
312*9880d681SAndroid Build Coastguard Worker /// @param toPrint string to print
printStr(char * toPrint)313*9880d681SAndroid Build Coastguard Worker void printStr(char *toPrint) {
314*9880d681SAndroid Build Coastguard Worker   if (toPrint) {
315*9880d681SAndroid Build Coastguard Worker     fprintf(stderr, "%s", toPrint);
316*9880d681SAndroid Build Coastguard Worker   }
317*9880d681SAndroid Build Coastguard Worker   else {
318*9880d681SAndroid Build Coastguard Worker     fprintf(stderr, "::printStr(...):NULL arg.\n");
319*9880d681SAndroid Build Coastguard Worker   }
320*9880d681SAndroid Build Coastguard Worker }
321*9880d681SAndroid Build Coastguard Worker 
322*9880d681SAndroid Build Coastguard Worker 
323*9880d681SAndroid Build Coastguard Worker /// Deletes the true previously allocated exception whose address
324*9880d681SAndroid Build Coastguard Worker /// is calculated from the supplied OurBaseException_t::unwindException
325*9880d681SAndroid Build Coastguard Worker /// member address. Handles (ignores), NULL pointers.
326*9880d681SAndroid Build Coastguard Worker /// @param expToDelete exception to delete
deleteOurException(OurUnwindException * expToDelete)327*9880d681SAndroid Build Coastguard Worker void deleteOurException(OurUnwindException *expToDelete) {
328*9880d681SAndroid Build Coastguard Worker #ifdef DEBUG
329*9880d681SAndroid Build Coastguard Worker   fprintf(stderr,
330*9880d681SAndroid Build Coastguard Worker           "deleteOurException(...).\n");
331*9880d681SAndroid Build Coastguard Worker #endif
332*9880d681SAndroid Build Coastguard Worker 
333*9880d681SAndroid Build Coastguard Worker   if (expToDelete &&
334*9880d681SAndroid Build Coastguard Worker       (expToDelete->exception_class == ourBaseExceptionClass)) {
335*9880d681SAndroid Build Coastguard Worker 
336*9880d681SAndroid Build Coastguard Worker     free(((char*) expToDelete) + ourBaseFromUnwindOffset);
337*9880d681SAndroid Build Coastguard Worker   }
338*9880d681SAndroid Build Coastguard Worker }
339*9880d681SAndroid Build Coastguard Worker 
340*9880d681SAndroid Build Coastguard Worker 
341*9880d681SAndroid Build Coastguard Worker /// This function is the struct _Unwind_Exception API mandated delete function
342*9880d681SAndroid Build Coastguard Worker /// used by foreign exception handlers when deleting our exception
343*9880d681SAndroid Build Coastguard Worker /// (OurException), instances.
344*9880d681SAndroid Build Coastguard Worker /// @param reason See @link http://mentorembedded.github.com/cxx-abi/abi-eh.html
345*9880d681SAndroid Build Coastguard Worker /// @unlink
346*9880d681SAndroid Build Coastguard Worker /// @param expToDelete exception instance to delete
deleteFromUnwindOurException(_Unwind_Reason_Code reason,OurUnwindException * expToDelete)347*9880d681SAndroid Build Coastguard Worker void deleteFromUnwindOurException(_Unwind_Reason_Code reason,
348*9880d681SAndroid Build Coastguard Worker                                   OurUnwindException *expToDelete) {
349*9880d681SAndroid Build Coastguard Worker #ifdef DEBUG
350*9880d681SAndroid Build Coastguard Worker   fprintf(stderr,
351*9880d681SAndroid Build Coastguard Worker           "deleteFromUnwindOurException(...).\n");
352*9880d681SAndroid Build Coastguard Worker #endif
353*9880d681SAndroid Build Coastguard Worker 
354*9880d681SAndroid Build Coastguard Worker   deleteOurException(expToDelete);
355*9880d681SAndroid Build Coastguard Worker }
356*9880d681SAndroid Build Coastguard Worker 
357*9880d681SAndroid Build Coastguard Worker 
358*9880d681SAndroid Build Coastguard Worker /// Creates (allocates on the heap), an exception (OurException instance),
359*9880d681SAndroid Build Coastguard Worker /// of the supplied type info type.
360*9880d681SAndroid Build Coastguard Worker /// @param type type info type
createOurException(int type)361*9880d681SAndroid Build Coastguard Worker OurUnwindException *createOurException(int type) {
362*9880d681SAndroid Build Coastguard Worker   size_t size = sizeof(OurException);
363*9880d681SAndroid Build Coastguard Worker   OurException *ret = (OurException*) memset(malloc(size), 0, size);
364*9880d681SAndroid Build Coastguard Worker   (ret->type).type = type;
365*9880d681SAndroid Build Coastguard Worker   (ret->unwindException).exception_class = ourBaseExceptionClass;
366*9880d681SAndroid Build Coastguard Worker   (ret->unwindException).exception_cleanup = deleteFromUnwindOurException;
367*9880d681SAndroid Build Coastguard Worker 
368*9880d681SAndroid Build Coastguard Worker   return(&(ret->unwindException));
369*9880d681SAndroid Build Coastguard Worker }
370*9880d681SAndroid Build Coastguard Worker 
371*9880d681SAndroid Build Coastguard Worker 
372*9880d681SAndroid Build Coastguard Worker /// Read a uleb128 encoded value and advance pointer
373*9880d681SAndroid Build Coastguard Worker /// See Variable Length Data in:
374*9880d681SAndroid Build Coastguard Worker /// @link http://dwarfstd.org/Dwarf3.pdf @unlink
375*9880d681SAndroid Build Coastguard Worker /// @param data reference variable holding memory pointer to decode from
376*9880d681SAndroid Build Coastguard Worker /// @returns decoded value
readULEB128(const uint8_t ** data)377*9880d681SAndroid Build Coastguard Worker static uintptr_t readULEB128(const uint8_t **data) {
378*9880d681SAndroid Build Coastguard Worker   uintptr_t result = 0;
379*9880d681SAndroid Build Coastguard Worker   uintptr_t shift = 0;
380*9880d681SAndroid Build Coastguard Worker   unsigned char byte;
381*9880d681SAndroid Build Coastguard Worker   const uint8_t *p = *data;
382*9880d681SAndroid Build Coastguard Worker 
383*9880d681SAndroid Build Coastguard Worker   do {
384*9880d681SAndroid Build Coastguard Worker     byte = *p++;
385*9880d681SAndroid Build Coastguard Worker     result |= (byte & 0x7f) << shift;
386*9880d681SAndroid Build Coastguard Worker     shift += 7;
387*9880d681SAndroid Build Coastguard Worker   }
388*9880d681SAndroid Build Coastguard Worker   while (byte & 0x80);
389*9880d681SAndroid Build Coastguard Worker 
390*9880d681SAndroid Build Coastguard Worker   *data = p;
391*9880d681SAndroid Build Coastguard Worker 
392*9880d681SAndroid Build Coastguard Worker   return result;
393*9880d681SAndroid Build Coastguard Worker }
394*9880d681SAndroid Build Coastguard Worker 
395*9880d681SAndroid Build Coastguard Worker 
396*9880d681SAndroid Build Coastguard Worker /// Read a sleb128 encoded value and advance pointer
397*9880d681SAndroid Build Coastguard Worker /// See Variable Length Data in:
398*9880d681SAndroid Build Coastguard Worker /// @link http://dwarfstd.org/Dwarf3.pdf @unlink
399*9880d681SAndroid Build Coastguard Worker /// @param data reference variable holding memory pointer to decode from
400*9880d681SAndroid Build Coastguard Worker /// @returns decoded value
readSLEB128(const uint8_t ** data)401*9880d681SAndroid Build Coastguard Worker static uintptr_t readSLEB128(const uint8_t **data) {
402*9880d681SAndroid Build Coastguard Worker   uintptr_t result = 0;
403*9880d681SAndroid Build Coastguard Worker   uintptr_t shift = 0;
404*9880d681SAndroid Build Coastguard Worker   unsigned char byte;
405*9880d681SAndroid Build Coastguard Worker   const uint8_t *p = *data;
406*9880d681SAndroid Build Coastguard Worker 
407*9880d681SAndroid Build Coastguard Worker   do {
408*9880d681SAndroid Build Coastguard Worker     byte = *p++;
409*9880d681SAndroid Build Coastguard Worker     result |= (byte & 0x7f) << shift;
410*9880d681SAndroid Build Coastguard Worker     shift += 7;
411*9880d681SAndroid Build Coastguard Worker   }
412*9880d681SAndroid Build Coastguard Worker   while (byte & 0x80);
413*9880d681SAndroid Build Coastguard Worker 
414*9880d681SAndroid Build Coastguard Worker   *data = p;
415*9880d681SAndroid Build Coastguard Worker 
416*9880d681SAndroid Build Coastguard Worker   if ((byte & 0x40) && (shift < (sizeof(result) << 3))) {
417*9880d681SAndroid Build Coastguard Worker     result |= (~0 << shift);
418*9880d681SAndroid Build Coastguard Worker   }
419*9880d681SAndroid Build Coastguard Worker 
420*9880d681SAndroid Build Coastguard Worker   return result;
421*9880d681SAndroid Build Coastguard Worker }
422*9880d681SAndroid Build Coastguard Worker 
getEncodingSize(uint8_t Encoding)423*9880d681SAndroid Build Coastguard Worker unsigned getEncodingSize(uint8_t Encoding) {
424*9880d681SAndroid Build Coastguard Worker   if (Encoding == llvm::dwarf::DW_EH_PE_omit)
425*9880d681SAndroid Build Coastguard Worker     return 0;
426*9880d681SAndroid Build Coastguard Worker 
427*9880d681SAndroid Build Coastguard Worker   switch (Encoding & 0x0F) {
428*9880d681SAndroid Build Coastguard Worker   case llvm::dwarf::DW_EH_PE_absptr:
429*9880d681SAndroid Build Coastguard Worker     return sizeof(uintptr_t);
430*9880d681SAndroid Build Coastguard Worker   case llvm::dwarf::DW_EH_PE_udata2:
431*9880d681SAndroid Build Coastguard Worker     return sizeof(uint16_t);
432*9880d681SAndroid Build Coastguard Worker   case llvm::dwarf::DW_EH_PE_udata4:
433*9880d681SAndroid Build Coastguard Worker     return sizeof(uint32_t);
434*9880d681SAndroid Build Coastguard Worker   case llvm::dwarf::DW_EH_PE_udata8:
435*9880d681SAndroid Build Coastguard Worker     return sizeof(uint64_t);
436*9880d681SAndroid Build Coastguard Worker   case llvm::dwarf::DW_EH_PE_sdata2:
437*9880d681SAndroid Build Coastguard Worker     return sizeof(int16_t);
438*9880d681SAndroid Build Coastguard Worker   case llvm::dwarf::DW_EH_PE_sdata4:
439*9880d681SAndroid Build Coastguard Worker     return sizeof(int32_t);
440*9880d681SAndroid Build Coastguard Worker   case llvm::dwarf::DW_EH_PE_sdata8:
441*9880d681SAndroid Build Coastguard Worker     return sizeof(int64_t);
442*9880d681SAndroid Build Coastguard Worker   default:
443*9880d681SAndroid Build Coastguard Worker     // not supported
444*9880d681SAndroid Build Coastguard Worker     abort();
445*9880d681SAndroid Build Coastguard Worker   }
446*9880d681SAndroid Build Coastguard Worker }
447*9880d681SAndroid Build Coastguard Worker 
448*9880d681SAndroid Build Coastguard Worker /// Read a pointer encoded value and advance pointer
449*9880d681SAndroid Build Coastguard Worker /// See Variable Length Data in:
450*9880d681SAndroid Build Coastguard Worker /// @link http://dwarfstd.org/Dwarf3.pdf @unlink
451*9880d681SAndroid Build Coastguard Worker /// @param data reference variable holding memory pointer to decode from
452*9880d681SAndroid Build Coastguard Worker /// @param encoding dwarf encoding type
453*9880d681SAndroid Build Coastguard Worker /// @returns decoded value
readEncodedPointer(const uint8_t ** data,uint8_t encoding)454*9880d681SAndroid Build Coastguard Worker static uintptr_t readEncodedPointer(const uint8_t **data, uint8_t encoding) {
455*9880d681SAndroid Build Coastguard Worker   uintptr_t result = 0;
456*9880d681SAndroid Build Coastguard Worker   const uint8_t *p = *data;
457*9880d681SAndroid Build Coastguard Worker 
458*9880d681SAndroid Build Coastguard Worker   if (encoding == llvm::dwarf::DW_EH_PE_omit)
459*9880d681SAndroid Build Coastguard Worker     return(result);
460*9880d681SAndroid Build Coastguard Worker 
461*9880d681SAndroid Build Coastguard Worker   // first get value
462*9880d681SAndroid Build Coastguard Worker   switch (encoding & 0x0F) {
463*9880d681SAndroid Build Coastguard Worker     case llvm::dwarf::DW_EH_PE_absptr:
464*9880d681SAndroid Build Coastguard Worker       result = *((uintptr_t*)p);
465*9880d681SAndroid Build Coastguard Worker       p += sizeof(uintptr_t);
466*9880d681SAndroid Build Coastguard Worker       break;
467*9880d681SAndroid Build Coastguard Worker     case llvm::dwarf::DW_EH_PE_uleb128:
468*9880d681SAndroid Build Coastguard Worker       result = readULEB128(&p);
469*9880d681SAndroid Build Coastguard Worker       break;
470*9880d681SAndroid Build Coastguard Worker       // Note: This case has not been tested
471*9880d681SAndroid Build Coastguard Worker     case llvm::dwarf::DW_EH_PE_sleb128:
472*9880d681SAndroid Build Coastguard Worker       result = readSLEB128(&p);
473*9880d681SAndroid Build Coastguard Worker       break;
474*9880d681SAndroid Build Coastguard Worker     case llvm::dwarf::DW_EH_PE_udata2:
475*9880d681SAndroid Build Coastguard Worker       result = *((uint16_t*)p);
476*9880d681SAndroid Build Coastguard Worker       p += sizeof(uint16_t);
477*9880d681SAndroid Build Coastguard Worker       break;
478*9880d681SAndroid Build Coastguard Worker     case llvm::dwarf::DW_EH_PE_udata4:
479*9880d681SAndroid Build Coastguard Worker       result = *((uint32_t*)p);
480*9880d681SAndroid Build Coastguard Worker       p += sizeof(uint32_t);
481*9880d681SAndroid Build Coastguard Worker       break;
482*9880d681SAndroid Build Coastguard Worker     case llvm::dwarf::DW_EH_PE_udata8:
483*9880d681SAndroid Build Coastguard Worker       result = *((uint64_t*)p);
484*9880d681SAndroid Build Coastguard Worker       p += sizeof(uint64_t);
485*9880d681SAndroid Build Coastguard Worker       break;
486*9880d681SAndroid Build Coastguard Worker     case llvm::dwarf::DW_EH_PE_sdata2:
487*9880d681SAndroid Build Coastguard Worker       result = *((int16_t*)p);
488*9880d681SAndroid Build Coastguard Worker       p += sizeof(int16_t);
489*9880d681SAndroid Build Coastguard Worker       break;
490*9880d681SAndroid Build Coastguard Worker     case llvm::dwarf::DW_EH_PE_sdata4:
491*9880d681SAndroid Build Coastguard Worker       result = *((int32_t*)p);
492*9880d681SAndroid Build Coastguard Worker       p += sizeof(int32_t);
493*9880d681SAndroid Build Coastguard Worker       break;
494*9880d681SAndroid Build Coastguard Worker     case llvm::dwarf::DW_EH_PE_sdata8:
495*9880d681SAndroid Build Coastguard Worker       result = *((int64_t*)p);
496*9880d681SAndroid Build Coastguard Worker       p += sizeof(int64_t);
497*9880d681SAndroid Build Coastguard Worker       break;
498*9880d681SAndroid Build Coastguard Worker     default:
499*9880d681SAndroid Build Coastguard Worker       // not supported
500*9880d681SAndroid Build Coastguard Worker       abort();
501*9880d681SAndroid Build Coastguard Worker       break;
502*9880d681SAndroid Build Coastguard Worker   }
503*9880d681SAndroid Build Coastguard Worker 
504*9880d681SAndroid Build Coastguard Worker   // then add relative offset
505*9880d681SAndroid Build Coastguard Worker   switch (encoding & 0x70) {
506*9880d681SAndroid Build Coastguard Worker     case llvm::dwarf::DW_EH_PE_absptr:
507*9880d681SAndroid Build Coastguard Worker       // do nothing
508*9880d681SAndroid Build Coastguard Worker       break;
509*9880d681SAndroid Build Coastguard Worker     case llvm::dwarf::DW_EH_PE_pcrel:
510*9880d681SAndroid Build Coastguard Worker       result += (uintptr_t)(*data);
511*9880d681SAndroid Build Coastguard Worker       break;
512*9880d681SAndroid Build Coastguard Worker     case llvm::dwarf::DW_EH_PE_textrel:
513*9880d681SAndroid Build Coastguard Worker     case llvm::dwarf::DW_EH_PE_datarel:
514*9880d681SAndroid Build Coastguard Worker     case llvm::dwarf::DW_EH_PE_funcrel:
515*9880d681SAndroid Build Coastguard Worker     case llvm::dwarf::DW_EH_PE_aligned:
516*9880d681SAndroid Build Coastguard Worker     default:
517*9880d681SAndroid Build Coastguard Worker       // not supported
518*9880d681SAndroid Build Coastguard Worker       abort();
519*9880d681SAndroid Build Coastguard Worker       break;
520*9880d681SAndroid Build Coastguard Worker   }
521*9880d681SAndroid Build Coastguard Worker 
522*9880d681SAndroid Build Coastguard Worker   // then apply indirection
523*9880d681SAndroid Build Coastguard Worker   if (encoding & llvm::dwarf::DW_EH_PE_indirect) {
524*9880d681SAndroid Build Coastguard Worker     result = *((uintptr_t*)result);
525*9880d681SAndroid Build Coastguard Worker   }
526*9880d681SAndroid Build Coastguard Worker 
527*9880d681SAndroid Build Coastguard Worker   *data = p;
528*9880d681SAndroid Build Coastguard Worker 
529*9880d681SAndroid Build Coastguard Worker   return result;
530*9880d681SAndroid Build Coastguard Worker }
531*9880d681SAndroid Build Coastguard Worker 
532*9880d681SAndroid Build Coastguard Worker 
533*9880d681SAndroid Build Coastguard Worker /// Deals with Dwarf actions matching our type infos
534*9880d681SAndroid Build Coastguard Worker /// (OurExceptionType_t instances). Returns whether or not a dwarf emitted
535*9880d681SAndroid Build Coastguard Worker /// action matches the supplied exception type. If such a match succeeds,
536*9880d681SAndroid Build Coastguard Worker /// the resultAction argument will be set with > 0 index value. Only
537*9880d681SAndroid Build Coastguard Worker /// corresponding llvm.eh.selector type info arguments, cleanup arguments
538*9880d681SAndroid Build Coastguard Worker /// are supported. Filters are not supported.
539*9880d681SAndroid Build Coastguard Worker /// See Variable Length Data in:
540*9880d681SAndroid Build Coastguard Worker /// @link http://dwarfstd.org/Dwarf3.pdf @unlink
541*9880d681SAndroid Build Coastguard Worker /// Also see @link http://mentorembedded.github.com/cxx-abi/abi-eh.html @unlink
542*9880d681SAndroid Build Coastguard Worker /// @param resultAction reference variable which will be set with result
543*9880d681SAndroid Build Coastguard Worker /// @param classInfo our array of type info pointers (to globals)
544*9880d681SAndroid Build Coastguard Worker /// @param actionEntry index into above type info array or 0 (clean up).
545*9880d681SAndroid Build Coastguard Worker ///        We do not support filters.
546*9880d681SAndroid Build Coastguard Worker /// @param exceptionClass exception class (_Unwind_Exception::exception_class)
547*9880d681SAndroid Build Coastguard Worker ///        of thrown exception.
548*9880d681SAndroid Build Coastguard Worker /// @param exceptionObject thrown _Unwind_Exception instance.
549*9880d681SAndroid Build Coastguard Worker /// @returns whether or not a type info was found. False is returned if only
550*9880d681SAndroid Build Coastguard Worker ///          a cleanup was found
handleActionValue(int64_t * resultAction,uint8_t TTypeEncoding,const uint8_t * ClassInfo,uintptr_t actionEntry,uint64_t exceptionClass,struct _Unwind_Exception * exceptionObject)551*9880d681SAndroid Build Coastguard Worker static bool handleActionValue(int64_t *resultAction,
552*9880d681SAndroid Build Coastguard Worker                               uint8_t TTypeEncoding,
553*9880d681SAndroid Build Coastguard Worker                               const uint8_t *ClassInfo,
554*9880d681SAndroid Build Coastguard Worker                               uintptr_t actionEntry,
555*9880d681SAndroid Build Coastguard Worker                               uint64_t exceptionClass,
556*9880d681SAndroid Build Coastguard Worker                               struct _Unwind_Exception *exceptionObject) {
557*9880d681SAndroid Build Coastguard Worker   bool ret = false;
558*9880d681SAndroid Build Coastguard Worker 
559*9880d681SAndroid Build Coastguard Worker   if (!resultAction ||
560*9880d681SAndroid Build Coastguard Worker       !exceptionObject ||
561*9880d681SAndroid Build Coastguard Worker       (exceptionClass != ourBaseExceptionClass))
562*9880d681SAndroid Build Coastguard Worker     return(ret);
563*9880d681SAndroid Build Coastguard Worker 
564*9880d681SAndroid Build Coastguard Worker   struct OurBaseException_t *excp = (struct OurBaseException_t*)
565*9880d681SAndroid Build Coastguard Worker   (((char*) exceptionObject) + ourBaseFromUnwindOffset);
566*9880d681SAndroid Build Coastguard Worker   struct OurExceptionType_t *excpType = &(excp->type);
567*9880d681SAndroid Build Coastguard Worker   int type = excpType->type;
568*9880d681SAndroid Build Coastguard Worker 
569*9880d681SAndroid Build Coastguard Worker #ifdef DEBUG
570*9880d681SAndroid Build Coastguard Worker   fprintf(stderr,
571*9880d681SAndroid Build Coastguard Worker           "handleActionValue(...): exceptionObject = <%p>, "
572*9880d681SAndroid Build Coastguard Worker           "excp = <%p>.\n",
573*9880d681SAndroid Build Coastguard Worker           (void*)exceptionObject,
574*9880d681SAndroid Build Coastguard Worker           (void*)excp);
575*9880d681SAndroid Build Coastguard Worker #endif
576*9880d681SAndroid Build Coastguard Worker 
577*9880d681SAndroid Build Coastguard Worker   const uint8_t *actionPos = (uint8_t*) actionEntry,
578*9880d681SAndroid Build Coastguard Worker   *tempActionPos;
579*9880d681SAndroid Build Coastguard Worker   int64_t typeOffset = 0,
580*9880d681SAndroid Build Coastguard Worker   actionOffset;
581*9880d681SAndroid Build Coastguard Worker 
582*9880d681SAndroid Build Coastguard Worker   for (int i = 0; true; ++i) {
583*9880d681SAndroid Build Coastguard Worker     // Each emitted dwarf action corresponds to a 2 tuple of
584*9880d681SAndroid Build Coastguard Worker     // type info address offset, and action offset to the next
585*9880d681SAndroid Build Coastguard Worker     // emitted action.
586*9880d681SAndroid Build Coastguard Worker     typeOffset = readSLEB128(&actionPos);
587*9880d681SAndroid Build Coastguard Worker     tempActionPos = actionPos;
588*9880d681SAndroid Build Coastguard Worker     actionOffset = readSLEB128(&tempActionPos);
589*9880d681SAndroid Build Coastguard Worker 
590*9880d681SAndroid Build Coastguard Worker #ifdef DEBUG
591*9880d681SAndroid Build Coastguard Worker     fprintf(stderr,
592*9880d681SAndroid Build Coastguard Worker             "handleActionValue(...):typeOffset: <%" PRIi64 ">, "
593*9880d681SAndroid Build Coastguard Worker             "actionOffset: <%" PRIi64 ">.\n",
594*9880d681SAndroid Build Coastguard Worker             typeOffset,
595*9880d681SAndroid Build Coastguard Worker             actionOffset);
596*9880d681SAndroid Build Coastguard Worker #endif
597*9880d681SAndroid Build Coastguard Worker     assert((typeOffset >= 0) &&
598*9880d681SAndroid Build Coastguard Worker            "handleActionValue(...):filters are not supported.");
599*9880d681SAndroid Build Coastguard Worker 
600*9880d681SAndroid Build Coastguard Worker     // Note: A typeOffset == 0 implies that a cleanup llvm.eh.selector
601*9880d681SAndroid Build Coastguard Worker     //       argument has been matched.
602*9880d681SAndroid Build Coastguard Worker     if (typeOffset > 0) {
603*9880d681SAndroid Build Coastguard Worker #ifdef DEBUG
604*9880d681SAndroid Build Coastguard Worker       fprintf(stderr,
605*9880d681SAndroid Build Coastguard Worker               "handleActionValue(...):actionValue <%d> found.\n",
606*9880d681SAndroid Build Coastguard Worker               i);
607*9880d681SAndroid Build Coastguard Worker #endif
608*9880d681SAndroid Build Coastguard Worker       unsigned EncSize = getEncodingSize(TTypeEncoding);
609*9880d681SAndroid Build Coastguard Worker       const uint8_t *EntryP = ClassInfo - typeOffset * EncSize;
610*9880d681SAndroid Build Coastguard Worker       uintptr_t P = readEncodedPointer(&EntryP, TTypeEncoding);
611*9880d681SAndroid Build Coastguard Worker       struct OurExceptionType_t *ThisClassInfo =
612*9880d681SAndroid Build Coastguard Worker         reinterpret_cast<struct OurExceptionType_t *>(P);
613*9880d681SAndroid Build Coastguard Worker       if (ThisClassInfo->type == type) {
614*9880d681SAndroid Build Coastguard Worker         *resultAction = i + 1;
615*9880d681SAndroid Build Coastguard Worker         ret = true;
616*9880d681SAndroid Build Coastguard Worker         break;
617*9880d681SAndroid Build Coastguard Worker       }
618*9880d681SAndroid Build Coastguard Worker     }
619*9880d681SAndroid Build Coastguard Worker 
620*9880d681SAndroid Build Coastguard Worker #ifdef DEBUG
621*9880d681SAndroid Build Coastguard Worker     fprintf(stderr,
622*9880d681SAndroid Build Coastguard Worker             "handleActionValue(...):actionValue not found.\n");
623*9880d681SAndroid Build Coastguard Worker #endif
624*9880d681SAndroid Build Coastguard Worker     if (!actionOffset)
625*9880d681SAndroid Build Coastguard Worker       break;
626*9880d681SAndroid Build Coastguard Worker 
627*9880d681SAndroid Build Coastguard Worker     actionPos += actionOffset;
628*9880d681SAndroid Build Coastguard Worker   }
629*9880d681SAndroid Build Coastguard Worker 
630*9880d681SAndroid Build Coastguard Worker   return(ret);
631*9880d681SAndroid Build Coastguard Worker }
632*9880d681SAndroid Build Coastguard Worker 
633*9880d681SAndroid Build Coastguard Worker 
634*9880d681SAndroid Build Coastguard Worker /// Deals with the Language specific data portion of the emitted dwarf code.
635*9880d681SAndroid Build Coastguard Worker /// See @link http://mentorembedded.github.com/cxx-abi/abi-eh.html @unlink
636*9880d681SAndroid Build Coastguard Worker /// @param version unsupported (ignored), unwind version
637*9880d681SAndroid Build Coastguard Worker /// @param lsda language specific data area
638*9880d681SAndroid Build Coastguard Worker /// @param _Unwind_Action actions minimally supported unwind stage
639*9880d681SAndroid Build Coastguard Worker ///        (forced specifically not supported)
640*9880d681SAndroid Build Coastguard Worker /// @param exceptionClass exception class (_Unwind_Exception::exception_class)
641*9880d681SAndroid Build Coastguard Worker ///        of thrown exception.
642*9880d681SAndroid Build Coastguard Worker /// @param exceptionObject thrown _Unwind_Exception instance.
643*9880d681SAndroid Build Coastguard Worker /// @param context unwind system context
644*9880d681SAndroid Build Coastguard Worker /// @returns minimally supported unwinding control indicator
handleLsda(int version,const uint8_t * lsda,_Unwind_Action actions,uint64_t exceptionClass,struct _Unwind_Exception * exceptionObject,_Unwind_Context_t context)645*9880d681SAndroid Build Coastguard Worker static _Unwind_Reason_Code handleLsda(int version,
646*9880d681SAndroid Build Coastguard Worker                                       const uint8_t *lsda,
647*9880d681SAndroid Build Coastguard Worker                                       _Unwind_Action actions,
648*9880d681SAndroid Build Coastguard Worker                                       uint64_t exceptionClass,
649*9880d681SAndroid Build Coastguard Worker                                     struct _Unwind_Exception *exceptionObject,
650*9880d681SAndroid Build Coastguard Worker                                       _Unwind_Context_t context) {
651*9880d681SAndroid Build Coastguard Worker   _Unwind_Reason_Code ret = _URC_CONTINUE_UNWIND;
652*9880d681SAndroid Build Coastguard Worker 
653*9880d681SAndroid Build Coastguard Worker   if (!lsda)
654*9880d681SAndroid Build Coastguard Worker     return(ret);
655*9880d681SAndroid Build Coastguard Worker 
656*9880d681SAndroid Build Coastguard Worker #ifdef DEBUG
657*9880d681SAndroid Build Coastguard Worker   fprintf(stderr,
658*9880d681SAndroid Build Coastguard Worker           "handleLsda(...):lsda is non-zero.\n");
659*9880d681SAndroid Build Coastguard Worker #endif
660*9880d681SAndroid Build Coastguard Worker 
661*9880d681SAndroid Build Coastguard Worker   // Get the current instruction pointer and offset it before next
662*9880d681SAndroid Build Coastguard Worker   // instruction in the current frame which threw the exception.
663*9880d681SAndroid Build Coastguard Worker   uintptr_t pc = _Unwind_GetIP(context)-1;
664*9880d681SAndroid Build Coastguard Worker 
665*9880d681SAndroid Build Coastguard Worker   // Get beginning current frame's code (as defined by the
666*9880d681SAndroid Build Coastguard Worker   // emitted dwarf code)
667*9880d681SAndroid Build Coastguard Worker   uintptr_t funcStart = _Unwind_GetRegionStart(context);
668*9880d681SAndroid Build Coastguard Worker   uintptr_t pcOffset = pc - funcStart;
669*9880d681SAndroid Build Coastguard Worker   const uint8_t *ClassInfo = NULL;
670*9880d681SAndroid Build Coastguard Worker 
671*9880d681SAndroid Build Coastguard Worker   // Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding
672*9880d681SAndroid Build Coastguard Worker   //       dwarf emission
673*9880d681SAndroid Build Coastguard Worker 
674*9880d681SAndroid Build Coastguard Worker   // Parse LSDA header.
675*9880d681SAndroid Build Coastguard Worker   uint8_t lpStartEncoding = *lsda++;
676*9880d681SAndroid Build Coastguard Worker 
677*9880d681SAndroid Build Coastguard Worker   if (lpStartEncoding != llvm::dwarf::DW_EH_PE_omit) {
678*9880d681SAndroid Build Coastguard Worker     readEncodedPointer(&lsda, lpStartEncoding);
679*9880d681SAndroid Build Coastguard Worker   }
680*9880d681SAndroid Build Coastguard Worker 
681*9880d681SAndroid Build Coastguard Worker   uint8_t ttypeEncoding = *lsda++;
682*9880d681SAndroid Build Coastguard Worker   uintptr_t classInfoOffset;
683*9880d681SAndroid Build Coastguard Worker 
684*9880d681SAndroid Build Coastguard Worker   if (ttypeEncoding != llvm::dwarf::DW_EH_PE_omit) {
685*9880d681SAndroid Build Coastguard Worker     // Calculate type info locations in emitted dwarf code which
686*9880d681SAndroid Build Coastguard Worker     // were flagged by type info arguments to llvm.eh.selector
687*9880d681SAndroid Build Coastguard Worker     // intrinsic
688*9880d681SAndroid Build Coastguard Worker     classInfoOffset = readULEB128(&lsda);
689*9880d681SAndroid Build Coastguard Worker     ClassInfo = lsda + classInfoOffset;
690*9880d681SAndroid Build Coastguard Worker   }
691*9880d681SAndroid Build Coastguard Worker 
692*9880d681SAndroid Build Coastguard Worker   // Walk call-site table looking for range that
693*9880d681SAndroid Build Coastguard Worker   // includes current PC.
694*9880d681SAndroid Build Coastguard Worker 
695*9880d681SAndroid Build Coastguard Worker   uint8_t         callSiteEncoding = *lsda++;
696*9880d681SAndroid Build Coastguard Worker   uint32_t        callSiteTableLength = readULEB128(&lsda);
697*9880d681SAndroid Build Coastguard Worker   const uint8_t   *callSiteTableStart = lsda;
698*9880d681SAndroid Build Coastguard Worker   const uint8_t   *callSiteTableEnd = callSiteTableStart +
699*9880d681SAndroid Build Coastguard Worker   callSiteTableLength;
700*9880d681SAndroid Build Coastguard Worker   const uint8_t   *actionTableStart = callSiteTableEnd;
701*9880d681SAndroid Build Coastguard Worker   const uint8_t   *callSitePtr = callSiteTableStart;
702*9880d681SAndroid Build Coastguard Worker 
703*9880d681SAndroid Build Coastguard Worker   while (callSitePtr < callSiteTableEnd) {
704*9880d681SAndroid Build Coastguard Worker     uintptr_t start = readEncodedPointer(&callSitePtr,
705*9880d681SAndroid Build Coastguard Worker                                          callSiteEncoding);
706*9880d681SAndroid Build Coastguard Worker     uintptr_t length = readEncodedPointer(&callSitePtr,
707*9880d681SAndroid Build Coastguard Worker                                           callSiteEncoding);
708*9880d681SAndroid Build Coastguard Worker     uintptr_t landingPad = readEncodedPointer(&callSitePtr,
709*9880d681SAndroid Build Coastguard Worker                                               callSiteEncoding);
710*9880d681SAndroid Build Coastguard Worker 
711*9880d681SAndroid Build Coastguard Worker     // Note: Action value
712*9880d681SAndroid Build Coastguard Worker     uintptr_t actionEntry = readULEB128(&callSitePtr);
713*9880d681SAndroid Build Coastguard Worker 
714*9880d681SAndroid Build Coastguard Worker     if (exceptionClass != ourBaseExceptionClass) {
715*9880d681SAndroid Build Coastguard Worker       // We have been notified of a foreign exception being thrown,
716*9880d681SAndroid Build Coastguard Worker       // and we therefore need to execute cleanup landing pads
717*9880d681SAndroid Build Coastguard Worker       actionEntry = 0;
718*9880d681SAndroid Build Coastguard Worker     }
719*9880d681SAndroid Build Coastguard Worker 
720*9880d681SAndroid Build Coastguard Worker     if (landingPad == 0) {
721*9880d681SAndroid Build Coastguard Worker #ifdef DEBUG
722*9880d681SAndroid Build Coastguard Worker       fprintf(stderr,
723*9880d681SAndroid Build Coastguard Worker               "handleLsda(...): No landing pad found.\n");
724*9880d681SAndroid Build Coastguard Worker #endif
725*9880d681SAndroid Build Coastguard Worker 
726*9880d681SAndroid Build Coastguard Worker       continue; // no landing pad for this entry
727*9880d681SAndroid Build Coastguard Worker     }
728*9880d681SAndroid Build Coastguard Worker 
729*9880d681SAndroid Build Coastguard Worker     if (actionEntry) {
730*9880d681SAndroid Build Coastguard Worker       actionEntry += ((uintptr_t) actionTableStart) - 1;
731*9880d681SAndroid Build Coastguard Worker     }
732*9880d681SAndroid Build Coastguard Worker     else {
733*9880d681SAndroid Build Coastguard Worker #ifdef DEBUG
734*9880d681SAndroid Build Coastguard Worker       fprintf(stderr,
735*9880d681SAndroid Build Coastguard Worker               "handleLsda(...):No action table found.\n");
736*9880d681SAndroid Build Coastguard Worker #endif
737*9880d681SAndroid Build Coastguard Worker     }
738*9880d681SAndroid Build Coastguard Worker 
739*9880d681SAndroid Build Coastguard Worker     bool exceptionMatched = false;
740*9880d681SAndroid Build Coastguard Worker 
741*9880d681SAndroid Build Coastguard Worker     if ((start <= pcOffset) && (pcOffset < (start + length))) {
742*9880d681SAndroid Build Coastguard Worker #ifdef DEBUG
743*9880d681SAndroid Build Coastguard Worker       fprintf(stderr,
744*9880d681SAndroid Build Coastguard Worker               "handleLsda(...): Landing pad found.\n");
745*9880d681SAndroid Build Coastguard Worker #endif
746*9880d681SAndroid Build Coastguard Worker       int64_t actionValue = 0;
747*9880d681SAndroid Build Coastguard Worker 
748*9880d681SAndroid Build Coastguard Worker       if (actionEntry) {
749*9880d681SAndroid Build Coastguard Worker         exceptionMatched = handleActionValue(&actionValue,
750*9880d681SAndroid Build Coastguard Worker                                              ttypeEncoding,
751*9880d681SAndroid Build Coastguard Worker                                              ClassInfo,
752*9880d681SAndroid Build Coastguard Worker                                              actionEntry,
753*9880d681SAndroid Build Coastguard Worker                                              exceptionClass,
754*9880d681SAndroid Build Coastguard Worker                                              exceptionObject);
755*9880d681SAndroid Build Coastguard Worker       }
756*9880d681SAndroid Build Coastguard Worker 
757*9880d681SAndroid Build Coastguard Worker       if (!(actions & _UA_SEARCH_PHASE)) {
758*9880d681SAndroid Build Coastguard Worker #ifdef DEBUG
759*9880d681SAndroid Build Coastguard Worker         fprintf(stderr,
760*9880d681SAndroid Build Coastguard Worker                 "handleLsda(...): installed landing pad "
761*9880d681SAndroid Build Coastguard Worker                 "context.\n");
762*9880d681SAndroid Build Coastguard Worker #endif
763*9880d681SAndroid Build Coastguard Worker 
764*9880d681SAndroid Build Coastguard Worker         // Found landing pad for the PC.
765*9880d681SAndroid Build Coastguard Worker         // Set Instruction Pointer to so we re-enter function
766*9880d681SAndroid Build Coastguard Worker         // at landing pad. The landing pad is created by the
767*9880d681SAndroid Build Coastguard Worker         // compiler to take two parameters in registers.
768*9880d681SAndroid Build Coastguard Worker         _Unwind_SetGR(context,
769*9880d681SAndroid Build Coastguard Worker                       __builtin_eh_return_data_regno(0),
770*9880d681SAndroid Build Coastguard Worker                       (uintptr_t)exceptionObject);
771*9880d681SAndroid Build Coastguard Worker 
772*9880d681SAndroid Build Coastguard Worker         // Note: this virtual register directly corresponds
773*9880d681SAndroid Build Coastguard Worker         //       to the return of the llvm.eh.selector intrinsic
774*9880d681SAndroid Build Coastguard Worker         if (!actionEntry || !exceptionMatched) {
775*9880d681SAndroid Build Coastguard Worker           // We indicate cleanup only
776*9880d681SAndroid Build Coastguard Worker           _Unwind_SetGR(context,
777*9880d681SAndroid Build Coastguard Worker                         __builtin_eh_return_data_regno(1),
778*9880d681SAndroid Build Coastguard Worker                         0);
779*9880d681SAndroid Build Coastguard Worker         }
780*9880d681SAndroid Build Coastguard Worker         else {
781*9880d681SAndroid Build Coastguard Worker           // Matched type info index of llvm.eh.selector intrinsic
782*9880d681SAndroid Build Coastguard Worker           // passed here.
783*9880d681SAndroid Build Coastguard Worker           _Unwind_SetGR(context,
784*9880d681SAndroid Build Coastguard Worker                         __builtin_eh_return_data_regno(1),
785*9880d681SAndroid Build Coastguard Worker                         actionValue);
786*9880d681SAndroid Build Coastguard Worker         }
787*9880d681SAndroid Build Coastguard Worker 
788*9880d681SAndroid Build Coastguard Worker         // To execute landing pad set here
789*9880d681SAndroid Build Coastguard Worker         _Unwind_SetIP(context, funcStart + landingPad);
790*9880d681SAndroid Build Coastguard Worker         ret = _URC_INSTALL_CONTEXT;
791*9880d681SAndroid Build Coastguard Worker       }
792*9880d681SAndroid Build Coastguard Worker       else if (exceptionMatched) {
793*9880d681SAndroid Build Coastguard Worker #ifdef DEBUG
794*9880d681SAndroid Build Coastguard Worker         fprintf(stderr,
795*9880d681SAndroid Build Coastguard Worker                 "handleLsda(...): setting handler found.\n");
796*9880d681SAndroid Build Coastguard Worker #endif
797*9880d681SAndroid Build Coastguard Worker         ret = _URC_HANDLER_FOUND;
798*9880d681SAndroid Build Coastguard Worker       }
799*9880d681SAndroid Build Coastguard Worker       else {
800*9880d681SAndroid Build Coastguard Worker         // Note: Only non-clean up handlers are marked as
801*9880d681SAndroid Build Coastguard Worker         //       found. Otherwise the clean up handlers will be
802*9880d681SAndroid Build Coastguard Worker         //       re-found and executed during the clean up
803*9880d681SAndroid Build Coastguard Worker         //       phase.
804*9880d681SAndroid Build Coastguard Worker #ifdef DEBUG
805*9880d681SAndroid Build Coastguard Worker         fprintf(stderr,
806*9880d681SAndroid Build Coastguard Worker                 "handleLsda(...): cleanup handler found.\n");
807*9880d681SAndroid Build Coastguard Worker #endif
808*9880d681SAndroid Build Coastguard Worker       }
809*9880d681SAndroid Build Coastguard Worker 
810*9880d681SAndroid Build Coastguard Worker       break;
811*9880d681SAndroid Build Coastguard Worker     }
812*9880d681SAndroid Build Coastguard Worker   }
813*9880d681SAndroid Build Coastguard Worker 
814*9880d681SAndroid Build Coastguard Worker   return(ret);
815*9880d681SAndroid Build Coastguard Worker }
816*9880d681SAndroid Build Coastguard Worker 
817*9880d681SAndroid Build Coastguard Worker 
818*9880d681SAndroid Build Coastguard Worker /// This is the personality function which is embedded (dwarf emitted), in the
819*9880d681SAndroid Build Coastguard Worker /// dwarf unwind info block. Again see: JITDwarfEmitter.cpp.
820*9880d681SAndroid Build Coastguard Worker /// See @link http://mentorembedded.github.com/cxx-abi/abi-eh.html @unlink
821*9880d681SAndroid Build Coastguard Worker /// @param version unsupported (ignored), unwind version
822*9880d681SAndroid Build Coastguard Worker /// @param _Unwind_Action actions minimally supported unwind stage
823*9880d681SAndroid Build Coastguard Worker ///        (forced specifically not supported)
824*9880d681SAndroid Build Coastguard Worker /// @param exceptionClass exception class (_Unwind_Exception::exception_class)
825*9880d681SAndroid Build Coastguard Worker ///        of thrown exception.
826*9880d681SAndroid Build Coastguard Worker /// @param exceptionObject thrown _Unwind_Exception instance.
827*9880d681SAndroid Build Coastguard Worker /// @param context unwind system context
828*9880d681SAndroid Build Coastguard Worker /// @returns minimally supported unwinding control indicator
ourPersonality(int version,_Unwind_Action actions,uint64_t exceptionClass,struct _Unwind_Exception * exceptionObject,_Unwind_Context_t context)829*9880d681SAndroid Build Coastguard Worker _Unwind_Reason_Code ourPersonality(int version,
830*9880d681SAndroid Build Coastguard Worker                                    _Unwind_Action actions,
831*9880d681SAndroid Build Coastguard Worker                                    uint64_t exceptionClass,
832*9880d681SAndroid Build Coastguard Worker                                    struct _Unwind_Exception *exceptionObject,
833*9880d681SAndroid Build Coastguard Worker                                    _Unwind_Context_t context) {
834*9880d681SAndroid Build Coastguard Worker #ifdef DEBUG
835*9880d681SAndroid Build Coastguard Worker   fprintf(stderr,
836*9880d681SAndroid Build Coastguard Worker           "We are in ourPersonality(...):actions is <%d>.\n",
837*9880d681SAndroid Build Coastguard Worker           actions);
838*9880d681SAndroid Build Coastguard Worker 
839*9880d681SAndroid Build Coastguard Worker   if (actions & _UA_SEARCH_PHASE) {
840*9880d681SAndroid Build Coastguard Worker     fprintf(stderr, "ourPersonality(...):In search phase.\n");
841*9880d681SAndroid Build Coastguard Worker   }
842*9880d681SAndroid Build Coastguard Worker   else {
843*9880d681SAndroid Build Coastguard Worker     fprintf(stderr, "ourPersonality(...):In non-search phase.\n");
844*9880d681SAndroid Build Coastguard Worker   }
845*9880d681SAndroid Build Coastguard Worker #endif
846*9880d681SAndroid Build Coastguard Worker 
847*9880d681SAndroid Build Coastguard Worker   const uint8_t *lsda = _Unwind_GetLanguageSpecificData(context);
848*9880d681SAndroid Build Coastguard Worker 
849*9880d681SAndroid Build Coastguard Worker #ifdef DEBUG
850*9880d681SAndroid Build Coastguard Worker   fprintf(stderr,
851*9880d681SAndroid Build Coastguard Worker           "ourPersonality(...):lsda = <%p>.\n",
852*9880d681SAndroid Build Coastguard Worker           (void*)lsda);
853*9880d681SAndroid Build Coastguard Worker #endif
854*9880d681SAndroid Build Coastguard Worker 
855*9880d681SAndroid Build Coastguard Worker   // The real work of the personality function is captured here
856*9880d681SAndroid Build Coastguard Worker   return(handleLsda(version,
857*9880d681SAndroid Build Coastguard Worker                     lsda,
858*9880d681SAndroid Build Coastguard Worker                     actions,
859*9880d681SAndroid Build Coastguard Worker                     exceptionClass,
860*9880d681SAndroid Build Coastguard Worker                     exceptionObject,
861*9880d681SAndroid Build Coastguard Worker                     context));
862*9880d681SAndroid Build Coastguard Worker }
863*9880d681SAndroid Build Coastguard Worker 
864*9880d681SAndroid Build Coastguard Worker 
865*9880d681SAndroid Build Coastguard Worker /// Generates our _Unwind_Exception class from a given character array.
866*9880d681SAndroid Build Coastguard Worker /// thereby handling arbitrary lengths (not in standard), and handling
867*9880d681SAndroid Build Coastguard Worker /// embedded \0s.
868*9880d681SAndroid Build Coastguard Worker /// See @link http://mentorembedded.github.com/cxx-abi/abi-eh.html @unlink
869*9880d681SAndroid Build Coastguard Worker /// @param classChars char array to encode. NULL values not checkedf
870*9880d681SAndroid Build Coastguard Worker /// @param classCharsSize number of chars in classChars. Value is not checked.
871*9880d681SAndroid Build Coastguard Worker /// @returns class value
genClass(const unsigned char classChars[],size_t classCharsSize)872*9880d681SAndroid Build Coastguard Worker uint64_t genClass(const unsigned char classChars[], size_t classCharsSize)
873*9880d681SAndroid Build Coastguard Worker {
874*9880d681SAndroid Build Coastguard Worker   uint64_t ret = classChars[0];
875*9880d681SAndroid Build Coastguard Worker 
876*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 1; i < classCharsSize; ++i) {
877*9880d681SAndroid Build Coastguard Worker     ret <<= 8;
878*9880d681SAndroid Build Coastguard Worker     ret += classChars[i];
879*9880d681SAndroid Build Coastguard Worker   }
880*9880d681SAndroid Build Coastguard Worker 
881*9880d681SAndroid Build Coastguard Worker   return(ret);
882*9880d681SAndroid Build Coastguard Worker }
883*9880d681SAndroid Build Coastguard Worker 
884*9880d681SAndroid Build Coastguard Worker } // extern "C"
885*9880d681SAndroid Build Coastguard Worker 
886*9880d681SAndroid Build Coastguard Worker //
887*9880d681SAndroid Build Coastguard Worker // Runtime C Library functions End
888*9880d681SAndroid Build Coastguard Worker //
889*9880d681SAndroid Build Coastguard Worker 
890*9880d681SAndroid Build Coastguard Worker //
891*9880d681SAndroid Build Coastguard Worker // Code generation functions
892*9880d681SAndroid Build Coastguard Worker //
893*9880d681SAndroid Build Coastguard Worker 
894*9880d681SAndroid Build Coastguard Worker /// Generates code to print given constant string
895*9880d681SAndroid Build Coastguard Worker /// @param context llvm context
896*9880d681SAndroid Build Coastguard Worker /// @param module code for module instance
897*9880d681SAndroid Build Coastguard Worker /// @param builder builder instance
898*9880d681SAndroid Build Coastguard Worker /// @param toPrint string to print
899*9880d681SAndroid Build Coastguard Worker /// @param useGlobal A value of true (default) indicates a GlobalValue is
900*9880d681SAndroid Build Coastguard Worker ///        generated, and is used to hold the constant string. A value of
901*9880d681SAndroid Build Coastguard Worker ///        false indicates that the constant string will be stored on the
902*9880d681SAndroid Build Coastguard Worker ///        stack.
generateStringPrint(llvm::LLVMContext & context,llvm::Module & module,llvm::IRBuilder<> & builder,std::string toPrint,bool useGlobal=true)903*9880d681SAndroid Build Coastguard Worker void generateStringPrint(llvm::LLVMContext &context,
904*9880d681SAndroid Build Coastguard Worker                          llvm::Module &module,
905*9880d681SAndroid Build Coastguard Worker                          llvm::IRBuilder<> &builder,
906*9880d681SAndroid Build Coastguard Worker                          std::string toPrint,
907*9880d681SAndroid Build Coastguard Worker                          bool useGlobal = true) {
908*9880d681SAndroid Build Coastguard Worker   llvm::Function *printFunct = module.getFunction("printStr");
909*9880d681SAndroid Build Coastguard Worker 
910*9880d681SAndroid Build Coastguard Worker   llvm::Value *stringVar;
911*9880d681SAndroid Build Coastguard Worker   llvm::Constant *stringConstant =
912*9880d681SAndroid Build Coastguard Worker   llvm::ConstantDataArray::getString(context, toPrint);
913*9880d681SAndroid Build Coastguard Worker 
914*9880d681SAndroid Build Coastguard Worker   if (useGlobal) {
915*9880d681SAndroid Build Coastguard Worker     // Note: Does not work without allocation
916*9880d681SAndroid Build Coastguard Worker     stringVar =
917*9880d681SAndroid Build Coastguard Worker     new llvm::GlobalVariable(module,
918*9880d681SAndroid Build Coastguard Worker                              stringConstant->getType(),
919*9880d681SAndroid Build Coastguard Worker                              true,
920*9880d681SAndroid Build Coastguard Worker                              llvm::GlobalValue::PrivateLinkage,
921*9880d681SAndroid Build Coastguard Worker                              stringConstant,
922*9880d681SAndroid Build Coastguard Worker                              "");
923*9880d681SAndroid Build Coastguard Worker   }
924*9880d681SAndroid Build Coastguard Worker   else {
925*9880d681SAndroid Build Coastguard Worker     stringVar = builder.CreateAlloca(stringConstant->getType());
926*9880d681SAndroid Build Coastguard Worker     builder.CreateStore(stringConstant, stringVar);
927*9880d681SAndroid Build Coastguard Worker   }
928*9880d681SAndroid Build Coastguard Worker 
929*9880d681SAndroid Build Coastguard Worker   llvm::Value *cast = builder.CreatePointerCast(stringVar,
930*9880d681SAndroid Build Coastguard Worker                                                 builder.getInt8PtrTy());
931*9880d681SAndroid Build Coastguard Worker   builder.CreateCall(printFunct, cast);
932*9880d681SAndroid Build Coastguard Worker }
933*9880d681SAndroid Build Coastguard Worker 
934*9880d681SAndroid Build Coastguard Worker 
935*9880d681SAndroid Build Coastguard Worker /// Generates code to print given runtime integer according to constant
936*9880d681SAndroid Build Coastguard Worker /// string format, and a given print function.
937*9880d681SAndroid Build Coastguard Worker /// @param context llvm context
938*9880d681SAndroid Build Coastguard Worker /// @param module code for module instance
939*9880d681SAndroid Build Coastguard Worker /// @param builder builder instance
940*9880d681SAndroid Build Coastguard Worker /// @param printFunct function used to "print" integer
941*9880d681SAndroid Build Coastguard Worker /// @param toPrint string to print
942*9880d681SAndroid Build Coastguard Worker /// @param format printf like formating string for print
943*9880d681SAndroid Build Coastguard Worker /// @param useGlobal A value of true (default) indicates a GlobalValue is
944*9880d681SAndroid Build Coastguard Worker ///        generated, and is used to hold the constant string. A value of
945*9880d681SAndroid Build Coastguard Worker ///        false indicates that the constant string will be stored on the
946*9880d681SAndroid Build Coastguard Worker ///        stack.
generateIntegerPrint(llvm::LLVMContext & context,llvm::Module & module,llvm::IRBuilder<> & builder,llvm::Function & printFunct,llvm::Value & toPrint,std::string format,bool useGlobal=true)947*9880d681SAndroid Build Coastguard Worker void generateIntegerPrint(llvm::LLVMContext &context,
948*9880d681SAndroid Build Coastguard Worker                           llvm::Module &module,
949*9880d681SAndroid Build Coastguard Worker                           llvm::IRBuilder<> &builder,
950*9880d681SAndroid Build Coastguard Worker                           llvm::Function &printFunct,
951*9880d681SAndroid Build Coastguard Worker                           llvm::Value &toPrint,
952*9880d681SAndroid Build Coastguard Worker                           std::string format,
953*9880d681SAndroid Build Coastguard Worker                           bool useGlobal = true) {
954*9880d681SAndroid Build Coastguard Worker   llvm::Constant *stringConstant =
955*9880d681SAndroid Build Coastguard Worker     llvm::ConstantDataArray::getString(context, format);
956*9880d681SAndroid Build Coastguard Worker   llvm::Value *stringVar;
957*9880d681SAndroid Build Coastguard Worker 
958*9880d681SAndroid Build Coastguard Worker   if (useGlobal) {
959*9880d681SAndroid Build Coastguard Worker     // Note: Does not seem to work without allocation
960*9880d681SAndroid Build Coastguard Worker     stringVar =
961*9880d681SAndroid Build Coastguard Worker     new llvm::GlobalVariable(module,
962*9880d681SAndroid Build Coastguard Worker                              stringConstant->getType(),
963*9880d681SAndroid Build Coastguard Worker                              true,
964*9880d681SAndroid Build Coastguard Worker                              llvm::GlobalValue::PrivateLinkage,
965*9880d681SAndroid Build Coastguard Worker                              stringConstant,
966*9880d681SAndroid Build Coastguard Worker                              "");
967*9880d681SAndroid Build Coastguard Worker   }
968*9880d681SAndroid Build Coastguard Worker   else {
969*9880d681SAndroid Build Coastguard Worker     stringVar = builder.CreateAlloca(stringConstant->getType());
970*9880d681SAndroid Build Coastguard Worker     builder.CreateStore(stringConstant, stringVar);
971*9880d681SAndroid Build Coastguard Worker   }
972*9880d681SAndroid Build Coastguard Worker 
973*9880d681SAndroid Build Coastguard Worker   llvm::Value *cast = builder.CreateBitCast(stringVar,
974*9880d681SAndroid Build Coastguard Worker                                             builder.getInt8PtrTy());
975*9880d681SAndroid Build Coastguard Worker   builder.CreateCall(&printFunct, {&toPrint, cast});
976*9880d681SAndroid Build Coastguard Worker }
977*9880d681SAndroid Build Coastguard Worker 
978*9880d681SAndroid Build Coastguard Worker 
979*9880d681SAndroid Build Coastguard Worker /// Generates code to handle finally block type semantics: always runs
980*9880d681SAndroid Build Coastguard Worker /// regardless of whether a thrown exception is passing through or the
981*9880d681SAndroid Build Coastguard Worker /// parent function is simply exiting. In addition to printing some state
982*9880d681SAndroid Build Coastguard Worker /// to stderr, this code will resume the exception handling--runs the
983*9880d681SAndroid Build Coastguard Worker /// unwind resume block, if the exception has not been previously caught
984*9880d681SAndroid Build Coastguard Worker /// by a catch clause, and will otherwise execute the end block (terminator
985*9880d681SAndroid Build Coastguard Worker /// block). In addition this function creates the corresponding function's
986*9880d681SAndroid Build Coastguard Worker /// stack storage for the exception pointer and catch flag status.
987*9880d681SAndroid Build Coastguard Worker /// @param context llvm context
988*9880d681SAndroid Build Coastguard Worker /// @param module code for module instance
989*9880d681SAndroid Build Coastguard Worker /// @param builder builder instance
990*9880d681SAndroid Build Coastguard Worker /// @param toAddTo parent function to add block to
991*9880d681SAndroid Build Coastguard Worker /// @param blockName block name of new "finally" block.
992*9880d681SAndroid Build Coastguard Worker /// @param functionId output id used for printing
993*9880d681SAndroid Build Coastguard Worker /// @param terminatorBlock terminator "end" block
994*9880d681SAndroid Build Coastguard Worker /// @param unwindResumeBlock unwind resume block
995*9880d681SAndroid Build Coastguard Worker /// @param exceptionCaughtFlag reference exception caught/thrown status storage
996*9880d681SAndroid Build Coastguard Worker /// @param exceptionStorage reference to exception pointer storage
997*9880d681SAndroid Build Coastguard Worker /// @param caughtResultStorage reference to landingpad result storage
998*9880d681SAndroid Build Coastguard Worker /// @returns newly created block
createFinallyBlock(llvm::LLVMContext & context,llvm::Module & module,llvm::IRBuilder<> & builder,llvm::Function & toAddTo,std::string & blockName,std::string & functionId,llvm::BasicBlock & terminatorBlock,llvm::BasicBlock & unwindResumeBlock,llvm::Value ** exceptionCaughtFlag,llvm::Value ** exceptionStorage,llvm::Value ** caughtResultStorage)999*9880d681SAndroid Build Coastguard Worker static llvm::BasicBlock *createFinallyBlock(llvm::LLVMContext &context,
1000*9880d681SAndroid Build Coastguard Worker                                             llvm::Module &module,
1001*9880d681SAndroid Build Coastguard Worker                                             llvm::IRBuilder<> &builder,
1002*9880d681SAndroid Build Coastguard Worker                                             llvm::Function &toAddTo,
1003*9880d681SAndroid Build Coastguard Worker                                             std::string &blockName,
1004*9880d681SAndroid Build Coastguard Worker                                             std::string &functionId,
1005*9880d681SAndroid Build Coastguard Worker                                             llvm::BasicBlock &terminatorBlock,
1006*9880d681SAndroid Build Coastguard Worker                                             llvm::BasicBlock &unwindResumeBlock,
1007*9880d681SAndroid Build Coastguard Worker                                             llvm::Value **exceptionCaughtFlag,
1008*9880d681SAndroid Build Coastguard Worker                                             llvm::Value **exceptionStorage,
1009*9880d681SAndroid Build Coastguard Worker                                             llvm::Value **caughtResultStorage) {
1010*9880d681SAndroid Build Coastguard Worker   assert(exceptionCaughtFlag &&
1011*9880d681SAndroid Build Coastguard Worker          "ExceptionDemo::createFinallyBlock(...):exceptionCaughtFlag "
1012*9880d681SAndroid Build Coastguard Worker          "is NULL");
1013*9880d681SAndroid Build Coastguard Worker   assert(exceptionStorage &&
1014*9880d681SAndroid Build Coastguard Worker          "ExceptionDemo::createFinallyBlock(...):exceptionStorage "
1015*9880d681SAndroid Build Coastguard Worker          "is NULL");
1016*9880d681SAndroid Build Coastguard Worker   assert(caughtResultStorage &&
1017*9880d681SAndroid Build Coastguard Worker          "ExceptionDemo::createFinallyBlock(...):caughtResultStorage "
1018*9880d681SAndroid Build Coastguard Worker          "is NULL");
1019*9880d681SAndroid Build Coastguard Worker 
1020*9880d681SAndroid Build Coastguard Worker   *exceptionCaughtFlag = createEntryBlockAlloca(toAddTo,
1021*9880d681SAndroid Build Coastguard Worker                                          "exceptionCaught",
1022*9880d681SAndroid Build Coastguard Worker                                          ourExceptionNotThrownState->getType(),
1023*9880d681SAndroid Build Coastguard Worker                                          ourExceptionNotThrownState);
1024*9880d681SAndroid Build Coastguard Worker 
1025*9880d681SAndroid Build Coastguard Worker   llvm::PointerType *exceptionStorageType = builder.getInt8PtrTy();
1026*9880d681SAndroid Build Coastguard Worker   *exceptionStorage = createEntryBlockAlloca(toAddTo,
1027*9880d681SAndroid Build Coastguard Worker                                              "exceptionStorage",
1028*9880d681SAndroid Build Coastguard Worker                                              exceptionStorageType,
1029*9880d681SAndroid Build Coastguard Worker                                              llvm::ConstantPointerNull::get(
1030*9880d681SAndroid Build Coastguard Worker                                                exceptionStorageType));
1031*9880d681SAndroid Build Coastguard Worker   *caughtResultStorage = createEntryBlockAlloca(toAddTo,
1032*9880d681SAndroid Build Coastguard Worker                                               "caughtResultStorage",
1033*9880d681SAndroid Build Coastguard Worker                                               ourCaughtResultType,
1034*9880d681SAndroid Build Coastguard Worker                                               llvm::ConstantAggregateZero::get(
1035*9880d681SAndroid Build Coastguard Worker                                                 ourCaughtResultType));
1036*9880d681SAndroid Build Coastguard Worker 
1037*9880d681SAndroid Build Coastguard Worker   llvm::BasicBlock *ret = llvm::BasicBlock::Create(context,
1038*9880d681SAndroid Build Coastguard Worker                                                    blockName,
1039*9880d681SAndroid Build Coastguard Worker                                                    &toAddTo);
1040*9880d681SAndroid Build Coastguard Worker 
1041*9880d681SAndroid Build Coastguard Worker   builder.SetInsertPoint(ret);
1042*9880d681SAndroid Build Coastguard Worker 
1043*9880d681SAndroid Build Coastguard Worker   std::ostringstream bufferToPrint;
1044*9880d681SAndroid Build Coastguard Worker   bufferToPrint << "Gen: Executing finally block "
1045*9880d681SAndroid Build Coastguard Worker     << blockName << " in " << functionId << "\n";
1046*9880d681SAndroid Build Coastguard Worker   generateStringPrint(context,
1047*9880d681SAndroid Build Coastguard Worker                       module,
1048*9880d681SAndroid Build Coastguard Worker                       builder,
1049*9880d681SAndroid Build Coastguard Worker                       bufferToPrint.str(),
1050*9880d681SAndroid Build Coastguard Worker                       USE_GLOBAL_STR_CONSTS);
1051*9880d681SAndroid Build Coastguard Worker 
1052*9880d681SAndroid Build Coastguard Worker   llvm::SwitchInst *theSwitch = builder.CreateSwitch(builder.CreateLoad(
1053*9880d681SAndroid Build Coastguard Worker                                                        *exceptionCaughtFlag),
1054*9880d681SAndroid Build Coastguard Worker                                                      &terminatorBlock,
1055*9880d681SAndroid Build Coastguard Worker                                                      2);
1056*9880d681SAndroid Build Coastguard Worker   theSwitch->addCase(ourExceptionCaughtState, &terminatorBlock);
1057*9880d681SAndroid Build Coastguard Worker   theSwitch->addCase(ourExceptionThrownState, &unwindResumeBlock);
1058*9880d681SAndroid Build Coastguard Worker 
1059*9880d681SAndroid Build Coastguard Worker   return(ret);
1060*9880d681SAndroid Build Coastguard Worker }
1061*9880d681SAndroid Build Coastguard Worker 
1062*9880d681SAndroid Build Coastguard Worker 
1063*9880d681SAndroid Build Coastguard Worker /// Generates catch block semantics which print a string to indicate type of
1064*9880d681SAndroid Build Coastguard Worker /// catch executed, sets an exception caught flag, and executes passed in
1065*9880d681SAndroid Build Coastguard Worker /// end block (terminator block).
1066*9880d681SAndroid Build Coastguard Worker /// @param context llvm context
1067*9880d681SAndroid Build Coastguard Worker /// @param module code for module instance
1068*9880d681SAndroid Build Coastguard Worker /// @param builder builder instance
1069*9880d681SAndroid Build Coastguard Worker /// @param toAddTo parent function to add block to
1070*9880d681SAndroid Build Coastguard Worker /// @param blockName block name of new "catch" block.
1071*9880d681SAndroid Build Coastguard Worker /// @param functionId output id used for printing
1072*9880d681SAndroid Build Coastguard Worker /// @param terminatorBlock terminator "end" block
1073*9880d681SAndroid Build Coastguard Worker /// @param exceptionCaughtFlag exception caught/thrown status
1074*9880d681SAndroid Build Coastguard Worker /// @returns newly created block
createCatchBlock(llvm::LLVMContext & context,llvm::Module & module,llvm::IRBuilder<> & builder,llvm::Function & toAddTo,std::string & blockName,std::string & functionId,llvm::BasicBlock & terminatorBlock,llvm::Value & exceptionCaughtFlag)1075*9880d681SAndroid Build Coastguard Worker static llvm::BasicBlock *createCatchBlock(llvm::LLVMContext &context,
1076*9880d681SAndroid Build Coastguard Worker                                           llvm::Module &module,
1077*9880d681SAndroid Build Coastguard Worker                                           llvm::IRBuilder<> &builder,
1078*9880d681SAndroid Build Coastguard Worker                                           llvm::Function &toAddTo,
1079*9880d681SAndroid Build Coastguard Worker                                           std::string &blockName,
1080*9880d681SAndroid Build Coastguard Worker                                           std::string &functionId,
1081*9880d681SAndroid Build Coastguard Worker                                           llvm::BasicBlock &terminatorBlock,
1082*9880d681SAndroid Build Coastguard Worker                                           llvm::Value &exceptionCaughtFlag) {
1083*9880d681SAndroid Build Coastguard Worker 
1084*9880d681SAndroid Build Coastguard Worker   llvm::BasicBlock *ret = llvm::BasicBlock::Create(context,
1085*9880d681SAndroid Build Coastguard Worker                                                    blockName,
1086*9880d681SAndroid Build Coastguard Worker                                                    &toAddTo);
1087*9880d681SAndroid Build Coastguard Worker 
1088*9880d681SAndroid Build Coastguard Worker   builder.SetInsertPoint(ret);
1089*9880d681SAndroid Build Coastguard Worker 
1090*9880d681SAndroid Build Coastguard Worker   std::ostringstream bufferToPrint;
1091*9880d681SAndroid Build Coastguard Worker   bufferToPrint << "Gen: Executing catch block "
1092*9880d681SAndroid Build Coastguard Worker   << blockName
1093*9880d681SAndroid Build Coastguard Worker   << " in "
1094*9880d681SAndroid Build Coastguard Worker   << functionId
1095*9880d681SAndroid Build Coastguard Worker   << std::endl;
1096*9880d681SAndroid Build Coastguard Worker   generateStringPrint(context,
1097*9880d681SAndroid Build Coastguard Worker                       module,
1098*9880d681SAndroid Build Coastguard Worker                       builder,
1099*9880d681SAndroid Build Coastguard Worker                       bufferToPrint.str(),
1100*9880d681SAndroid Build Coastguard Worker                       USE_GLOBAL_STR_CONSTS);
1101*9880d681SAndroid Build Coastguard Worker   builder.CreateStore(ourExceptionCaughtState, &exceptionCaughtFlag);
1102*9880d681SAndroid Build Coastguard Worker   builder.CreateBr(&terminatorBlock);
1103*9880d681SAndroid Build Coastguard Worker 
1104*9880d681SAndroid Build Coastguard Worker   return(ret);
1105*9880d681SAndroid Build Coastguard Worker }
1106*9880d681SAndroid Build Coastguard Worker 
1107*9880d681SAndroid Build Coastguard Worker 
1108*9880d681SAndroid Build Coastguard Worker /// Generates a function which invokes a function (toInvoke) and, whose
1109*9880d681SAndroid Build Coastguard Worker /// unwind block will "catch" the type info types correspondingly held in the
1110*9880d681SAndroid Build Coastguard Worker /// exceptionTypesToCatch argument. If the toInvoke function throws an
1111*9880d681SAndroid Build Coastguard Worker /// exception which does not match any type info types contained in
1112*9880d681SAndroid Build Coastguard Worker /// exceptionTypesToCatch, the generated code will call _Unwind_Resume
1113*9880d681SAndroid Build Coastguard Worker /// with the raised exception. On the other hand the generated code will
1114*9880d681SAndroid Build Coastguard Worker /// normally exit if the toInvoke function does not throw an exception.
1115*9880d681SAndroid Build Coastguard Worker /// The generated "finally" block is always run regardless of the cause of
1116*9880d681SAndroid Build Coastguard Worker /// the generated function exit.
1117*9880d681SAndroid Build Coastguard Worker /// The generated function is returned after being verified.
1118*9880d681SAndroid Build Coastguard Worker /// @param module code for module instance
1119*9880d681SAndroid Build Coastguard Worker /// @param builder builder instance
1120*9880d681SAndroid Build Coastguard Worker /// @param fpm a function pass manager holding optional IR to IR
1121*9880d681SAndroid Build Coastguard Worker ///        transformations
1122*9880d681SAndroid Build Coastguard Worker /// @param toInvoke inner function to invoke
1123*9880d681SAndroid Build Coastguard Worker /// @param ourId id used to printing purposes
1124*9880d681SAndroid Build Coastguard Worker /// @param numExceptionsToCatch length of exceptionTypesToCatch array
1125*9880d681SAndroid Build Coastguard Worker /// @param exceptionTypesToCatch array of type info types to "catch"
1126*9880d681SAndroid Build Coastguard Worker /// @returns generated function
createCatchWrappedInvokeFunction(llvm::Module & module,llvm::IRBuilder<> & builder,llvm::legacy::FunctionPassManager & fpm,llvm::Function & toInvoke,std::string ourId,unsigned numExceptionsToCatch,unsigned exceptionTypesToCatch[])1127*9880d681SAndroid Build Coastguard Worker static llvm::Function *createCatchWrappedInvokeFunction(
1128*9880d681SAndroid Build Coastguard Worker     llvm::Module &module, llvm::IRBuilder<> &builder,
1129*9880d681SAndroid Build Coastguard Worker     llvm::legacy::FunctionPassManager &fpm, llvm::Function &toInvoke,
1130*9880d681SAndroid Build Coastguard Worker     std::string ourId, unsigned numExceptionsToCatch,
1131*9880d681SAndroid Build Coastguard Worker     unsigned exceptionTypesToCatch[]) {
1132*9880d681SAndroid Build Coastguard Worker 
1133*9880d681SAndroid Build Coastguard Worker   llvm::LLVMContext &context = module.getContext();
1134*9880d681SAndroid Build Coastguard Worker   llvm::Function *toPrint32Int = module.getFunction("print32Int");
1135*9880d681SAndroid Build Coastguard Worker 
1136*9880d681SAndroid Build Coastguard Worker   ArgTypes argTypes;
1137*9880d681SAndroid Build Coastguard Worker   argTypes.push_back(builder.getInt32Ty());
1138*9880d681SAndroid Build Coastguard Worker 
1139*9880d681SAndroid Build Coastguard Worker   ArgNames argNames;
1140*9880d681SAndroid Build Coastguard Worker   argNames.push_back("exceptTypeToThrow");
1141*9880d681SAndroid Build Coastguard Worker 
1142*9880d681SAndroid Build Coastguard Worker   llvm::Function *ret = createFunction(module,
1143*9880d681SAndroid Build Coastguard Worker                                        builder.getVoidTy(),
1144*9880d681SAndroid Build Coastguard Worker                                        argTypes,
1145*9880d681SAndroid Build Coastguard Worker                                        argNames,
1146*9880d681SAndroid Build Coastguard Worker                                        ourId,
1147*9880d681SAndroid Build Coastguard Worker                                        llvm::Function::ExternalLinkage,
1148*9880d681SAndroid Build Coastguard Worker                                        false,
1149*9880d681SAndroid Build Coastguard Worker                                        false);
1150*9880d681SAndroid Build Coastguard Worker 
1151*9880d681SAndroid Build Coastguard Worker   // Block which calls invoke
1152*9880d681SAndroid Build Coastguard Worker   llvm::BasicBlock *entryBlock = llvm::BasicBlock::Create(context,
1153*9880d681SAndroid Build Coastguard Worker                                                           "entry",
1154*9880d681SAndroid Build Coastguard Worker                                                           ret);
1155*9880d681SAndroid Build Coastguard Worker   // Normal block for invoke
1156*9880d681SAndroid Build Coastguard Worker   llvm::BasicBlock *normalBlock = llvm::BasicBlock::Create(context,
1157*9880d681SAndroid Build Coastguard Worker                                                            "normal",
1158*9880d681SAndroid Build Coastguard Worker                                                            ret);
1159*9880d681SAndroid Build Coastguard Worker   // Unwind block for invoke
1160*9880d681SAndroid Build Coastguard Worker   llvm::BasicBlock *exceptionBlock = llvm::BasicBlock::Create(context,
1161*9880d681SAndroid Build Coastguard Worker                                                               "exception",
1162*9880d681SAndroid Build Coastguard Worker                                                               ret);
1163*9880d681SAndroid Build Coastguard Worker 
1164*9880d681SAndroid Build Coastguard Worker   // Block which routes exception to correct catch handler block
1165*9880d681SAndroid Build Coastguard Worker   llvm::BasicBlock *exceptionRouteBlock = llvm::BasicBlock::Create(context,
1166*9880d681SAndroid Build Coastguard Worker                                                              "exceptionRoute",
1167*9880d681SAndroid Build Coastguard Worker                                                              ret);
1168*9880d681SAndroid Build Coastguard Worker 
1169*9880d681SAndroid Build Coastguard Worker   // Foreign exception handler
1170*9880d681SAndroid Build Coastguard Worker   llvm::BasicBlock *externalExceptionBlock = llvm::BasicBlock::Create(context,
1171*9880d681SAndroid Build Coastguard Worker                                                           "externalException",
1172*9880d681SAndroid Build Coastguard Worker                                                           ret);
1173*9880d681SAndroid Build Coastguard Worker 
1174*9880d681SAndroid Build Coastguard Worker   // Block which calls _Unwind_Resume
1175*9880d681SAndroid Build Coastguard Worker   llvm::BasicBlock *unwindResumeBlock = llvm::BasicBlock::Create(context,
1176*9880d681SAndroid Build Coastguard Worker                                                                "unwindResume",
1177*9880d681SAndroid Build Coastguard Worker                                                                ret);
1178*9880d681SAndroid Build Coastguard Worker 
1179*9880d681SAndroid Build Coastguard Worker   // Clean up block which delete exception if needed
1180*9880d681SAndroid Build Coastguard Worker   llvm::BasicBlock *endBlock = llvm::BasicBlock::Create(context, "end", ret);
1181*9880d681SAndroid Build Coastguard Worker 
1182*9880d681SAndroid Build Coastguard Worker   std::string nextName;
1183*9880d681SAndroid Build Coastguard Worker   std::vector<llvm::BasicBlock*> catchBlocks(numExceptionsToCatch);
1184*9880d681SAndroid Build Coastguard Worker   llvm::Value *exceptionCaughtFlag = NULL;
1185*9880d681SAndroid Build Coastguard Worker   llvm::Value *exceptionStorage = NULL;
1186*9880d681SAndroid Build Coastguard Worker   llvm::Value *caughtResultStorage = NULL;
1187*9880d681SAndroid Build Coastguard Worker 
1188*9880d681SAndroid Build Coastguard Worker   // Finally block which will branch to unwindResumeBlock if
1189*9880d681SAndroid Build Coastguard Worker   // exception is not caught. Initializes/allocates stack locations.
1190*9880d681SAndroid Build Coastguard Worker   llvm::BasicBlock *finallyBlock = createFinallyBlock(context,
1191*9880d681SAndroid Build Coastguard Worker                                                       module,
1192*9880d681SAndroid Build Coastguard Worker                                                       builder,
1193*9880d681SAndroid Build Coastguard Worker                                                       *ret,
1194*9880d681SAndroid Build Coastguard Worker                                                       nextName = "finally",
1195*9880d681SAndroid Build Coastguard Worker                                                       ourId,
1196*9880d681SAndroid Build Coastguard Worker                                                       *endBlock,
1197*9880d681SAndroid Build Coastguard Worker                                                       *unwindResumeBlock,
1198*9880d681SAndroid Build Coastguard Worker                                                       &exceptionCaughtFlag,
1199*9880d681SAndroid Build Coastguard Worker                                                       &exceptionStorage,
1200*9880d681SAndroid Build Coastguard Worker                                                       &caughtResultStorage
1201*9880d681SAndroid Build Coastguard Worker                                                       );
1202*9880d681SAndroid Build Coastguard Worker 
1203*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0; i < numExceptionsToCatch; ++i) {
1204*9880d681SAndroid Build Coastguard Worker     nextName = ourTypeInfoNames[exceptionTypesToCatch[i]];
1205*9880d681SAndroid Build Coastguard Worker 
1206*9880d681SAndroid Build Coastguard Worker     // One catch block per type info to be caught
1207*9880d681SAndroid Build Coastguard Worker     catchBlocks[i] = createCatchBlock(context,
1208*9880d681SAndroid Build Coastguard Worker                                       module,
1209*9880d681SAndroid Build Coastguard Worker                                       builder,
1210*9880d681SAndroid Build Coastguard Worker                                       *ret,
1211*9880d681SAndroid Build Coastguard Worker                                       nextName,
1212*9880d681SAndroid Build Coastguard Worker                                       ourId,
1213*9880d681SAndroid Build Coastguard Worker                                       *finallyBlock,
1214*9880d681SAndroid Build Coastguard Worker                                       *exceptionCaughtFlag);
1215*9880d681SAndroid Build Coastguard Worker   }
1216*9880d681SAndroid Build Coastguard Worker 
1217*9880d681SAndroid Build Coastguard Worker   // Entry Block
1218*9880d681SAndroid Build Coastguard Worker 
1219*9880d681SAndroid Build Coastguard Worker   builder.SetInsertPoint(entryBlock);
1220*9880d681SAndroid Build Coastguard Worker 
1221*9880d681SAndroid Build Coastguard Worker   std::vector<llvm::Value*> args;
1222*9880d681SAndroid Build Coastguard Worker   args.push_back(namedValues["exceptTypeToThrow"]);
1223*9880d681SAndroid Build Coastguard Worker   builder.CreateInvoke(&toInvoke,
1224*9880d681SAndroid Build Coastguard Worker                        normalBlock,
1225*9880d681SAndroid Build Coastguard Worker                        exceptionBlock,
1226*9880d681SAndroid Build Coastguard Worker                        args);
1227*9880d681SAndroid Build Coastguard Worker 
1228*9880d681SAndroid Build Coastguard Worker   // End Block
1229*9880d681SAndroid Build Coastguard Worker 
1230*9880d681SAndroid Build Coastguard Worker   builder.SetInsertPoint(endBlock);
1231*9880d681SAndroid Build Coastguard Worker 
1232*9880d681SAndroid Build Coastguard Worker   generateStringPrint(context,
1233*9880d681SAndroid Build Coastguard Worker                       module,
1234*9880d681SAndroid Build Coastguard Worker                       builder,
1235*9880d681SAndroid Build Coastguard Worker                       "Gen: In end block: exiting in " + ourId + ".\n",
1236*9880d681SAndroid Build Coastguard Worker                       USE_GLOBAL_STR_CONSTS);
1237*9880d681SAndroid Build Coastguard Worker   llvm::Function *deleteOurException = module.getFunction("deleteOurException");
1238*9880d681SAndroid Build Coastguard Worker 
1239*9880d681SAndroid Build Coastguard Worker   // Note: function handles NULL exceptions
1240*9880d681SAndroid Build Coastguard Worker   builder.CreateCall(deleteOurException,
1241*9880d681SAndroid Build Coastguard Worker                      builder.CreateLoad(exceptionStorage));
1242*9880d681SAndroid Build Coastguard Worker   builder.CreateRetVoid();
1243*9880d681SAndroid Build Coastguard Worker 
1244*9880d681SAndroid Build Coastguard Worker   // Normal Block
1245*9880d681SAndroid Build Coastguard Worker 
1246*9880d681SAndroid Build Coastguard Worker   builder.SetInsertPoint(normalBlock);
1247*9880d681SAndroid Build Coastguard Worker 
1248*9880d681SAndroid Build Coastguard Worker   generateStringPrint(context,
1249*9880d681SAndroid Build Coastguard Worker                       module,
1250*9880d681SAndroid Build Coastguard Worker                       builder,
1251*9880d681SAndroid Build Coastguard Worker                       "Gen: No exception in " + ourId + "!\n",
1252*9880d681SAndroid Build Coastguard Worker                       USE_GLOBAL_STR_CONSTS);
1253*9880d681SAndroid Build Coastguard Worker 
1254*9880d681SAndroid Build Coastguard Worker   // Finally block is always called
1255*9880d681SAndroid Build Coastguard Worker   builder.CreateBr(finallyBlock);
1256*9880d681SAndroid Build Coastguard Worker 
1257*9880d681SAndroid Build Coastguard Worker   // Unwind Resume Block
1258*9880d681SAndroid Build Coastguard Worker 
1259*9880d681SAndroid Build Coastguard Worker   builder.SetInsertPoint(unwindResumeBlock);
1260*9880d681SAndroid Build Coastguard Worker 
1261*9880d681SAndroid Build Coastguard Worker   builder.CreateResume(builder.CreateLoad(caughtResultStorage));
1262*9880d681SAndroid Build Coastguard Worker 
1263*9880d681SAndroid Build Coastguard Worker   // Exception Block
1264*9880d681SAndroid Build Coastguard Worker 
1265*9880d681SAndroid Build Coastguard Worker   builder.SetInsertPoint(exceptionBlock);
1266*9880d681SAndroid Build Coastguard Worker 
1267*9880d681SAndroid Build Coastguard Worker   llvm::Function *personality = module.getFunction("ourPersonality");
1268*9880d681SAndroid Build Coastguard Worker   ret->setPersonalityFn(personality);
1269*9880d681SAndroid Build Coastguard Worker 
1270*9880d681SAndroid Build Coastguard Worker   llvm::LandingPadInst *caughtResult =
1271*9880d681SAndroid Build Coastguard Worker     builder.CreateLandingPad(ourCaughtResultType,
1272*9880d681SAndroid Build Coastguard Worker                              numExceptionsToCatch,
1273*9880d681SAndroid Build Coastguard Worker                              "landingPad");
1274*9880d681SAndroid Build Coastguard Worker 
1275*9880d681SAndroid Build Coastguard Worker   caughtResult->setCleanup(true);
1276*9880d681SAndroid Build Coastguard Worker 
1277*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0; i < numExceptionsToCatch; ++i) {
1278*9880d681SAndroid Build Coastguard Worker     // Set up type infos to be caught
1279*9880d681SAndroid Build Coastguard Worker     caughtResult->addClause(module.getGlobalVariable(
1280*9880d681SAndroid Build Coastguard Worker                              ourTypeInfoNames[exceptionTypesToCatch[i]]));
1281*9880d681SAndroid Build Coastguard Worker   }
1282*9880d681SAndroid Build Coastguard Worker 
1283*9880d681SAndroid Build Coastguard Worker   llvm::Value *unwindException = builder.CreateExtractValue(caughtResult, 0);
1284*9880d681SAndroid Build Coastguard Worker   llvm::Value *retTypeInfoIndex = builder.CreateExtractValue(caughtResult, 1);
1285*9880d681SAndroid Build Coastguard Worker 
1286*9880d681SAndroid Build Coastguard Worker   // FIXME: Redundant storage which, beyond utilizing value of
1287*9880d681SAndroid Build Coastguard Worker   //        caughtResultStore for unwindException storage, may be alleviated
1288*9880d681SAndroid Build Coastguard Worker   //        altogether with a block rearrangement
1289*9880d681SAndroid Build Coastguard Worker   builder.CreateStore(caughtResult, caughtResultStorage);
1290*9880d681SAndroid Build Coastguard Worker   builder.CreateStore(unwindException, exceptionStorage);
1291*9880d681SAndroid Build Coastguard Worker   builder.CreateStore(ourExceptionThrownState, exceptionCaughtFlag);
1292*9880d681SAndroid Build Coastguard Worker 
1293*9880d681SAndroid Build Coastguard Worker   // Retrieve exception_class member from thrown exception
1294*9880d681SAndroid Build Coastguard Worker   // (_Unwind_Exception instance). This member tells us whether or not
1295*9880d681SAndroid Build Coastguard Worker   // the exception is foreign.
1296*9880d681SAndroid Build Coastguard Worker   llvm::Value *unwindExceptionClass =
1297*9880d681SAndroid Build Coastguard Worker       builder.CreateLoad(builder.CreateStructGEP(
1298*9880d681SAndroid Build Coastguard Worker           ourUnwindExceptionType,
1299*9880d681SAndroid Build Coastguard Worker           builder.CreatePointerCast(unwindException,
1300*9880d681SAndroid Build Coastguard Worker                                     ourUnwindExceptionType->getPointerTo()),
1301*9880d681SAndroid Build Coastguard Worker           0));
1302*9880d681SAndroid Build Coastguard Worker 
1303*9880d681SAndroid Build Coastguard Worker   // Branch to the externalExceptionBlock if the exception is foreign or
1304*9880d681SAndroid Build Coastguard Worker   // to a catch router if not. Either way the finally block will be run.
1305*9880d681SAndroid Build Coastguard Worker   builder.CreateCondBr(builder.CreateICmpEQ(unwindExceptionClass,
1306*9880d681SAndroid Build Coastguard Worker                             llvm::ConstantInt::get(builder.getInt64Ty(),
1307*9880d681SAndroid Build Coastguard Worker                                                    ourBaseExceptionClass)),
1308*9880d681SAndroid Build Coastguard Worker                        exceptionRouteBlock,
1309*9880d681SAndroid Build Coastguard Worker                        externalExceptionBlock);
1310*9880d681SAndroid Build Coastguard Worker 
1311*9880d681SAndroid Build Coastguard Worker   // External Exception Block
1312*9880d681SAndroid Build Coastguard Worker 
1313*9880d681SAndroid Build Coastguard Worker   builder.SetInsertPoint(externalExceptionBlock);
1314*9880d681SAndroid Build Coastguard Worker 
1315*9880d681SAndroid Build Coastguard Worker   generateStringPrint(context,
1316*9880d681SAndroid Build Coastguard Worker                       module,
1317*9880d681SAndroid Build Coastguard Worker                       builder,
1318*9880d681SAndroid Build Coastguard Worker                       "Gen: Foreign exception received.\n",
1319*9880d681SAndroid Build Coastguard Worker                       USE_GLOBAL_STR_CONSTS);
1320*9880d681SAndroid Build Coastguard Worker 
1321*9880d681SAndroid Build Coastguard Worker   // Branch to the finally block
1322*9880d681SAndroid Build Coastguard Worker   builder.CreateBr(finallyBlock);
1323*9880d681SAndroid Build Coastguard Worker 
1324*9880d681SAndroid Build Coastguard Worker   // Exception Route Block
1325*9880d681SAndroid Build Coastguard Worker 
1326*9880d681SAndroid Build Coastguard Worker   builder.SetInsertPoint(exceptionRouteBlock);
1327*9880d681SAndroid Build Coastguard Worker 
1328*9880d681SAndroid Build Coastguard Worker   // Casts exception pointer (_Unwind_Exception instance) to parent
1329*9880d681SAndroid Build Coastguard Worker   // (OurException instance).
1330*9880d681SAndroid Build Coastguard Worker   //
1331*9880d681SAndroid Build Coastguard Worker   // Note: ourBaseFromUnwindOffset is usually negative
1332*9880d681SAndroid Build Coastguard Worker   llvm::Value *typeInfoThrown = builder.CreatePointerCast(
1333*9880d681SAndroid Build Coastguard Worker                                   builder.CreateConstGEP1_64(unwindException,
1334*9880d681SAndroid Build Coastguard Worker                                                        ourBaseFromUnwindOffset),
1335*9880d681SAndroid Build Coastguard Worker                                   ourExceptionType->getPointerTo());
1336*9880d681SAndroid Build Coastguard Worker 
1337*9880d681SAndroid Build Coastguard Worker   // Retrieve thrown exception type info type
1338*9880d681SAndroid Build Coastguard Worker   //
1339*9880d681SAndroid Build Coastguard Worker   // Note: Index is not relative to pointer but instead to structure
1340*9880d681SAndroid Build Coastguard Worker   //       unlike a true getelementptr (GEP) instruction
1341*9880d681SAndroid Build Coastguard Worker   typeInfoThrown = builder.CreateStructGEP(ourExceptionType, typeInfoThrown, 0);
1342*9880d681SAndroid Build Coastguard Worker 
1343*9880d681SAndroid Build Coastguard Worker   llvm::Value *typeInfoThrownType =
1344*9880d681SAndroid Build Coastguard Worker       builder.CreateStructGEP(builder.getInt8PtrTy(), typeInfoThrown, 0);
1345*9880d681SAndroid Build Coastguard Worker 
1346*9880d681SAndroid Build Coastguard Worker   generateIntegerPrint(context,
1347*9880d681SAndroid Build Coastguard Worker                        module,
1348*9880d681SAndroid Build Coastguard Worker                        builder,
1349*9880d681SAndroid Build Coastguard Worker                        *toPrint32Int,
1350*9880d681SAndroid Build Coastguard Worker                        *(builder.CreateLoad(typeInfoThrownType)),
1351*9880d681SAndroid Build Coastguard Worker                        "Gen: Exception type <%d> received (stack unwound) "
1352*9880d681SAndroid Build Coastguard Worker                        " in " +
1353*9880d681SAndroid Build Coastguard Worker                        ourId +
1354*9880d681SAndroid Build Coastguard Worker                        ".\n",
1355*9880d681SAndroid Build Coastguard Worker                        USE_GLOBAL_STR_CONSTS);
1356*9880d681SAndroid Build Coastguard Worker 
1357*9880d681SAndroid Build Coastguard Worker   // Route to matched type info catch block or run cleanup finally block
1358*9880d681SAndroid Build Coastguard Worker   llvm::SwitchInst *switchToCatchBlock = builder.CreateSwitch(retTypeInfoIndex,
1359*9880d681SAndroid Build Coastguard Worker                                                           finallyBlock,
1360*9880d681SAndroid Build Coastguard Worker                                                           numExceptionsToCatch);
1361*9880d681SAndroid Build Coastguard Worker 
1362*9880d681SAndroid Build Coastguard Worker   unsigned nextTypeToCatch;
1363*9880d681SAndroid Build Coastguard Worker 
1364*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 1; i <= numExceptionsToCatch; ++i) {
1365*9880d681SAndroid Build Coastguard Worker     nextTypeToCatch = i - 1;
1366*9880d681SAndroid Build Coastguard Worker     switchToCatchBlock->addCase(llvm::ConstantInt::get(
1367*9880d681SAndroid Build Coastguard Worker                                    llvm::Type::getInt32Ty(context), i),
1368*9880d681SAndroid Build Coastguard Worker                                 catchBlocks[nextTypeToCatch]);
1369*9880d681SAndroid Build Coastguard Worker   }
1370*9880d681SAndroid Build Coastguard Worker 
1371*9880d681SAndroid Build Coastguard Worker   llvm::verifyFunction(*ret);
1372*9880d681SAndroid Build Coastguard Worker   fpm.run(*ret);
1373*9880d681SAndroid Build Coastguard Worker 
1374*9880d681SAndroid Build Coastguard Worker   return(ret);
1375*9880d681SAndroid Build Coastguard Worker }
1376*9880d681SAndroid Build Coastguard Worker 
1377*9880d681SAndroid Build Coastguard Worker 
1378*9880d681SAndroid Build Coastguard Worker /// Generates function which throws either an exception matched to a runtime
1379*9880d681SAndroid Build Coastguard Worker /// determined type info type (argument to generated function), or if this
1380*9880d681SAndroid Build Coastguard Worker /// runtime value matches nativeThrowType, throws a foreign exception by
1381*9880d681SAndroid Build Coastguard Worker /// calling nativeThrowFunct.
1382*9880d681SAndroid Build Coastguard Worker /// @param module code for module instance
1383*9880d681SAndroid Build Coastguard Worker /// @param builder builder instance
1384*9880d681SAndroid Build Coastguard Worker /// @param fpm a function pass manager holding optional IR to IR
1385*9880d681SAndroid Build Coastguard Worker ///        transformations
1386*9880d681SAndroid Build Coastguard Worker /// @param ourId id used to printing purposes
1387*9880d681SAndroid Build Coastguard Worker /// @param nativeThrowType a runtime argument of this value results in
1388*9880d681SAndroid Build Coastguard Worker ///        nativeThrowFunct being called to generate/throw exception.
1389*9880d681SAndroid Build Coastguard Worker /// @param nativeThrowFunct function which will throw a foreign exception
1390*9880d681SAndroid Build Coastguard Worker ///        if the above nativeThrowType matches generated function's arg.
1391*9880d681SAndroid Build Coastguard Worker /// @returns generated function
1392*9880d681SAndroid Build Coastguard Worker static llvm::Function *
createThrowExceptionFunction(llvm::Module & module,llvm::IRBuilder<> & builder,llvm::legacy::FunctionPassManager & fpm,std::string ourId,int32_t nativeThrowType,llvm::Function & nativeThrowFunct)1393*9880d681SAndroid Build Coastguard Worker createThrowExceptionFunction(llvm::Module &module, llvm::IRBuilder<> &builder,
1394*9880d681SAndroid Build Coastguard Worker                              llvm::legacy::FunctionPassManager &fpm,
1395*9880d681SAndroid Build Coastguard Worker                              std::string ourId, int32_t nativeThrowType,
1396*9880d681SAndroid Build Coastguard Worker                              llvm::Function &nativeThrowFunct) {
1397*9880d681SAndroid Build Coastguard Worker   llvm::LLVMContext &context = module.getContext();
1398*9880d681SAndroid Build Coastguard Worker   namedValues.clear();
1399*9880d681SAndroid Build Coastguard Worker   ArgTypes unwindArgTypes;
1400*9880d681SAndroid Build Coastguard Worker   unwindArgTypes.push_back(builder.getInt32Ty());
1401*9880d681SAndroid Build Coastguard Worker   ArgNames unwindArgNames;
1402*9880d681SAndroid Build Coastguard Worker   unwindArgNames.push_back("exceptTypeToThrow");
1403*9880d681SAndroid Build Coastguard Worker 
1404*9880d681SAndroid Build Coastguard Worker   llvm::Function *ret = createFunction(module,
1405*9880d681SAndroid Build Coastguard Worker                                        builder.getVoidTy(),
1406*9880d681SAndroid Build Coastguard Worker                                        unwindArgTypes,
1407*9880d681SAndroid Build Coastguard Worker                                        unwindArgNames,
1408*9880d681SAndroid Build Coastguard Worker                                        ourId,
1409*9880d681SAndroid Build Coastguard Worker                                        llvm::Function::ExternalLinkage,
1410*9880d681SAndroid Build Coastguard Worker                                        false,
1411*9880d681SAndroid Build Coastguard Worker                                        false);
1412*9880d681SAndroid Build Coastguard Worker 
1413*9880d681SAndroid Build Coastguard Worker   // Throws either one of our exception or a native C++ exception depending
1414*9880d681SAndroid Build Coastguard Worker   // on a runtime argument value containing a type info type.
1415*9880d681SAndroid Build Coastguard Worker   llvm::BasicBlock *entryBlock = llvm::BasicBlock::Create(context,
1416*9880d681SAndroid Build Coastguard Worker                                                           "entry",
1417*9880d681SAndroid Build Coastguard Worker                                                           ret);
1418*9880d681SAndroid Build Coastguard Worker   // Throws a foreign exception
1419*9880d681SAndroid Build Coastguard Worker   llvm::BasicBlock *nativeThrowBlock = llvm::BasicBlock::Create(context,
1420*9880d681SAndroid Build Coastguard Worker                                                                 "nativeThrow",
1421*9880d681SAndroid Build Coastguard Worker                                                                 ret);
1422*9880d681SAndroid Build Coastguard Worker   // Throws one of our Exceptions
1423*9880d681SAndroid Build Coastguard Worker   llvm::BasicBlock *generatedThrowBlock = llvm::BasicBlock::Create(context,
1424*9880d681SAndroid Build Coastguard Worker                                                              "generatedThrow",
1425*9880d681SAndroid Build Coastguard Worker                                                              ret);
1426*9880d681SAndroid Build Coastguard Worker   // Retrieved runtime type info type to throw
1427*9880d681SAndroid Build Coastguard Worker   llvm::Value *exceptionType = namedValues["exceptTypeToThrow"];
1428*9880d681SAndroid Build Coastguard Worker 
1429*9880d681SAndroid Build Coastguard Worker   // nativeThrowBlock block
1430*9880d681SAndroid Build Coastguard Worker 
1431*9880d681SAndroid Build Coastguard Worker   builder.SetInsertPoint(nativeThrowBlock);
1432*9880d681SAndroid Build Coastguard Worker 
1433*9880d681SAndroid Build Coastguard Worker   // Throws foreign exception
1434*9880d681SAndroid Build Coastguard Worker   builder.CreateCall(&nativeThrowFunct, exceptionType);
1435*9880d681SAndroid Build Coastguard Worker   builder.CreateUnreachable();
1436*9880d681SAndroid Build Coastguard Worker 
1437*9880d681SAndroid Build Coastguard Worker   // entry block
1438*9880d681SAndroid Build Coastguard Worker 
1439*9880d681SAndroid Build Coastguard Worker   builder.SetInsertPoint(entryBlock);
1440*9880d681SAndroid Build Coastguard Worker 
1441*9880d681SAndroid Build Coastguard Worker   llvm::Function *toPrint32Int = module.getFunction("print32Int");
1442*9880d681SAndroid Build Coastguard Worker   generateIntegerPrint(context,
1443*9880d681SAndroid Build Coastguard Worker                        module,
1444*9880d681SAndroid Build Coastguard Worker                        builder,
1445*9880d681SAndroid Build Coastguard Worker                        *toPrint32Int,
1446*9880d681SAndroid Build Coastguard Worker                        *exceptionType,
1447*9880d681SAndroid Build Coastguard Worker                        "\nGen: About to throw exception type <%d> in " +
1448*9880d681SAndroid Build Coastguard Worker                        ourId +
1449*9880d681SAndroid Build Coastguard Worker                        ".\n",
1450*9880d681SAndroid Build Coastguard Worker                        USE_GLOBAL_STR_CONSTS);
1451*9880d681SAndroid Build Coastguard Worker 
1452*9880d681SAndroid Build Coastguard Worker   // Switches on runtime type info type value to determine whether or not
1453*9880d681SAndroid Build Coastguard Worker   // a foreign exception is thrown. Defaults to throwing one of our
1454*9880d681SAndroid Build Coastguard Worker   // generated exceptions.
1455*9880d681SAndroid Build Coastguard Worker   llvm::SwitchInst *theSwitch = builder.CreateSwitch(exceptionType,
1456*9880d681SAndroid Build Coastguard Worker                                                      generatedThrowBlock,
1457*9880d681SAndroid Build Coastguard Worker                                                      1);
1458*9880d681SAndroid Build Coastguard Worker 
1459*9880d681SAndroid Build Coastguard Worker   theSwitch->addCase(llvm::ConstantInt::get(llvm::Type::getInt32Ty(context),
1460*9880d681SAndroid Build Coastguard Worker                                             nativeThrowType),
1461*9880d681SAndroid Build Coastguard Worker                      nativeThrowBlock);
1462*9880d681SAndroid Build Coastguard Worker 
1463*9880d681SAndroid Build Coastguard Worker   // generatedThrow block
1464*9880d681SAndroid Build Coastguard Worker 
1465*9880d681SAndroid Build Coastguard Worker   builder.SetInsertPoint(generatedThrowBlock);
1466*9880d681SAndroid Build Coastguard Worker 
1467*9880d681SAndroid Build Coastguard Worker   llvm::Function *createOurException = module.getFunction("createOurException");
1468*9880d681SAndroid Build Coastguard Worker   llvm::Function *raiseOurException = module.getFunction(
1469*9880d681SAndroid Build Coastguard Worker                                         "_Unwind_RaiseException");
1470*9880d681SAndroid Build Coastguard Worker 
1471*9880d681SAndroid Build Coastguard Worker   // Creates exception to throw with runtime type info type.
1472*9880d681SAndroid Build Coastguard Worker   llvm::Value *exception = builder.CreateCall(createOurException,
1473*9880d681SAndroid Build Coastguard Worker                                               namedValues["exceptTypeToThrow"]);
1474*9880d681SAndroid Build Coastguard Worker 
1475*9880d681SAndroid Build Coastguard Worker   // Throw generated Exception
1476*9880d681SAndroid Build Coastguard Worker   builder.CreateCall(raiseOurException, exception);
1477*9880d681SAndroid Build Coastguard Worker   builder.CreateUnreachable();
1478*9880d681SAndroid Build Coastguard Worker 
1479*9880d681SAndroid Build Coastguard Worker   llvm::verifyFunction(*ret);
1480*9880d681SAndroid Build Coastguard Worker   fpm.run(*ret);
1481*9880d681SAndroid Build Coastguard Worker 
1482*9880d681SAndroid Build Coastguard Worker   return(ret);
1483*9880d681SAndroid Build Coastguard Worker }
1484*9880d681SAndroid Build Coastguard Worker 
1485*9880d681SAndroid Build Coastguard Worker static void createStandardUtilityFunctions(unsigned numTypeInfos,
1486*9880d681SAndroid Build Coastguard Worker                                            llvm::Module &module,
1487*9880d681SAndroid Build Coastguard Worker                                            llvm::IRBuilder<> &builder);
1488*9880d681SAndroid Build Coastguard Worker 
1489*9880d681SAndroid Build Coastguard Worker /// Creates test code by generating and organizing these functions into the
1490*9880d681SAndroid Build Coastguard Worker /// test case. The test case consists of an outer function setup to invoke
1491*9880d681SAndroid Build Coastguard Worker /// an inner function within an environment having multiple catch and single
1492*9880d681SAndroid Build Coastguard Worker /// finally blocks. This inner function is also setup to invoke a throw
1493*9880d681SAndroid Build Coastguard Worker /// function within an evironment similar in nature to the outer function's
1494*9880d681SAndroid Build Coastguard Worker /// catch and finally blocks. Each of these two functions catch mutually
1495*9880d681SAndroid Build Coastguard Worker /// exclusive subsets (even or odd) of the type info types configured
1496*9880d681SAndroid Build Coastguard Worker /// for this this. All generated functions have a runtime argument which
1497*9880d681SAndroid Build Coastguard Worker /// holds a type info type to throw that each function takes and passes it
1498*9880d681SAndroid Build Coastguard Worker /// to the inner one if such a inner function exists. This type info type is
1499*9880d681SAndroid Build Coastguard Worker /// looked at by the generated throw function to see whether or not it should
1500*9880d681SAndroid Build Coastguard Worker /// throw a generated exception with the same type info type, or instead call
1501*9880d681SAndroid Build Coastguard Worker /// a supplied a function which in turn will throw a foreign exception.
1502*9880d681SAndroid Build Coastguard Worker /// @param module code for module instance
1503*9880d681SAndroid Build Coastguard Worker /// @param builder builder instance
1504*9880d681SAndroid Build Coastguard Worker /// @param fpm a function pass manager holding optional IR to IR
1505*9880d681SAndroid Build Coastguard Worker ///        transformations
1506*9880d681SAndroid Build Coastguard Worker /// @param nativeThrowFunctName name of external function which will throw
1507*9880d681SAndroid Build Coastguard Worker ///        a foreign exception
1508*9880d681SAndroid Build Coastguard Worker /// @returns outermost generated test function.
1509*9880d681SAndroid Build Coastguard Worker llvm::Function *
createUnwindExceptionTest(llvm::Module & module,llvm::IRBuilder<> & builder,llvm::legacy::FunctionPassManager & fpm,std::string nativeThrowFunctName)1510*9880d681SAndroid Build Coastguard Worker createUnwindExceptionTest(llvm::Module &module, llvm::IRBuilder<> &builder,
1511*9880d681SAndroid Build Coastguard Worker                           llvm::legacy::FunctionPassManager &fpm,
1512*9880d681SAndroid Build Coastguard Worker                           std::string nativeThrowFunctName) {
1513*9880d681SAndroid Build Coastguard Worker   // Number of type infos to generate
1514*9880d681SAndroid Build Coastguard Worker   unsigned numTypeInfos = 6;
1515*9880d681SAndroid Build Coastguard Worker 
1516*9880d681SAndroid Build Coastguard Worker   // Initialze intrisics and external functions to use along with exception
1517*9880d681SAndroid Build Coastguard Worker   // and type info globals.
1518*9880d681SAndroid Build Coastguard Worker   createStandardUtilityFunctions(numTypeInfos,
1519*9880d681SAndroid Build Coastguard Worker                                  module,
1520*9880d681SAndroid Build Coastguard Worker                                  builder);
1521*9880d681SAndroid Build Coastguard Worker   llvm::Function *nativeThrowFunct = module.getFunction(nativeThrowFunctName);
1522*9880d681SAndroid Build Coastguard Worker 
1523*9880d681SAndroid Build Coastguard Worker   // Create exception throw function using the value ~0 to cause
1524*9880d681SAndroid Build Coastguard Worker   // foreign exceptions to be thrown.
1525*9880d681SAndroid Build Coastguard Worker   llvm::Function *throwFunct = createThrowExceptionFunction(module,
1526*9880d681SAndroid Build Coastguard Worker                                                             builder,
1527*9880d681SAndroid Build Coastguard Worker                                                             fpm,
1528*9880d681SAndroid Build Coastguard Worker                                                             "throwFunct",
1529*9880d681SAndroid Build Coastguard Worker                                                             ~0,
1530*9880d681SAndroid Build Coastguard Worker                                                             *nativeThrowFunct);
1531*9880d681SAndroid Build Coastguard Worker   // Inner function will catch even type infos
1532*9880d681SAndroid Build Coastguard Worker   unsigned innerExceptionTypesToCatch[] = {6, 2, 4};
1533*9880d681SAndroid Build Coastguard Worker   size_t numExceptionTypesToCatch = sizeof(innerExceptionTypesToCatch) /
1534*9880d681SAndroid Build Coastguard Worker                                     sizeof(unsigned);
1535*9880d681SAndroid Build Coastguard Worker 
1536*9880d681SAndroid Build Coastguard Worker   // Generate inner function.
1537*9880d681SAndroid Build Coastguard Worker   llvm::Function *innerCatchFunct = createCatchWrappedInvokeFunction(module,
1538*9880d681SAndroid Build Coastguard Worker                                                     builder,
1539*9880d681SAndroid Build Coastguard Worker                                                     fpm,
1540*9880d681SAndroid Build Coastguard Worker                                                     *throwFunct,
1541*9880d681SAndroid Build Coastguard Worker                                                     "innerCatchFunct",
1542*9880d681SAndroid Build Coastguard Worker                                                     numExceptionTypesToCatch,
1543*9880d681SAndroid Build Coastguard Worker                                                     innerExceptionTypesToCatch);
1544*9880d681SAndroid Build Coastguard Worker 
1545*9880d681SAndroid Build Coastguard Worker   // Outer function will catch odd type infos
1546*9880d681SAndroid Build Coastguard Worker   unsigned outerExceptionTypesToCatch[] = {3, 1, 5};
1547*9880d681SAndroid Build Coastguard Worker   numExceptionTypesToCatch = sizeof(outerExceptionTypesToCatch) /
1548*9880d681SAndroid Build Coastguard Worker   sizeof(unsigned);
1549*9880d681SAndroid Build Coastguard Worker 
1550*9880d681SAndroid Build Coastguard Worker   // Generate outer function
1551*9880d681SAndroid Build Coastguard Worker   llvm::Function *outerCatchFunct = createCatchWrappedInvokeFunction(module,
1552*9880d681SAndroid Build Coastguard Worker                                                     builder,
1553*9880d681SAndroid Build Coastguard Worker                                                     fpm,
1554*9880d681SAndroid Build Coastguard Worker                                                     *innerCatchFunct,
1555*9880d681SAndroid Build Coastguard Worker                                                     "outerCatchFunct",
1556*9880d681SAndroid Build Coastguard Worker                                                     numExceptionTypesToCatch,
1557*9880d681SAndroid Build Coastguard Worker                                                     outerExceptionTypesToCatch);
1558*9880d681SAndroid Build Coastguard Worker 
1559*9880d681SAndroid Build Coastguard Worker   // Return outer function to run
1560*9880d681SAndroid Build Coastguard Worker   return(outerCatchFunct);
1561*9880d681SAndroid Build Coastguard Worker }
1562*9880d681SAndroid Build Coastguard Worker 
1563*9880d681SAndroid Build Coastguard Worker namespace {
1564*9880d681SAndroid Build Coastguard Worker /// Represents our foreign exceptions
1565*9880d681SAndroid Build Coastguard Worker class OurCppRunException : public std::runtime_error {
1566*9880d681SAndroid Build Coastguard Worker public:
OurCppRunException(const std::string reason)1567*9880d681SAndroid Build Coastguard Worker   OurCppRunException(const std::string reason) :
1568*9880d681SAndroid Build Coastguard Worker   std::runtime_error(reason) {}
1569*9880d681SAndroid Build Coastguard Worker 
OurCppRunException(const OurCppRunException & toCopy)1570*9880d681SAndroid Build Coastguard Worker   OurCppRunException (const OurCppRunException &toCopy) :
1571*9880d681SAndroid Build Coastguard Worker   std::runtime_error(toCopy) {}
1572*9880d681SAndroid Build Coastguard Worker 
operator =(const OurCppRunException & toCopy)1573*9880d681SAndroid Build Coastguard Worker   OurCppRunException &operator = (const OurCppRunException &toCopy) {
1574*9880d681SAndroid Build Coastguard Worker     return(reinterpret_cast<OurCppRunException&>(
1575*9880d681SAndroid Build Coastguard Worker                                  std::runtime_error::operator=(toCopy)));
1576*9880d681SAndroid Build Coastguard Worker   }
1577*9880d681SAndroid Build Coastguard Worker 
~OurCppRunException(void)1578*9880d681SAndroid Build Coastguard Worker   ~OurCppRunException(void) throw() override {}
1579*9880d681SAndroid Build Coastguard Worker };
1580*9880d681SAndroid Build Coastguard Worker } // end anonymous namespace
1581*9880d681SAndroid Build Coastguard Worker 
1582*9880d681SAndroid Build Coastguard Worker /// Throws foreign C++ exception.
1583*9880d681SAndroid Build Coastguard Worker /// @param ignoreIt unused parameter that allows function to match implied
1584*9880d681SAndroid Build Coastguard Worker ///        generated function contract.
1585*9880d681SAndroid Build Coastguard Worker extern "C"
throwCppException(int32_t ignoreIt)1586*9880d681SAndroid Build Coastguard Worker void throwCppException (int32_t ignoreIt) {
1587*9880d681SAndroid Build Coastguard Worker   throw(OurCppRunException("thrown by throwCppException(...)"));
1588*9880d681SAndroid Build Coastguard Worker }
1589*9880d681SAndroid Build Coastguard Worker 
1590*9880d681SAndroid Build Coastguard Worker typedef void (*OurExceptionThrowFunctType) (int32_t typeToThrow);
1591*9880d681SAndroid Build Coastguard Worker 
1592*9880d681SAndroid Build Coastguard Worker /// This is a test harness which runs test by executing generated
1593*9880d681SAndroid Build Coastguard Worker /// function with a type info type to throw. Harness wraps the execution
1594*9880d681SAndroid Build Coastguard Worker /// of generated function in a C++ try catch clause.
1595*9880d681SAndroid Build Coastguard Worker /// @param engine execution engine to use for executing generated function.
1596*9880d681SAndroid Build Coastguard Worker ///        This demo program expects this to be a JIT instance for demo
1597*9880d681SAndroid Build Coastguard Worker ///        purposes.
1598*9880d681SAndroid Build Coastguard Worker /// @param function generated test function to run
1599*9880d681SAndroid Build Coastguard Worker /// @param typeToThrow type info type of generated exception to throw, or
1600*9880d681SAndroid Build Coastguard Worker ///        indicator to cause foreign exception to be thrown.
1601*9880d681SAndroid Build Coastguard Worker static
runExceptionThrow(llvm::ExecutionEngine * engine,llvm::Function * function,int32_t typeToThrow)1602*9880d681SAndroid Build Coastguard Worker void runExceptionThrow(llvm::ExecutionEngine *engine,
1603*9880d681SAndroid Build Coastguard Worker                        llvm::Function *function,
1604*9880d681SAndroid Build Coastguard Worker                        int32_t typeToThrow) {
1605*9880d681SAndroid Build Coastguard Worker 
1606*9880d681SAndroid Build Coastguard Worker   // Find test's function pointer
1607*9880d681SAndroid Build Coastguard Worker   OurExceptionThrowFunctType functPtr =
1608*9880d681SAndroid Build Coastguard Worker     reinterpret_cast<OurExceptionThrowFunctType>(
1609*9880d681SAndroid Build Coastguard Worker        reinterpret_cast<intptr_t>(engine->getPointerToFunction(function)));
1610*9880d681SAndroid Build Coastguard Worker 
1611*9880d681SAndroid Build Coastguard Worker   try {
1612*9880d681SAndroid Build Coastguard Worker     // Run test
1613*9880d681SAndroid Build Coastguard Worker     (*functPtr)(typeToThrow);
1614*9880d681SAndroid Build Coastguard Worker   }
1615*9880d681SAndroid Build Coastguard Worker   catch (OurCppRunException exc) {
1616*9880d681SAndroid Build Coastguard Worker     // Catch foreign C++ exception
1617*9880d681SAndroid Build Coastguard Worker     fprintf(stderr,
1618*9880d681SAndroid Build Coastguard Worker             "\nrunExceptionThrow(...):In C++ catch OurCppRunException "
1619*9880d681SAndroid Build Coastguard Worker             "with reason: %s.\n",
1620*9880d681SAndroid Build Coastguard Worker             exc.what());
1621*9880d681SAndroid Build Coastguard Worker   }
1622*9880d681SAndroid Build Coastguard Worker   catch (...) {
1623*9880d681SAndroid Build Coastguard Worker     // Catch all exceptions including our generated ones. This latter
1624*9880d681SAndroid Build Coastguard Worker     // functionality works according to the example in rules 1.6.4 of
1625*9880d681SAndroid Build Coastguard Worker     // http://mentorembedded.github.com/cxx-abi/abi-eh.html (v1.22),
1626*9880d681SAndroid Build Coastguard Worker     // given that these will be exceptions foreign to C++
1627*9880d681SAndroid Build Coastguard Worker     // (the _Unwind_Exception::exception_class should be different from
1628*9880d681SAndroid Build Coastguard Worker     // the one used by C++).
1629*9880d681SAndroid Build Coastguard Worker     fprintf(stderr,
1630*9880d681SAndroid Build Coastguard Worker             "\nrunExceptionThrow(...):In C++ catch all.\n");
1631*9880d681SAndroid Build Coastguard Worker   }
1632*9880d681SAndroid Build Coastguard Worker }
1633*9880d681SAndroid Build Coastguard Worker 
1634*9880d681SAndroid Build Coastguard Worker //
1635*9880d681SAndroid Build Coastguard Worker // End test functions
1636*9880d681SAndroid Build Coastguard Worker //
1637*9880d681SAndroid Build Coastguard Worker 
1638*9880d681SAndroid Build Coastguard Worker typedef llvm::ArrayRef<llvm::Type*> TypeArray;
1639*9880d681SAndroid Build Coastguard Worker 
1640*9880d681SAndroid Build Coastguard Worker /// This initialization routine creates type info globals and
1641*9880d681SAndroid Build Coastguard Worker /// adds external function declarations to module.
1642*9880d681SAndroid Build Coastguard Worker /// @param numTypeInfos number of linear type info associated type info types
1643*9880d681SAndroid Build Coastguard Worker ///        to create as GlobalVariable instances, starting with the value 1.
1644*9880d681SAndroid Build Coastguard Worker /// @param module code for module instance
1645*9880d681SAndroid Build Coastguard Worker /// @param builder builder instance
createStandardUtilityFunctions(unsigned numTypeInfos,llvm::Module & module,llvm::IRBuilder<> & builder)1646*9880d681SAndroid Build Coastguard Worker static void createStandardUtilityFunctions(unsigned numTypeInfos,
1647*9880d681SAndroid Build Coastguard Worker                                            llvm::Module &module,
1648*9880d681SAndroid Build Coastguard Worker                                            llvm::IRBuilder<> &builder) {
1649*9880d681SAndroid Build Coastguard Worker 
1650*9880d681SAndroid Build Coastguard Worker   llvm::LLVMContext &context = module.getContext();
1651*9880d681SAndroid Build Coastguard Worker 
1652*9880d681SAndroid Build Coastguard Worker   // Exception initializations
1653*9880d681SAndroid Build Coastguard Worker 
1654*9880d681SAndroid Build Coastguard Worker   // Setup exception catch state
1655*9880d681SAndroid Build Coastguard Worker   ourExceptionNotThrownState =
1656*9880d681SAndroid Build Coastguard Worker     llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 0),
1657*9880d681SAndroid Build Coastguard Worker   ourExceptionThrownState =
1658*9880d681SAndroid Build Coastguard Worker     llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 1),
1659*9880d681SAndroid Build Coastguard Worker   ourExceptionCaughtState =
1660*9880d681SAndroid Build Coastguard Worker     llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 2),
1661*9880d681SAndroid Build Coastguard Worker 
1662*9880d681SAndroid Build Coastguard Worker 
1663*9880d681SAndroid Build Coastguard Worker 
1664*9880d681SAndroid Build Coastguard Worker   // Create our type info type
1665*9880d681SAndroid Build Coastguard Worker   ourTypeInfoType = llvm::StructType::get(context,
1666*9880d681SAndroid Build Coastguard Worker                                           TypeArray(builder.getInt32Ty()));
1667*9880d681SAndroid Build Coastguard Worker 
1668*9880d681SAndroid Build Coastguard Worker   llvm::Type *caughtResultFieldTypes[] = {
1669*9880d681SAndroid Build Coastguard Worker     builder.getInt8PtrTy(),
1670*9880d681SAndroid Build Coastguard Worker     builder.getInt32Ty()
1671*9880d681SAndroid Build Coastguard Worker   };
1672*9880d681SAndroid Build Coastguard Worker 
1673*9880d681SAndroid Build Coastguard Worker   // Create our landingpad result type
1674*9880d681SAndroid Build Coastguard Worker   ourCaughtResultType = llvm::StructType::get(context,
1675*9880d681SAndroid Build Coastguard Worker                                             TypeArray(caughtResultFieldTypes));
1676*9880d681SAndroid Build Coastguard Worker 
1677*9880d681SAndroid Build Coastguard Worker   // Create OurException type
1678*9880d681SAndroid Build Coastguard Worker   ourExceptionType = llvm::StructType::get(context,
1679*9880d681SAndroid Build Coastguard Worker                                            TypeArray(ourTypeInfoType));
1680*9880d681SAndroid Build Coastguard Worker 
1681*9880d681SAndroid Build Coastguard Worker   // Create portion of _Unwind_Exception type
1682*9880d681SAndroid Build Coastguard Worker   //
1683*9880d681SAndroid Build Coastguard Worker   // Note: Declaring only a portion of the _Unwind_Exception struct.
1684*9880d681SAndroid Build Coastguard Worker   //       Does this cause problems?
1685*9880d681SAndroid Build Coastguard Worker   ourUnwindExceptionType =
1686*9880d681SAndroid Build Coastguard Worker     llvm::StructType::get(context,
1687*9880d681SAndroid Build Coastguard Worker                     TypeArray(builder.getInt64Ty()));
1688*9880d681SAndroid Build Coastguard Worker 
1689*9880d681SAndroid Build Coastguard Worker   struct OurBaseException_t dummyException;
1690*9880d681SAndroid Build Coastguard Worker 
1691*9880d681SAndroid Build Coastguard Worker   // Calculate offset of OurException::unwindException member.
1692*9880d681SAndroid Build Coastguard Worker   ourBaseFromUnwindOffset = ((uintptr_t) &dummyException) -
1693*9880d681SAndroid Build Coastguard Worker                             ((uintptr_t) &(dummyException.unwindException));
1694*9880d681SAndroid Build Coastguard Worker 
1695*9880d681SAndroid Build Coastguard Worker #ifdef DEBUG
1696*9880d681SAndroid Build Coastguard Worker   fprintf(stderr,
1697*9880d681SAndroid Build Coastguard Worker           "createStandardUtilityFunctions(...):ourBaseFromUnwindOffset "
1698*9880d681SAndroid Build Coastguard Worker           "= %" PRIi64 ", sizeof(struct OurBaseException_t) - "
1699*9880d681SAndroid Build Coastguard Worker           "sizeof(struct _Unwind_Exception) = %lu.\n",
1700*9880d681SAndroid Build Coastguard Worker           ourBaseFromUnwindOffset,
1701*9880d681SAndroid Build Coastguard Worker           sizeof(struct OurBaseException_t) -
1702*9880d681SAndroid Build Coastguard Worker           sizeof(struct _Unwind_Exception));
1703*9880d681SAndroid Build Coastguard Worker #endif
1704*9880d681SAndroid Build Coastguard Worker 
1705*9880d681SAndroid Build Coastguard Worker   size_t numChars = sizeof(ourBaseExcpClassChars) / sizeof(char);
1706*9880d681SAndroid Build Coastguard Worker 
1707*9880d681SAndroid Build Coastguard Worker   // Create our _Unwind_Exception::exception_class value
1708*9880d681SAndroid Build Coastguard Worker   ourBaseExceptionClass = genClass(ourBaseExcpClassChars, numChars);
1709*9880d681SAndroid Build Coastguard Worker 
1710*9880d681SAndroid Build Coastguard Worker   // Type infos
1711*9880d681SAndroid Build Coastguard Worker 
1712*9880d681SAndroid Build Coastguard Worker   std::string baseStr = "typeInfo", typeInfoName;
1713*9880d681SAndroid Build Coastguard Worker   std::ostringstream typeInfoNameBuilder;
1714*9880d681SAndroid Build Coastguard Worker   std::vector<llvm::Constant*> structVals;
1715*9880d681SAndroid Build Coastguard Worker 
1716*9880d681SAndroid Build Coastguard Worker   llvm::Constant *nextStruct;
1717*9880d681SAndroid Build Coastguard Worker 
1718*9880d681SAndroid Build Coastguard Worker   // Generate each type info
1719*9880d681SAndroid Build Coastguard Worker   //
1720*9880d681SAndroid Build Coastguard Worker   // Note: First type info is not used.
1721*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0; i <= numTypeInfos; ++i) {
1722*9880d681SAndroid Build Coastguard Worker     structVals.clear();
1723*9880d681SAndroid Build Coastguard Worker     structVals.push_back(llvm::ConstantInt::get(builder.getInt32Ty(), i));
1724*9880d681SAndroid Build Coastguard Worker     nextStruct = llvm::ConstantStruct::get(ourTypeInfoType, structVals);
1725*9880d681SAndroid Build Coastguard Worker 
1726*9880d681SAndroid Build Coastguard Worker     typeInfoNameBuilder.str("");
1727*9880d681SAndroid Build Coastguard Worker     typeInfoNameBuilder << baseStr << i;
1728*9880d681SAndroid Build Coastguard Worker     typeInfoName = typeInfoNameBuilder.str();
1729*9880d681SAndroid Build Coastguard Worker 
1730*9880d681SAndroid Build Coastguard Worker     // Note: Does not seem to work without allocation
1731*9880d681SAndroid Build Coastguard Worker     new llvm::GlobalVariable(module,
1732*9880d681SAndroid Build Coastguard Worker                              ourTypeInfoType,
1733*9880d681SAndroid Build Coastguard Worker                              true,
1734*9880d681SAndroid Build Coastguard Worker                              llvm::GlobalValue::ExternalLinkage,
1735*9880d681SAndroid Build Coastguard Worker                              nextStruct,
1736*9880d681SAndroid Build Coastguard Worker                              typeInfoName);
1737*9880d681SAndroid Build Coastguard Worker 
1738*9880d681SAndroid Build Coastguard Worker     ourTypeInfoNames.push_back(typeInfoName);
1739*9880d681SAndroid Build Coastguard Worker     ourTypeInfoNamesIndex[i] = typeInfoName;
1740*9880d681SAndroid Build Coastguard Worker   }
1741*9880d681SAndroid Build Coastguard Worker 
1742*9880d681SAndroid Build Coastguard Worker   ArgNames argNames;
1743*9880d681SAndroid Build Coastguard Worker   ArgTypes argTypes;
1744*9880d681SAndroid Build Coastguard Worker   llvm::Function *funct = NULL;
1745*9880d681SAndroid Build Coastguard Worker 
1746*9880d681SAndroid Build Coastguard Worker   // print32Int
1747*9880d681SAndroid Build Coastguard Worker 
1748*9880d681SAndroid Build Coastguard Worker   llvm::Type *retType = builder.getVoidTy();
1749*9880d681SAndroid Build Coastguard Worker 
1750*9880d681SAndroid Build Coastguard Worker   argTypes.clear();
1751*9880d681SAndroid Build Coastguard Worker   argTypes.push_back(builder.getInt32Ty());
1752*9880d681SAndroid Build Coastguard Worker   argTypes.push_back(builder.getInt8PtrTy());
1753*9880d681SAndroid Build Coastguard Worker 
1754*9880d681SAndroid Build Coastguard Worker   argNames.clear();
1755*9880d681SAndroid Build Coastguard Worker 
1756*9880d681SAndroid Build Coastguard Worker   createFunction(module,
1757*9880d681SAndroid Build Coastguard Worker                  retType,
1758*9880d681SAndroid Build Coastguard Worker                  argTypes,
1759*9880d681SAndroid Build Coastguard Worker                  argNames,
1760*9880d681SAndroid Build Coastguard Worker                  "print32Int",
1761*9880d681SAndroid Build Coastguard Worker                  llvm::Function::ExternalLinkage,
1762*9880d681SAndroid Build Coastguard Worker                  true,
1763*9880d681SAndroid Build Coastguard Worker                  false);
1764*9880d681SAndroid Build Coastguard Worker 
1765*9880d681SAndroid Build Coastguard Worker   // print64Int
1766*9880d681SAndroid Build Coastguard Worker 
1767*9880d681SAndroid Build Coastguard Worker   retType = builder.getVoidTy();
1768*9880d681SAndroid Build Coastguard Worker 
1769*9880d681SAndroid Build Coastguard Worker   argTypes.clear();
1770*9880d681SAndroid Build Coastguard Worker   argTypes.push_back(builder.getInt64Ty());
1771*9880d681SAndroid Build Coastguard Worker   argTypes.push_back(builder.getInt8PtrTy());
1772*9880d681SAndroid Build Coastguard Worker 
1773*9880d681SAndroid Build Coastguard Worker   argNames.clear();
1774*9880d681SAndroid Build Coastguard Worker 
1775*9880d681SAndroid Build Coastguard Worker   createFunction(module,
1776*9880d681SAndroid Build Coastguard Worker                  retType,
1777*9880d681SAndroid Build Coastguard Worker                  argTypes,
1778*9880d681SAndroid Build Coastguard Worker                  argNames,
1779*9880d681SAndroid Build Coastguard Worker                  "print64Int",
1780*9880d681SAndroid Build Coastguard Worker                  llvm::Function::ExternalLinkage,
1781*9880d681SAndroid Build Coastguard Worker                  true,
1782*9880d681SAndroid Build Coastguard Worker                  false);
1783*9880d681SAndroid Build Coastguard Worker 
1784*9880d681SAndroid Build Coastguard Worker   // printStr
1785*9880d681SAndroid Build Coastguard Worker 
1786*9880d681SAndroid Build Coastguard Worker   retType = builder.getVoidTy();
1787*9880d681SAndroid Build Coastguard Worker 
1788*9880d681SAndroid Build Coastguard Worker   argTypes.clear();
1789*9880d681SAndroid Build Coastguard Worker   argTypes.push_back(builder.getInt8PtrTy());
1790*9880d681SAndroid Build Coastguard Worker 
1791*9880d681SAndroid Build Coastguard Worker   argNames.clear();
1792*9880d681SAndroid Build Coastguard Worker 
1793*9880d681SAndroid Build Coastguard Worker   createFunction(module,
1794*9880d681SAndroid Build Coastguard Worker                  retType,
1795*9880d681SAndroid Build Coastguard Worker                  argTypes,
1796*9880d681SAndroid Build Coastguard Worker                  argNames,
1797*9880d681SAndroid Build Coastguard Worker                  "printStr",
1798*9880d681SAndroid Build Coastguard Worker                  llvm::Function::ExternalLinkage,
1799*9880d681SAndroid Build Coastguard Worker                  true,
1800*9880d681SAndroid Build Coastguard Worker                  false);
1801*9880d681SAndroid Build Coastguard Worker 
1802*9880d681SAndroid Build Coastguard Worker   // throwCppException
1803*9880d681SAndroid Build Coastguard Worker 
1804*9880d681SAndroid Build Coastguard Worker   retType = builder.getVoidTy();
1805*9880d681SAndroid Build Coastguard Worker 
1806*9880d681SAndroid Build Coastguard Worker   argTypes.clear();
1807*9880d681SAndroid Build Coastguard Worker   argTypes.push_back(builder.getInt32Ty());
1808*9880d681SAndroid Build Coastguard Worker 
1809*9880d681SAndroid Build Coastguard Worker   argNames.clear();
1810*9880d681SAndroid Build Coastguard Worker 
1811*9880d681SAndroid Build Coastguard Worker   createFunction(module,
1812*9880d681SAndroid Build Coastguard Worker                  retType,
1813*9880d681SAndroid Build Coastguard Worker                  argTypes,
1814*9880d681SAndroid Build Coastguard Worker                  argNames,
1815*9880d681SAndroid Build Coastguard Worker                  "throwCppException",
1816*9880d681SAndroid Build Coastguard Worker                  llvm::Function::ExternalLinkage,
1817*9880d681SAndroid Build Coastguard Worker                  true,
1818*9880d681SAndroid Build Coastguard Worker                  false);
1819*9880d681SAndroid Build Coastguard Worker 
1820*9880d681SAndroid Build Coastguard Worker   // deleteOurException
1821*9880d681SAndroid Build Coastguard Worker 
1822*9880d681SAndroid Build Coastguard Worker   retType = builder.getVoidTy();
1823*9880d681SAndroid Build Coastguard Worker 
1824*9880d681SAndroid Build Coastguard Worker   argTypes.clear();
1825*9880d681SAndroid Build Coastguard Worker   argTypes.push_back(builder.getInt8PtrTy());
1826*9880d681SAndroid Build Coastguard Worker 
1827*9880d681SAndroid Build Coastguard Worker   argNames.clear();
1828*9880d681SAndroid Build Coastguard Worker 
1829*9880d681SAndroid Build Coastguard Worker   createFunction(module,
1830*9880d681SAndroid Build Coastguard Worker                  retType,
1831*9880d681SAndroid Build Coastguard Worker                  argTypes,
1832*9880d681SAndroid Build Coastguard Worker                  argNames,
1833*9880d681SAndroid Build Coastguard Worker                  "deleteOurException",
1834*9880d681SAndroid Build Coastguard Worker                  llvm::Function::ExternalLinkage,
1835*9880d681SAndroid Build Coastguard Worker                  true,
1836*9880d681SAndroid Build Coastguard Worker                  false);
1837*9880d681SAndroid Build Coastguard Worker 
1838*9880d681SAndroid Build Coastguard Worker   // createOurException
1839*9880d681SAndroid Build Coastguard Worker 
1840*9880d681SAndroid Build Coastguard Worker   retType = builder.getInt8PtrTy();
1841*9880d681SAndroid Build Coastguard Worker 
1842*9880d681SAndroid Build Coastguard Worker   argTypes.clear();
1843*9880d681SAndroid Build Coastguard Worker   argTypes.push_back(builder.getInt32Ty());
1844*9880d681SAndroid Build Coastguard Worker 
1845*9880d681SAndroid Build Coastguard Worker   argNames.clear();
1846*9880d681SAndroid Build Coastguard Worker 
1847*9880d681SAndroid Build Coastguard Worker   createFunction(module,
1848*9880d681SAndroid Build Coastguard Worker                  retType,
1849*9880d681SAndroid Build Coastguard Worker                  argTypes,
1850*9880d681SAndroid Build Coastguard Worker                  argNames,
1851*9880d681SAndroid Build Coastguard Worker                  "createOurException",
1852*9880d681SAndroid Build Coastguard Worker                  llvm::Function::ExternalLinkage,
1853*9880d681SAndroid Build Coastguard Worker                  true,
1854*9880d681SAndroid Build Coastguard Worker                  false);
1855*9880d681SAndroid Build Coastguard Worker 
1856*9880d681SAndroid Build Coastguard Worker   // _Unwind_RaiseException
1857*9880d681SAndroid Build Coastguard Worker 
1858*9880d681SAndroid Build Coastguard Worker   retType = builder.getInt32Ty();
1859*9880d681SAndroid Build Coastguard Worker 
1860*9880d681SAndroid Build Coastguard Worker   argTypes.clear();
1861*9880d681SAndroid Build Coastguard Worker   argTypes.push_back(builder.getInt8PtrTy());
1862*9880d681SAndroid Build Coastguard Worker 
1863*9880d681SAndroid Build Coastguard Worker   argNames.clear();
1864*9880d681SAndroid Build Coastguard Worker 
1865*9880d681SAndroid Build Coastguard Worker   funct = createFunction(module,
1866*9880d681SAndroid Build Coastguard Worker                          retType,
1867*9880d681SAndroid Build Coastguard Worker                          argTypes,
1868*9880d681SAndroid Build Coastguard Worker                          argNames,
1869*9880d681SAndroid Build Coastguard Worker                          "_Unwind_RaiseException",
1870*9880d681SAndroid Build Coastguard Worker                          llvm::Function::ExternalLinkage,
1871*9880d681SAndroid Build Coastguard Worker                          true,
1872*9880d681SAndroid Build Coastguard Worker                          false);
1873*9880d681SAndroid Build Coastguard Worker 
1874*9880d681SAndroid Build Coastguard Worker   funct->setDoesNotReturn();
1875*9880d681SAndroid Build Coastguard Worker 
1876*9880d681SAndroid Build Coastguard Worker   // _Unwind_Resume
1877*9880d681SAndroid Build Coastguard Worker 
1878*9880d681SAndroid Build Coastguard Worker   retType = builder.getInt32Ty();
1879*9880d681SAndroid Build Coastguard Worker 
1880*9880d681SAndroid Build Coastguard Worker   argTypes.clear();
1881*9880d681SAndroid Build Coastguard Worker   argTypes.push_back(builder.getInt8PtrTy());
1882*9880d681SAndroid Build Coastguard Worker 
1883*9880d681SAndroid Build Coastguard Worker   argNames.clear();
1884*9880d681SAndroid Build Coastguard Worker 
1885*9880d681SAndroid Build Coastguard Worker   funct = createFunction(module,
1886*9880d681SAndroid Build Coastguard Worker                          retType,
1887*9880d681SAndroid Build Coastguard Worker                          argTypes,
1888*9880d681SAndroid Build Coastguard Worker                          argNames,
1889*9880d681SAndroid Build Coastguard Worker                          "_Unwind_Resume",
1890*9880d681SAndroid Build Coastguard Worker                          llvm::Function::ExternalLinkage,
1891*9880d681SAndroid Build Coastguard Worker                          true,
1892*9880d681SAndroid Build Coastguard Worker                          false);
1893*9880d681SAndroid Build Coastguard Worker 
1894*9880d681SAndroid Build Coastguard Worker   funct->setDoesNotReturn();
1895*9880d681SAndroid Build Coastguard Worker 
1896*9880d681SAndroid Build Coastguard Worker   // ourPersonality
1897*9880d681SAndroid Build Coastguard Worker 
1898*9880d681SAndroid Build Coastguard Worker   retType = builder.getInt32Ty();
1899*9880d681SAndroid Build Coastguard Worker 
1900*9880d681SAndroid Build Coastguard Worker   argTypes.clear();
1901*9880d681SAndroid Build Coastguard Worker   argTypes.push_back(builder.getInt32Ty());
1902*9880d681SAndroid Build Coastguard Worker   argTypes.push_back(builder.getInt32Ty());
1903*9880d681SAndroid Build Coastguard Worker   argTypes.push_back(builder.getInt64Ty());
1904*9880d681SAndroid Build Coastguard Worker   argTypes.push_back(builder.getInt8PtrTy());
1905*9880d681SAndroid Build Coastguard Worker   argTypes.push_back(builder.getInt8PtrTy());
1906*9880d681SAndroid Build Coastguard Worker 
1907*9880d681SAndroid Build Coastguard Worker   argNames.clear();
1908*9880d681SAndroid Build Coastguard Worker 
1909*9880d681SAndroid Build Coastguard Worker   createFunction(module,
1910*9880d681SAndroid Build Coastguard Worker                  retType,
1911*9880d681SAndroid Build Coastguard Worker                  argTypes,
1912*9880d681SAndroid Build Coastguard Worker                  argNames,
1913*9880d681SAndroid Build Coastguard Worker                  "ourPersonality",
1914*9880d681SAndroid Build Coastguard Worker                  llvm::Function::ExternalLinkage,
1915*9880d681SAndroid Build Coastguard Worker                  true,
1916*9880d681SAndroid Build Coastguard Worker                  false);
1917*9880d681SAndroid Build Coastguard Worker 
1918*9880d681SAndroid Build Coastguard Worker   // llvm.eh.typeid.for intrinsic
1919*9880d681SAndroid Build Coastguard Worker 
1920*9880d681SAndroid Build Coastguard Worker   getDeclaration(&module, llvm::Intrinsic::eh_typeid_for);
1921*9880d681SAndroid Build Coastguard Worker }
1922*9880d681SAndroid Build Coastguard Worker 
1923*9880d681SAndroid Build Coastguard Worker 
1924*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
1925*9880d681SAndroid Build Coastguard Worker // Main test driver code.
1926*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
1927*9880d681SAndroid Build Coastguard Worker 
1928*9880d681SAndroid Build Coastguard Worker /// Demo main routine which takes the type info types to throw. A test will
1929*9880d681SAndroid Build Coastguard Worker /// be run for each given type info type. While type info types with the value
1930*9880d681SAndroid Build Coastguard Worker /// of -1 will trigger a foreign C++ exception to be thrown; type info types
1931*9880d681SAndroid Build Coastguard Worker /// <= 6 and >= 1 will be caught by test functions; and type info types > 6
1932*9880d681SAndroid Build Coastguard Worker /// will result in exceptions which pass through to the test harness. All other
1933*9880d681SAndroid Build Coastguard Worker /// type info types are not supported and could cause a crash.
main(int argc,char * argv[])1934*9880d681SAndroid Build Coastguard Worker int main(int argc, char *argv[]) {
1935*9880d681SAndroid Build Coastguard Worker   if (argc == 1) {
1936*9880d681SAndroid Build Coastguard Worker     fprintf(stderr,
1937*9880d681SAndroid Build Coastguard Worker             "\nUsage: ExceptionDemo <exception type to throw> "
1938*9880d681SAndroid Build Coastguard Worker             "[<type 2>...<type n>].\n"
1939*9880d681SAndroid Build Coastguard Worker             "   Each type must have the value of 1 - 6 for "
1940*9880d681SAndroid Build Coastguard Worker             "generated exceptions to be caught;\n"
1941*9880d681SAndroid Build Coastguard Worker             "   the value -1 for foreign C++ exceptions to be "
1942*9880d681SAndroid Build Coastguard Worker             "generated and thrown;\n"
1943*9880d681SAndroid Build Coastguard Worker             "   or the values > 6 for exceptions to be ignored.\n"
1944*9880d681SAndroid Build Coastguard Worker             "\nTry: ExceptionDemo 2 3 7 -1\n"
1945*9880d681SAndroid Build Coastguard Worker             "   for a full test.\n\n");
1946*9880d681SAndroid Build Coastguard Worker     return(0);
1947*9880d681SAndroid Build Coastguard Worker   }
1948*9880d681SAndroid Build Coastguard Worker 
1949*9880d681SAndroid Build Coastguard Worker   // If not set, exception handling will not be turned on
1950*9880d681SAndroid Build Coastguard Worker   llvm::TargetOptions Opts;
1951*9880d681SAndroid Build Coastguard Worker 
1952*9880d681SAndroid Build Coastguard Worker   llvm::InitializeNativeTarget();
1953*9880d681SAndroid Build Coastguard Worker   llvm::InitializeNativeTargetAsmPrinter();
1954*9880d681SAndroid Build Coastguard Worker   llvm::LLVMContext Context;
1955*9880d681SAndroid Build Coastguard Worker   llvm::IRBuilder<> theBuilder(Context);
1956*9880d681SAndroid Build Coastguard Worker 
1957*9880d681SAndroid Build Coastguard Worker   // Make the module, which holds all the code.
1958*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<llvm::Module> Owner =
1959*9880d681SAndroid Build Coastguard Worker       llvm::make_unique<llvm::Module>("my cool jit", Context);
1960*9880d681SAndroid Build Coastguard Worker   llvm::Module *module = Owner.get();
1961*9880d681SAndroid Build Coastguard Worker 
1962*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<llvm::RTDyldMemoryManager> MemMgr(new llvm::SectionMemoryManager());
1963*9880d681SAndroid Build Coastguard Worker 
1964*9880d681SAndroid Build Coastguard Worker   // Build engine with JIT
1965*9880d681SAndroid Build Coastguard Worker   llvm::EngineBuilder factory(std::move(Owner));
1966*9880d681SAndroid Build Coastguard Worker   factory.setEngineKind(llvm::EngineKind::JIT);
1967*9880d681SAndroid Build Coastguard Worker   factory.setTargetOptions(Opts);
1968*9880d681SAndroid Build Coastguard Worker   factory.setMCJITMemoryManager(std::move(MemMgr));
1969*9880d681SAndroid Build Coastguard Worker   llvm::ExecutionEngine *executionEngine = factory.create();
1970*9880d681SAndroid Build Coastguard Worker 
1971*9880d681SAndroid Build Coastguard Worker   {
1972*9880d681SAndroid Build Coastguard Worker     llvm::legacy::FunctionPassManager fpm(module);
1973*9880d681SAndroid Build Coastguard Worker 
1974*9880d681SAndroid Build Coastguard Worker     // Set up the optimizer pipeline.
1975*9880d681SAndroid Build Coastguard Worker     // Start with registering info about how the
1976*9880d681SAndroid Build Coastguard Worker     // target lays out data structures.
1977*9880d681SAndroid Build Coastguard Worker     module->setDataLayout(executionEngine->getDataLayout());
1978*9880d681SAndroid Build Coastguard Worker 
1979*9880d681SAndroid Build Coastguard Worker     // Optimizations turned on
1980*9880d681SAndroid Build Coastguard Worker #ifdef ADD_OPT_PASSES
1981*9880d681SAndroid Build Coastguard Worker 
1982*9880d681SAndroid Build Coastguard Worker     // Basic AliasAnslysis support for GVN.
1983*9880d681SAndroid Build Coastguard Worker     fpm.add(llvm::createBasicAliasAnalysisPass());
1984*9880d681SAndroid Build Coastguard Worker 
1985*9880d681SAndroid Build Coastguard Worker     // Promote allocas to registers.
1986*9880d681SAndroid Build Coastguard Worker     fpm.add(llvm::createPromoteMemoryToRegisterPass());
1987*9880d681SAndroid Build Coastguard Worker 
1988*9880d681SAndroid Build Coastguard Worker     // Do simple "peephole" optimizations and bit-twiddling optzns.
1989*9880d681SAndroid Build Coastguard Worker     fpm.add(llvm::createInstructionCombiningPass());
1990*9880d681SAndroid Build Coastguard Worker 
1991*9880d681SAndroid Build Coastguard Worker     // Reassociate expressions.
1992*9880d681SAndroid Build Coastguard Worker     fpm.add(llvm::createReassociatePass());
1993*9880d681SAndroid Build Coastguard Worker 
1994*9880d681SAndroid Build Coastguard Worker     // Eliminate Common SubExpressions.
1995*9880d681SAndroid Build Coastguard Worker     fpm.add(llvm::createGVNPass());
1996*9880d681SAndroid Build Coastguard Worker 
1997*9880d681SAndroid Build Coastguard Worker     // Simplify the control flow graph (deleting unreachable
1998*9880d681SAndroid Build Coastguard Worker     // blocks, etc).
1999*9880d681SAndroid Build Coastguard Worker     fpm.add(llvm::createCFGSimplificationPass());
2000*9880d681SAndroid Build Coastguard Worker #endif  // ADD_OPT_PASSES
2001*9880d681SAndroid Build Coastguard Worker 
2002*9880d681SAndroid Build Coastguard Worker     fpm.doInitialization();
2003*9880d681SAndroid Build Coastguard Worker 
2004*9880d681SAndroid Build Coastguard Worker     // Generate test code using function throwCppException(...) as
2005*9880d681SAndroid Build Coastguard Worker     // the function which throws foreign exceptions.
2006*9880d681SAndroid Build Coastguard Worker     llvm::Function *toRun =
2007*9880d681SAndroid Build Coastguard Worker     createUnwindExceptionTest(*module,
2008*9880d681SAndroid Build Coastguard Worker                               theBuilder,
2009*9880d681SAndroid Build Coastguard Worker                               fpm,
2010*9880d681SAndroid Build Coastguard Worker                               "throwCppException");
2011*9880d681SAndroid Build Coastguard Worker 
2012*9880d681SAndroid Build Coastguard Worker     executionEngine->finalizeObject();
2013*9880d681SAndroid Build Coastguard Worker 
2014*9880d681SAndroid Build Coastguard Worker     fprintf(stderr, "\nBegin module dump:\n\n");
2015*9880d681SAndroid Build Coastguard Worker 
2016*9880d681SAndroid Build Coastguard Worker     module->dump();
2017*9880d681SAndroid Build Coastguard Worker 
2018*9880d681SAndroid Build Coastguard Worker     fprintf(stderr, "\nEnd module dump:\n");
2019*9880d681SAndroid Build Coastguard Worker 
2020*9880d681SAndroid Build Coastguard Worker     fprintf(stderr, "\n\nBegin Test:\n");
2021*9880d681SAndroid Build Coastguard Worker 
2022*9880d681SAndroid Build Coastguard Worker     for (int i = 1; i < argc; ++i) {
2023*9880d681SAndroid Build Coastguard Worker       // Run test for each argument whose value is the exception
2024*9880d681SAndroid Build Coastguard Worker       // type to throw.
2025*9880d681SAndroid Build Coastguard Worker       runExceptionThrow(executionEngine,
2026*9880d681SAndroid Build Coastguard Worker                         toRun,
2027*9880d681SAndroid Build Coastguard Worker                         (unsigned) strtoul(argv[i], NULL, 10));
2028*9880d681SAndroid Build Coastguard Worker     }
2029*9880d681SAndroid Build Coastguard Worker 
2030*9880d681SAndroid Build Coastguard Worker     fprintf(stderr, "\nEnd Test:\n\n");
2031*9880d681SAndroid Build Coastguard Worker   }
2032*9880d681SAndroid Build Coastguard Worker 
2033*9880d681SAndroid Build Coastguard Worker   delete executionEngine;
2034*9880d681SAndroid Build Coastguard Worker 
2035*9880d681SAndroid Build Coastguard Worker   return 0;
2036*9880d681SAndroid Build Coastguard Worker }
2037