@@ -357,7 +357,7 @@ llvm::Value *irgen::emitReferenceToObjCProtocol(IRGenFunction &IGF,
357357// / The function's output type is (value, witnessTable...)
358358// /
359359// / The value is NULL if the cast failed.
360- static llvm::Function *
360+ static llvm::Constant *
361361emitExistentialScalarCastFn (IRGenModule &IGM,
362362 unsigned numProtocols,
363363 CheckedCastMode mode,
@@ -385,13 +385,7 @@ emitExistentialScalarCastFn(IRGenModule &IGM,
385385 }
386386 }
387387
388- // See if we already defined this function.
389-
390- if (auto fn = IGM.Module .getFunction (name))
391- return fn;
392-
393388 // Build the function type.
394-
395389 llvm::SmallVector<llvm::Type *, 4 > argTys;
396390 llvm::SmallVector<llvm::Type *, 4 > returnTys;
397391 argTys.push_back (IGM.Int8PtrTy );
@@ -405,84 +399,77 @@ emitExistentialScalarCastFn(IRGenModule &IGM,
405399 }
406400
407401 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 ();
439402
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+ }
443441
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+ }
453454
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);
462457
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+ }
478466
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+ });
486473}
487474
488475llvm::Value *irgen::emitMetatypeToAnyObjectDowncast (IRGenFunction &IGF,
0 commit comments