internal static void BuildNotifierReaderPromisePollFunction(FunctionModuleContext moduleContext, NIType signature, LLVMValueRef notifierReaderPromisePollFunction)
        {
            NIType notifierReaderPromiseType = signature.GetGenericParameters().ElementAt(0),
                   valueType = notifierReaderPromiseType.GetGenericParameters().ElementAt(0);
            LLVMTypeRef optionValueLLVMType       = moduleContext.LLVMContext.AsLLVMType(valueType.CreateOption()),
                        optionOptionValueLLVMType = moduleContext.LLVMContext.AsLLVMType(valueType.CreateOption().CreateOption());

            LLVMBasicBlockRef entryBlock       = notifierReaderPromisePollFunction.AppendBasicBlock("entry"),
                              writerReadyBlock = notifierReaderPromisePollFunction.AppendBasicBlock("writerReady"),
                              writerDroppedWithoutValueBlock = notifierReaderPromisePollFunction.AppendBasicBlock("writerDroppedWithoutValue"),
                              writerDroppedWithValueBlock    = notifierReaderPromisePollFunction.AppendBasicBlock("writerDroppedWithValue"),
                              endBlock = notifierReaderPromisePollFunction.AppendBasicBlock("end");
            var builder = moduleContext.LLVMContext.CreateIRBuilder();

            builder.PositionBuilderAtEnd(entryBlock);
            LLVMValueRef notifierReaderPromisePtr = notifierReaderPromisePollFunction.GetParam(0u),
                         waker                 = notifierReaderPromisePollFunction.GetParam(1u),
                         pollResultPtr         = notifierReaderPromisePollFunction.GetParam(2u),
                         notifierReaderPromise = builder.CreateLoad(notifierReaderPromisePtr, "notifierReaderPromise"),
                         refCountPtr           = builder.CreateExtractValue(notifierReaderPromise, 0u, "refCountPtr"),
                         sharedDataPtr         = builder.CreateStructGEP(refCountPtr, 1u, "sharedDataPtr"),
                         wakerPtr              = builder.CreateStructGEP(sharedDataPtr, SharedDataWakerFieldIndex, "wakerPtr"),
                         statePtr              = builder.CreateStructGEP(sharedDataPtr, SharedDataStateFieldIndex, "statePtr");

            builder.CreateStore(waker, wakerPtr);
            // This is Release because it needs the writer thread to observe the waker store,
            // and Acquire because it may need to observe the writer thread's value store.
            LLVMValueRef oldState = builder.CreateAtomicRMW(
                LLVMAtomicRMWBinOp.LLVMAtomicRMWBinOpOr,
                statePtr,
                moduleContext.LLVMContext.AsLLVMValue(ReaderWaitingForValue),
                LLVMAtomicOrdering.LLVMAtomicOrderingAcquireRelease,
                false),
                         oldWriterState    = builder.CreateAnd(oldState, moduleContext.LLVMContext.AsLLVMValue(WriterStateMask), "oldWriterState");
            LLVMValueRef writerStateSwitch = builder.CreateSwitch(oldWriterState, writerReadyBlock, 2u);

            writerStateSwitch.AddCase(moduleContext.LLVMContext.AsLLVMValue(WriterDroppedWithoutValue), writerDroppedWithoutValueBlock);
            writerStateSwitch.AddCase(moduleContext.LLVMContext.AsLLVMValue(WriterDroppedWithValue), writerDroppedWithValueBlock);

            builder.PositionBuilderAtEnd(writerReadyBlock);
            // output None
            builder.CreateStore(LLVMTypeRef.ConstNull(optionOptionValueLLVMType), pollResultPtr);
            builder.CreateRetVoid();

            builder.PositionBuilderAtEnd(writerDroppedWithoutValueBlock);
            // output Some(None)
            builder.CreateStore(moduleContext.LLVMContext.BuildOptionValue(builder, optionOptionValueLLVMType, LLVMTypeRef.ConstNull(optionValueLLVMType)), pollResultPtr);
            builder.CreateBr(endBlock);

            builder.PositionBuilderAtEnd(writerDroppedWithValueBlock);
            // output Some(Some(value))
            LLVMValueRef valuePtr = builder.CreateStructGEP(sharedDataPtr, SharedDataValueFieldIndex, "valuePtr"),
                         value    = builder.CreateLoad(valuePtr, "value");

            builder.CreateStore(moduleContext.LLVMContext.BuildOptionValue(builder, optionOptionValueLLVMType, moduleContext.LLVMContext.BuildOptionValue(builder, optionValueLLVMType, value)), pollResultPtr);
            builder.CreateBr(endBlock);

            builder.PositionBuilderAtEnd(endBlock);
            LLVMValueRef decrementRefCountFunction = GetDecrementRefCountFunction(moduleContext, valueType.CreateNotifierSharedDataType());

            builder.CreateCall(decrementRefCountFunction, new LLVMValueRef[] { refCountPtr }, string.Empty);
            builder.CreateRetVoid();
        }