@@ -357,7 +357,7 @@ llvm::Value *irgen::emitReferenceToObjCProtocol(IRGenFunction &IGF,
357
357
// / The function's output type is (value, witnessTable...)
358
358
// /
359
359
// / The value is NULL if the cast failed.
360
- static llvm::Function *
360
+ static llvm::Constant *
361
361
emitExistentialScalarCastFn (IRGenModule &IGM,
362
362
unsigned numProtocols,
363
363
CheckedCastMode mode,
@@ -385,13 +385,7 @@ emitExistentialScalarCastFn(IRGenModule &IGM,
385
385
}
386
386
}
387
387
388
- // See if we already defined this function.
389
-
390
- if (auto fn = IGM.Module .getFunction (name))
391
- return fn;
392
-
393
388
// Build the function type.
394
-
395
389
llvm::SmallVector<llvm::Type *, 4 > argTys;
396
390
llvm::SmallVector<llvm::Type *, 4 > returnTys;
397
391
argTys.push_back (IGM.Int8PtrTy );
@@ -405,84 +399,77 @@ emitExistentialScalarCastFn(IRGenModule &IGM,
405
399
}
406
400
407
401
llvm::Type *returnTy = llvm::StructType::get (IGM.getLLVMContext (), returnTys);
408
-
409
- auto fnTy = llvm::FunctionType::get (returnTy, argTys, /* vararg*/ false );
410
- auto fn = llvm::Function::Create (fnTy, llvm::GlobalValue::PrivateLinkage,
411
- llvm::Twine (name), IGM.getModule ());
412
- fn->setAttributes (IGM.constructInitialAttributes ());
413
-
414
- IRGenFunction IGF (IGM, fn);
415
- if (IGM.DebugInfo )
416
- IGM.DebugInfo ->emitArtificialFunction (IGF, fn);
417
- Explosion args = IGF.collectParameters ();
418
-
419
- auto value = args.claimNext ();
420
- auto ref = args.claimNext ();
421
- auto failBB = IGF.createBasicBlock (" fail" );
422
- auto conformsToProtocol = IGM.getConformsToProtocolFn ();
423
-
424
- Explosion rets;
425
- rets.add (value);
426
-
427
- // Check the class constraint if necessary.
428
- if (checkSuperclassConstraint) {
429
- auto superclassMetadata = args.claimNext ();
430
- auto castFn = IGF.IGM .getDynamicCastMetatypeFn ();
431
- auto castResult = IGF.Builder .CreateCall (castFn, {ref,
432
- superclassMetadata});
433
-
434
- auto cc = cast<llvm::Function>(castFn)->getCallingConv ();
435
-
436
- // FIXME: Eventually, we may want to throw.
437
- castResult->setCallingConv (cc);
438
- castResult->setDoesNotThrow ();
439
402
440
- auto isClass = IGF.Builder .CreateICmpNE (
441
- castResult,
442
- llvm::ConstantPointerNull::get (IGF.IGM .TypeMetadataPtrTy ));
403
+ return IGM.getOrCreateHelperFunction (name, returnTy, argTys,
404
+ [&](IRGenFunction &IGF) {
405
+ Explosion args = IGF.collectParameters ();
406
+
407
+ auto value = args.claimNext ();
408
+ auto ref = args.claimNext ();
409
+ auto failBB = IGF.createBasicBlock (" fail" );
410
+ auto conformsToProtocol = IGM.getConformsToProtocolFn ();
411
+
412
+ Explosion rets;
413
+ rets.add (value);
414
+
415
+ // Check the class constraint if necessary.
416
+ if (checkSuperclassConstraint) {
417
+ auto superclassMetadata = args.claimNext ();
418
+ auto castFn = IGF.IGM .getDynamicCastMetatypeFn ();
419
+ auto castResult = IGF.Builder .CreateCall (castFn, {ref,
420
+ superclassMetadata});
421
+
422
+ auto cc = cast<llvm::Function>(castFn)->getCallingConv ();
423
+
424
+ // FIXME: Eventually, we may want to throw.
425
+ castResult->setCallingConv (cc);
426
+ castResult->setDoesNotThrow ();
427
+
428
+ auto isClass = IGF.Builder .CreateICmpNE (
429
+ castResult,
430
+ llvm::ConstantPointerNull::get (IGF.IGM .TypeMetadataPtrTy ));
431
+
432
+ auto contBB = IGF.createBasicBlock (" cont" );
433
+ IGF.Builder .CreateCondBr (isClass, contBB, failBB);
434
+ IGF.Builder .emitBlock (contBB);
435
+ } else if (checkClassConstraint) {
436
+ auto isClass = IGF.Builder .CreateCall (IGM.getIsClassTypeFn (), ref);
437
+ auto contBB = IGF.createBasicBlock (" cont" );
438
+ IGF.Builder .CreateCondBr (isClass, contBB, failBB);
439
+ IGF.Builder .emitBlock (contBB);
440
+ }
443
441
444
- auto contBB = IGF.createBasicBlock (" cont" );
445
- IGF.Builder .CreateCondBr (isClass, contBB, failBB);
446
- IGF.Builder .emitBlock (contBB);
447
- } else if (checkClassConstraint) {
448
- auto isClass = IGF.Builder .CreateCall (IGM.getIsClassTypeFn (), ref);
449
- auto contBB = IGF.createBasicBlock (" cont" );
450
- IGF.Builder .CreateCondBr (isClass, contBB, failBB);
451
- IGF.Builder .emitBlock (contBB);
452
- }
442
+ // Look up each protocol conformance we want.
443
+ for (unsigned i = 0 ; i < numProtocols; ++i) {
444
+ auto proto = args.claimNext ();
445
+ auto witness = IGF.Builder .CreateCall (conformsToProtocol, {ref, proto});
446
+ auto isNull = IGF.Builder .CreateICmpEQ (witness,
447
+ llvm::ConstantPointerNull::get (IGM.WitnessTablePtrTy ));
448
+ auto contBB = IGF.createBasicBlock (" cont" );
449
+ IGF.Builder .CreateCondBr (isNull, failBB, contBB);
450
+
451
+ IGF.Builder .emitBlock (contBB);
452
+ rets.add (witness);
453
+ }
453
454
454
- // Look up each protocol conformance we want.
455
- for (unsigned i = 0 ; i < numProtocols; ++i) {
456
- auto proto = args.claimNext ();
457
- auto witness = IGF.Builder .CreateCall (conformsToProtocol, {ref, proto});
458
- auto isNull = IGF.Builder .CreateICmpEQ (witness,
459
- llvm::ConstantPointerNull::get (IGM.WitnessTablePtrTy ));
460
- auto contBB = IGF.createBasicBlock (" cont" );
461
- IGF.Builder .CreateCondBr (isNull, failBB, contBB);
455
+ // If we succeeded, return the witnesses.
456
+ IGF.emitScalarReturn (returnTy, rets);
462
457
463
- IGF.Builder .emitBlock (contBB);
464
- rets.add (witness);
465
- }
466
-
467
- // If we succeeded, return the witnesses.
468
- IGF.emitScalarReturn (returnTy, rets);
469
-
470
- // If we failed, return nil or trap.
471
- IGF.Builder .emitBlock (failBB);
472
- switch (mode) {
473
- case CheckedCastMode::Conditional: {
474
- auto null = llvm::ConstantStruct::getNullValue (returnTy);
475
- IGF.Builder .CreateRet (null);
476
- break ;
477
- }
458
+ // If we failed, return nil or trap.
459
+ IGF.Builder .emitBlock (failBB);
460
+ switch (mode) {
461
+ case CheckedCastMode::Conditional: {
462
+ auto null = llvm::ConstantStruct::getNullValue (returnTy);
463
+ IGF.Builder .CreateRet (null);
464
+ break ;
465
+ }
478
466
479
- case CheckedCastMode::Unconditional: {
480
- IGF.emitTrap (" type cast failed" , /* EmitUnreachable=*/ true );
481
- break ;
482
- }
483
- }
484
-
485
- return fn;
467
+ case CheckedCastMode::Unconditional: {
468
+ IGF.emitTrap (" type cast failed" , /* EmitUnreachable=*/ true );
469
+ break ;
470
+ }
471
+ }
472
+ });
486
473
}
487
474
488
475
llvm::Value *irgen::emitMetatypeToAnyObjectDowncast (IRGenFunction &IGF,
0 commit comments