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