llvm.org GIT mirror llvm / e449654
Remove exception handling support from the old JIT. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@181354 91177308-0d34-0410-b5e6-96231b3b80d8 Rafael Espindola 6 years ago
14 changed file(s) with 5 addition(s) and 836 deletion(s). Raw diff Collapse all Expand all
4040 functionality, or simply have a lot to talk about), see the `NOTE` below
4141 for adding a new subsection.
4242
43 * Support for exception handling has been removed from the old JIT. Use MCJIT
44 if you need EH support.
45
4346 * ... next change ...
4447
4548 .. NOTE
19491949
19501950 // If not set, exception handling will not be turned on
19511951 llvm::TargetOptions Opts;
1952 Opts.JITExceptionHandling = true;
19531952
19541953 llvm::InitializeNativeTarget();
19551954 llvm::InitializeNativeTargetAsmPrinter();
114114 /// emitting a function.
115115 virtual void deallocateFunctionBody(void *Body) = 0;
116116
117 /// startExceptionTable - When we finished JITing the function, if exception
118 /// handling is set, we emit the exception table.
119 virtual uint8_t* startExceptionTable(const Function* F,
120 uintptr_t &ActualSize) = 0;
121
122 /// endExceptionTable - This method is called when the JIT is done emitting
123 /// the exception table.
124 virtual void endExceptionTable(const Function *F, uint8_t *TableStart,
125 uint8_t *TableEnd, uint8_t* FrameRegister) = 0;
126
127 /// deallocateExceptionTable - Free the specified exception table's memory.
128 /// The argument must be the return value from a call to startExceptionTable()
129 /// that hasn't been deallocated yet. This is never called when the JIT is
130 /// currently emitting an exception table.
131 virtual void deallocateExceptionTable(void *ET) = 0;
132
133117 /// CheckInvariants - For testing only. Return true if all internal
134118 /// invariants are preserved, or return false and set ErrorStr to a helpful
135119 /// error message.
155155 virtual void deallocateFunctionBody(void *Body) {
156156 llvm_unreachable("Unexpected call!");
157157 }
158 virtual uint8_t *startExceptionTable(const Function *F,
159 uintptr_t &ActualSize) {
160 llvm_unreachable("Unexpected call!");
161 return 0;
162 }
163 virtual void endExceptionTable(const Function *F, uint8_t *TableStart,
164 uint8_t *TableEnd, uint8_t *FrameRegister) {
165 llvm_unreachable("Unexpected call!");
166 }
167 virtual void deallocateExceptionTable(void *ET) {
168 llvm_unreachable("Unexpected call!");
169 }
170158 };
171159
172160 }
4444 NoFramePointerElimNonLeaf(false), LessPreciseFPMADOption(false),
4545 UnsafeFPMath(false), NoInfsFPMath(false),
4646 NoNaNsFPMath(false), HonorSignDependentRoundingFPMathOption(false),
47 UseSoftFloat(false), NoZerosInBSS(false), JITExceptionHandling(false),
47 UseSoftFloat(false), NoZerosInBSS(false),
4848 JITEmitDebugInfo(false), JITEmitDebugInfoToDisk(false),
4949 GuaranteedTailCallOpt(false), DisableTailCalls(false),
5050 StackAlignmentOverride(0), RealignStack(true), SSPBufferSize(0),
121121 /// .bss section. This flag disables such behaviour (necessary, e.g. for
122122 /// crt*.o compiling).
123123 unsigned NoZerosInBSS : 1;
124
125 /// JITExceptionHandling - This flag indicates that the JIT should emit
126 /// exception handling information.
127 unsigned JITExceptionHandling : 1;
128124
129125 /// JITEmitDebugInfo - This flag indicates that the JIT should try to emit
130126 /// debug information and notify a debugger about it.
5858 ARE_EQUAL(HonorSignDependentRoundingFPMathOption) &&
5959 ARE_EQUAL(UseSoftFloat) &&
6060 ARE_EQUAL(NoZerosInBSS) &&
61 ARE_EQUAL(JITExceptionHandling) &&
6261 ARE_EQUAL(JITEmitDebugInfo) &&
6362 ARE_EQUAL(JITEmitDebugInfoToDisk) &&
6463 ARE_EQUAL(GuaranteedTailCallOpt) &&
22
33 add_llvm_library(LLVMJIT
44 JIT.cpp
5 JITDwarfEmitter.cpp
65 JITEmitter.cpp
76 JITMemoryManager.cpp
87 )
+0
-596
lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp less more
None //===----- JITDwarfEmitter.cpp - Write dwarf tables into memory -----------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines a JITDwarfEmitter object that is used by the JIT to
10 // write dwarf tables to memory.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "JITDwarfEmitter.h"
15 #include "JIT.h"
16 #include "llvm/ADT/DenseMap.h"
17 #include "llvm/CodeGen/JITCodeEmitter.h"
18 #include "llvm/CodeGen/MachineFunction.h"
19 #include "llvm/CodeGen/MachineModuleInfo.h"
20 #include "llvm/ExecutionEngine/JITMemoryManager.h"
21 #include "llvm/IR/DataLayout.h"
22 #include "llvm/IR/Function.h"
23 #include "llvm/MC/MCAsmInfo.h"
24 #include "llvm/MC/MCSymbol.h"
25 #include "llvm/MC/MachineLocation.h"
26 #include "llvm/Support/ErrorHandling.h"
27 #include "llvm/Target/TargetFrameLowering.h"
28 #include "llvm/Target/TargetInstrInfo.h"
29 #include "llvm/Target/TargetMachine.h"
30 #include "llvm/Target/TargetRegisterInfo.h"
31 using namespace llvm;
32
33 JITDwarfEmitter::JITDwarfEmitter(JIT& theJit) : MMI(0), Jit(theJit) {}
34
35
36 unsigned char* JITDwarfEmitter::EmitDwarfTable(MachineFunction& F,
37 JITCodeEmitter& jce,
38 unsigned char* StartFunction,
39 unsigned char* EndFunction,
40 unsigned char* &EHFramePtr) {
41 assert(MMI && "MachineModuleInfo not registered!");
42
43 const TargetMachine& TM = F.getTarget();
44 TD = TM.getDataLayout();
45 stackGrowthDirection = TM.getFrameLowering()->getStackGrowthDirection();
46 RI = TM.getRegisterInfo();
47 MAI = TM.getMCAsmInfo();
48 JCE = &jce;
49
50 unsigned char* ExceptionTable = EmitExceptionTable(&F, StartFunction,
51 EndFunction);
52
53 unsigned char* Result = 0;
54
55 const std::vector Personalities = MMI->getPersonalities();
56 EHFramePtr = EmitCommonEHFrame(Personalities[MMI->getPersonalityIndex()]);
57
58 Result = EmitEHFrame(Personalities[MMI->getPersonalityIndex()], EHFramePtr,
59 StartFunction, EndFunction, ExceptionTable);
60
61 return Result;
62 }
63
64
65 void
66 JITDwarfEmitter::EmitFrameMoves(intptr_t BaseLabelPtr,
67 const std::vector &Moves) const {
68 unsigned PointerSize = TD->getPointerSize();
69 int stackGrowth = stackGrowthDirection == TargetFrameLowering::StackGrowsUp ?
70 PointerSize : -PointerSize;
71 MCSymbol *BaseLabel = 0;
72
73 for (unsigned i = 0, N = Moves.size(); i < N; ++i) {
74 const MachineMove &Move = Moves[i];
75 MCSymbol *Label = Move.getLabel();
76
77 // Throw out move if the label is invalid.
78 if (Label && (*JCE->getLabelLocations())[Label] == 0)
79 continue;
80
81 intptr_t LabelPtr = 0;
82 if (Label) LabelPtr = JCE->getLabelAddress(Label);
83
84 const MachineLocation &Dst = Move.getDestination();
85 const MachineLocation &Src = Move.getSource();
86
87 // Advance row if new location.
88 if (BaseLabelPtr && Label && BaseLabel != Label) {
89 JCE->emitByte(dwarf::DW_CFA_advance_loc4);
90 JCE->emitInt32(LabelPtr - BaseLabelPtr);
91
92 BaseLabel = Label;
93 BaseLabelPtr = LabelPtr;
94 }
95
96 // If advancing cfa.
97 if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) {
98 if (!Src.isReg()) {
99 if (Src.getReg() == MachineLocation::VirtualFP) {
100 JCE->emitByte(dwarf::DW_CFA_def_cfa_offset);
101 } else {
102 JCE->emitByte(dwarf::DW_CFA_def_cfa);
103 JCE->emitULEB128Bytes(RI->getDwarfRegNum(Src.getReg(), true));
104 }
105
106 JCE->emitULEB128Bytes(-Src.getOffset());
107 } else {
108 llvm_unreachable("Machine move not supported yet.");
109 }
110 } else if (Src.isReg() &&
111 Src.getReg() == MachineLocation::VirtualFP) {
112 if (Dst.isReg()) {
113 JCE->emitByte(dwarf::DW_CFA_def_cfa_register);
114 JCE->emitULEB128Bytes(RI->getDwarfRegNum(Dst.getReg(), true));
115 } else {
116 llvm_unreachable("Machine move not supported yet.");
117 }
118 } else {
119 unsigned Reg = RI->getDwarfRegNum(Src.getReg(), true);
120 int Offset = Dst.getOffset() / stackGrowth;
121
122 if (Offset < 0) {
123 JCE->emitByte(dwarf::DW_CFA_offset_extended_sf);
124 JCE->emitULEB128Bytes(Reg);
125 JCE->emitSLEB128Bytes(Offset);
126 } else if (Reg < 64) {
127 JCE->emitByte(dwarf::DW_CFA_offset + Reg);
128 JCE->emitULEB128Bytes(Offset);
129 } else {
130 JCE->emitByte(dwarf::DW_CFA_offset_extended);
131 JCE->emitULEB128Bytes(Reg);
132 JCE->emitULEB128Bytes(Offset);
133 }
134 }
135 }
136 }
137
138 /// SharedTypeIds - How many leading type ids two landing pads have in common.
139 static unsigned SharedTypeIds(const LandingPadInfo *L,
140 const LandingPadInfo *R) {
141 const std::vector &LIds = L->TypeIds, &RIds = R->TypeIds;
142 unsigned LSize = LIds.size(), RSize = RIds.size();
143 unsigned MinSize = LSize < RSize ? LSize : RSize;
144 unsigned Count = 0;
145
146 for (; Count != MinSize; ++Count)
147 if (LIds[Count] != RIds[Count])
148 return Count;
149
150 return Count;
151 }
152
153
154 /// PadLT - Order landing pads lexicographically by type id.
155 static bool PadLT(const LandingPadInfo *L, const LandingPadInfo *R) {
156 const std::vector &LIds = L->TypeIds, &RIds = R->TypeIds;
157 unsigned LSize = LIds.size(), RSize = RIds.size();
158 unsigned MinSize = LSize < RSize ? LSize : RSize;
159
160 for (unsigned i = 0; i != MinSize; ++i)
161 if (LIds[i] != RIds[i])
162 return LIds[i] < RIds[i];
163
164 return LSize < RSize;
165 }
166
167 namespace {
168
169 /// ActionEntry - Structure describing an entry in the actions table.
170 struct ActionEntry {
171 int ValueForTypeID; // The value to write - may not be equal to the type id.
172 int NextAction;
173 struct ActionEntry *Previous;
174 };
175
176 /// PadRange - Structure holding a try-range and the associated landing pad.
177 struct PadRange {
178 // The index of the landing pad.
179 unsigned PadIndex;
180 // The index of the begin and end labels in the landing pad's label lists.
181 unsigned RangeIndex;
182 };
183
184 typedef DenseMap RangeMapType;
185
186 /// CallSiteEntry - Structure describing an entry in the call-site table.
187 struct CallSiteEntry {
188 MCSymbol *BeginLabel; // zero indicates the start of the function.
189 MCSymbol *EndLabel; // zero indicates the end of the function.
190 MCSymbol *PadLabel; // zero indicates that there is no landing pad.
191 unsigned Action;
192 };
193
194 }
195
196 unsigned char* JITDwarfEmitter::EmitExceptionTable(MachineFunction* MF,
197 unsigned char* StartFunction,
198 unsigned char* EndFunction) const {
199 assert(MMI && "MachineModuleInfo not registered!");
200
201 // Map all labels and get rid of any dead landing pads.
202 MMI->TidyLandingPads(JCE->getLabelLocations());
203
204 const std::vector &TypeInfos = MMI->getTypeInfos();
205 const std::vector &FilterIds = MMI->getFilterIds();
206 const std::vector &PadInfos = MMI->getLandingPads();
207 if (PadInfos.empty()) return 0;
208
209 // Sort the landing pads in order of their type ids. This is used to fold
210 // duplicate actions.
211 SmallVector LandingPads;
212 LandingPads.reserve(PadInfos.size());
213 for (unsigned i = 0, N = PadInfos.size(); i != N; ++i)
214 LandingPads.push_back(&PadInfos[i]);
215 std::sort(LandingPads.begin(), LandingPads.end(), PadLT);
216
217 // Negative type ids index into FilterIds, positive type ids index into
218 // TypeInfos. The value written for a positive type id is just the type
219 // id itself. For a negative type id, however, the value written is the
220 // (negative) byte offset of the corresponding FilterIds entry. The byte
221 // offset is usually equal to the type id, because the FilterIds entries
222 // are written using a variable width encoding which outputs one byte per
223 // entry as long as the value written is not too large, but can differ.
224 // This kind of complication does not occur for positive type ids because
225 // type infos are output using a fixed width encoding.
226 // FilterOffsets[i] holds the byte offset corresponding to FilterIds[i].
227 SmallVector FilterOffsets;
228 FilterOffsets.reserve(FilterIds.size());
229 int Offset = -1;
230 for(std::vector::const_iterator I = FilterIds.begin(),
231 E = FilterIds.end(); I != E; ++I) {
232 FilterOffsets.push_back(Offset);
233 Offset -= MCAsmInfo::getULEB128Size(*I);
234 }
235
236 // Compute the actions table and gather the first action index for each
237 // landing pad site.
238 SmallVector Actions;
239 SmallVector FirstActions;
240 FirstActions.reserve(LandingPads.size());
241
242 int FirstAction = 0;
243 unsigned SizeActions = 0;
244 for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) {
245 const LandingPadInfo *LP = LandingPads[i];
246 const std::vector &TypeIds = LP->TypeIds;
247 const unsigned NumShared = i ? SharedTypeIds(LP, LandingPads[i-1]) : 0;
248 unsigned SizeSiteActions = 0;
249
250 if (NumShared < TypeIds.size()) {
251 unsigned SizeAction = 0;
252 ActionEntry *PrevAction = 0;
253
254 if (NumShared) {
255 const unsigned SizePrevIds = LandingPads[i-1]->TypeIds.size();
256 assert(Actions.size());
257 PrevAction = &Actions.back();
258 SizeAction = MCAsmInfo::getSLEB128Size(PrevAction->NextAction) +
259 MCAsmInfo::getSLEB128Size(PrevAction->ValueForTypeID);
260 for (unsigned j = NumShared; j != SizePrevIds; ++j) {
261 SizeAction -= MCAsmInfo::getSLEB128Size(PrevAction->ValueForTypeID);
262 SizeAction += -PrevAction->NextAction;
263 PrevAction = PrevAction->Previous;
264 }
265 }
266
267 // Compute the actions.
268 for (unsigned I = NumShared, M = TypeIds.size(); I != M; ++I) {
269 int TypeID = TypeIds[I];
270 assert(-1-TypeID < (int)FilterOffsets.size() && "Unknown filter id!");
271 int ValueForTypeID = TypeID < 0 ? FilterOffsets[-1 - TypeID] : TypeID;
272 unsigned SizeTypeID = MCAsmInfo::getSLEB128Size(ValueForTypeID);
273
274 int NextAction = SizeAction ? -(SizeAction + SizeTypeID) : 0;
275 SizeAction = SizeTypeID + MCAsmInfo::getSLEB128Size(NextAction);
276 SizeSiteActions += SizeAction;
277
278 ActionEntry Action = {ValueForTypeID, NextAction, PrevAction};
279 Actions.push_back(Action);
280
281 PrevAction = &Actions.back();
282 }
283
284 // Record the first action of the landing pad site.
285 FirstAction = SizeActions + SizeSiteActions - SizeAction + 1;
286 } // else identical - re-use previous FirstAction
287
288 FirstActions.push_back(FirstAction);
289
290 // Compute this sites contribution to size.
291 SizeActions += SizeSiteActions;
292 }
293
294 // Compute the call-site table. Entries must be ordered by address.
295 SmallVector CallSites;
296
297 RangeMapType PadMap;
298 for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) {
299 const LandingPadInfo *LandingPad = LandingPads[i];
300 for (unsigned j=0, E = LandingPad->BeginLabels.size(); j != E; ++j) {
301 MCSymbol *BeginLabel = LandingPad->BeginLabels[j];
302 assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!");
303 PadRange P = { i, j };
304 PadMap[BeginLabel] = P;
305 }
306 }
307
308 bool MayThrow = false;
309 MCSymbol *LastLabel = 0;
310 for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
311 I != E; ++I) {
312 for (MachineBasicBlock::const_iterator MI = I->begin(), E = I->end();
313 MI != E; ++MI) {
314 if (!MI->isLabel()) {
315 MayThrow |= MI->isCall();
316 continue;
317 }
318
319 MCSymbol *BeginLabel = MI->getOperand(0).getMCSymbol();
320 assert(BeginLabel && "Invalid label!");
321
322 if (BeginLabel == LastLabel)
323 MayThrow = false;
324
325 RangeMapType::iterator L = PadMap.find(BeginLabel);
326
327 if (L == PadMap.end())
328 continue;
329
330 PadRange P = L->second;
331 const LandingPadInfo *LandingPad = LandingPads[P.PadIndex];
332
333 assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] &&
334 "Inconsistent landing pad map!");
335
336 // If some instruction between the previous try-range and this one may
337 // throw, create a call-site entry with no landing pad for the region
338 // between the try-ranges.
339 if (MayThrow) {
340 CallSiteEntry Site = {LastLabel, BeginLabel, 0, 0};
341 CallSites.push_back(Site);
342 }
343
344 LastLabel = LandingPad->EndLabels[P.RangeIndex];
345 CallSiteEntry Site = {BeginLabel, LastLabel,
346 LandingPad->LandingPadLabel, FirstActions[P.PadIndex]};
347
348 assert(Site.BeginLabel && Site.EndLabel && Site.PadLabel &&
349 "Invalid landing pad!");
350
351 // Try to merge with the previous call-site.
352 if (CallSites.size()) {
353 CallSiteEntry &Prev = CallSites.back();
354 if (Site.PadLabel == Prev.PadLabel && Site.Action == Prev.Action) {
355 // Extend the range of the previous entry.
356 Prev.EndLabel = Site.EndLabel;
357 continue;
358 }
359 }
360
361 // Otherwise, create a new call-site.
362 CallSites.push_back(Site);
363 }
364 }
365 // If some instruction between the previous try-range and the end of the
366 // function may throw, create a call-site entry with no landing pad for the
367 // region following the try-range.
368 if (MayThrow) {
369 CallSiteEntry Site = {LastLabel, 0, 0, 0};
370 CallSites.push_back(Site);
371 }
372
373 // Final tallies.
374 unsigned SizeSites = CallSites.size() * (sizeof(int32_t) + // Site start.
375 sizeof(int32_t) + // Site length.
376 sizeof(int32_t)); // Landing pad.
377 for (unsigned i = 0, e = CallSites.size(); i < e; ++i)
378 SizeSites += MCAsmInfo::getULEB128Size(CallSites[i].Action);
379
380 unsigned SizeTypes = TypeInfos.size() * TD->getPointerSize();
381
382 unsigned TypeOffset = sizeof(int8_t) + // Call site format
383 // Call-site table length
384 MCAsmInfo::getULEB128Size(SizeSites) +
385 SizeSites + SizeActions + SizeTypes;
386
387 // Begin the exception table.
388 JCE->emitAlignmentWithFill(4, 0);
389 // Asm->EOL("Padding");
390
391 unsigned char* DwarfExceptionTable = (unsigned char*)JCE->getCurrentPCValue();
392
393 // Emit the header.
394 JCE->emitByte(dwarf::DW_EH_PE_omit);
395 // Asm->EOL("LPStart format (DW_EH_PE_omit)");
396 JCE->emitByte(dwarf::DW_EH_PE_absptr);
397 // Asm->EOL("TType format (DW_EH_PE_absptr)");
398 JCE->emitULEB128Bytes(TypeOffset);
399 // Asm->EOL("TType base offset");
400 JCE->emitByte(dwarf::DW_EH_PE_udata4);
401 // Asm->EOL("Call site format (DW_EH_PE_udata4)");
402 JCE->emitULEB128Bytes(SizeSites);
403 // Asm->EOL("Call-site table length");
404
405 // Emit the landing pad site information.
406 for (unsigned i = 0; i < CallSites.size(); ++i) {
407 CallSiteEntry &S = CallSites[i];
408 intptr_t BeginLabelPtr = 0;
409 intptr_t EndLabelPtr = 0;
410
411 if (!S.BeginLabel) {
412 BeginLabelPtr = (intptr_t)StartFunction;
413 JCE->emitInt32(0);
414 } else {
415 BeginLabelPtr = JCE->getLabelAddress(S.BeginLabel);
416 JCE->emitInt32(BeginLabelPtr - (intptr_t)StartFunction);
417 }
418
419 // Asm->EOL("Region start");
420
421 if (!S.EndLabel)
422 EndLabelPtr = (intptr_t)EndFunction;
423 else
424 EndLabelPtr = JCE->getLabelAddress(S.EndLabel);
425
426 JCE->emitInt32(EndLabelPtr - BeginLabelPtr);
427 //Asm->EOL("Region length");
428
429 if (!S.PadLabel) {
430 JCE->emitInt32(0);
431 } else {
432 unsigned PadLabelPtr = JCE->getLabelAddress(S.PadLabel);
433 JCE->emitInt32(PadLabelPtr - (intptr_t)StartFunction);
434 }
435 // Asm->EOL("Landing pad");
436
437 JCE->emitULEB128Bytes(S.Action);
438 // Asm->EOL("Action");
439 }
440
441 // Emit the actions.
442 for (unsigned I = 0, N = Actions.size(); I != N; ++I) {
443 ActionEntry &Action = Actions[I];
444
445 JCE->emitSLEB128Bytes(Action.ValueForTypeID);
446 //Asm->EOL("TypeInfo index");
447 JCE->emitSLEB128Bytes(Action.NextAction);
448 //Asm->EOL("Next action");
449 }
450
451 // Emit the type ids.
452 for (unsigned M = TypeInfos.size(); M; --M) {
453 const GlobalVariable *GV = TypeInfos[M - 1];
454
455 if (GV) {
456 if (TD->getPointerSize() == sizeof(int32_t))
457 JCE->emitInt32((intptr_t)Jit.getOrEmitGlobalVariable(GV));
458 else
459 JCE->emitInt64((intptr_t)Jit.getOrEmitGlobalVariable(GV));
460 } else {
461 if (TD->getPointerSize() == sizeof(int32_t))
462 JCE->emitInt32(0);
463 else
464 JCE->emitInt64(0);
465 }
466 // Asm->EOL("TypeInfo");
467 }
468
469 // Emit the filter typeids.
470 for (unsigned j = 0, M = FilterIds.size(); j < M; ++j) {
471 unsigned TypeID = FilterIds[j];
472 JCE->emitULEB128Bytes(TypeID);
473 //Asm->EOL("Filter TypeInfo index");
474 }
475
476 JCE->emitAlignmentWithFill(4, 0);
477
478 return DwarfExceptionTable;
479 }
480
481 unsigned char*
482 JITDwarfEmitter::EmitCommonEHFrame(const Function* Personality) const {
483 unsigned PointerSize = TD->getPointerSize();
484 int stackGrowth = stackGrowthDirection == TargetFrameLowering::StackGrowsUp ?
485 PointerSize : -PointerSize;
486
487 unsigned char* StartCommonPtr = (unsigned char*)JCE->getCurrentPCValue();
488 // EH Common Frame header
489 JCE->allocateSpace(4, 0);
490 unsigned char* FrameCommonBeginPtr = (unsigned char*)JCE->getCurrentPCValue();
491 JCE->emitInt32((int)0);
492 JCE->emitByte(dwarf::DW_CIE_VERSION);
493 JCE->emitString(Personality ? "zPLR" : "zR");
494 JCE->emitULEB128Bytes(1);
495 JCE->emitSLEB128Bytes(stackGrowth);
496 JCE->emitByte(RI->getDwarfRegNum(RI->getRARegister(), true));
497
498 if (Personality) {
499 // Augmentation Size: 3 small ULEBs of one byte each, and the personality
500 // function which size is PointerSize.
501 JCE->emitULEB128Bytes(3 + PointerSize);
502
503 // We set the encoding of the personality as direct encoding because we use
504 // the function pointer. The encoding is not relative because the current
505 // PC value may be bigger than the personality function pointer.
506 if (PointerSize == 4) {
507 JCE->emitByte(dwarf::DW_EH_PE_sdata4);
508 JCE->emitInt32(((intptr_t)Jit.getPointerToGlobal(Personality)));
509 } else {
510 JCE->emitByte(dwarf::DW_EH_PE_sdata8);
511 JCE->emitInt64(((intptr_t)Jit.getPointerToGlobal(Personality)));
512 }
513
514 // LSDA encoding: This must match the encoding used in EmitEHFrame ()
515 if (PointerSize == 4)
516 JCE->emitULEB128Bytes(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4);
517 else
518 JCE->emitULEB128Bytes(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8);
519 JCE->emitULEB128Bytes(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4);
520 } else {
521 JCE->emitULEB128Bytes(1);
522 JCE->emitULEB128Bytes(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4);
523 }
524
525 EmitFrameMoves(0, MAI->getInitialFrameState());
526
527 JCE->emitAlignmentWithFill(PointerSize, dwarf::DW_CFA_nop);
528
529 JCE->emitInt32At((uintptr_t*)StartCommonPtr,
530 (uintptr_t)((unsigned char*)JCE->getCurrentPCValue() -
531 FrameCommonBeginPtr));
532
533 return StartCommonPtr;
534 }
535
536
537 unsigned char*
538 JITDwarfEmitter::EmitEHFrame(const Function* Personality,
539 unsigned char* StartCommonPtr,
540 unsigned char* StartFunction,
541 unsigned char* EndFunction,
542 unsigned char* ExceptionTable) const {
543 unsigned PointerSize = TD->getPointerSize();
544
545 // EH frame header.
546 unsigned char* StartEHPtr = (unsigned char*)JCE->getCurrentPCValue();
547 JCE->allocateSpace(4, 0);
548 unsigned char* FrameBeginPtr = (unsigned char*)JCE->getCurrentPCValue();
549 // FDE CIE Offset
550 JCE->emitInt32(FrameBeginPtr - StartCommonPtr);
551 JCE->emitInt32(StartFunction - (unsigned char*)JCE->getCurrentPCValue());
552 JCE->emitInt32(EndFunction - StartFunction);
553
554 // If there is a personality and landing pads then point to the language
555 // specific data area in the exception table.
556 if (Personality) {
557 JCE->emitULEB128Bytes(PointerSize == 4 ? 4 : 8);
558
559 if (PointerSize == 4) {
560 if (!MMI->getLandingPads().empty())
561 JCE->emitInt32(ExceptionTable-(unsigned char*)JCE->getCurrentPCValue());
562 else
563 JCE->emitInt32((int)0);
564 } else {
565 if (!MMI->getLandingPads().empty())
566 JCE->emitInt64(ExceptionTable-(unsigned char*)JCE->getCurrentPCValue());
567 else
568 JCE->emitInt64((int)0);
569 }
570 } else {
571 JCE->emitULEB128Bytes(0);
572 }
573
574 // Indicate locations of function specific callee saved registers in
575 // frame.
576 EmitFrameMoves((intptr_t)StartFunction, MMI->getFrameMoves());
577
578 JCE->emitAlignmentWithFill(PointerSize, dwarf::DW_CFA_nop);
579
580 // Indicate the size of the table
581 JCE->emitInt32At((uintptr_t*)StartEHPtr,
582 (uintptr_t)((unsigned char*)JCE->getCurrentPCValue() -
583 StartEHPtr));
584
585 // Double zeroes for the unwind runtime
586 if (PointerSize == 8) {
587 JCE->emitInt64(0);
588 JCE->emitInt64(0);
589 } else {
590 JCE->emitInt32(0);
591 JCE->emitInt32(0);
592 }
593
594 return StartEHPtr;
595 }
362362 /// Instance of the JIT
363363 JIT *TheJIT;
364364
365 bool JITExceptionHandling;
366
367365 public:
368366 JITEmitter(JIT &jit, JITMemoryManager *JMM, TargetMachine &TM)
369367 : SizeEstimate(0), Resolver(jit, *this), MMI(0), CurFn(0),
370 EmittedFunctions(this), TheJIT(&jit),
371 JITExceptionHandling(TM.Options.JITExceptionHandling) {
368 EmittedFunctions(this), TheJIT(&jit) {
372369 MemMgr = JMM ? JMM : JITMemoryManager::CreateDefaultMemManager();
373370 if (jit.getJITInfo().needsGOT()) {
374371 MemMgr->AllocateGOT();
375372 DEBUG(dbgs() << "JIT is managing a GOT\n");
376373 }
377374
378 if (JITExceptionHandling) {
379 DE.reset(new JITDwarfEmitter(jit));
380 }
381375 }
382376 ~JITEmitter() {
383377 delete MemMgr;
963957 }
964958 });
965959
966 if (JITExceptionHandling) {
967 uintptr_t ActualSize = 0;
968 SavedBufferBegin = BufferBegin;
969 SavedBufferEnd = BufferEnd;
970 SavedCurBufferPtr = CurBufferPtr;
971 uint8_t *FrameRegister;
972
973 while (true) {
974 BufferBegin = CurBufferPtr = MemMgr->startExceptionTable(F.getFunction(),
975 ActualSize);
976 BufferEnd = BufferBegin+ActualSize;
977 EmittedFunctions[F.getFunction()].ExceptionTable = BufferBegin;
978 uint8_t *EhStart;
979 FrameRegister = DE->EmitDwarfTable(F, *this, FnStart, FnEnd, EhStart);
980
981 // If the buffer was large enough to hold the table then we are done.
982 if (CurBufferPtr != BufferEnd)
983 break;
984
985 // Try again with twice as much space.
986 ActualSize = (CurBufferPtr - BufferBegin) * 2;
987 MemMgr->deallocateExceptionTable(BufferBegin);
988 }
989 MemMgr->endExceptionTable(F.getFunction(), BufferBegin, CurBufferPtr,
990 FrameRegister);
991 BufferBegin = SavedBufferBegin;
992 BufferEnd = SavedBufferEnd;
993 CurBufferPtr = SavedCurBufferPtr;
994
995 if (JITExceptionHandling) {
996 TheJIT->RegisterTable(F.getFunction(), FrameRegister);
997 }
998 }
999
1000960 if (MMI)
1001961 MMI->EndFunction();
1002962
1026986 Emitted = EmittedFunctions.find(F);
1027987 if (Emitted != EmittedFunctions.end()) {
1028988 MemMgr->deallocateFunctionBody(Emitted->second.FunctionBody);
1029 MemMgr->deallocateExceptionTable(Emitted->second.ExceptionTable);
1030989 TheJIT->NotifyFreeingMachineCode(Emitted->second.Code);
1031990
1032991 EmittedFunctions.erase(Emitted);
1033 }
1034
1035 if (JITExceptionHandling) {
1036 TheJIT->DeregisterTable(F);
1037992 }
1038993 }
1039994
512512 return false;
513513 }
514514
515 /// startExceptionTable - Use startFunctionBody to allocate memory for the
516 /// function's exception table.
517 uint8_t* startExceptionTable(const Function* F, uintptr_t &ActualSize) {
518 return startFunctionBody(F, ActualSize);
519 }
520
521 /// endExceptionTable - The exception table of F is now allocated,
522 /// and takes the memory in the range [TableStart,TableEnd).
523 void endExceptionTable(const Function *F, uint8_t *TableStart,
524 uint8_t *TableEnd, uint8_t* FrameRegister) {
525 assert(TableEnd > TableStart);
526 assert(TableStart == (uint8_t *)(CurBlock+1) &&
527 "Mismatched table start/end!");
528
529 uintptr_t BlockSize = TableEnd - (uint8_t *)CurBlock;
530
531 // Release the memory at the end of this block that isn't needed.
532 FreeMemoryList =CurBlock->TrimAllocationToSize(FreeMemoryList, BlockSize);
533 }
534
535515 uint8_t *getGOTBase() const {
536516 return GOTBase;
537517 }
554534 /// function body.
555535 void deallocateFunctionBody(void *Body) {
556536 if (Body) deallocateBlock(Body);
557 }
558
559 /// deallocateExceptionTable - Deallocate memory for the specified
560 /// exception table.
561 void deallocateExceptionTable(void *ET) {
562 if (ET) deallocateBlock(ET);
563537 }
564538
565539 /// setMemoryWritable - When code generation is in progress,
9797 void RecordingMemoryManager::deallocateFunctionBody(void *Body) {
9898 llvm_unreachable("Unexpected!");
9999 }
100 uint8_t* RecordingMemoryManager::startExceptionTable(const Function* F, uintptr_t &ActualSize) {
101 llvm_unreachable("Unexpected!");
102 return 0;
103 }
104 void RecordingMemoryManager::endExceptionTable(const Function *F, uint8_t *TableStart,
105 uint8_t *TableEnd, uint8_t* FrameRegister) {
106 llvm_unreachable("Unexpected!");
107 }
108 void RecordingMemoryManager::deallocateExceptionTable(void *ET) {
109 llvm_unreachable("Unexpected!");
110 }
111100
112101 static int jit_noop() {
113102 return 0;
7474 uint8_t *allocateSpace(intptr_t Size, unsigned Alignment);
7575 uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment);
7676 void deallocateFunctionBody(void *Body);
77 uint8_t* startExceptionTable(const Function* F, uintptr_t &ActualSize);
78 void endExceptionTable(const Function *F, uint8_t *TableStart,
79 uint8_t *TableEnd, uint8_t* FrameRegister);
80 void deallocateExceptionTable(void *ET);
81
8277 };
8378
8479 } // end namespace llvm
158158 clEnumValEnd));
159159
160160 cl::opt
161 EnableJITExceptionHandling("jit-enable-eh",
162 cl::desc("Emit exception handling information"),
163 cl::init(false));
164
165 cl::opt
166161 GenerateSoftFloatCalls("soft-float",
167162 cl::desc("Generate software floating point library calls"),
168163 cl::init(false));
380375
381376 // Remote target execution doesn't handle EH or debug registration.
382377 if (!RemoteMCJIT) {
383 Options.JITExceptionHandling = EnableJITExceptionHandling;
384378 Options.JITEmitDebugInfo = EmitJitDebugInfo;
385379 Options.JITEmitDebugInfoToDisk = EmitJitDebugInfoToDisk;
386380 }
142142 deallocateFunctionBodyCalls.push_back(DeallocateFunctionBodyCall(Body));
143143 Base->deallocateFunctionBody(Body);
144144 }
145 struct DeallocateExceptionTableCall {
146 DeallocateExceptionTableCall(const void *ET) : ET(ET) {}
147 const void *ET;
148 };
149 std::vector deallocateExceptionTableCalls;
150 virtual void deallocateExceptionTable(void *ET) {
151 deallocateExceptionTableCalls.push_back(DeallocateExceptionTableCall(ET));
152 Base->deallocateExceptionTable(ET);
153 }
154 struct StartExceptionTableCall {
155 StartExceptionTableCall(uint8_t *Result, const Function *F,
156 uintptr_t ActualSize, uintptr_t ActualSizeResult)
157 : Result(Result), F(F), F_dump(DumpFunction(F)),
158 ActualSize(ActualSize), ActualSizeResult(ActualSizeResult) {}
159 uint8_t *Result;
160 const Function *F;
161 std::string F_dump;
162 uintptr_t ActualSize;
163 uintptr_t ActualSizeResult;
164 };
165 std::vector startExceptionTableCalls;
166 virtual uint8_t *startExceptionTable(const Function *F,
167 uintptr_t &ActualSize) {
168 uintptr_t InitialActualSize = ActualSize;
169 uint8_t *Result = Base->startExceptionTable(F, ActualSize);
170 startExceptionTableCalls.push_back(
171 StartExceptionTableCall(Result, F, InitialActualSize, ActualSize));
172 return Result;
173 }
174 struct EndExceptionTableCall {
175 EndExceptionTableCall(const Function *F, uint8_t *TableStart,
176 uint8_t *TableEnd, uint8_t* FrameRegister)
177 : F(F), F_dump(DumpFunction(F)),
178 TableStart(TableStart), TableEnd(TableEnd),
179 FrameRegister(FrameRegister) {}
180 const Function *F;
181 std::string F_dump;
182 uint8_t *TableStart;
183 uint8_t *TableEnd;
184 uint8_t *FrameRegister;
185 };
186 std::vector endExceptionTableCalls;
187 virtual void endExceptionTable(const Function *F, uint8_t *TableStart,
188 uint8_t *TableEnd, uint8_t* FrameRegister) {
189 endExceptionTableCalls.push_back(
190 EndExceptionTableCall(F, TableStart, TableEnd, FrameRegister));
191 return Base->endExceptionTable(F, TableStart, TableEnd, FrameRegister);
192 }
193145 };
194146
195147 bool LoadAssemblyInto(Module *M, const char *assembly) {
215167 RJMM->setPoisonMemory(true);
216168 std::string Error;
217169 TargetOptions Options;
218 Options.JITExceptionHandling = true;
219170 TheJIT.reset(EngineBuilder(M).setEngineKind(EngineKind::JIT)
220171 .setJITMemoryManager(RJMM)
221172 .setErrorStr(&Error)
299250 // F2() should *still* increment G.
300251 F2Ptr();
301252 EXPECT_EQ(3, *GPtr);
302 }
303
304 // Regression test for a bug. The JITEmitter wasn't checking to verify that
305 // it hadn't run out of space while generating the DWARF exception information
306 // for an emitted function.
307
308 class ExceptionMemoryManagerMock : public RecordingJITMemoryManager {
309 public:
310 virtual uint8_t *startExceptionTable(const Function *F,
311 uintptr_t &ActualSize) {
312 // force an insufficient size the first time through.
313 bool ChangeActualSize = false;
314 if (ActualSize == 0)
315 ChangeActualSize = true;;
316 uint8_t *result =
317 RecordingJITMemoryManager::startExceptionTable(F, ActualSize);
318 if (ChangeActualSize)
319 ActualSize = 1;
320 return result;
321 }
322 };
323
324 class JITExceptionMemoryTest : public JITTest {
325 protected:
326 virtual RecordingJITMemoryManager *createMemoryManager() {
327 return new ExceptionMemoryManagerMock;
328 }
329 };
330
331 TEST_F(JITExceptionMemoryTest, ExceptionTableOverflow) {
332 Function *F = Function::Create(TypeBuilder::get(Context),
333 Function::ExternalLinkage,
334 "func1", M);
335 BasicBlock *Block = BasicBlock::Create(Context, "block", F);
336 IRBuilder<> Builder(Block);
337 Builder.CreateRetVoid();
338 TheJIT->getPointerToFunction(F);
339 ASSERT_TRUE(RJMM->startExceptionTableCalls.size() == 2);
340 ASSERT_TRUE(RJMM->deallocateExceptionTableCalls.size() == 1);
341 ASSERT_TRUE(RJMM->endExceptionTableCalls.size() == 1);
342253 }
343254
344255 int PlusOne(int arg) {
500411 }
501412 EXPECT_EQ(RJMM->startFunctionBodyCalls.size(),
502413 RJMM->deallocateFunctionBodyCalls.size());
503
504 SmallPtrSet ExceptionTablesDeallocated;
505 unsigned NumTablesDeallocated = 0;
506 for (unsigned i = 0, e = RJMM->deallocateExceptionTableCalls.size();
507 i != e; ++i) {
508 ExceptionTablesDeallocated.insert(
509 RJMM->deallocateExceptionTableCalls[i].ET);
510 if (RJMM->deallocateExceptionTableCalls[i].ET != NULL) {
511 // If JITEmitDebugInfo is off, we'll "deallocate" NULL, which doesn't
512 // appear in startExceptionTableCalls.
513 NumTablesDeallocated++;
514 }
515 }
516 for (unsigned i = 0, e = RJMM->startExceptionTableCalls.size(); i != e; ++i) {
517 EXPECT_TRUE(ExceptionTablesDeallocated.count(
518 RJMM->startExceptionTableCalls[i].Result))
519 << "Function's exception table leaked: \n"
520 << RJMM->startExceptionTableCalls[i].F_dump;
521 }
522 EXPECT_EQ(RJMM->startExceptionTableCalls.size(),
523 NumTablesDeallocated);
524414 }
525415
526416 // ARM, MIPS and PPC still emit stubs for calls since the target may be