llvm.org GIT mirror llvm / 626ab1c
reindent this whole file and do a variety of stylistic cleanups. This code is still a long way from following best practices. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@129140 91177308-0d34-0410-b5e6-96231b3b80d8 Chris Lattner 8 years ago
1 changed file(s) with 1413 addition(s) and 1435 deletion(s). Raw diff Collapse all Expand all
None //===-- examples/ExceptionDemo/ExceptionDemo.cpp -
1 // An example use of the llvm Exception mechanism --===//
0 //===-- ExceptionDemo.cpp - An example using llvm Exceptions --------------===//
21 //
32 // The LLVM Compiler Infrastructure
43 //
54 // This file is distributed under the University of Illinois Open Source
65 // License. See LICENSE.TXT for details.
76 //
8 //===--------------------------------------------------------------------===//
7 //===----------------------------------------------------------------------===//
98 //
109 // Demo program which implements an example LLVM exception implementation, and
1110 // shows several test cases including the handling of foreign exceptions.
4544 // This code uses code from the llvm compiler-rt project and the llvm
4645 // Kaleidoscope project.
4746 //
48 //===--------------------------------------------------------------------===//
49
47 //===----------------------------------------------------------------------===//
5048
5149 #include "llvm/LLVMContext.h"
5250 #include "llvm/DerivedTypes.h"
6361 #include "llvm/Support/IRBuilder.h"
6462 #include "llvm/Support/Dwarf.h"
6563
66 #include
67 #include
6864 #include
69 #include
70 #include
7165 #include
7266
7367
7973 // http://refspecs.freestandards.org/abi-eh-1.21.html
8074
8175 extern "C" {
82
83 typedef enum {
76
77 typedef enum {
8478 _URC_NO_REASON = 0,
8579 _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
8680 _URC_FATAL_PHASE2_ERROR = 2,
9084 _URC_HANDLER_FOUND = 6,
9185 _URC_INSTALL_CONTEXT = 7,
9286 _URC_CONTINUE_UNWIND = 8
93 } _Unwind_Reason_Code;
94
95 typedef enum {
87 } _Unwind_Reason_Code;
88
89 typedef enum {
9690 _UA_SEARCH_PHASE = 1,
9791 _UA_CLEANUP_PHASE = 2,
9892 _UA_HANDLER_FRAME = 4,
9993 _UA_FORCE_UNWIND = 8,
10094 _UA_END_OF_STACK = 16
101 } _Unwind_Action;
102
103 struct _Unwind_Exception;
104
105 typedef void (*_Unwind_Exception_Cleanup_Fn) (_Unwind_Reason_Code,
106 struct _Unwind_Exception *);
107
108 struct _Unwind_Exception {
95 } _Unwind_Action;
96
97 struct _Unwind_Exception;
98
99 typedef void (*_Unwind_Exception_Cleanup_Fn) (_Unwind_Reason_Code,
100 struct _Unwind_Exception *);
101
102 struct _Unwind_Exception {
109103 uint64_t exception_class;
110104 _Unwind_Exception_Cleanup_Fn exception_cleanup;
111
105
112106 uintptr_t private_1;
113107 uintptr_t private_2;
114
108
115109 // @@@ The IA-64 ABI says that this structure must be double-word aligned.
116110 // Taking that literally does not make much sense generically. Instead
117111 // we provide the maximum alignment required by any type for the machine.
118 } __attribute__((__aligned__));
119
120 struct _Unwind_Context;
121 typedef struct _Unwind_Context* _Unwind_Context_t;
122
123 extern const uint8_t* _Unwind_GetLanguageSpecificData (_Unwind_Context_t c);
124 extern uintptr_t _Unwind_GetGR (_Unwind_Context_t c, int i);
125 extern void _Unwind_SetGR (_Unwind_Context_t c, int i, uintptr_t n);
126 extern void _Unwind_SetIP (_Unwind_Context_t, uintptr_t new_value);
127 extern uintptr_t _Unwind_GetIP (_Unwind_Context_t context);
128 extern uintptr_t _Unwind_GetRegionStart (_Unwind_Context_t context);
129
112 } __attribute__((__aligned__));
113
114 struct _Unwind_Context;
115 typedef struct _Unwind_Context* _Unwind_Context_t;
116
117 extern const uint8_t* _Unwind_GetLanguageSpecificData (_Unwind_Context_t c);
118 extern uintptr_t _Unwind_GetGR (_Unwind_Context_t c, int i);
119 extern void _Unwind_SetGR (_Unwind_Context_t c, int i, uintptr_t n);
120 extern void _Unwind_SetIP (_Unwind_Context_t, uintptr_t new_value);
121 extern uintptr_t _Unwind_GetIP (_Unwind_Context_t context);
122 extern uintptr_t _Unwind_GetRegionStart (_Unwind_Context_t context);
123
130124 } // extern "C"
131125
132126 //
135129
136130 /// This is our simplistic type info
137131 struct OurExceptionType_t {
138 /// type info type
139 int type;
132 /// type info type
133 int type;
140134 };
141135
142136
147141 /// on a double word boundary. This is necessary to match the standard:
148142 /// http://refspecs.freestandards.org/abi-eh-1.21.html
149143 struct OurBaseException_t {
150 struct OurExceptionType_t type;
151
152 // Note: This is properly aligned in unwind.h
153 struct _Unwind_Exception unwindException;
144 struct OurExceptionType_t type;
145
146 // Note: This is properly aligned in unwind.h
147 struct _Unwind_Exception unwindException;
154148 };
155149
156150
168162 int64_t ourBaseFromUnwindOffset;
169163
170164 const unsigned char ourBaseExcpClassChars[] =
171 {'o', 'b', 'j', '\0', 'b', 'a', 's', '\0'};
165 {'o', 'b', 'j', '\0', 'b', 'a', 's', '\0'};
172166
173167
174168 static uint64_t ourBaseExceptionClass = 0;
211205 llvm::GlobalValue::LinkageTypes linkage,
212206 bool declarationOnly,
213207 bool isVarArg) {
214 llvm::FunctionType* functType = llvm::FunctionType::get(retType,
215 theArgTypes,
216 isVarArg);
217 llvm::Function* ret = llvm::Function::Create(functType,
218 linkage,
219 functName,
220 &module);
221 if (!ret || declarationOnly)
222 return(ret);
223
224 namedValues.clear();
225 unsigned i = 0;
226 for (llvm::Function::arg_iterator argIndex = ret->arg_begin();
227 i != theArgNames.size();
228 ++argIndex, ++i) {
229
230 argIndex->setName(theArgNames[i]);
231 namedValues[theArgNames[i]] = argIndex;
232 }
233
208 llvm::FunctionType *functType =
209 llvm::FunctionType::get(retType, theArgTypes, isVarArg);
210 llvm::Function *ret =
211 llvm::Function::Create(functType, linkage, functName, &module);
212 if (!ret || declarationOnly)
234213 return(ret);
214
215 namedValues.clear();
216 unsigned i = 0;
217 for (llvm::Function::arg_iterator argIndex = ret->arg_begin();
218 i != theArgNames.size();
219 ++argIndex, ++i) {
220
221 argIndex->setName(theArgNames[i]);
222 namedValues[theArgNames[i]] = argIndex;
223 }
224
225 return(ret);
235226 }
236227
237228
243234 /// @param initWith optional constant initialization value
244235 /// @returns AllocaInst instance
245236 static llvm::AllocaInst *createEntryBlockAlloca(llvm::Function& function,
246 const std::string &varName,
247 const llvm::Type* type,
248 llvm::Constant* initWith = NULL) {
249 llvm::BasicBlock& block = function.getEntryBlock();
250 llvm::IRBuilder<> tmp(&block, block.begin());
251 llvm::AllocaInst* ret = tmp.CreateAlloca(type, 0, varName.c_str());
252
253 if (initWith)
254 tmp.CreateStore(initWith, ret);
255
256 return(ret);
237 const std::string &varName,
238 const llvm::Type* type,
239 llvm::Constant* initWith = 0) {
240 llvm::BasicBlock& block = function.getEntryBlock();
241 llvm::IRBuilder<> tmp(&block, block.begin());
242 llvm::AllocaInst* ret = tmp.CreateAlloca(type, 0, varName.c_str());
243
244 if (initWith)
245 tmp.CreateStore(initWith, ret);
246
247 return(ret);
257248 }
258249
259250
274265 /// @param intToPrint integer to print
275266 /// @param format printf like format to use when printing
276267 void print32Int(int intToPrint, const char* format) {
277 if (format) {
278 // Note: No NULL check
279 fprintf(stderr, format, intToPrint);
280 }
281 else {
282 // Note: No NULL check
283 fprintf(stderr, "::print32Int(...):NULL arg.\n");
284 }
268 if (format) {
269 // Note: No NULL check
270 fprintf(stderr, format, intToPrint);
271 }
272 else {
273 // Note: No NULL check
274 fprintf(stderr, "::print32Int(...):NULL arg.\n");
275 }
285276 }
286277
287278
291282 /// @param intToPrint integer to print
292283 /// @param format printf like format to use when printing
293284 void print64Int(long int intToPrint, const char* format) {
294 if (format) {
295 // Note: No NULL check
296 fprintf(stderr, format, intToPrint);
297 }
298 else {
299 // Note: No NULL check
300 fprintf(stderr, "::print64Int(...):NULL arg.\n");
301 }
285 if (format) {
286 // Note: No NULL check
287 fprintf(stderr, format, intToPrint);
288 }
289 else {
290 // Note: No NULL check
291 fprintf(stderr, "::print64Int(...):NULL arg.\n");
292 }
302293 }
303294
304295
305296 /// Prints a C string to stderr
306297 /// @param toPrint string to print
307298 void printStr(char* toPrint) {
308 if (toPrint) {
309 fprintf(stderr, "%s", toPrint);
310 }
311 else {
312 fprintf(stderr, "::printStr(...):NULL arg.\n");
313 }
299 if (toPrint) {
300 fprintf(stderr, "%s", toPrint);
301 }
302 else {
303 fprintf(stderr, "::printStr(...):NULL arg.\n");
304 }
314305 }
315306
316307
320311 /// @param expToDelete exception to delete
321312 void deleteOurException(OurUnwindException* expToDelete) {
322313 #ifdef DEBUG
323 fprintf(stderr,
324 "deleteOurException(...).\n");
314 fprintf(stderr,
315 "deleteOurException(...).\n");
325316 #endif
326
327 if (expToDelete &&
328 (expToDelete->exception_class == ourBaseExceptionClass)) {
329
330 free(((char*) expToDelete) + ourBaseFromUnwindOffset);
331 }
317
318 if (expToDelete &&
319 (expToDelete->exception_class == ourBaseExceptionClass)) {
320
321 free(((char*) expToDelete) + ourBaseFromUnwindOffset);
322 }
332323 }
333324
334325
341332 void deleteFromUnwindOurException(_Unwind_Reason_Code reason,
342333 OurUnwindException* expToDelete) {
343334 #ifdef DEBUG
344 fprintf(stderr,
345 "deleteFromUnwindOurException(...).\n");
335 fprintf(stderr,
336 "deleteFromUnwindOurException(...).\n");
346337 #endif
347
348 deleteOurException(expToDelete);
338
339 deleteOurException(expToDelete);
349340 }
350341
351342
353344 /// of the supplied type info type.
354345 /// @param type type info type
355346 OurUnwindException* createOurException(int type) {
356 size_t size = sizeof(OurException);
357 OurException* ret = (OurException*) memset(malloc(size), 0, size);
358 (ret->type).type = type;
359 (ret->unwindException).exception_class = ourBaseExceptionClass;
360 (ret->unwindException).exception_cleanup = deleteFromUnwindOurException;
361
362 return(&(ret->unwindException));
347 size_t size = sizeof(OurException);
348 OurException* ret = (OurException*) memset(malloc(size), 0, size);
349 (ret->type).type = type;
350 (ret->unwindException).exception_class = ourBaseExceptionClass;
351 (ret->unwindException).exception_cleanup = deleteFromUnwindOurException;
352
353 return(&(ret->unwindException));
363354 }
364355
365356
369360 /// @param data reference variable holding memory pointer to decode from
370361 /// @returns decoded value
371362 static uintptr_t readULEB128(const uint8_t** data) {
372 uintptr_t result = 0;
373 uintptr_t shift = 0;
374 unsigned char byte;
375 const uint8_t* p = *data;
376
377 do {
378 byte = *p++;
379 result |= (byte & 0x7f) << shift;
380 shift += 7;
381 }
382 while (byte & 0x80);
383
384 *data = p;
385
386 return result;
363 uintptr_t result = 0;
364 uintptr_t shift = 0;
365 unsigned char byte;
366 const uint8_t* p = *data;
367
368 do {
369 byte = *p++;
370 result |= (byte & 0x7f) << shift;
371 shift += 7;
372 }
373 while (byte & 0x80);
374
375 *data = p;
376
377 return result;
387378 }
388379
389380
393384 /// @param data reference variable holding memory pointer to decode from
394385 /// @returns decoded value
395386 static uintptr_t readSLEB128(const uint8_t** data) {
396 uintptr_t result = 0;
397 uintptr_t shift = 0;
398 unsigned char byte;
399 const uint8_t* p = *data;
400
401 do {
402 byte = *p++;
403 result |= (byte & 0x7f) << shift;
404 shift += 7;
405 }
406 while (byte & 0x80);
407
408 *data = p;
409
410 if ((byte & 0x40) && (shift < (sizeof(result) << 3))) {
411 result |= (~0 << shift);
412 }
413
414 return result;
387 uintptr_t result = 0;
388 uintptr_t shift = 0;
389 unsigned char byte;
390 const uint8_t* p = *data;
391
392 do {
393 byte = *p++;
394 result |= (byte & 0x7f) << shift;
395 shift += 7;
396 }
397 while (byte & 0x80);
398
399 *data = p;
400
401 if ((byte & 0x40) && (shift < (sizeof(result) << 3))) {
402 result |= (~0 << shift);
403 }
404
405 return result;
415406 }
416407
417408
422413 /// @param encoding dwarf encoding type
423414 /// @returns decoded value
424415 static uintptr_t readEncodedPointer(const uint8_t** data, uint8_t encoding) {
425 uintptr_t result = 0;
426 const uint8_t* p = *data;
427
428 if (encoding == llvm::dwarf::DW_EH_PE_omit)
429 return(result);
430
431 // first get value
432 switch (encoding & 0x0F) {
433 case llvm::dwarf::DW_EH_PE_absptr:
434 result = *((uintptr_t*)p);
435 p += sizeof(uintptr_t);
436 break;
437 case llvm::dwarf::DW_EH_PE_uleb128:
438 result = readULEB128(&p);
439 break;
440 // Note: This case has not been tested
441 case llvm::dwarf::DW_EH_PE_sleb128:
442 result = readSLEB128(&p);
443 break;
444 case llvm::dwarf::DW_EH_PE_udata2:
445 result = *((uint16_t*)p);
446 p += sizeof(uint16_t);
447 break;
448 case llvm::dwarf::DW_EH_PE_udata4:
449 result = *((uint32_t*)p);
450 p += sizeof(uint32_t);
451 break;
452 case llvm::dwarf::DW_EH_PE_udata8:
453 result = *((uint64_t*)p);
454 p += sizeof(uint64_t);
455 break;
456 case llvm::dwarf::DW_EH_PE_sdata2:
457 result = *((int16_t*)p);
458 p += sizeof(int16_t);
459 break;
460 case llvm::dwarf::DW_EH_PE_sdata4:
461 result = *((int32_t*)p);
462 p += sizeof(int32_t);
463 break;
464 case llvm::dwarf::DW_EH_PE_sdata8:
465 result = *((int64_t*)p);
466 p += sizeof(int64_t);
467 break;
468 default:
469 // not supported
470 abort();
471 break;
472 }
473
474 // then add relative offset
475 switch (encoding & 0x70) {
476 case llvm::dwarf::DW_EH_PE_absptr:
477 // do nothing
478 break;
479 case llvm::dwarf::DW_EH_PE_pcrel:
480 result += (uintptr_t)(*data);
481 break;
482 case llvm::dwarf::DW_EH_PE_textrel:
483 case llvm::dwarf::DW_EH_PE_datarel:
484 case llvm::dwarf::DW_EH_PE_funcrel:
485 case llvm::dwarf::DW_EH_PE_aligned:
486 default:
487 // not supported
488 abort();
489 break;
490 }
491
492 // then apply indirection
493 if (encoding & llvm::dwarf::DW_EH_PE_indirect) {
494 result = *((uintptr_t*)result);
495 }
496
497 *data = p;
498
499 return result;
416 uintptr_t result = 0;
417 const uint8_t* p = *data;
418
419 if (encoding == llvm::dwarf::DW_EH_PE_omit)
420 return(result);
421
422 // first get value
423 switch (encoding & 0x0F) {
424 case llvm::dwarf::DW_EH_PE_absptr:
425 result = *((uintptr_t*)p);
426 p += sizeof(uintptr_t);
427 break;
428 case llvm::dwarf::DW_EH_PE_uleb128:
429 result = readULEB128(&p);
430 break;
431 // Note: This case has not been tested
432 case llvm::dwarf::DW_EH_PE_sleb128:
433 result = readSLEB128(&p);
434 break;
435 case llvm::dwarf::DW_EH_PE_udata2:
436 result = *((uint16_t*)p);
437 p += sizeof(uint16_t);
438 break;
439 case llvm::dwarf::DW_EH_PE_udata4:
440 result = *((uint32_t*)p);
441 p += sizeof(uint32_t);
442 break;
443 case llvm::dwarf::DW_EH_PE_udata8:
444 result = *((uint64_t*)p);
445 p += sizeof(uint64_t);
446 break;
447 case llvm::dwarf::DW_EH_PE_sdata2:
448 result = *((int16_t*)p);
449 p += sizeof(int16_t);
450 break;
451 case llvm::dwarf::DW_EH_PE_sdata4:
452 result = *((int32_t*)p);
453 p += sizeof(int32_t);
454 break;
455 case llvm::dwarf::DW_EH_PE_sdata8:
456 result = *((int64_t*)p);
457 p += sizeof(int64_t);
458 break;
459 default:
460 // not supported
461 abort();
462 break;
463 }
464
465 // then add relative offset
466 switch (encoding & 0x70) {
467 case llvm::dwarf::DW_EH_PE_absptr:
468 // do nothing
469 break;
470 case llvm::dwarf::DW_EH_PE_pcrel:
471 result += (uintptr_t)(*data);
472 break;
473 case llvm::dwarf::DW_EH_PE_textrel:
474 case llvm::dwarf::DW_EH_PE_datarel:
475 case llvm::dwarf::DW_EH_PE_funcrel:
476 case llvm::dwarf::DW_EH_PE_aligned:
477 default:
478 // not supported
479 abort();
480 break;
481 }
482
483 // then apply indirection
484 if (encoding & llvm::dwarf::DW_EH_PE_indirect) {
485 result = *((uintptr_t*)result);
486 }
487
488 *data = p;
489
490 return result;
500491 }
501492
502493
523514 uintptr_t actionEntry,
524515 uint64_t exceptionClass,
525516 struct _Unwind_Exception *exceptionObject) {
526 bool ret = false;
527
528 if (!resultAction ||
529 !exceptionObject ||
530 (exceptionClass != ourBaseExceptionClass))
531 return(ret);
532
533 struct OurBaseException_t* excp = (struct OurBaseException_t*)
534 (((char*) exceptionObject) + ourBaseFromUnwindOffset);
535 struct OurExceptionType_t *excpType = &(excp->type);
536 int type = excpType->type;
537
517 bool ret = false;
518
519 if (!resultAction ||
520 !exceptionObject ||
521 (exceptionClass != ourBaseExceptionClass))
522 return(ret);
523
524 struct OurBaseException_t* excp = (struct OurBaseException_t*)
525 (((char*) exceptionObject) + ourBaseFromUnwindOffset);
526 struct OurExceptionType_t *excpType = &(excp->type);
527 int type = excpType->type;
528
529 #ifdef DEBUG
530 fprintf(stderr,
531 "handleActionValue(...): exceptionObject = <%p>, "
532 "excp = <%p>.\n",
533 exceptionObject,
534 excp);
535 #endif
536
537 const uint8_t *actionPos = (uint8_t*) actionEntry,
538 *tempActionPos;
539 int64_t typeOffset = 0,
540 actionOffset;
541
542 for (int i = 0; true; ++i) {
543 // Each emitted dwarf action corresponds to a 2 tuple of
544 // type info address offset, and action offset to the next
545 // emitted action.
546 typeOffset = readSLEB128(&actionPos);
547 tempActionPos = actionPos;
548 actionOffset = readSLEB128(&tempActionPos);
549
538550 #ifdef DEBUG
539551 fprintf(stderr,
540 "handleActionValue(...): exceptionObject = <%p>, "
541 "excp = <%p>.\n",
542 exceptionObject,
543 excp);
552 "handleActionValue(...):typeOffset: <%lld>, "
553 "actionOffset: <%lld>.\n",
554 typeOffset,
555 actionOffset);
544556 #endif
545
546 const uint8_t *actionPos = (uint8_t*) actionEntry,
547 *tempActionPos;
548 int64_t typeOffset = 0,
549 actionOffset;
550
551 for (int i = 0; true; ++i) {
552 // Each emitted dwarf action corresponds to a 2 tuple of
553 // type info address offset, and action offset to the next
554 // emitted action.
555 typeOffset = readSLEB128(&actionPos);
556 tempActionPos = actionPos;
557 actionOffset = readSLEB128(&tempActionPos);
558
557 assert((typeOffset >= 0) &&
558 "handleActionValue(...):filters are not supported.");
559
560 // Note: A typeOffset == 0 implies that a cleanup llvm.eh.selector
561 // argument has been matched.
562 if ((typeOffset > 0) &&
563 (type == (classInfo[-typeOffset])->type)) {
559564 #ifdef DEBUG
560 fprintf(stderr,
561 "handleActionValue(...):typeOffset: <%lld>, "
562 "actionOffset: <%lld>.\n",
563 typeOffset,
564 actionOffset);
565 fprintf(stderr,
566 "handleActionValue(...):actionValue <%d> found.\n",
567 i);
565568 #endif
566 assert((typeOffset >= 0) &&
567 "handleActionValue(...):filters are not supported.");
568
569 // Note: A typeOffset == 0 implies that a cleanup llvm.eh.selector
570 // argument has been matched.
571 if ((typeOffset > 0) &&
572 (type == (classInfo[-typeOffset])->type)) {
569 *resultAction = i + 1;
570 ret = true;
571 break;
572 }
573
573574 #ifdef DEBUG
574 fprintf(stderr,
575 "handleActionValue(...):actionValue <%d> found.\n",
576 i);
575 fprintf(stderr,
576 "handleActionValue(...):actionValue not found.\n");
577577 #endif
578 *resultAction = i + 1;
579 ret = true;
580 break;
581 }
582
583 #ifdef DEBUG
584 fprintf(stderr,
585 "handleActionValue(...):actionValue not found.\n");
586 #endif
587 if (!actionOffset)
588 break;
589
590 actionPos += actionOffset;
591 }
592
593 return(ret);
578 if (!actionOffset)
579 break;
580
581 actionPos += actionOffset;
582 }
583
584 return(ret);
594585 }
595586
596587
606597 /// @param context unwind system context
607598 /// @returns minimally supported unwinding control indicator
608599 static _Unwind_Reason_Code handleLsda(int version,
609 const uint8_t* lsda,
610 _Unwind_Action actions,
611 uint64_t exceptionClass,
612 struct _Unwind_Exception* exceptionObject,
613 _Unwind_Context_t context) {
614 _Unwind_Reason_Code ret = _URC_CONTINUE_UNWIND;
615
616 if (!lsda)
617 return(ret);
618
600 const uint8_t* lsda,
601 _Unwind_Action actions,
602 uint64_t exceptionClass,
603 struct _Unwind_Exception* exceptionObject,
604 _Unwind_Context_t context) {
605 _Unwind_Reason_Code ret = _URC_CONTINUE_UNWIND;
606
607 if (!lsda)
608 return(ret);
609
619610 #ifdef DEBUG
620 fprintf(stderr,
621 "handleLsda(...):lsda is non-zero.\n");
611 fprintf(stderr,
612 "handleLsda(...):lsda is non-zero.\n");
622613 #endif
623
624 // Get the current instruction pointer and offset it before next
625 // instruction in the current frame which threw the exception.
626 uintptr_t pc = _Unwind_GetIP(context)-1;
627
628 // Get beginning current frame's code (as defined by the
629 // emitted dwarf code)
630 uintptr_t funcStart = _Unwind_GetRegionStart(context);
631 uintptr_t pcOffset = pc - funcStart;
632 struct OurExceptionType_t** classInfo = NULL;
633
634 // Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding
635 // dwarf emission
636
637 // Parse LSDA header.
638 uint8_t lpStartEncoding = *lsda++;
639
640 if (lpStartEncoding != llvm::dwarf::DW_EH_PE_omit) {
641 readEncodedPointer(&lsda, lpStartEncoding);
614
615 // Get the current instruction pointer and offset it before next
616 // instruction in the current frame which threw the exception.
617 uintptr_t pc = _Unwind_GetIP(context)-1;
618
619 // Get beginning current frame's code (as defined by the
620 // emitted dwarf code)
621 uintptr_t funcStart = _Unwind_GetRegionStart(context);
622 uintptr_t pcOffset = pc - funcStart;
623 struct OurExceptionType_t** classInfo = NULL;
624
625 // Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding
626 // dwarf emission
627
628 // Parse LSDA header.
629 uint8_t lpStartEncoding = *lsda++;
630
631 if (lpStartEncoding != llvm::dwarf::DW_EH_PE_omit) {
632 readEncodedPointer(&lsda, lpStartEncoding);
633 }
634
635 uint8_t ttypeEncoding = *lsda++;
636 uintptr_t classInfoOffset;
637
638 if (ttypeEncoding != llvm::dwarf::DW_EH_PE_omit) {
639 // Calculate type info locations in emitted dwarf code which
640 // were flagged by type info arguments to llvm.eh.selector
641 // intrinsic
642 classInfoOffset = readULEB128(&lsda);
643 classInfo = (struct OurExceptionType_t**) (lsda + classInfoOffset);
644 }
645
646 // Walk call-site table looking for range that
647 // includes current PC.
648
649 uint8_t callSiteEncoding = *lsda++;
650 uint32_t callSiteTableLength = readULEB128(&lsda);
651 const uint8_t* callSiteTableStart = lsda;
652 const uint8_t* callSiteTableEnd = callSiteTableStart +
653 callSiteTableLength;
654 const uint8_t* actionTableStart = callSiteTableEnd;
655 const uint8_t* callSitePtr = callSiteTableStart;
656
657 bool foreignException = false;
658
659 while (callSitePtr < callSiteTableEnd) {
660 uintptr_t start = readEncodedPointer(&callSitePtr,
661 callSiteEncoding);
662 uintptr_t length = readEncodedPointer(&callSitePtr,
663 callSiteEncoding);
664 uintptr_t landingPad = readEncodedPointer(&callSitePtr,
665 callSiteEncoding);
666
667 // Note: Action value
668 uintptr_t actionEntry = readULEB128(&callSitePtr);
669
670 if (exceptionClass != ourBaseExceptionClass) {
671 // We have been notified of a foreign exception being thrown,
672 // and we therefore need to execute cleanup landing pads
673 actionEntry = 0;
674 foreignException = true;
642675 }
643
644 uint8_t ttypeEncoding = *lsda++;
645 uintptr_t classInfoOffset;
646
647 if (ttypeEncoding != llvm::dwarf::DW_EH_PE_omit) {
648 // Calculate type info locations in emitted dwarf code which
649 // were flagged by type info arguments to llvm.eh.selector
650 // intrinsic
651 classInfoOffset = readULEB128(&lsda);
652 classInfo = (struct OurExceptionType_t**) (lsda + classInfoOffset);
676
677 if (landingPad == 0) {
678 #ifdef DEBUG
679 fprintf(stderr,
680 "handleLsda(...): No landing pad found.\n");
681 #endif
682
683 continue; // no landing pad for this entry
653684 }
654
655 // Walk call-site table looking for range that
656 // includes current PC.
657
658 uint8_t callSiteEncoding = *lsda++;
659 uint32_t callSiteTableLength = readULEB128(&lsda);
660 const uint8_t* callSiteTableStart = lsda;
661 const uint8_t* callSiteTableEnd = callSiteTableStart +
662 callSiteTableLength;
663 const uint8_t* actionTableStart = callSiteTableEnd;
664 const uint8_t* callSitePtr = callSiteTableStart;
665
666 bool foreignException = false;
667
668 while (callSitePtr < callSiteTableEnd) {
669 uintptr_t start = readEncodedPointer(&callSitePtr,
670 callSiteEncoding);
671 uintptr_t length = readEncodedPointer(&callSitePtr,
672 callSiteEncoding);
673 uintptr_t landingPad = readEncodedPointer(&callSitePtr,
674 callSiteEncoding);
675
676 // Note: Action value
677 uintptr_t actionEntry = readULEB128(&callSitePtr);
678
679 if (exceptionClass != ourBaseExceptionClass) {
680 // We have been notified of a foreign exception being thrown,
681 // and we therefore need to execute cleanup landing pads
682 actionEntry = 0;
683 foreignException = true;
684 }
685
686 if (landingPad == 0) {
685
686 if (actionEntry) {
687 actionEntry += ((uintptr_t) actionTableStart) - 1;
688 }
689 else {
687690 #ifdef DEBUG
688 fprintf(stderr,
689 "handleLsda(...): No landing pad found.\n");
691 fprintf(stderr,
692 "handleLsda(...):No action table found.\n");
690693 #endif
691
692 continue; // no landing pad for this entry
693 }
694
695 if (actionEntry) {
696 actionEntry += ((uintptr_t) actionTableStart) - 1;
694 }
695
696 bool exceptionMatched = false;
697
698 if ((start <= pcOffset) && (pcOffset < (start + length))) {
699 #ifdef DEBUG
700 fprintf(stderr,
701 "handleLsda(...): Landing pad found.\n");
702 #endif
703 int64_t actionValue = 0;
704
705 if (actionEntry) {
706 exceptionMatched = handleActionValue
707 (
708 &actionValue,
709 classInfo,
710 actionEntry,
711 exceptionClass,
712 exceptionObject
713 );
714 }
715
716 if (!(actions & _UA_SEARCH_PHASE)) {
717 #ifdef DEBUG
718 fprintf(stderr,
719 "handleLsda(...): installed landing pad "
720 "context.\n");
721 #endif
722
723 // Found landing pad for the PC.
724 // Set Instruction Pointer to so we re-enter function
725 // at landing pad. The landing pad is created by the
726 // compiler to take two parameters in registers.
727 _Unwind_SetGR(context,
728 __builtin_eh_return_data_regno(0),
729 (uintptr_t)exceptionObject);
730
731 // Note: this virtual register directly corresponds
732 // to the return of the llvm.eh.selector intrinsic
733 if (!actionEntry || !exceptionMatched) {
734 // We indicate cleanup only
735 _Unwind_SetGR(context,
736 __builtin_eh_return_data_regno(1),
737 0);
697738 }
698739 else {
740 // Matched type info index of llvm.eh.selector intrinsic
741 // passed here.
742 _Unwind_SetGR(context,
743 __builtin_eh_return_data_regno(1),
744 actionValue);
745 }
746
747 // To execute landing pad set here
748 _Unwind_SetIP(context, funcStart + landingPad);
749 ret = _URC_INSTALL_CONTEXT;
750 }
751 else if (exceptionMatched) {
699752 #ifdef DEBUG
700 fprintf(stderr,
701 "handleLsda(...):No action table found.\n");
753 fprintf(stderr,
754 "handleLsda(...): setting handler found.\n");
702755 #endif
703 }
704
705 bool exceptionMatched = false;
706
707 if ((start <= pcOffset) && (pcOffset < (start + length))) {
756 ret = _URC_HANDLER_FOUND;
757 }
758 else {
759 // Note: Only non-clean up handlers are marked as
760 // found. Otherwise the clean up handlers will be
761 // re-found and executed during the clean up
762 // phase.
708763 #ifdef DEBUG
709 fprintf(stderr,
710 "handleLsda(...): Landing pad found.\n");
764 fprintf(stderr,
765 "handleLsda(...): cleanup handler found.\n");
711766 #endif
712 int64_t actionValue = 0;
713
714 if (actionEntry) {
715 exceptionMatched = handleActionValue
716 (
717 &actionValue,
718 classInfo,
719 actionEntry,
720 exceptionClass,
721 exceptionObject
722 );
723 }
724
725 if (!(actions & _UA_SEARCH_PHASE)) {
726 #ifdef DEBUG
727 fprintf(stderr,
728 "handleLsda(...): installed landing pad "
729 "context.\n");
730 #endif
731
732 // Found landing pad for the PC.
733 // Set Instruction Pointer to so we re-enter function
734 // at landing pad. The landing pad is created by the
735 // compiler to take two parameters in registers.
736 _Unwind_SetGR(context,
737 __builtin_eh_return_data_regno(0),
738 (uintptr_t)exceptionObject);
739
740 // Note: this virtual register directly corresponds
741 // to the return of the llvm.eh.selector intrinsic
742 if (!actionEntry || !exceptionMatched) {
743 // We indicate cleanup only
744 _Unwind_SetGR(context,
745 __builtin_eh_return_data_regno(1),
746 0);
747 }
748 else {
749 // Matched type info index of llvm.eh.selector intrinsic
750 // passed here.
751 _Unwind_SetGR(context,
752 __builtin_eh_return_data_regno(1),
753 actionValue);
754 }
755
756 // To execute landing pad set here
757 _Unwind_SetIP(context, funcStart + landingPad);
758 ret = _URC_INSTALL_CONTEXT;
759 }
760 else if (exceptionMatched) {
761 #ifdef DEBUG
762 fprintf(stderr,
763 "handleLsda(...): setting handler found.\n");
764 #endif
765 ret = _URC_HANDLER_FOUND;
766 }
767 else {
768 // Note: Only non-clean up handlers are marked as
769 // found. Otherwise the clean up handlers will be
770 // re-found and executed during the clean up
771 // phase.
772 #ifdef DEBUG
773 fprintf(stderr,
774 "handleLsda(...): cleanup handler found.\n");
775 #endif
776 }
777
778 break;
779 }
767 }
768
769 break;
780770 }
781
782 return(ret);
771 }
772
773 return(ret);
783774 }
784775
785776
795786 /// @param context unwind system context
796787 /// @returns minimally supported unwinding control indicator
797788 _Unwind_Reason_Code ourPersonality(int version,
798 _Unwind_Action actions,
799 uint64_t exceptionClass,
800 struct _Unwind_Exception* exceptionObject,
801 _Unwind_Context_t context) {
789 _Unwind_Action actions,
790 uint64_t exceptionClass,
791 struct _Unwind_Exception* exceptionObject,
792 _Unwind_Context_t context) {
802793 #ifdef DEBUG
803 fprintf(stderr,
804 "We are in ourPersonality(...):actions is <%d>.\n",
805 actions);
806
807 if (actions & _UA_SEARCH_PHASE) {
808 fprintf(stderr, "ourPersonality(...):In search phase.\n");
809 }
810 else {
811 fprintf(stderr, "ourPersonality(...):In non-search phase.\n");
812 }
794 fprintf(stderr,
795 "We are in ourPersonality(...):actions is <%d>.\n",
796 actions);
797
798 if (actions & _UA_SEARCH_PHASE) {
799 fprintf(stderr, "ourPersonality(...):In search phase.\n");
800 }
801 else {
802 fprintf(stderr, "ourPersonality(...):In non-search phase.\n");
803 }
813804 #endif
814
815 const uint8_t* lsda = _Unwind_GetLanguageSpecificData(context);
816
805
806 const uint8_t* lsda = _Unwind_GetLanguageSpecificData(context);
807
817808 #ifdef DEBUG
818 fprintf(stderr,
819 "ourPersonality(...):lsda = <%p>.\n",
820 lsda);
809 fprintf(stderr,
810 "ourPersonality(...):lsda = <%p>.\n",
811 lsda);
821812 #endif
822
823 // The real work of the personality function is captured here
824 return(handleLsda(version,
825 lsda,
826 actions,
827 exceptionClass,
828 exceptionObject,
829 context));
813
814 // The real work of the personality function is captured here
815 return(handleLsda(version,
816 lsda,
817 actions,
818 exceptionClass,
819 exceptionObject,
820 context));
830821 }
831822
832823
839830 /// @returns class value
840831 uint64_t genClass(const unsigned char classChars[], size_t classCharsSize)
841832 {
842 uint64_t ret = classChars[0];
843
844 for (unsigned i = 1; i < classCharsSize; ++i) {
845 ret <<= 8;
846 ret += classChars[i];
847 }
848
849 return(ret);
833 uint64_t ret = classChars[0];
834
835 for (unsigned i = 1; i < classCharsSize; ++i) {
836 ret <<= 8;
837 ret += classChars[i];
838 }
839
840 return(ret);
850841 }
851842
852843 } // extern "C"
873864 llvm::IRBuilder<>& builder,
874865 std::string toPrint,
875866 bool useGlobal = true) {
876 llvm::Function *printFunct = module.getFunction("printStr");
877
878 llvm::Value *stringVar;
879 llvm::Constant* stringConstant =
880 llvm::ConstantArray::get(context, toPrint);
881
882 if (useGlobal) {
883 // Note: Does not work without allocation
884 stringVar =
885 new llvm::GlobalVariable(module,
886 stringConstant->getType(),
887 true,
888 llvm::GlobalValue::LinkerPrivateLinkage,
889 stringConstant,
890 "");
891 }
892 else {
893 stringVar = builder.CreateAlloca(stringConstant->getType());
894 builder.CreateStore(stringConstant, stringVar);
895 }
896
897 llvm::Value* cast =
898 builder.CreatePointerCast(stringVar,
899 builder.getInt8Ty()->getPointerTo());
900 builder.CreateCall(printFunct, cast);
867 llvm::Function *printFunct = module.getFunction("printStr");
868
869 llvm::Value *stringVar;
870 llvm::Constant* stringConstant =
871 llvm::ConstantArray::get(context, toPrint);
872
873 if (useGlobal) {
874 // Note: Does not work without allocation
875 stringVar =
876 new llvm::GlobalVariable(module,
877 stringConstant->getType(),
878 true,
879 llvm::GlobalValue::LinkerPrivateLinkage,
880 stringConstant,
881 "");
882 }
883 else {
884 stringVar = builder.CreateAlloca(stringConstant->getType());
885 builder.CreateStore(stringConstant, stringVar);
886 }
887
888 llvm::Value* cast =
889 builder.CreatePointerCast(stringVar,
890 builder.getInt8Ty()->getPointerTo());
891 builder.CreateCall(printFunct, cast);
901892 }
902893
903894
920911 llvm::Value& toPrint,
921912 std::string format,
922913 bool useGlobal = true) {
923 llvm::Constant *stringConstant = llvm::ConstantArray::get(context, format);
924 llvm::Value *stringVar;
925
926 if (useGlobal) {
927 // Note: Does not seem to work without allocation
928 stringVar =
929 new llvm::GlobalVariable(module,
930 stringConstant->getType(),
931 true,
932 llvm::GlobalValue::LinkerPrivateLinkage,
933 stringConstant,
934 "");
935 }
936 else {
937 stringVar = builder.CreateAlloca(stringConstant->getType());
938 builder.CreateStore(stringConstant, stringVar);
939 }
940
941 llvm::Value* cast =
942 builder.CreateBitCast(stringVar,
943 builder.getInt8Ty()->getPointerTo());
944 builder.CreateCall2(&printFunct, &toPrint, cast);
914 llvm::Constant *stringConstant = llvm::ConstantArray::get(context, format);
915 llvm::Value *stringVar;
916
917 if (useGlobal) {
918 // Note: Does not seem to work without allocation
919 stringVar =
920 new llvm::GlobalVariable(module,
921 stringConstant->getType(),
922 true,
923 llvm::GlobalValue::LinkerPrivateLinkage,
924 stringConstant,
925 "");
926 }
927 else {
928 stringVar = builder.CreateAlloca(stringConstant->getType());
929 builder.CreateStore(stringConstant, stringVar);
930 }
931
932 llvm::Value* cast =
933 builder.CreateBitCast(stringVar,
934 builder.getInt8Ty()->getPointerTo());
935 builder.CreateCall2(&printFunct, &toPrint, cast);
945936 }
946937
947938
965956 /// @param exceptionStorage reference to exception pointer storage
966957 /// @returns newly created block
967958 static llvm::BasicBlock* createFinallyBlock(llvm::LLVMContext& context,
968 llvm::Module& module,
969 llvm::IRBuilder<>& builder,
970 llvm::Function& toAddTo,
971 std::string& blockName,
972 std::string& functionId,
973 llvm::BasicBlock& terminatorBlock,
974 llvm::BasicBlock& unwindResumeBlock,
975 llvm::Value** exceptionCaughtFlag,
976 llvm::Value** exceptionStorage) {
977 assert(exceptionCaughtFlag &&
978 "ExceptionDemo::createFinallyBlock(...):exceptionCaughtFlag "
979 "is NULL");
980 assert(exceptionStorage &&
981 "ExceptionDemo::createFinallyBlock(...):exceptionStorage "
982 "is NULL");
983
984 *exceptionCaughtFlag =
985 createEntryBlockAlloca(toAddTo,
986 "exceptionCaught",
987 ourExceptionNotThrownState->getType(),
988 ourExceptionNotThrownState);
989
990 const llvm::PointerType* exceptionStorageType =
991 builder.getInt8Ty()->getPointerTo();
992 *exceptionStorage =
993 createEntryBlockAlloca(toAddTo,
994 "exceptionStorage",
995 exceptionStorageType,
996 llvm::ConstantPointerNull::get(
997 exceptionStorageType));
998
999 llvm::BasicBlock *ret = llvm::BasicBlock::Create(context,
1000 blockName,
1001 &toAddTo);
1002
1003 builder.SetInsertPoint(ret);
1004
1005 std::ostringstream bufferToPrint;
1006 bufferToPrint << "Gen: Executing finally block "
1007 << blockName
1008 << " in "
1009 << functionId
1010 << std::endl;
1011 generateStringPrint(context,
1012 module,
1013 builder,
1014 bufferToPrint.str(),
1015 USE_GLOBAL_STR_CONSTS);
1016
1017 llvm::SwitchInst* theSwitch =
1018 builder.CreateSwitch(builder.CreateLoad(*exceptionCaughtFlag),
1019 &terminatorBlock,
1020 2);
1021 theSwitch->addCase(ourExceptionCaughtState, &terminatorBlock);
1022 theSwitch->addCase(ourExceptionThrownState, &unwindResumeBlock);
1023
1024 return(ret);
959 llvm::Module& module,
960 llvm::IRBuilder<>& builder,
961 llvm::Function& toAddTo,
962 std::string& blockName,
963 std::string& functionId,
964 llvm::BasicBlock& terminatorBlock,
965 llvm::BasicBlock& unwindResumeBlock,
966 llvm::Value** exceptionCaughtFlag,
967 llvm::Value** exceptionStorage) {
968 assert(exceptionCaughtFlag &&
969 "ExceptionDemo::createFinallyBlock(...):exceptionCaughtFlag "
970 "is NULL");
971 assert(exceptionStorage &&
972 "ExceptionDemo::createFinallyBlock(...):exceptionStorage "
973 "is NULL");
974
975 *exceptionCaughtFlag =
976 createEntryBlockAlloca(toAddTo,
977 "exceptionCaught",
978 ourExceptionNotThrownState->getType(),
979 ourExceptionNotThrownState);
980
981 const llvm::PointerType* exceptionStorageType =
982 builder.getInt8Ty()->getPointerTo();
983 *exceptionStorage =
984 createEntryBlockAlloca(toAddTo,
985 "exceptionStorage",
986 exceptionStorageType,
987 llvm::ConstantPointerNull::get(
988 exceptionStorageType));
989
990 llvm::BasicBlock *ret = llvm::BasicBlock::Create(context,
991 blockName,
992 &toAddTo);
993
994 builder.SetInsertPoint(ret);
995
996 std::ostringstream bufferToPrint;
997 bufferToPrint << "Gen: Executing finally block "
998 << blockName << " in " << functionId << "\n";
999 generateStringPrint(context,
1000 module,
1001 builder,
1002 bufferToPrint.str(),
1003 USE_GLOBAL_STR_CONSTS);
1004
1005 llvm::SwitchInst* theSwitch =
1006 builder.CreateSwitch(builder.CreateLoad(*exceptionCaughtFlag),
1007 &terminatorBlock,
1008 2);
1009 theSwitch->addCase(ourExceptionCaughtState, &terminatorBlock);
1010 theSwitch->addCase(ourExceptionThrownState, &unwindResumeBlock);
1011
1012 return(ret);
10251013 }
10261014
10271015
10451033 std::string& functionId,
10461034 llvm::BasicBlock& terminatorBlock,
10471035 llvm::Value& exceptionCaughtFlag) {
1048
1049 llvm::BasicBlock *ret = llvm::BasicBlock::Create(context,
1050 blockName,
1051 &toAddTo);
1052
1053 builder.SetInsertPoint(ret);
1054
1055 std::ostringstream bufferToPrint;
1056 bufferToPrint << "Gen: Executing catch block "
1057 << blockName
1058 << " in "
1059 << functionId
1060 << std::endl;
1061 generateStringPrint(context,
1062 module,
1063 builder,
1064 bufferToPrint.str(),
1065 USE_GLOBAL_STR_CONSTS);
1066 builder.CreateStore(ourExceptionCaughtState, &exceptionCaughtFlag);
1067 builder.CreateBr(&terminatorBlock);
1068
1069 return(ret);
1036
1037 llvm::BasicBlock *ret = llvm::BasicBlock::Create(context,
1038 blockName,
1039 &toAddTo);
1040
1041 builder.SetInsertPoint(ret);
1042
1043 std::ostringstream bufferToPrint;
1044 bufferToPrint << "Gen: Executing catch block "
1045 << blockName
1046 << " in "
1047 << functionId
1048 << std::endl;
1049 generateStringPrint(context,
1050 module,
1051 builder,
1052 bufferToPrint.str(),
1053 USE_GLOBAL_STR_CONSTS);
1054 builder.CreateStore(ourExceptionCaughtState, &exceptionCaughtFlag);
1055 builder.CreateBr(&terminatorBlock);
1056
1057 return(ret);
10701058 }
10711059
10721060
10911079 /// @returns generated function
10921080 static
10931081 llvm::Function* createCatchWrappedInvokeFunction(llvm::Module& module,
1094 llvm::IRBuilder<>& builder,
1095 llvm::FunctionPassManager& fpm,
1096 llvm::Function& toInvoke,
1097 std::string ourId,
1098 unsigned numExceptionsToCatch,
1099 unsigned exceptionTypesToCatch[]) {
1100
1101 llvm::LLVMContext& context = module.getContext();
1102 llvm::Function *toPrint32Int = module.getFunction("print32Int");
1103
1104 ArgTypes argTypes;
1105 argTypes.push_back(builder.getInt32Ty());
1106
1107 ArgNames argNames;
1108 argNames.push_back("exceptTypeToThrow");
1109
1110 llvm::Function* ret = createFunction(module,
1111 builder.getVoidTy(),
1112 argTypes,
1113 argNames,
1114 ourId,
1115 llvm::Function::ExternalLinkage,
1116 false,
1117 false);
1118
1119 // Block which calls invoke
1120 llvm::BasicBlock *entryBlock = llvm::BasicBlock::Create(context,
1121 "entry",
1122 ret);
1123 // Normal block for invoke
1124 llvm::BasicBlock *normalBlock = llvm::BasicBlock::Create(context,
1125 "normal",
1126 ret);
1127 // Unwind block for invoke
1128 llvm::BasicBlock *exceptionBlock =
1129 llvm::BasicBlock::Create(context, "exception", ret);
1130
1131 // Block which routes exception to correct catch handler block
1132 llvm::BasicBlock *exceptionRouteBlock =
1133 llvm::BasicBlock::Create(context, "exceptionRoute", ret);
1134
1135 // Foreign exception handler
1136 llvm::BasicBlock *externalExceptionBlock =
1137 llvm::BasicBlock::Create(context, "externalException", ret);
1138
1139 // Block which calls _Unwind_Resume
1140 llvm::BasicBlock *unwindResumeBlock =
1141 llvm::BasicBlock::Create(context, "unwindResume", ret);
1142
1143 // Clean up block which delete exception if needed
1144 llvm::BasicBlock *endBlock =
1145 llvm::BasicBlock::Create(context, "end", ret);
1146
1147 std::string nextName;
1148 std::vector catchBlocks(numExceptionsToCatch);
1149 llvm::Value* exceptionCaughtFlag = NULL;
1150 llvm::Value* exceptionStorage = NULL;
1151
1152 // Finally block which will branch to unwindResumeBlock if
1153 // exception is not caught. Initializes/allocates stack locations.
1154 llvm::BasicBlock* finallyBlock = createFinallyBlock(context,
1155 module,
1156 builder,
1157 *ret,
1158 nextName = "finally",
1159 ourId,
1160 *endBlock,
1161 *unwindResumeBlock,
1162 &exceptionCaughtFlag,
1163 &exceptionStorage);
1164
1165 for (unsigned i = 0; i < numExceptionsToCatch; ++i) {
1166 nextName = ourTypeInfoNames[exceptionTypesToCatch[i]];
1167
1168 // One catch block per type info to be caught
1169 catchBlocks[i] = createCatchBlock(context,
1170 module,
1171 builder,
1172 *ret,
1173 nextName,
1174 ourId,
1175 *finallyBlock,
1176 *exceptionCaughtFlag);
1177 }
1178
1179 // Entry Block
1180
1181 builder.SetInsertPoint(entryBlock);
1182
1183 std::vector args;
1184 args.push_back(namedValues["exceptTypeToThrow"]);
1185 builder.CreateInvoke(&toInvoke,
1186 normalBlock,
1187 exceptionBlock,
1188 args.begin(),
1189 args.end());
1190
1191 // End Block
1192
1193 builder.SetInsertPoint(endBlock);
1194
1195 generateStringPrint(context,
1196 module,
1197 builder,
1198 "Gen: In end block: exiting in " + ourId + ".\n",
1199 USE_GLOBAL_STR_CONSTS);
1200 llvm::Function *deleteOurException =
1201 module.getFunction("deleteOurException");
1202
1203 // Note: function handles NULL exceptions
1204 builder.CreateCall(deleteOurException,
1205 builder.CreateLoad(exceptionStorage));
1206 builder.CreateRetVoid();
1207
1208 // Normal Block
1209
1210 builder.SetInsertPoint(normalBlock);
1211
1212 generateStringPrint(context,
1213 module,
1214 builder,
1215 "Gen: No exception in " + ourId + "!\n",
1216 USE_GLOBAL_STR_CONSTS);
1217
1218 // Finally block is always called
1219 builder.CreateBr(finallyBlock);
1220
1221 // Unwind Resume Block
1222
1223 builder.SetInsertPoint(unwindResumeBlock);
1224
1225 llvm::Function *resumeOurException =
1226 module.getFunction("_Unwind_Resume");
1227 builder.CreateCall(resumeOurException,
1228 builder.CreateLoad(exceptionStorage));
1229 builder.CreateUnreachable();
1230
1231 // Exception Block
1232
1233 builder.SetInsertPoint(exceptionBlock);
1234
1235 llvm::Function *ehException = module.getFunction("llvm.eh.exception");
1236
1237 // Retrieve thrown exception
1238 llvm::Value* unwindException = builder.CreateCall(ehException);
1239
1240 // Store exception and flag
1241 builder.CreateStore(unwindException, exceptionStorage);
1242 builder.CreateStore(ourExceptionThrownState, exceptionCaughtFlag);
1243 llvm::Function *personality = module.getFunction("ourPersonality");
1244 llvm::Value* functPtr =
1245 builder.CreatePointerCast(personality,
1246 builder.getInt8Ty()->getPointerTo());
1247
1248 args.clear();
1249 args.push_back(unwindException);
1250 args.push_back(functPtr);
1251
1252 // Note: Skipping index 0
1253 for (unsigned i = 0; i < numExceptionsToCatch; ++i) {
1254 // Set up type infos to be caught
1255 args.push_back(
1256 module.getGlobalVariable(
1257 ourTypeInfoNames[exceptionTypesToCatch[i]]));
1258 }
1259
1260 args.push_back(llvm::ConstantInt::get(builder.getInt32Ty(), 0));
1261
1262 llvm::Function *ehSelector = module.getFunction("llvm.eh.selector");
1263
1264 // Set up this exeption block as the landing pad which will handle
1265 // given type infos. See case Intrinsic::eh_selector in
1266 // SelectionDAGBuilder::visitIntrinsicCall(...) and AddCatchInfo(...)
1267 // implemented in FunctionLoweringInfo.cpp to see how the implementation
1268 // handles this call. This landing pad (this exception block), will be
1269 // called either because it nees to cleanup (call finally) or a type
1270 // info was found which matched the thrown exception.
1271 llvm::Value* retTypeInfoIndex = builder.CreateCall(ehSelector,
1272 args.begin(),
1273 args.end());
1274
1275 // Retrieve exception_class member from thrown exception
1276 // (_Unwind_Exception instance). This member tells us whether or not
1277 // the exception is foreign.
1278 llvm::Value* unwindExceptionClass =
1279 builder.CreateLoad(
1280 builder.CreateStructGEP(
1281 builder.CreatePointerCast(
1282 unwindException,
1283 ourUnwindExceptionType->getPointerTo()),
1284 0));
1285
1286 // Branch to the externalExceptionBlock if the exception is foreign or
1287 // to a catch router if not. Either way the finally block will be run.
1288 builder.CreateCondBr(
1289 builder.CreateICmpEQ(unwindExceptionClass,
1290 llvm::ConstantInt::get(builder.getInt64Ty(),
1291 ourBaseExceptionClass)),
1292 exceptionRouteBlock,
1293 externalExceptionBlock);
1294
1295 // External Exception Block
1296
1297 builder.SetInsertPoint(externalExceptionBlock);
1298
1299 generateStringPrint(context,
1300 module,
1301 builder,
1302 "Gen: Foreign exception received.\n",
1303 USE_GLOBAL_STR_CONSTS);
1304
1305 // Branch to the finally block
1306 builder.CreateBr(finallyBlock);
1307
1308 // Exception Route Block
1309
1310 builder.SetInsertPoint(exceptionRouteBlock);
1311
1312 // Casts exception pointer (_Unwind_Exception instance) to parent
1313 // (OurException instance).
1314 //
1315 // Note: ourBaseFromUnwindOffset is usually negative
1316 llvm::Value* typeInfoThrown =
1317 builder.CreatePointerCast(
1318 builder.CreateConstGEP1_64(unwindException,
1319 ourBaseFromUnwindOffset),
1320 ourExceptionType->getPointerTo());
1321
1322 // Retrieve thrown exception type info type
1323 //
1324 // Note: Index is not relative to pointer but instead to structure
1325 // unlike a true getelementptr (GEP) instruction
1326 typeInfoThrown = builder.CreateStructGEP(typeInfoThrown, 0);
1327
1328 llvm::Value* typeInfoThrownType =
1329 builder.CreateStructGEP(typeInfoThrown, 0);
1330
1331 generateIntegerPrint(context,
1332 module,
1333 builder,
1334 *toPrint32Int,
1335 *(builder.CreateLoad(typeInfoThrownType)),
1336 "Gen: Exception type <%d> received (stack unwound) "
1337 " in " +
1338 ourId +
1339 ".\n",
1340 USE_GLOBAL_STR_CONSTS);
1341
1342 // Route to matched type info catch block or run cleanup finally block
1343 llvm::SwitchInst* switchToCatchBlock =
1344 builder.CreateSwitch(retTypeInfoIndex,
1345 finallyBlock,
1346 numExceptionsToCatch);
1347
1348 unsigned nextTypeToCatch;
1349
1350 for (unsigned i = 1; i <= numExceptionsToCatch; ++i) {
1351 nextTypeToCatch = i - 1;
1352 switchToCatchBlock->addCase(llvm::ConstantInt::get(
1353 llvm::Type::getInt32Ty(context),
1354 i),
1355 catchBlocks[nextTypeToCatch]);
1356 }
1357
1358 llvm::verifyFunction(*ret);
1359 fpm.run(*ret);
1360
1361 return(ret);
1082 llvm::IRBuilder<>& builder,
1083 llvm::FunctionPassManager& fpm,
1084 llvm::Function& toInvoke,
1085 std::string ourId,
1086 unsigned numExceptionsToCatch,
1087 unsigned exceptionTypesToCatch[]) {
1088
1089 llvm::LLVMContext& context = module.getContext();
1090 llvm::Function *toPrint32Int = module.getFunction("print32Int");
1091
1092 ArgTypes argTypes;
1093 argTypes.push_back(builder.getInt32Ty());
1094
1095 ArgNames argNames;
1096 argNames.push_back("exceptTypeToThrow");
1097
1098 llvm::Function* ret = createFunction(module,
1099 builder.getVoidTy(),
1100 argTypes,
1101 argNames,
1102 ourId,
1103 llvm::Function::ExternalLinkage,
1104 false,
1105 false);
1106
1107 // Block which calls invoke
1108 llvm::BasicBlock *entryBlock = llvm::BasicBlock::Create(context,
1109 "entry",
1110 ret);
1111 // Normal block for invoke
1112 llvm::BasicBlock *normalBlock = llvm::BasicBlock::Create(context,
1113 "normal",
1114 ret);
1115 // Unwind block for invoke
1116 llvm::BasicBlock *exceptionBlock =
1117 llvm::BasicBlock::Create(context, "exception", ret);
1118
1119 // Block which routes exception to correct catch handler block
1120 llvm::BasicBlock *exceptionRouteBlock =
1121 llvm::BasicBlock::Create(context, "exceptionRoute", ret);
1122
1123 // Foreign exception handler
1124 llvm::BasicBlock *externalExceptionBlock =
1125 llvm::BasicBlock::Create(context, "externalException", ret);
1126
1127 // Block which calls _Unwind_Resume
1128 llvm::BasicBlock *unwindResumeBlock =
1129 llvm::BasicBlock::Create(context, "unwindResume", ret);
1130
1131 // Clean up block which delete exception if needed
1132 llvm::BasicBlock *endBlock =
1133 llvm::BasicBlock::Create(context, "end", ret);
1134
1135 std::string nextName;
1136 std::vector catchBlocks(numExceptionsToCatch);
1137 llvm::Value* exceptionCaughtFlag = NULL;
1138 llvm::Value* exceptionStorage = NULL;
1139
1140 // Finally block which will branch to unwindResumeBlock if
1141 // exception is not caught. Initializes/allocates stack locations.
1142 llvm::BasicBlock* finallyBlock = createFinallyBlock(context,
1143 module,
1144 builder,
1145 *ret,
1146 nextName = "finally",
1147 ourId,
1148 *endBlock,
1149 *unwindResumeBlock,
1150 &exceptionCaughtFlag,
1151 &exceptionStorage);
1152
1153 for (unsigned i = 0; i < numExceptionsToCatch; ++i) {
1154 nextName = ourTypeInfoNames[exceptionTypesToCatch[i]];
1155
1156 // One catch block per type info to be caught
1157 catchBlocks[i] = createCatchBlock(context,
1158 module,
1159 builder,
1160 *ret,
1161 nextName,
1162 ourId,
1163 *finallyBlock,
1164 *exceptionCaughtFlag);
1165 }
1166
1167 // Entry Block
1168
1169 builder.SetInsertPoint(entryBlock);
1170
1171 std::vector args;
1172 args.push_back(namedValues["exceptTypeToThrow"]);
1173 builder.CreateInvoke(&toInvoke,
1174 normalBlock,
1175 exceptionBlock,
1176 args.begin(),
1177 args.end());
1178
1179 // End Block
1180
1181 builder.SetInsertPoint(endBlock);
1182
1183 generateStringPrint(context,
1184 module,
1185 builder,
1186 "Gen: In end block: exiting in " + ourId + ".\n",
1187 USE_GLOBAL_STR_CONSTS);
1188 llvm::Function *deleteOurException =
1189 module.getFunction("deleteOurException");
1190
1191 // Note: function handles NULL exceptions
1192 builder.CreateCall(deleteOurException,
1193 builder.CreateLoad(exceptionStorage));
1194 builder.CreateRetVoid();
1195
1196 // Normal Block
1197
1198 builder.SetInsertPoint(normalBlock);
1199
1200 generateStringPrint(context,
1201 module,
1202 builder,
1203 "Gen: No exception in " + ourId + "!\n",
1204 USE_GLOBAL_STR_CONSTS);
1205
1206 // Finally block is always called
1207 builder.CreateBr(finallyBlock);
1208
1209 // Unwind Resume Block
1210
1211 builder.SetInsertPoint(unwindResumeBlock);
1212
1213 llvm::Function *resumeOurException =
1214 module.getFunction("_Unwind_Resume");
1215 builder.CreateCall(resumeOurException,
1216 builder.CreateLoad(exceptionStorage));
1217 builder.CreateUnreachable();
1218
1219 // Exception Block
1220
1221 builder.SetInsertPoint(exceptionBlock);
1222
1223 llvm::Function *ehException = module.getFunction("llvm.eh.exception");
1224
1225 // Retrieve thrown exception
1226 llvm::Value* unwindException = builder.CreateCall(ehException);
1227
1228 // Store exception and flag
1229 builder.CreateStore(unwindException, exceptionStorage);
1230 builder.CreateStore(ourExceptionThrownState, exceptionCaughtFlag);
1231 llvm::Function *personality = module.getFunction("ourPersonality");
1232 llvm::Value* functPtr =
1233 builder.CreatePointerCast(personality,
1234 builder.getInt8Ty()->getPointerTo());
1235
1236 args.clear();
1237 args.push_back(unwindException);
1238 args.push_back(functPtr);
1239
1240 // Note: Skipping index 0
1241 for (unsigned i = 0; i < numExceptionsToCatch; ++i) {
1242 // Set up type infos to be caught
1243 args.push_back(module.getGlobalVariable(
1244 ourTypeInfoNames[exceptionTypesToCatch[i]]));
1245 }
1246
1247 args.push_back(llvm::ConstantInt::get(builder.getInt32Ty(), 0));
1248
1249 llvm::Function *ehSelector = module.getFunction("llvm.eh.selector");
1250
1251 // Set up this exeption block as the landing pad which will handle
1252 // given type infos. See case Intrinsic::eh_selector in
1253 // SelectionDAGBuilder::visitIntrinsicCall(...) and AddCatchInfo(...)
1254 // implemented in FunctionLoweringInfo.cpp to see how the implementation
1255 // handles this call. This landing pad (this exception block), will be
1256 // called either because it nees to cleanup (call finally) or a type
1257 // info was found which matched the thrown exception.
1258 llvm::Value* retTypeInfoIndex = builder.CreateCall(ehSelector,
1259 args.begin(),
1260 args.end());
1261
1262 // Retrieve exception_class member from thrown exception
1263 // (_Unwind_Exception instance). This member tells us whether or not
1264 // the exception is foreign.
1265 llvm::Value* unwindExceptionClass =
1266 builder.CreateLoad(builder.CreateStructGEP(
1267 builder.CreatePointerCast(unwindException,
1268 ourUnwindExceptionType->getPointerTo()),
1269 0));
1270
1271 // Branch to the externalExceptionBlock if the exception is foreign or
1272 // to a catch router if not. Either way the finally block will be run.
1273 builder.CreateCondBr(builder.CreateICmpEQ(unwindExceptionClass,
1274 llvm::ConstantInt::get(builder.getInt64Ty(),
1275 ourBaseExceptionClass)),
1276 exceptionRouteBlock,
1277 externalExceptionBlock);
1278
1279 // External Exception Block
1280
1281 builder.SetInsertPoint(externalExceptionBlock);
1282
1283 generateStringPrint(context,
1284 module,
1285 builder,
1286 "Gen: Foreign exception received.\n",
1287 USE_GLOBAL_STR_CONSTS);
1288
1289 // Branch to the finally block
1290 builder.CreateBr(finallyBlock);
1291
1292 // Exception Route Block
1293
1294 builder.SetInsertPoint(exceptionRouteBlock);
1295
1296 // Casts exception pointer (_Unwind_Exception instance) to parent
1297 // (OurException instance).
1298 //
1299 // Note: ourBaseFromUnwindOffset is usually negative
1300 llvm::Value* typeInfoThrown =
1301 builder.CreatePointerCast(builder.CreateConstGEP1_64(unwindException,
1302 ourBaseFromUnwindOffset),
1303 ourExceptionType->getPointerTo());
1304
1305 // Retrieve thrown exception type info type
1306 //
1307 // Note: Index is not relative to pointer but instead to structure
1308 // unlike a true getelementptr (GEP) instruction
1309 typeInfoThrown = builder.CreateStructGEP(typeInfoThrown, 0);
1310
1311 llvm::Value* typeInfoThrownType =
1312 builder.CreateStructGEP(typeInfoThrown, 0);
1313
1314 generateIntegerPrint(context,
1315 module,
1316 builder,
1317 *toPrint32Int,
1318 *(builder.CreateLoad(typeInfoThrownType)),
1319 "Gen: Exception type <%d> received (stack unwound) "
1320 " in " +
1321 ourId +
1322 ".\n",
1323 USE_GLOBAL_STR_CONSTS);
1324
1325 // Route to matched type info catch block or run cleanup finally block
1326 llvm::SwitchInst* switchToCatchBlock =
1327 builder.CreateSwitch(retTypeInfoIndex,
1328 finallyBlock,
1329 numExceptionsToCatch);
1330
1331 unsigned nextTypeToCatch;
1332
1333 for (unsigned i = 1; i <= numExceptionsToCatch; ++i) {
1334 nextTypeToCatch = i - 1;
1335 switchToCatchBlock->addCase(llvm::ConstantInt::get(
1336 llvm::Type::getInt32Ty(context), i),
1337 catchBlocks[nextTypeToCatch]);
1338 }
1339
1340 llvm::verifyFunction(*ret);
1341 fpm.run(*ret);
1342
1343 return(ret);
13621344 }
13631345
13641346
13781360 /// @returns generated function
13791361 static
13801362 llvm::Function* createThrowExceptionFunction(llvm::Module& module,
1381 llvm::IRBuilder<>& builder,
1382 llvm::FunctionPassManager& fpm,
1383 std::string ourId,
1384 int32_t nativeThrowType,
1385 llvm::Function& nativeThrowFunct) {
1386 llvm::LLVMContext& context = module.getContext();
1387 namedValues.clear();
1388 ArgTypes unwindArgTypes;
1389 unwindArgTypes.push_back(builder.getInt32Ty());
1390 ArgNames unwindArgNames;
1391 unwindArgNames.push_back("exceptTypeToThrow");
1392
1393 llvm::Function *ret = createFunction(module,
1394 builder.getVoidTy(),
1395 unwindArgTypes,
1396 unwindArgNames,
1397 ourId,
1398 llvm::Function::ExternalLinkage,
1399 false,
1400 false);
1401
1402 // Throws either one of our exception or a native C++ exception depending
1403 // on a runtime argument value containing a type info type.
1404 llvm::BasicBlock *entryBlock = llvm::BasicBlock::Create(context,
1405 "entry",
1406 ret);
1407 // Throws a foreign exception
1408 llvm::BasicBlock *nativeThrowBlock =
1409 llvm::BasicBlock::Create(context,
1410 "nativeThrow",
1411 ret);
1412 // Throws one of our Exceptions
1413 llvm::BasicBlock *generatedThrowBlock =
1414 llvm::BasicBlock::Create(context,
1415 "generatedThrow",
1416 ret);
1417 // Retrieved runtime type info type to throw
1418 llvm::Value* exceptionType = namedValues["exceptTypeToThrow"];
1419
1420 // nativeThrowBlock block
1421
1422 builder.SetInsertPoint(nativeThrowBlock);
1423
1424 // Throws foreign exception
1425 builder.CreateCall(&nativeThrowFunct, exceptionType);
1426 builder.CreateUnreachable();
1427
1428 // entry block
1429
1430 builder.SetInsertPoint(entryBlock);
1431
1432 llvm::Function *toPrint32Int = module.getFunction("print32Int");
1433 generateIntegerPrint(context,
1434 module,
1435 builder,
1436 *toPrint32Int,
1437 *exceptionType,
1438 "\nGen: About to throw exception type <%d> in " +
1439 ourId +
1440 ".\n",
1441 USE_GLOBAL_STR_CONSTS);
1442
1443 // Switches on runtime type info type value to determine whether or not
1444 // a foreign exception is thrown. Defaults to throwing one of our
1445 // generated exceptions.
1446 llvm::SwitchInst* theSwitch = builder.CreateSwitch(exceptionType,
1447 generatedThrowBlock,
1448 1);
1449
1450 theSwitch->addCase(llvm::ConstantInt::get(llvm::Type::getInt32Ty(context),
1451 nativeThrowType),
1452 nativeThrowBlock);
1453
1454 // generatedThrow block
1455
1456 builder.SetInsertPoint(generatedThrowBlock);
1457
1458 llvm::Function *createOurException =
1459 module.getFunction("createOurException");
1460 llvm::Function *raiseOurException =
1461 module.getFunction("_Unwind_RaiseException");
1462
1463 // Creates exception to throw with runtime type info type.
1464 llvm::Value* exception =
1465 builder.CreateCall(createOurException,
1466 namedValues["exceptTypeToThrow"]);
1467
1468 // Throw generated Exception
1469 builder.CreateCall(raiseOurException, exception);
1470 builder.CreateUnreachable();
1471
1472 llvm::verifyFunction(*ret);
1473 fpm.run(*ret);
1474
1475 return(ret);
1363 llvm::IRBuilder<>& builder,
1364 llvm::FunctionPassManager& fpm,
1365 std::string ourId,
1366 int32_t nativeThrowType,
1367 llvm::Function& nativeThrowFunct) {
1368 llvm::LLVMContext& context = module.getContext();
1369 namedValues.clear();
1370 ArgTypes unwindArgTypes;
1371 unwindArgTypes.push_back(builder.getInt32Ty());
1372 ArgNames unwindArgNames;
1373 unwindArgNames.push_back("exceptTypeToThrow");
1374
1375 llvm::Function *ret = createFunction(module,
1376 builder.getVoidTy(),
1377 unwindArgTypes,
1378 unwindArgNames,
1379 ourId,
1380 llvm::Function::ExternalLinkage,
1381 false,
1382 false);
1383
1384 // Throws either one of our exception or a native C++ exception depending
1385 // on a runtime argument value containing a type info type.
1386 llvm::BasicBlock *entryBlock = llvm::BasicBlock::Create(context,
1387 "entry",
1388 ret);
1389 // Throws a foreign exception
1390 llvm::BasicBlock *nativeThrowBlock =
1391 llvm::BasicBlock::Create(context,
1392 "nativeThrow",
1393 ret);
1394 // Throws one of our Exceptions
1395 llvm::BasicBlock *generatedThrowBlock =
1396 llvm::BasicBlock::Create(context,
1397 "generatedThrow",
1398 ret);
1399 // Retrieved runtime type info type to throw
1400 llvm::Value* exceptionType = namedValues["exceptTypeToThrow"];
1401
1402 // nativeThrowBlock block
1403
1404 builder.SetInsertPoint(nativeThrowBlock);
1405
1406 // Throws foreign exception
1407 builder.CreateCall(&nativeThrowFunct, exceptionType);
1408 builder.CreateUnreachable();
1409
1410 // entry block
1411
1412 builder.SetInsertPoint(entryBlock);
1413
1414 llvm::Function *toPrint32Int = module.getFunction("print32Int");
1415 generateIntegerPrint(context,
1416 module,
1417 builder,
1418 *toPrint32Int,
1419 *exceptionType,
1420 "\nGen: About to throw exception type <%d> in " +
1421 ourId +
1422 ".\n",
1423 USE_GLOBAL_STR_CONSTS);
1424
1425 // Switches on runtime type info type value to determine whether or not
1426 // a foreign exception is thrown. Defaults to throwing one of our
1427 // generated exceptions.
1428 llvm::SwitchInst* theSwitch = builder.CreateSwitch(exceptionType,
1429 generatedThrowBlock,
1430 1);
1431
1432 theSwitch->addCase(llvm::ConstantInt::get(llvm::Type::getInt32Ty(context),
1433 nativeThrowType),
1434 nativeThrowBlock);
1435
1436 // generatedThrow block
1437
1438 builder.SetInsertPoint(generatedThrowBlock);
1439
1440 llvm::Function *createOurException =
1441 module.getFunction("createOurException");
1442 llvm::Function *raiseOurException =
1443 module.getFunction("_Unwind_RaiseException");
1444
1445 // Creates exception to throw with runtime type info type.
1446 llvm::Value* exception =
1447 builder.CreateCall(createOurException,
1448 namedValues["exceptTypeToThrow"]);
1449
1450 // Throw generated Exception
1451 builder.CreateCall(raiseOurException, exception);
1452 builder.CreateUnreachable();
1453
1454 llvm::verifyFunction(*ret);
1455 fpm.run(*ret);
1456
1457 return(ret);
14761458 }
14771459
14781460 static void createStandardUtilityFunctions(unsigned numTypeInfos,
15031485 llvm::IRBuilder<>& builder,
15041486 llvm::FunctionPassManager& fpm,
15051487 std::string nativeThrowFunctName) {
1506 // Number of type infos to generate
1507 unsigned numTypeInfos = 6;
1508
1509 // Initialze intrisics and external functions to use along with exception
1510 // and type info globals.
1511 createStandardUtilityFunctions(numTypeInfos,
1512 module,
1513 builder);
1514 llvm::Function *nativeThrowFunct =
1515 module.getFunction(nativeThrowFunctName);
1516
1517 // Create exception throw function using the value ~0 to cause
1518 // foreign exceptions to be thrown.
1519 llvm::Function* throwFunct =
1520 createThrowExceptionFunction(module,
1521 builder,
1522 fpm,
1523 "throwFunct",
1524 ~0,
1525 *nativeThrowFunct);
1526 // Inner function will catch even type infos
1527 unsigned innerExceptionTypesToCatch[] = {6, 2, 4};
1528 size_t numExceptionTypesToCatch = sizeof(innerExceptionTypesToCatch) /
1529 sizeof(unsigned);
1530
1531 // Generate inner function.
1532 llvm::Function* innerCatchFunct =
1533 createCatchWrappedInvokeFunction(module,
1534 builder,
1535 fpm,
1536 *throwFunct,
1537 "innerCatchFunct",
1538 numExceptionTypesToCatch,
1539 innerExceptionTypesToCatch);
1540
1541 // Outer function will catch odd type infos
1542 unsigned outerExceptionTypesToCatch[] = {3, 1, 5};
1543 numExceptionTypesToCatch = sizeof(outerExceptionTypesToCatch) /
1544 sizeof(unsigned);
1545
1546 // Generate outer function
1547 llvm::Function* outerCatchFunct =
1548 createCatchWrappedInvokeFunction(module,
1549 builder,
1550 fpm,
1551 *innerCatchFunct,
1552 "outerCatchFunct",
1553 numExceptionTypesToCatch,
1554 outerExceptionTypesToCatch);
1555
1556 // Return outer function to run
1557 return(outerCatchFunct);
1488 // Number of type infos to generate
1489 unsigned numTypeInfos = 6;
1490
1491 // Initialze intrisics and external functions to use along with exception
1492 // and type info globals.
1493 createStandardUtilityFunctions(numTypeInfos,
1494 module,
1495 builder);
1496 llvm::Function *nativeThrowFunct =
1497 module.getFunction(nativeThrowFunctName);
1498
1499 // Create exception throw function using the value ~0 to cause
1500 // foreign exceptions to be thrown.
1501 llvm::Function* throwFunct =
1502 createThrowExceptionFunction(module,
1503 builder,
1504 fpm,
1505 "throwFunct",
1506 ~0,
1507 *nativeThrowFunct);
1508 // Inner function will catch even type infos
1509 unsigned innerExceptionTypesToCatch[] = {6, 2, 4};
1510 size_t numExceptionTypesToCatch = sizeof(innerExceptionTypesToCatch) /
1511 sizeof(unsigned);
1512
1513 // Generate inner function.
1514 llvm::Function* innerCatchFunct =
1515 createCatchWrappedInvokeFunction(module,
1516 builder,
1517 fpm,
1518 *throwFunct,
1519 "innerCatchFunct",
1520 numExceptionTypesToCatch,
1521 innerExceptionTypesToCatch);
1522
1523 // Outer function will catch odd type infos
1524 unsigned outerExceptionTypesToCatch[] = {3, 1, 5};
1525 numExceptionTypesToCatch = sizeof(outerExceptionTypesToCatch) /
1526 sizeof(unsigned);
1527
1528 // Generate outer function
1529 llvm::Function* outerCatchFunct =
1530 createCatchWrappedInvokeFunction(module,
1531 builder,
1532 fpm,
1533 *innerCatchFunct,
1534 "outerCatchFunct",
1535 numExceptionTypesToCatch,
1536 outerExceptionTypesToCatch);
1537
1538 // Return outer function to run
1539 return(outerCatchFunct);
15581540 }
15591541
15601542
15611543 /// Represents our foreign exceptions
15621544 class OurCppRunException : public std::runtime_error {
15631545 public:
1564 OurCppRunException(const std::string reason) :
1565 std::runtime_error(reason) {}
1566
1567 OurCppRunException (const OurCppRunException& toCopy) :
1568 std::runtime_error(toCopy) {}
1569
1570 OurCppRunException& operator = (const OurCppRunException& toCopy) {
1571 return(reinterpret_cast(
1572 std::runtime_error::operator = (toCopy)
1573 ));
1574 }
1575
1576 ~OurCppRunException (void) throw () {}
1546 OurCppRunException(const std::string reason) :
1547 std::runtime_error(reason) {}
1548
1549 OurCppRunException (const OurCppRunException& toCopy) :
1550 std::runtime_error(toCopy) {}
1551
1552 OurCppRunException& operator = (const OurCppRunException& toCopy) {
1553 return(reinterpret_cast(
1554 std::runtime_error::operator=(toCopy)));
1555 }
1556
1557 ~OurCppRunException (void) throw () {}
15771558 };
15781559
15791560
15821563 /// generated function contract.
15831564 extern "C"
15841565 void throwCppException (int32_t ignoreIt) {
1585 throw(OurCppRunException("thrown by throwCppException(...)"));
1566 throw(OurCppRunException("thrown by throwCppException(...)"));
15861567 }
15871568
15881569 typedef void (*OurExceptionThrowFunctType) (int32_t typeToThrow);
16001581 void runExceptionThrow(llvm::ExecutionEngine* engine,
16011582 llvm::Function* function,
16021583 int32_t typeToThrow) {
1603
1604 // Find test's function pointer
1605 OurExceptionThrowFunctType functPtr =
1606 reinterpret_cast(
1607 reinterpret_cast(
1608 engine->getPointerToFunction(function)
1609 )
1610 );
1611
1612 try {
1613 // Run test
1614 (*functPtr)(typeToThrow);
1615 }
1616 catch (OurCppRunException exc) {
1617 // Catch foreign C++ exception
1618 fprintf(stderr,
1619 "\nrunExceptionThrow(...):In C++ catch OurCppRunException "
1620 "with reason: %s.\n",
1621 exc.what());
1622 }
1623 catch (...) {
1624 // Catch all exceptions including our generated ones. I'm not sure
1625 // why this latter functionality should work, as it seems that
1626 // our exceptions should be foreign to C++ (the _Unwind_Exception::
1627 // exception_class should be different from the one used by C++), and
1628 // therefore C++ should ignore the generated exceptions.
1629
1630 fprintf(stderr,
1631 "\nrunExceptionThrow(...):In C++ catch all.\n");
1632 }
1584
1585 // Find test's function pointer
1586 OurExceptionThrowFunctType functPtr =
1587 reinterpret_cast(
1588 reinterpret_cast(engine->getPointerToFunction(function)));
1589
1590 try {
1591 // Run test
1592 (*functPtr)(typeToThrow);
1593 }
1594 catch (OurCppRunException exc) {
1595 // Catch foreign C++ exception
1596 fprintf(stderr,
1597 "\nrunExceptionThrow(...):In C++ catch OurCppRunException "
1598 "with reason: %s.\n",
1599 exc.what());
1600 }
1601 catch (...) {
1602 // Catch all exceptions including our generated ones. I'm not sure
1603 // why this latter functionality should work, as it seems that
1604 // our exceptions should be foreign to C++ (the _Unwind_Exception::
1605 // exception_class should be different from the one used by C++), and
1606 // therefore C++ should ignore the generated exceptions.
1607
1608 fprintf(stderr,
1609 "\nrunExceptionThrow(...):In C++ catch all.\n");
1610 }
16331611 }
16341612
16351613 //
16471625 static void createStandardUtilityFunctions(unsigned numTypeInfos,
16481626 llvm::Module& module,
16491627 llvm::IRBuilder<>& builder) {
1650
1651 llvm::LLVMContext& context = module.getContext();
1652
1653 // Exception initializations
1654
1655 // Setup exception catch state
1656 ourExceptionNotThrownState =
1657 llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 0),
1658 ourExceptionThrownState =
1659 llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 1),
1660 ourExceptionCaughtState =
1661 llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 2),
1662
1663
1664
1665 // Create our type info type
1666 ourTypeInfoType = llvm::StructType::get(context,
1667 TypeArray(builder.getInt32Ty()));
1668
1669 // Create OurException type
1670 ourExceptionType = llvm::StructType::get(context,
1671 TypeArray(ourTypeInfoType));
1672
1673 // Create portion of _Unwind_Exception type
1674 //
1675 // Note: Declaring only a portion of the _Unwind_Exception struct.
1676 // Does this cause problems?
1677 ourUnwindExceptionType = llvm::StructType::get(context,
1678 TypeArray(builder.getInt64Ty()));
1679 struct OurBaseException_t dummyException;
1680
1681 // Calculate offset of OurException::unwindException member.
1682 ourBaseFromUnwindOffset = ((uintptr_t) &dummyException) -
1683 ((uintptr_t) &(dummyException.unwindException));
1684
1628
1629 llvm::LLVMContext& context = module.getContext();
1630
1631 // Exception initializations
1632
1633 // Setup exception catch state
1634 ourExceptionNotThrownState =
1635 llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 0),
1636 ourExceptionThrownState =
1637 llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 1),
1638 ourExceptionCaughtState =
1639 llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 2),
1640
1641
1642
1643 // Create our type info type
1644 ourTypeInfoType = llvm::StructType::get(context,
1645 TypeArray(builder.getInt32Ty()));
1646
1647 // Create OurException type
1648 ourExceptionType = llvm::StructType::get(context,
1649 TypeArray(ourTypeInfoType));
1650
1651 // Create portion of _Unwind_Exception type
1652 //
1653 // Note: Declaring only a portion of the _Unwind_Exception struct.
1654 // Does this cause problems?
1655 ourUnwindExceptionType =
1656 llvm::StructType::get(context, TypeArray(builder.getInt64Ty()));
1657 struct OurBaseException_t dummyException;
1658
1659 // Calculate offset of OurException::unwindException member.
1660 ourBaseFromUnwindOffset = ((uintptr_t) &dummyException) -
1661 ((uintptr_t) &(dummyException.unwindException));
1662
16851663 #ifdef DEBUG
1686 fprintf(stderr,
1687 "createStandardUtilityFunctions(...):ourBaseFromUnwindOffset "
1688 "= %lld, sizeof(struct OurBaseException_t) - "
1689 "sizeof(struct _Unwind_Exception) = %lu.\n",
1690 ourBaseFromUnwindOffset,
1691 sizeof(struct OurBaseException_t) -
1692 sizeof(struct _Unwind_Exception));
1664 fprintf(stderr,
1665 "createStandardUtilityFunctions(...):ourBaseFromUnwindOffset "
1666 "= %lld, sizeof(struct OurBaseException_t) - "
1667 "sizeof(struct _Unwind_Exception) = %lu.\n",
1668 ourBaseFromUnwindOffset,
1669 sizeof(struct OurBaseException_t) -
1670 sizeof(struct _Unwind_Exception));
16931671 #endif
1694
1695 size_t numChars = sizeof(ourBaseExcpClassChars) / sizeof(char);
1696
1697 // Create our _Unwind_Exception::exception_class value
1698 ourBaseExceptionClass = genClass(ourBaseExcpClassChars, numChars);
1699
1700 // Type infos
1701
1702 std::string baseStr = "typeInfo", typeInfoName;
1703 std::ostringstream typeInfoNameBuilder;
1704 std::vector structVals;
1705
1706 llvm::Constant *nextStruct;
1707 llvm::GlobalVariable* nextGlobal = NULL;
1708
1709 // Generate each type info
1710 //
1711 // Note: First type info is not used.
1712 for (unsigned i = 0; i <= numTypeInfos; ++i) {
1713 structVals.clear();
1714 structVals.push_back(llvm::ConstantInt::get(builder.getInt32Ty(), i));
1715 nextStruct = llvm::ConstantStruct::get(ourTypeInfoType, structVals);
1716
1717 typeInfoNameBuilder.str("");
1718 typeInfoNameBuilder << baseStr << i;
1719 typeInfoName = typeInfoNameBuilder.str();
1720
1721 // Note: Does not seem to work without allocation
1722 nextGlobal =
1723 new llvm::GlobalVariable(module,
1724 ourTypeInfoType,
1725 true,
1726 llvm::GlobalValue::ExternalLinkage,
1727 nextStruct,
1728 typeInfoName);
1729
1730 ourTypeInfoNames.push_back(typeInfoName);
1731 ourTypeInfoNamesIndex[i] = typeInfoName;
1732 }
1733
1734 ArgNames argNames;
1735 ArgTypes argTypes;
1736 llvm::Function* funct = NULL;
1737
1738 // print32Int
1739
1740 const llvm::Type* retType = builder.getVoidTy();
1741
1742 argTypes.clear();
1743 argTypes.push_back(builder.getInt32Ty());
1744 argTypes.push_back(builder.getInt8Ty()->getPointerTo());
1745
1746 argNames.clear();
1747
1748 createFunction(module,
1749 retType,
1750 argTypes,
1751 argNames,
1752 "print32Int",
1753 llvm::Function::ExternalLinkage,
1754 true,
1755 false);
1756
1757 // print64Int
1758
1759 retType = builder.getVoidTy();
1760
1761 argTypes.clear();
1762 argTypes.push_back(builder.getInt64Ty());
1763 argTypes.push_back(builder.getInt8Ty()->getPointerTo());
1764
1765 argNames.clear();
1766
1767 createFunction(module,
1768 retType,
1769 argTypes,
1770 argNames,
1771 "print64Int",
1772 llvm::Function::ExternalLinkage,
1773 true,
1774 false);
1775
1776 // printStr
1777
1778 retType = builder.getVoidTy();
1779
1780 argTypes.clear();
1781 argTypes.push_back(builder.getInt8Ty()->getPointerTo());
1782
1783 argNames.clear();
1784
1785 createFunction(module,
1786 retType,
1787 argTypes,
1788 argNames,
1789 "printStr",
1790 llvm::Function::ExternalLinkage,
1791 true,
1792 false);
1793
1794 // throwCppException
1795
1796 retType = builder.getVoidTy();
1797
1798 argTypes.clear();
1799 argTypes.push_back(builder.getInt32Ty());
1800
1801 argNames.clear();
1802
1803 createFunction(module,
1804 retType,
1805 argTypes,
1806 argNames,
1807 "throwCppException",
1808 llvm::Function::ExternalLinkage,
1809 true,
1810 false);
1811
1812 // deleteOurException
1813
1814 retType = builder.getVoidTy();
1815
1816 argTypes.clear();
1817 argTypes.push_back(builder.getInt8Ty()->getPointerTo());
1818
1819 argNames.clear();
1820
1821 createFunction(module,
1822 retType,
1823 argTypes,
1824 argNames,
1825 "deleteOurException",
1826 llvm::Function::ExternalLinkage,
1827 true,
1828 false);
1829
1830 // createOurException
1831
1832 retType = builder.getInt8Ty()->getPointerTo();
1833
1834 argTypes.clear();
1835 argTypes.push_back(builder.getInt32Ty());
1836
1837 argNames.clear();
1838
1839 createFunction(module,
1840 retType,
1841 argTypes,
1842 argNames,
1843 "createOurException",
1844 llvm::Function::ExternalLinkage,
1845 true,
1846 false);
1847
1848 // _Unwind_RaiseException
1849
1850 retType = builder.getInt32Ty();
1851
1852 argTypes.clear();
1853 argTypes.push_back(builder.getInt8Ty()->getPointerTo());
1854
1855 argNames.clear();
1856
1857 funct = createFunction(module,
1858 retType,
1859 argTypes,
1860 argNames,
1861 "_Unwind_RaiseException",
1862 llvm::Function::ExternalLinkage,
1863 true,
1864 false);
1865
1866 funct->addFnAttr(llvm::Attribute::NoReturn);
1867
1868 // _Unwind_Resume
1869
1870 retType = builder.getInt32Ty();
1871
1872 argTypes.clear();
1873 argTypes.push_back(builder.getInt8Ty()->getPointerTo());
1874
1875 argNames.clear();
1876
1877 funct = createFunction(module,
1878 retType,
1879 argTypes,
1880 argNames,
1881 "_Unwind_Resume",
1882 llvm::Function::ExternalLinkage,
1883 true,
1884 false);
1885
1886 funct->addFnAttr(llvm::Attribute::NoReturn);
1887
1888 // ourPersonality
1889
1890 retType = builder.getInt32Ty();
1891
1892 argTypes.clear();
1893 argTypes.push_back(builder.getInt32Ty());
1894 argTypes.push_back(builder.getInt32Ty());
1895 argTypes.push_back(builder.getInt64Ty());
1896 argTypes.push_back(builder.getInt8Ty()->getPointerTo());
1897 argTypes.push_back(builder.getInt8Ty()->getPointerTo());
1898
1899 argNames.clear();
1900
1901 createFunction(module,
1902 retType,
1903 argTypes,
1904 argNames,
1905 "ourPersonality",
1906 llvm::Function::ExternalLinkage,
1907 true,
1908 false);
1909
1910 // llvm.eh.selector intrinsic
1911
1912 getDeclaration(&module, llvm::Intrinsic::eh_selector);
1913
1914 // llvm.eh.exception intrinsic
1915
1916 getDeclaration(&module, llvm::Intrinsic::eh_exception);
1917
1918 // llvm.eh.typeid.for intrinsic
1919
1920 getDeclaration(&module, llvm::Intrinsic::eh_typeid_for);
1921 }
1922
1923
1924 //===---------------------------------------------------------------------===//
1672
1673 size_t numChars = sizeof(ourBaseExcpClassChars) / sizeof(char);
1674
1675 // Create our _Unwind_Exception::exception_class value
1676 ourBaseExceptionClass = genClass(ourBaseExcpClassChars, numChars);
1677
1678 // Type infos
1679
1680 std::string baseStr = "typeInfo", typeInfoName;
1681 std::ostringstream typeInfoNameBuilder;
1682 std::vector structVals;
1683
1684 llvm::Constant *nextStruct;
1685 llvm::GlobalVariable* nextGlobal = NULL;
1686
1687 // Generate each type info
1688 //
1689 // Note: First type info is not used.
1690 for (unsigned i = 0; i <= numTypeInfos; ++i) {
1691 structVals.clear();
1692 structVals.push_back(llvm::ConstantInt::get(builder.getInt32Ty(), i));
1693 nextStruct = llvm::ConstantStruct::get(ourTypeInfoType, structVals);
1694
1695 typeInfoNameBuilder.str("");
1696 typeInfoNameBuilder << baseStr << i;
1697 typeInfoName = typeInfoNameBuilder.str();
1698
1699 // Note: Does not seem to work without allocation
1700 nextGlobal =
1701 new llvm::GlobalVariable(module,
1702 ourTypeInfoType,
1703 true,
1704 llvm::GlobalValue::ExternalLinkage,
1705 nextStruct,
1706 typeInfoName);
1707
1708 ourTypeInfoNames.push_back(typeInfoName);
1709 ourTypeInfoNamesIndex[i] = typeInfoName;
1710 }
1711
1712 ArgNames argNames;
1713 ArgTypes argTypes;
1714 llvm::Function* funct = NULL;
1715
1716 // print32Int
1717
1718 const llvm::Type* retType = builder.getVoidTy();
1719
1720 argTypes.clear();
1721 argTypes.push_back(builder.getInt32Ty());
1722 argTypes.push_back(builder.getInt8Ty()->getPointerTo());
1723
1724 argNames.clear();
1725
1726 createFunction(module,
1727 retType,
1728 argTypes,
1729 argNames,
1730 "print32Int",
1731 llvm::Function::ExternalLinkage,
1732 true,
1733 false);
1734
1735 // print64Int
1736
1737 retType = builder.getVoidTy();
1738
1739 argTypes.clear();
1740 argTypes.push_back(builder.getInt64Ty());
1741 argTypes.push_back(builder.getInt8Ty()->getPointerTo());
1742
1743 argNames.clear();
1744
1745 createFunction(module,
1746 retType,
1747 argTypes,
1748 argNames,
1749 "print64Int",
1750 llvm::Function::ExternalLinkage,
1751 true,
1752 false);
1753
1754 // printStr
1755
1756 retType = builder.getVoidTy();
1757
1758 argTypes.clear();
1759 argTypes.push_back(builder.getInt8Ty()->getPointerTo());
1760
1761 argNames.clear();
1762
1763 createFunction(module,
1764 retType,
1765 argTypes,
1766 argNames,
1767 "printStr",
1768 llvm::Function::ExternalLinkage,
1769 true,
1770 false);
1771
1772 // throwCppException
1773
1774 retType = builder.getVoidTy();
1775
1776 argTypes.clear();
1777 argTypes.push_back(builder.getInt32Ty());
1778
1779 argNames.clear();
1780
1781 createFunction(module,
1782 retType,
1783 argTypes,
1784 argNames,
1785 "throwCppException",
1786 llvm::Function::ExternalLinkage,
1787 true,
1788 false);
1789
1790 // deleteOurException
1791
1792 retType = builder.getVoidTy();
1793
1794 argTypes.clear();
1795 argTypes.push_back(builder.getInt8Ty()->getPointerTo());
1796
1797 argNames.clear();
1798
1799 createFunction(module,
1800 retType,
1801 argTypes,
1802 argNames,
1803 "deleteOurException",
1804 llvm::Function::ExternalLinkage,
1805 true,
1806 false);
1807
1808 // createOurException
1809
1810 retType = builder.getInt8Ty()->getPointerTo();
1811
1812 argTypes.clear();
1813 argTypes.push_back(builder.getInt32Ty());
1814
1815 argNames.clear();
1816
1817 createFunction(module,
1818 retType,
1819 argTypes,
1820 argNames,
1821 "createOurException",
1822 llvm::Function::ExternalLinkage,
1823 true,
1824 false);
1825
1826 // _Unwind_RaiseException
1827
1828 retType = builder.getInt32Ty();
1829
1830 argTypes.clear();
1831 argTypes.push_back(builder.getInt8Ty()->getPointerTo());
1832
1833 argNames.clear();
1834
1835 funct = createFunction(module,
1836 retType,
1837 argTypes,
1838 argNames,
1839 "_Unwind_RaiseException",
1840 llvm::Function::ExternalLinkage,
1841 true,
1842 false);
1843
1844 funct->addFnAttr(llvm::Attribute::NoReturn);
1845
1846 // _Unwind_Resume
1847
1848 retType = builder.getInt32Ty();
1849
1850 argTypes.clear();
1851 argTypes.push_back(builder.getInt8Ty()->getPointerTo());
1852
1853 argNames.clear();
1854
1855 funct = createFunction(module,
1856 retType,
1857 argTypes,
1858 argNames,
1859 "_Unwind_Resume",
1860 llvm::Function::ExternalLinkage,
1861 true,
1862 false);
1863
1864 funct->addFnAttr(llvm::Attribute::NoReturn);
1865
1866 // ourPersonality
1867
1868 retType = builder.getInt32Ty();
1869
1870 argTypes.clear();
1871 argTypes.push_back(builder.getInt32Ty());
1872 argTypes.push_back(builder.getInt32Ty());
1873 argTypes.push_back(builder.getInt64Ty());
1874 argTypes.push_back(builder.getInt8Ty()->getPointerTo());
1875 argTypes.push_back(builder.getInt8Ty()->getPointerTo());
1876
1877 argNames.clear();
1878
1879 createFunction(module,
1880 retType,
1881 argTypes,
1882 argNames,
1883 "ourPersonality",
1884 llvm::Function::ExternalLinkage,
1885 true,
1886 false);
1887
1888 // llvm.eh.selector intrinsic
1889
1890 getDeclaration(&module, llvm::Intrinsic::eh_selector);
1891
1892 // llvm.eh.exception intrinsic
1893
1894 getDeclaration(&module, llvm::Intrinsic::eh_exception);
1895
1896 // llvm.eh.typeid.for intrinsic
1897
1898 getDeclaration(&module, llvm::Intrinsic::eh_typeid_for);
1899 }
1900
1901
1902 //===----------------------------------------------------------------------===//
19251903 // Main test driver code.
1926 //===---------------------------------------------------------------------===//
1904 //===----------------------------------------------------------------------===//
19271905
19281906 /// Demo main routine which takes the type info types to throw. A test will
19291907 /// be run for each given type info type. While type info types with the value
19321910 /// will result in exceptions which pass through to the test harness. All other
19331911 /// type info types are not supported and could cause a crash.
19341912 int main(int argc, char* argv[]) {
1935 if (argc == 1) {
1936 fprintf(stderr,
1937 "\nUsage: ExceptionDemo "
1938 "[...].\n"
1939 " Each type must have the value of 1 - 6 for "
1940 "generated exceptions to be caught;\n"
1941 " the value -1 for foreign C++ exceptions to be "
1942 "generated and thrown;\n"
1943 " or the values > 6 for exceptions to be ignored.\n"
1944 "\nTry: ExceptionDemo 2 3 7 -1\n"
1945 " for a full test.\n\n");
1946 return(0);
1913 if (argc == 1) {
1914 fprintf(stderr,
1915 "\nUsage: ExceptionDemo "
1916 "[...].\n"
1917 " Each type must have the value of 1 - 6 for "
1918 "generated exceptions to be caught;\n"
1919 " the value -1 for foreign C++ exceptions to be "
1920 "generated and thrown;\n"
1921 " or the values > 6 for exceptions to be ignored.\n"
1922 "\nTry: ExceptionDemo 2 3 7 -1\n"
1923 " for a full test.\n\n");
1924 return(0);
1925 }
1926
1927 // If not set, exception handling will not be turned on
1928 llvm::JITExceptionHandling = true;
1929
1930 llvm::InitializeNativeTarget();
1931 llvm::LLVMContext& context = llvm::getGlobalContext();
1932 llvm::IRBuilder<> theBuilder(context);
1933
1934 // Make the module, which holds all the code.
1935 llvm::Module* module = new llvm::Module("my cool jit", context);
1936
1937 // Build engine with JIT
1938 llvm::EngineBuilder factory(module);
1939 factory.setEngineKind(llvm::EngineKind::JIT);
1940 factory.setAllocateGVsWithCode(false);
1941 llvm::ExecutionEngine* executionEngine = factory.create();
1942
1943 {
1944 llvm::FunctionPassManager fpm(module);
1945
1946 // Set up the optimizer pipeline.
1947 // Start with registering info about how the
1948 // target lays out data structures.
1949 fpm.add(new llvm::TargetData(*executionEngine->getTargetData()));
1950
1951 // Optimizations turned on
1952 #ifdef ADD_OPT_PASSES
1953
1954 // Basic AliasAnslysis support for GVN.
1955 fpm.add(llvm::createBasicAliasAnalysisPass());
1956
1957 // Promote allocas to registers.
1958 fpm.add(llvm::createPromoteMemoryToRegisterPass());
1959
1960 // Do simple "peephole" optimizations and bit-twiddling optzns.
1961 fpm.add(llvm::createInstructionCombiningPass());
1962
1963 // Reassociate expressions.
1964 fpm.add(llvm::createReassociatePass());
1965
1966 // Eliminate Common SubExpressions.
1967 fpm.add(llvm::createGVNPass());
1968
1969 // Simplify the control flow graph (deleting unreachable
1970 // blocks, etc).
1971 fpm.add(llvm::createCFGSimplificationPass());
1972 #endif // ADD_OPT_PASSES
1973
1974 fpm.doInitialization();
1975
1976 // Generate test code using function throwCppException(...) as
1977 // the function which throws foreign exceptions.
1978 llvm::Function* toRun =
1979 createUnwindExceptionTest(*module,
1980 theBuilder,
1981 fpm,
1982 "throwCppException");
1983
1984 fprintf(stderr, "\nBegin module dump:\n\n");
1985
1986 module->dump();
1987
1988 fprintf(stderr, "\nEnd module dump:\n");
1989
1990 fprintf(stderr, "\n\nBegin Test:\n");
1991
1992 for (int i = 1; i < argc; ++i) {
1993 // Run test for each argument whose value is the exception
1994 // type to throw.
1995 runExceptionThrow(executionEngine,
1996 toRun,
1997 (unsigned) strtoul(argv[i], NULL, 10));
19471998 }
1948
1949 // If not set, exception handling will not be turned on
1950 llvm::JITExceptionHandling = true;
1951
1952 llvm::InitializeNativeTarget();
1953 llvm::LLVMContext& context = llvm::getGlobalContext();
1954 llvm::IRBuilder<> theBuilder(context);
1955
1956 // Make the module, which holds all the code.
1957 llvm::Module* module = new llvm::Module("my cool jit", context);
1958
1959 // Build engine with JIT
1960 llvm::EngineBuilder factory(module);
1961 factory.setEngineKind(llvm::EngineKind::JIT);
1962 factory.setAllocateGVsWithCode(false);
1963 llvm::ExecutionEngine* executionEngine = factory.create();
1964
1965 {
1966 llvm::FunctionPassManager fpm(module);
1967
1968 // Set up the optimizer pipeline.
1969 // Start with registering info about how the
1970 // target lays out data structures.
1971 fpm.add(new llvm::TargetData(*executionEngine->getTargetData()));
1972
1973 // Optimizations turned on
1974 #ifdef ADD_OPT_PASSES
1975
1976 // Basic AliasAnslysis support for GVN.
1977 fpm.add(llvm::createBasicAliasAnalysisPass());
1978
1979 // Promote allocas to registers.
1980 fpm.add(llvm::createPromoteMemoryToRegisterPass());
1981
1982 // Do simple "peephole" optimizations and bit-twiddling optzns.
1983 fpm.add(llvm::createInstructionCombiningPass());
1984
1985 // Reassociate expressions.
1986 fpm.add(llvm::createReassociatePass());
1987
1988 // Eliminate Common SubExpressions.
1989 fpm.add(llvm::createGVNPass());
1990
1991 // Simplify the control flow graph (deleting unreachable
1992 // blocks, etc).
1993 fpm.add(llvm::createCFGSimplificationPass());
1994 #endif // ADD_OPT_PASSES
1995
1996 fpm.doInitialization();
1997
1998 // Generate test code using function throwCppException(...) as
1999 // the function which throws foreign exceptions.
2000 llvm::Function* toRun =
2001 createUnwindExceptionTest(*module,
2002 theBuilder,
2003 fpm,
2004 "throwCppException");
2005
2006 fprintf(stderr, "\nBegin module dump:\n\n");
2007
2008 module->dump();
2009
2010 fprintf(stderr, "\nEnd module dump:\n");
2011
2012 fprintf(stderr, "\n\nBegin Test:\n");
2013
2014 for (int i = 1; i < argc; ++i) {
2015 // Run test for each argument whose value is the exception
2016 // type to throw.
2017 runExceptionThrow(executionEngine,
2018 toRun,
2019 (unsigned) strtoul(argv[i], NULL, 10));
2020 }
2021
2022 fprintf(stderr, "\nEnd Test:\n\n");
2023 }
2024
2025 delete executionEngine;
2026
2027 return 0;
2028 }
2029
1999
2000 fprintf(stderr, "\nEnd Test:\n\n");
2001 }
2002
2003 delete executionEngine;
2004
2005 return 0;
2006 }
2007