llvm-project

Форк
0
/
ObjCARCInstKind.cpp 
704 строки · 23.2 Кб
1
//===- ARCInstKind.cpp - ObjC ARC Optimization ----------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
/// \file
9
/// This file defines several utility functions used by various ARC
10
/// optimizations which are IMHO too big to be in a header file.
11
///
12
/// WARNING: This file knows about certain library functions. It recognizes them
13
/// by name, and hardwires knowledge of their semantics.
14
///
15
/// WARNING: This file knows about how certain Objective-C library functions are
16
/// used. Naive LLVM IR transformations which would otherwise be
17
/// behavior-preserving may break these assumptions.
18
///
19
//===----------------------------------------------------------------------===//
20

21
#include "llvm/Analysis/ObjCARCInstKind.h"
22
#include "llvm/Analysis/ObjCARCAnalysisUtils.h"
23
#include "llvm/IR/Intrinsics.h"
24

25
using namespace llvm;
26
using namespace llvm::objcarc;
27

28
raw_ostream &llvm::objcarc::operator<<(raw_ostream &OS,
29
                                       const ARCInstKind Class) {
30
  switch (Class) {
31
  case ARCInstKind::Retain:
32
    return OS << "ARCInstKind::Retain";
33
  case ARCInstKind::RetainRV:
34
    return OS << "ARCInstKind::RetainRV";
35
  case ARCInstKind::UnsafeClaimRV:
36
    return OS << "ARCInstKind::UnsafeClaimRV";
37
  case ARCInstKind::RetainBlock:
38
    return OS << "ARCInstKind::RetainBlock";
39
  case ARCInstKind::Release:
40
    return OS << "ARCInstKind::Release";
41
  case ARCInstKind::Autorelease:
42
    return OS << "ARCInstKind::Autorelease";
43
  case ARCInstKind::AutoreleaseRV:
44
    return OS << "ARCInstKind::AutoreleaseRV";
45
  case ARCInstKind::AutoreleasepoolPush:
46
    return OS << "ARCInstKind::AutoreleasepoolPush";
47
  case ARCInstKind::AutoreleasepoolPop:
48
    return OS << "ARCInstKind::AutoreleasepoolPop";
49
  case ARCInstKind::NoopCast:
50
    return OS << "ARCInstKind::NoopCast";
51
  case ARCInstKind::FusedRetainAutorelease:
52
    return OS << "ARCInstKind::FusedRetainAutorelease";
53
  case ARCInstKind::FusedRetainAutoreleaseRV:
54
    return OS << "ARCInstKind::FusedRetainAutoreleaseRV";
55
  case ARCInstKind::LoadWeakRetained:
56
    return OS << "ARCInstKind::LoadWeakRetained";
57
  case ARCInstKind::StoreWeak:
58
    return OS << "ARCInstKind::StoreWeak";
59
  case ARCInstKind::InitWeak:
60
    return OS << "ARCInstKind::InitWeak";
61
  case ARCInstKind::LoadWeak:
62
    return OS << "ARCInstKind::LoadWeak";
63
  case ARCInstKind::MoveWeak:
64
    return OS << "ARCInstKind::MoveWeak";
65
  case ARCInstKind::CopyWeak:
66
    return OS << "ARCInstKind::CopyWeak";
67
  case ARCInstKind::DestroyWeak:
68
    return OS << "ARCInstKind::DestroyWeak";
69
  case ARCInstKind::StoreStrong:
70
    return OS << "ARCInstKind::StoreStrong";
71
  case ARCInstKind::CallOrUser:
72
    return OS << "ARCInstKind::CallOrUser";
73
  case ARCInstKind::Call:
74
    return OS << "ARCInstKind::Call";
75
  case ARCInstKind::User:
76
    return OS << "ARCInstKind::User";
77
  case ARCInstKind::IntrinsicUser:
78
    return OS << "ARCInstKind::IntrinsicUser";
79
  case ARCInstKind::None:
80
    return OS << "ARCInstKind::None";
81
  }
82
  llvm_unreachable("Unknown instruction class!");
83
}
84

85
ARCInstKind llvm::objcarc::GetFunctionClass(const Function *F) {
86

87
  Intrinsic::ID ID = F->getIntrinsicID();
88
  switch (ID) {
89
  default:
90
    return ARCInstKind::CallOrUser;
91
  case Intrinsic::objc_autorelease:
92
    return ARCInstKind::Autorelease;
93
  case Intrinsic::objc_autoreleasePoolPop:
94
    return ARCInstKind::AutoreleasepoolPop;
95
  case Intrinsic::objc_autoreleasePoolPush:
96
    return ARCInstKind::AutoreleasepoolPush;
97
  case Intrinsic::objc_autoreleaseReturnValue:
98
    return ARCInstKind::AutoreleaseRV;
99
  case Intrinsic::objc_copyWeak:
100
    return ARCInstKind::CopyWeak;
101
  case Intrinsic::objc_destroyWeak:
102
    return ARCInstKind::DestroyWeak;
103
  case Intrinsic::objc_initWeak:
104
    return ARCInstKind::InitWeak;
105
  case Intrinsic::objc_loadWeak:
106
    return ARCInstKind::LoadWeak;
107
  case Intrinsic::objc_loadWeakRetained:
108
    return ARCInstKind::LoadWeakRetained;
109
  case Intrinsic::objc_moveWeak:
110
    return ARCInstKind::MoveWeak;
111
  case Intrinsic::objc_release:
112
    return ARCInstKind::Release;
113
  case Intrinsic::objc_retain:
114
    return ARCInstKind::Retain;
115
  case Intrinsic::objc_retainAutorelease:
116
    return ARCInstKind::FusedRetainAutorelease;
117
  case Intrinsic::objc_retainAutoreleaseReturnValue:
118
    return ARCInstKind::FusedRetainAutoreleaseRV;
119
  case Intrinsic::objc_retainAutoreleasedReturnValue:
120
    return ARCInstKind::RetainRV;
121
  case Intrinsic::objc_retainBlock:
122
    return ARCInstKind::RetainBlock;
123
  case Intrinsic::objc_storeStrong:
124
    return ARCInstKind::StoreStrong;
125
  case Intrinsic::objc_storeWeak:
126
    return ARCInstKind::StoreWeak;
127
  case Intrinsic::objc_clang_arc_use:
128
    return ARCInstKind::IntrinsicUser;
129
  case Intrinsic::objc_unsafeClaimAutoreleasedReturnValue:
130
    return ARCInstKind::UnsafeClaimRV;
131
  case Intrinsic::objc_retainedObject:
132
    return ARCInstKind::NoopCast;
133
  case Intrinsic::objc_unretainedObject:
134
    return ARCInstKind::NoopCast;
135
  case Intrinsic::objc_unretainedPointer:
136
    return ARCInstKind::NoopCast;
137
  case Intrinsic::objc_retain_autorelease:
138
    return ARCInstKind::FusedRetainAutorelease;
139
  case Intrinsic::objc_sync_enter:
140
    return ARCInstKind::User;
141
  case Intrinsic::objc_sync_exit:
142
    return ARCInstKind::User;
143
  case Intrinsic::objc_clang_arc_noop_use:
144
  case Intrinsic::objc_arc_annotation_topdown_bbstart:
145
  case Intrinsic::objc_arc_annotation_topdown_bbend:
146
  case Intrinsic::objc_arc_annotation_bottomup_bbstart:
147
  case Intrinsic::objc_arc_annotation_bottomup_bbend:
148
    // Ignore annotation calls. This is important to stop the
149
    // optimizer from treating annotations as uses which would
150
    // make the state of the pointers they are attempting to
151
    // elucidate to be incorrect.
152
    return ARCInstKind::None;
153
  }
154
}
155

156
// A list of intrinsics that we know do not use objc pointers or decrement
157
// ref counts.
158
static bool isInertIntrinsic(unsigned ID) {
159
  // TODO: Make this into a covered switch.
160
  switch (ID) {
161
  case Intrinsic::returnaddress:
162
  case Intrinsic::addressofreturnaddress:
163
  case Intrinsic::frameaddress:
164
  case Intrinsic::stacksave:
165
  case Intrinsic::stackrestore:
166
  case Intrinsic::vastart:
167
  case Intrinsic::vacopy:
168
  case Intrinsic::vaend:
169
  case Intrinsic::objectsize:
170
  case Intrinsic::prefetch:
171
  case Intrinsic::stackprotector:
172
  case Intrinsic::eh_return_i32:
173
  case Intrinsic::eh_return_i64:
174
  case Intrinsic::eh_typeid_for:
175
  case Intrinsic::eh_dwarf_cfa:
176
  case Intrinsic::eh_sjlj_lsda:
177
  case Intrinsic::eh_sjlj_functioncontext:
178
  case Intrinsic::init_trampoline:
179
  case Intrinsic::adjust_trampoline:
180
  case Intrinsic::lifetime_start:
181
  case Intrinsic::lifetime_end:
182
  case Intrinsic::invariant_start:
183
  case Intrinsic::invariant_end:
184
  // Don't let dbg info affect our results.
185
  case Intrinsic::dbg_declare:
186
  case Intrinsic::dbg_value:
187
  case Intrinsic::dbg_label:
188
    // Short cut: Some intrinsics obviously don't use ObjC pointers.
189
    return true;
190
  default:
191
    return false;
192
  }
193
}
194

195
// A list of intrinsics that we know do not use objc pointers or decrement
196
// ref counts.
197
static bool isUseOnlyIntrinsic(unsigned ID) {
198
  // We are conservative and even though intrinsics are unlikely to touch
199
  // reference counts, we white list them for safety.
200
  //
201
  // TODO: Expand this into a covered switch. There is a lot more here.
202
  switch (ID) {
203
  case Intrinsic::memcpy:
204
  case Intrinsic::memmove:
205
  case Intrinsic::memset:
206
    return true;
207
  default:
208
    return false;
209
  }
210
}
211

212
/// Determine what kind of construct V is.
213
ARCInstKind llvm::objcarc::GetARCInstKind(const Value *V) {
214
  if (const Instruction *I = dyn_cast<Instruction>(V)) {
215
    // Any instruction other than bitcast and gep with a pointer operand have a
216
    // use of an objc pointer. Bitcasts, GEPs, Selects, PHIs transfer a pointer
217
    // to a subsequent use, rather than using it themselves, in this sense.
218
    // As a short cut, several other opcodes are known to have no pointer
219
    // operands of interest. And ret is never followed by a release, so it's
220
    // not interesting to examine.
221
    switch (I->getOpcode()) {
222
    case Instruction::Call: {
223
      const CallInst *CI = cast<CallInst>(I);
224
      // See if we have a function that we know something about.
225
      if (const Function *F = CI->getCalledFunction()) {
226
        ARCInstKind Class = GetFunctionClass(F);
227
        if (Class != ARCInstKind::CallOrUser)
228
          return Class;
229
        Intrinsic::ID ID = F->getIntrinsicID();
230
        if (isInertIntrinsic(ID))
231
          return ARCInstKind::None;
232
        if (isUseOnlyIntrinsic(ID))
233
          return ARCInstKind::User;
234
      }
235

236
      // Otherwise, be conservative.
237
      return GetCallSiteClass(*CI);
238
    }
239
    case Instruction::Invoke:
240
      // Otherwise, be conservative.
241
      return GetCallSiteClass(cast<InvokeInst>(*I));
242
    case Instruction::BitCast:
243
    case Instruction::GetElementPtr:
244
    case Instruction::Select:
245
    case Instruction::PHI:
246
    case Instruction::Ret:
247
    case Instruction::Br:
248
    case Instruction::Switch:
249
    case Instruction::IndirectBr:
250
    case Instruction::Alloca:
251
    case Instruction::VAArg:
252
    case Instruction::Add:
253
    case Instruction::FAdd:
254
    case Instruction::Sub:
255
    case Instruction::FSub:
256
    case Instruction::Mul:
257
    case Instruction::FMul:
258
    case Instruction::SDiv:
259
    case Instruction::UDiv:
260
    case Instruction::FDiv:
261
    case Instruction::SRem:
262
    case Instruction::URem:
263
    case Instruction::FRem:
264
    case Instruction::Shl:
265
    case Instruction::LShr:
266
    case Instruction::AShr:
267
    case Instruction::And:
268
    case Instruction::Or:
269
    case Instruction::Xor:
270
    case Instruction::SExt:
271
    case Instruction::ZExt:
272
    case Instruction::Trunc:
273
    case Instruction::IntToPtr:
274
    case Instruction::FCmp:
275
    case Instruction::FPTrunc:
276
    case Instruction::FPExt:
277
    case Instruction::FPToUI:
278
    case Instruction::FPToSI:
279
    case Instruction::UIToFP:
280
    case Instruction::SIToFP:
281
    case Instruction::InsertElement:
282
    case Instruction::ExtractElement:
283
    case Instruction::ShuffleVector:
284
    case Instruction::ExtractValue:
285
      break;
286
    case Instruction::ICmp:
287
      // Comparing a pointer with null, or any other constant, isn't an
288
      // interesting use, because we don't care what the pointer points to, or
289
      // about the values of any other dynamic reference-counted pointers.
290
      if (IsPotentialRetainableObjPtr(I->getOperand(1)))
291
        return ARCInstKind::User;
292
      break;
293
    default:
294
      // For anything else, check all the operands.
295
      // Note that this includes both operands of a Store: while the first
296
      // operand isn't actually being dereferenced, it is being stored to
297
      // memory where we can no longer track who might read it and dereference
298
      // it, so we have to consider it potentially used.
299
      for (const Use &U : I->operands())
300
        if (IsPotentialRetainableObjPtr(U))
301
          return ARCInstKind::User;
302
    }
303
  }
304

305
  // Otherwise, it's totally inert for ARC purposes.
306
  return ARCInstKind::None;
307
}
308

309
/// Test if the given class is a kind of user.
310
bool llvm::objcarc::IsUser(ARCInstKind Class) {
311
  switch (Class) {
312
  case ARCInstKind::User:
313
  case ARCInstKind::CallOrUser:
314
  case ARCInstKind::IntrinsicUser:
315
    return true;
316
  case ARCInstKind::Retain:
317
  case ARCInstKind::RetainRV:
318
  case ARCInstKind::RetainBlock:
319
  case ARCInstKind::Release:
320
  case ARCInstKind::Autorelease:
321
  case ARCInstKind::AutoreleaseRV:
322
  case ARCInstKind::AutoreleasepoolPush:
323
  case ARCInstKind::AutoreleasepoolPop:
324
  case ARCInstKind::NoopCast:
325
  case ARCInstKind::FusedRetainAutorelease:
326
  case ARCInstKind::FusedRetainAutoreleaseRV:
327
  case ARCInstKind::LoadWeakRetained:
328
  case ARCInstKind::StoreWeak:
329
  case ARCInstKind::InitWeak:
330
  case ARCInstKind::LoadWeak:
331
  case ARCInstKind::MoveWeak:
332
  case ARCInstKind::CopyWeak:
333
  case ARCInstKind::DestroyWeak:
334
  case ARCInstKind::StoreStrong:
335
  case ARCInstKind::Call:
336
  case ARCInstKind::None:
337
  case ARCInstKind::UnsafeClaimRV:
338
    return false;
339
  }
340
  llvm_unreachable("covered switch isn't covered?");
341
}
342

343
/// Test if the given class is objc_retain or equivalent.
344
bool llvm::objcarc::IsRetain(ARCInstKind Class) {
345
  switch (Class) {
346
  case ARCInstKind::Retain:
347
  case ARCInstKind::RetainRV:
348
    return true;
349
  // I believe we treat retain block as not a retain since it can copy its
350
  // block.
351
  case ARCInstKind::RetainBlock:
352
  case ARCInstKind::Release:
353
  case ARCInstKind::Autorelease:
354
  case ARCInstKind::AutoreleaseRV:
355
  case ARCInstKind::AutoreleasepoolPush:
356
  case ARCInstKind::AutoreleasepoolPop:
357
  case ARCInstKind::NoopCast:
358
  case ARCInstKind::FusedRetainAutorelease:
359
  case ARCInstKind::FusedRetainAutoreleaseRV:
360
  case ARCInstKind::LoadWeakRetained:
361
  case ARCInstKind::StoreWeak:
362
  case ARCInstKind::InitWeak:
363
  case ARCInstKind::LoadWeak:
364
  case ARCInstKind::MoveWeak:
365
  case ARCInstKind::CopyWeak:
366
  case ARCInstKind::DestroyWeak:
367
  case ARCInstKind::StoreStrong:
368
  case ARCInstKind::IntrinsicUser:
369
  case ARCInstKind::CallOrUser:
370
  case ARCInstKind::Call:
371
  case ARCInstKind::User:
372
  case ARCInstKind::None:
373
  case ARCInstKind::UnsafeClaimRV:
374
    return false;
375
  }
376
  llvm_unreachable("covered switch isn't covered?");
377
}
378

379
/// Test if the given class is objc_autorelease or equivalent.
380
bool llvm::objcarc::IsAutorelease(ARCInstKind Class) {
381
  switch (Class) {
382
  case ARCInstKind::Autorelease:
383
  case ARCInstKind::AutoreleaseRV:
384
    return true;
385
  case ARCInstKind::Retain:
386
  case ARCInstKind::RetainRV:
387
  case ARCInstKind::UnsafeClaimRV:
388
  case ARCInstKind::RetainBlock:
389
  case ARCInstKind::Release:
390
  case ARCInstKind::AutoreleasepoolPush:
391
  case ARCInstKind::AutoreleasepoolPop:
392
  case ARCInstKind::NoopCast:
393
  case ARCInstKind::FusedRetainAutorelease:
394
  case ARCInstKind::FusedRetainAutoreleaseRV:
395
  case ARCInstKind::LoadWeakRetained:
396
  case ARCInstKind::StoreWeak:
397
  case ARCInstKind::InitWeak:
398
  case ARCInstKind::LoadWeak:
399
  case ARCInstKind::MoveWeak:
400
  case ARCInstKind::CopyWeak:
401
  case ARCInstKind::DestroyWeak:
402
  case ARCInstKind::StoreStrong:
403
  case ARCInstKind::IntrinsicUser:
404
  case ARCInstKind::CallOrUser:
405
  case ARCInstKind::Call:
406
  case ARCInstKind::User:
407
  case ARCInstKind::None:
408
    return false;
409
  }
410
  llvm_unreachable("covered switch isn't covered?");
411
}
412

413
/// Test if the given class represents instructions which return their
414
/// argument verbatim.
415
bool llvm::objcarc::IsForwarding(ARCInstKind Class) {
416
  switch (Class) {
417
  case ARCInstKind::Retain:
418
  case ARCInstKind::RetainRV:
419
  case ARCInstKind::UnsafeClaimRV:
420
  case ARCInstKind::Autorelease:
421
  case ARCInstKind::AutoreleaseRV:
422
  case ARCInstKind::NoopCast:
423
    return true;
424
  case ARCInstKind::RetainBlock:
425
  case ARCInstKind::Release:
426
  case ARCInstKind::AutoreleasepoolPush:
427
  case ARCInstKind::AutoreleasepoolPop:
428
  case ARCInstKind::FusedRetainAutorelease:
429
  case ARCInstKind::FusedRetainAutoreleaseRV:
430
  case ARCInstKind::LoadWeakRetained:
431
  case ARCInstKind::StoreWeak:
432
  case ARCInstKind::InitWeak:
433
  case ARCInstKind::LoadWeak:
434
  case ARCInstKind::MoveWeak:
435
  case ARCInstKind::CopyWeak:
436
  case ARCInstKind::DestroyWeak:
437
  case ARCInstKind::StoreStrong:
438
  case ARCInstKind::IntrinsicUser:
439
  case ARCInstKind::CallOrUser:
440
  case ARCInstKind::Call:
441
  case ARCInstKind::User:
442
  case ARCInstKind::None:
443
    return false;
444
  }
445
  llvm_unreachable("covered switch isn't covered?");
446
}
447

448
/// Test if the given class represents instructions which do nothing if
449
/// passed a null pointer.
450
bool llvm::objcarc::IsNoopOnNull(ARCInstKind Class) {
451
  switch (Class) {
452
  case ARCInstKind::Retain:
453
  case ARCInstKind::RetainRV:
454
  case ARCInstKind::UnsafeClaimRV:
455
  case ARCInstKind::Release:
456
  case ARCInstKind::Autorelease:
457
  case ARCInstKind::AutoreleaseRV:
458
  case ARCInstKind::RetainBlock:
459
    return true;
460
  case ARCInstKind::AutoreleasepoolPush:
461
  case ARCInstKind::AutoreleasepoolPop:
462
  case ARCInstKind::FusedRetainAutorelease:
463
  case ARCInstKind::FusedRetainAutoreleaseRV:
464
  case ARCInstKind::LoadWeakRetained:
465
  case ARCInstKind::StoreWeak:
466
  case ARCInstKind::InitWeak:
467
  case ARCInstKind::LoadWeak:
468
  case ARCInstKind::MoveWeak:
469
  case ARCInstKind::CopyWeak:
470
  case ARCInstKind::DestroyWeak:
471
  case ARCInstKind::StoreStrong:
472
  case ARCInstKind::IntrinsicUser:
473
  case ARCInstKind::CallOrUser:
474
  case ARCInstKind::Call:
475
  case ARCInstKind::User:
476
  case ARCInstKind::None:
477
  case ARCInstKind::NoopCast:
478
    return false;
479
  }
480
  llvm_unreachable("covered switch isn't covered?");
481
}
482

483
/// Test if the given class represents instructions which do nothing if
484
/// passed a global variable.
485
bool llvm::objcarc::IsNoopOnGlobal(ARCInstKind Class) {
486
  switch (Class) {
487
  case ARCInstKind::Retain:
488
  case ARCInstKind::RetainRV:
489
  case ARCInstKind::UnsafeClaimRV:
490
  case ARCInstKind::Release:
491
  case ARCInstKind::Autorelease:
492
  case ARCInstKind::AutoreleaseRV:
493
  case ARCInstKind::RetainBlock:
494
  case ARCInstKind::FusedRetainAutorelease:
495
  case ARCInstKind::FusedRetainAutoreleaseRV:
496
    return true;
497
  case ARCInstKind::AutoreleasepoolPush:
498
  case ARCInstKind::AutoreleasepoolPop:
499
  case ARCInstKind::LoadWeakRetained:
500
  case ARCInstKind::StoreWeak:
501
  case ARCInstKind::InitWeak:
502
  case ARCInstKind::LoadWeak:
503
  case ARCInstKind::MoveWeak:
504
  case ARCInstKind::CopyWeak:
505
  case ARCInstKind::DestroyWeak:
506
  case ARCInstKind::StoreStrong:
507
  case ARCInstKind::IntrinsicUser:
508
  case ARCInstKind::CallOrUser:
509
  case ARCInstKind::Call:
510
  case ARCInstKind::User:
511
  case ARCInstKind::None:
512
  case ARCInstKind::NoopCast:
513
    return false;
514
  }
515
  llvm_unreachable("covered switch isn't covered?");
516
}
517

518
/// Test if the given class represents instructions which are always safe
519
/// to mark with the "tail" keyword.
520
bool llvm::objcarc::IsAlwaysTail(ARCInstKind Class) {
521
  // ARCInstKind::RetainBlock may be given a stack argument.
522
  switch (Class) {
523
  case ARCInstKind::Retain:
524
  case ARCInstKind::RetainRV:
525
  case ARCInstKind::UnsafeClaimRV:
526
  case ARCInstKind::AutoreleaseRV:
527
    return true;
528
  case ARCInstKind::Release:
529
  case ARCInstKind::Autorelease:
530
  case ARCInstKind::RetainBlock:
531
  case ARCInstKind::AutoreleasepoolPush:
532
  case ARCInstKind::AutoreleasepoolPop:
533
  case ARCInstKind::FusedRetainAutorelease:
534
  case ARCInstKind::FusedRetainAutoreleaseRV:
535
  case ARCInstKind::LoadWeakRetained:
536
  case ARCInstKind::StoreWeak:
537
  case ARCInstKind::InitWeak:
538
  case ARCInstKind::LoadWeak:
539
  case ARCInstKind::MoveWeak:
540
  case ARCInstKind::CopyWeak:
541
  case ARCInstKind::DestroyWeak:
542
  case ARCInstKind::StoreStrong:
543
  case ARCInstKind::IntrinsicUser:
544
  case ARCInstKind::CallOrUser:
545
  case ARCInstKind::Call:
546
  case ARCInstKind::User:
547
  case ARCInstKind::None:
548
  case ARCInstKind::NoopCast:
549
    return false;
550
  }
551
  llvm_unreachable("covered switch isn't covered?");
552
}
553

554
/// Test if the given class represents instructions which are never safe
555
/// to mark with the "tail" keyword.
556
bool llvm::objcarc::IsNeverTail(ARCInstKind Class) {
557
  /// It is never safe to tail call objc_autorelease since by tail calling
558
  /// objc_autorelease: fast autoreleasing causing our object to be potentially
559
  /// reclaimed from the autorelease pool which violates the semantics of
560
  /// __autoreleasing types in ARC.
561
  switch (Class) {
562
  case ARCInstKind::Autorelease:
563
    return true;
564
  case ARCInstKind::Retain:
565
  case ARCInstKind::RetainRV:
566
  case ARCInstKind::UnsafeClaimRV:
567
  case ARCInstKind::AutoreleaseRV:
568
  case ARCInstKind::Release:
569
  case ARCInstKind::RetainBlock:
570
  case ARCInstKind::AutoreleasepoolPush:
571
  case ARCInstKind::AutoreleasepoolPop:
572
  case ARCInstKind::FusedRetainAutorelease:
573
  case ARCInstKind::FusedRetainAutoreleaseRV:
574
  case ARCInstKind::LoadWeakRetained:
575
  case ARCInstKind::StoreWeak:
576
  case ARCInstKind::InitWeak:
577
  case ARCInstKind::LoadWeak:
578
  case ARCInstKind::MoveWeak:
579
  case ARCInstKind::CopyWeak:
580
  case ARCInstKind::DestroyWeak:
581
  case ARCInstKind::StoreStrong:
582
  case ARCInstKind::IntrinsicUser:
583
  case ARCInstKind::CallOrUser:
584
  case ARCInstKind::Call:
585
  case ARCInstKind::User:
586
  case ARCInstKind::None:
587
  case ARCInstKind::NoopCast:
588
    return false;
589
  }
590
  llvm_unreachable("covered switch isn't covered?");
591
}
592

593
/// Test if the given class represents instructions which are always safe
594
/// to mark with the nounwind attribute.
595
bool llvm::objcarc::IsNoThrow(ARCInstKind Class) {
596
  // objc_retainBlock is not nounwind because it calls user copy constructors
597
  // which could theoretically throw.
598
  switch (Class) {
599
  case ARCInstKind::Retain:
600
  case ARCInstKind::RetainRV:
601
  case ARCInstKind::UnsafeClaimRV:
602
  case ARCInstKind::Release:
603
  case ARCInstKind::Autorelease:
604
  case ARCInstKind::AutoreleaseRV:
605
  case ARCInstKind::AutoreleasepoolPush:
606
  case ARCInstKind::AutoreleasepoolPop:
607
    return true;
608
  case ARCInstKind::RetainBlock:
609
  case ARCInstKind::FusedRetainAutorelease:
610
  case ARCInstKind::FusedRetainAutoreleaseRV:
611
  case ARCInstKind::LoadWeakRetained:
612
  case ARCInstKind::StoreWeak:
613
  case ARCInstKind::InitWeak:
614
  case ARCInstKind::LoadWeak:
615
  case ARCInstKind::MoveWeak:
616
  case ARCInstKind::CopyWeak:
617
  case ARCInstKind::DestroyWeak:
618
  case ARCInstKind::StoreStrong:
619
  case ARCInstKind::IntrinsicUser:
620
  case ARCInstKind::CallOrUser:
621
  case ARCInstKind::Call:
622
  case ARCInstKind::User:
623
  case ARCInstKind::None:
624
  case ARCInstKind::NoopCast:
625
    return false;
626
  }
627
  llvm_unreachable("covered switch isn't covered?");
628
}
629

630
/// Test whether the given instruction can autorelease any pointer or cause an
631
/// autoreleasepool pop.
632
///
633
/// This means that it *could* interrupt the RV optimization.
634
bool llvm::objcarc::CanInterruptRV(ARCInstKind Class) {
635
  switch (Class) {
636
  case ARCInstKind::AutoreleasepoolPop:
637
  case ARCInstKind::CallOrUser:
638
  case ARCInstKind::Call:
639
  case ARCInstKind::Autorelease:
640
  case ARCInstKind::AutoreleaseRV:
641
  case ARCInstKind::FusedRetainAutorelease:
642
  case ARCInstKind::FusedRetainAutoreleaseRV:
643
    return true;
644
  case ARCInstKind::Retain:
645
  case ARCInstKind::RetainRV:
646
  case ARCInstKind::UnsafeClaimRV:
647
  case ARCInstKind::Release:
648
  case ARCInstKind::AutoreleasepoolPush:
649
  case ARCInstKind::RetainBlock:
650
  case ARCInstKind::LoadWeakRetained:
651
  case ARCInstKind::StoreWeak:
652
  case ARCInstKind::InitWeak:
653
  case ARCInstKind::LoadWeak:
654
  case ARCInstKind::MoveWeak:
655
  case ARCInstKind::CopyWeak:
656
  case ARCInstKind::DestroyWeak:
657
  case ARCInstKind::StoreStrong:
658
  case ARCInstKind::IntrinsicUser:
659
  case ARCInstKind::User:
660
  case ARCInstKind::None:
661
  case ARCInstKind::NoopCast:
662
    return false;
663
  }
664
  llvm_unreachable("covered switch isn't covered?");
665
}
666

667
bool llvm::objcarc::CanDecrementRefCount(ARCInstKind Kind) {
668
  switch (Kind) {
669
  case ARCInstKind::Retain:
670
  case ARCInstKind::RetainRV:
671
  case ARCInstKind::Autorelease:
672
  case ARCInstKind::AutoreleaseRV:
673
  case ARCInstKind::NoopCast:
674
  case ARCInstKind::FusedRetainAutorelease:
675
  case ARCInstKind::FusedRetainAutoreleaseRV:
676
  case ARCInstKind::IntrinsicUser:
677
  case ARCInstKind::User:
678
  case ARCInstKind::None:
679
    return false;
680

681
  // The cases below are conservative.
682

683
  // RetainBlock can result in user defined copy constructors being called
684
  // implying releases may occur.
685
  case ARCInstKind::RetainBlock:
686
  case ARCInstKind::Release:
687
  case ARCInstKind::AutoreleasepoolPush:
688
  case ARCInstKind::AutoreleasepoolPop:
689
  case ARCInstKind::LoadWeakRetained:
690
  case ARCInstKind::StoreWeak:
691
  case ARCInstKind::InitWeak:
692
  case ARCInstKind::LoadWeak:
693
  case ARCInstKind::MoveWeak:
694
  case ARCInstKind::CopyWeak:
695
  case ARCInstKind::DestroyWeak:
696
  case ARCInstKind::StoreStrong:
697
  case ARCInstKind::CallOrUser:
698
  case ARCInstKind::Call:
699
  case ARCInstKind::UnsafeClaimRV:
700
    return true;
701
  }
702

703
  llvm_unreachable("covered switch isn't covered?");
704
}
705

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.