@@ -625,9 +625,12 @@ struct Allocator {
625625 Allocate = 1 ,
626626 Deallocate = 2 ,
627627 };
628+ constexpr static std::array<Field, 3 > allFields () {
629+ return {Field::Flags, Field::Allocate, Field::Deallocate};
630+ }
628631 Kind kind;
629- Field (Kind kind) : kind(kind) {}
630- operator Kind () { return kind; }
632+ constexpr Field (Kind kind) : kind(kind) {}
633+ constexpr operator Kind () { return kind; }
631634
632635 llvm::Type *getType (IRGenModule &IGM) {
633636 switch (kind) {
@@ -660,6 +663,16 @@ struct Allocator {
660663 }
661664 }
662665
666+ bool isFunctionPointer () {
667+ switch (kind) {
668+ case Flags:
669+ return false ;
670+ case Field::Allocate:
671+ case Field::Deallocate:
672+ return true ;
673+ }
674+ }
675+
663676 llvm::FunctionType *getFunctionType (IRGenModule &IGM) {
664677 switch (kind) {
665678 case Flags:
@@ -693,8 +706,41 @@ struct Allocator {
693706 return IGM.getOptions ().PointerAuth .CoroDeallocationFunction ;
694707 }
695708 }
709+
710+ const PointerAuthEntity getEntity (IRGenModule &IGM) {
711+ switch (kind) {
712+ case Flags:
713+ llvm_unreachable (" no entity" );
714+ case Field::Allocate:
715+ return PointerAuthEntity::Special::CoroAllocationFunction;
716+ case Field::Deallocate:
717+ return PointerAuthEntity::Special::CoroDeallocationFunction;
718+ }
719+ }
696720 };
697721
722+ static void visitFields (llvm::function_ref<void (Field)> visitor) {
723+ for (auto field : Field::allFields ()) {
724+ visitor (field);
725+ }
726+ }
727+
728+ static ConstantInitFuture
729+ buildStruct (ConstantInitBuilder &builder, IRGenModule &IGM,
730+ llvm::function_ref<llvm::Constant *(Field)> valueForField) {
731+ auto allocator = builder.beginStruct (IGM.CoroAllocatorTy );
732+ visitFields ([&](auto field) {
733+ auto *value = valueForField (field);
734+ if (!field.isFunctionPointer ()) {
735+ allocator.add (value);
736+ return ;
737+ }
738+ allocator.addSignedPointer (value, field.getSchema (IGM),
739+ field.getEntity (IGM));
740+ });
741+ return allocator.finishAndCreateFuture ();
742+ }
743+
698744 llvm::Value *address;
699745 IRGenFunction &IGF;
700746
@@ -904,17 +950,22 @@ static llvm::Constant *getAddrOfGlobalCoroAllocator(
904950 auto taskAllocator = IGM.getOrCreateLazyGlobalVariable (
905951 entity,
906952 [&](ConstantInitBuilder &builder) -> ConstantInitFuture {
907- auto allocator = builder.beginStruct (IGM.CoroAllocatorTy );
908- auto flags = CoroAllocatorFlags (kind);
909- flags.setShouldDeallocateImmediately (shouldDeallocateImmediately);
910- allocator.addInt32 (flags.getOpaqueValue ());
911- allocator.addSignedPointer (
912- allocFn, IGM.getOptions ().PointerAuth .CoroAllocationFunction ,
913- PointerAuthEntity::Special::CoroAllocationFunction);
914- allocator.addSignedPointer (
915- deallocFn, IGM.getOptions ().PointerAuth .CoroDeallocationFunction ,
916- PointerAuthEntity::Special::CoroDeallocationFunction);
917- return allocator.finishAndCreateFuture ();
953+ return Allocator::buildStruct (
954+ builder, IGM, [&](auto field) -> llvm::Constant * {
955+ switch (field) {
956+ case Allocator::Field::Flags: {
957+ auto flags = CoroAllocatorFlags (kind);
958+ flags.setShouldDeallocateImmediately (
959+ shouldDeallocateImmediately);
960+ return llvm::ConstantInt::get (IGM.Int32Ty ,
961+ flags.getOpaqueValue ());
962+ }
963+ case Allocator::Field::Allocate:
964+ return allocFn;
965+ case Allocator::Field::Deallocate:
966+ return deallocFn;
967+ }
968+ });
918969 },
919970 [&](llvm::GlobalVariable *var) { var->setConstant (true ); });
920971 return taskAllocator;
0 commit comments