pub unsafe fn gen_upsert(
        &mut self,
        builder: LLVMBuilderRef,
        intrinsics: &mut Intrinsics,
        dict: LLVMValueRef,
        key: LLVMValueRef,
        hash: LLVMValueRef,
        default: LLVMValueRef,
        run: LLVMValueRef,
    ) -> WeldResult<LLVMValueRef> {
        if self.upsert.is_none() {
            let mut arg_tys = [
                self.dict_ty,
                LLVMPointerType(self.slot_ty.key_ty, 0),
                self.hash_type(),
                self.slot_ty.val_ty,
                self.run_handle_type(),
            ];

            // Generated Code:
            //
            // slot_array = slot.slot_array
            // capacity = slot.capacity
            // slot = slot_for_key(slot, capacity, hash, key)
            //
            // br slot.filled ? return : set_default
            //
            // set_default:
            // key = load keypointer
            // slot.key = key           |
            // slot.hash = hash         |-- slot.init
            // slot.filled = filled     |
            // dict.size = size + 1
            // resized = dict.resize(dict)
            // br resized ? reacquire : upsert
            //
            // reacquire:
            // resized_slot = slot_for_key(slot, capacity, hash, key)
            // br upsert
            //
            // upsert:
            // upsert_slot = phi [ slot, setdefault ] [ resized_slot, require ]
            // upsert_slot.value = default
            // br return
            //
            // return:
            // return_slot = phi [ slot, entry ] [ upsert_slot, upsert ]

            let ret_ty = LLVMPointerType(self.slot_ty.slot_ty, 0);

            let name = format!("{}.upsert", self.name);
            let (function, builder, entry_block) = self.define_function(ret_ty, &mut arg_tys, name);

            LLVMExtAddAttrsOnParameter(self.context, function, &[NoAlias, NoCapture, NonNull], 0);
            LLVMExtAddAttrsOnParameter(
                self.context,
                function,
                &[NoAlias, NoCapture, NonNull, ReadOnly],
                1,
            );
            LLVMExtAddAttrsOnParameter(self.context, function, &[NoAlias, NoCapture, NonNull], 4);

            let set_default_block =
                LLVMAppendBasicBlockInContext(self.context(), function, c_str!(""));
            let reacquire_slot_block =
                LLVMAppendBasicBlockInContext(self.context(), function, c_str!(""));
            let upsert_block = LLVMAppendBasicBlockInContext(self.context(), function, c_str!(""));
            let return_block = LLVMAppendBasicBlockInContext(self.context(), function, c_str!(""));

            let dict = LLVMGetParam(function, 0);
            let key = LLVMGetParam(function, 1);
            let hash = LLVMGetParam(function, 2);
            let default = LLVMGetParam(function, 3);
            let run = LLVMGetParam(function, 4);

            let slot_array = self.slot_array(builder, dict);
            let capacity = self.capacity(builder, dict);
            let slot = self.gen_slot_for_key(builder, slot_array, capacity, hash, key);

            let filled = self.slot_ty.filled(builder, slot);
            LLVMBuildCondBr(builder, filled, return_block, set_default_block);

            LLVMPositionBuilderAtEnd(builder, set_default_block);
            let key_loaded = self.load(builder, key).unwrap();

            self.slot_ty.init(builder, slot, key_loaded, hash, default);

            let size_pointer = LLVMBuildStructGEP(builder, dict, SIZE_INDEX, c_str!(""));
            let size = self.load(builder, size_pointer).unwrap();
            let new_size = LLVMBuildNSWAdd(builder, size, self.i64(1), c_str!(""));
            LLVMBuildStore(builder, new_size, size_pointer);

            // Check for resize.
            let resized = self.gen_resize(builder, intrinsics, dict, run);
            LLVMBuildCondBr(builder, resized, reacquire_slot_block, upsert_block);

            LLVMPositionBuilderAtEnd(builder, reacquire_slot_block);
            // Builder was resized - we need to reacquire the slot.
            let resized_slot_array = self.slot_array(builder, dict);
            let resized_capacity = self.capacity(builder, dict);
            let resized_slot =
                self.gen_slot_for_key(builder, resized_slot_array, resized_capacity, hash, key);

            LLVMBuildBr(builder, upsert_block);
            LLVMPositionBuilderAtEnd(builder, upsert_block);

            let slot_pointer_ty = LLVMPointerType(self.slot_ty.slot_ty, 0);

            let upsert_slot = LLVMBuildPhi(builder, slot_pointer_ty, c_str!(""));
            let value_pointer = self.slot_ty.value(builder, upsert_slot);
            LLVMBuildStore(builder, default, value_pointer);
            LLVMBuildBr(builder, return_block);

            LLVMPositionBuilderAtEnd(builder, return_block);
            let return_slot = LLVMBuildPhi(builder, ret_ty, c_str!(""));
            LLVMBuildRet(builder, return_slot);

            // Set the PHI values.
            let mut blocks = [set_default_block, reacquire_slot_block];
            let mut values = [slot, resized_slot];
            LLVMAddIncoming(
                upsert_slot,
                values.as_mut_ptr(),
                blocks.as_mut_ptr(),
                values.len() as u32,
            );

            let mut blocks = [entry_block, upsert_block];
            let mut values = [slot, upsert_slot];
            LLVMAddIncoming(
                return_slot,
                values.as_mut_ptr(),
                blocks.as_mut_ptr(),
                values.len() as u32,
            );

            self.upsert = Some(function);
            LLVMDisposeBuilder(builder);
        }

        let mut args = [dict, key, hash, default, run];
        Ok(LLVMBuildCall(
            builder,
            self.upsert.unwrap(),
            args.as_mut_ptr(),
            args.len() as u32,
            c_str!(""),
        ))
    }
Returns the pointer to the slot for a key.

If the key does not exist, a slot is initialized for the key, and a default value is
inserted into the slot. The slot is then returned. The insertion may cause the dictionary
to be resized.
weld/src/codegen/llvm2/dict.rs