void modify_branch_so_that_state_access_is_indexed(Branch* branch, int index) { Term* stateInput = find_state_input(branch); if (stateInput == NULL) return; // If the state output is connected directly to state input, then do nothing. Term* stateOutput = find_state_output(branch); if (stateOutput->input(0) == stateInput) return; Term* unpackList = apply(branch, FUNCS.unpack_state_from_list, TermList(stateInput)); unpackList->setIntProp("index", index); move_after_inputs(unpackList); for (int i=0; i < stateInput->users.length(); i++) { Term* term = stateInput->users[i]; if (term == unpackList) continue; remap_pointers_quick(term, stateInput, unpackList); } Term* stateResult = stateOutput->input(0); ca_assert(stateResult != NULL); Term* packList = apply(branch, FUNCS.pack_state_to_list, TermList(stateInput, stateResult)); packList->setIntProp("index", index); packList->setBoolProp("final", true); set_input(stateOutput, 0, packList); move_after(packList, stateResult); }
void for_loop_fix_state_input(Branch* contents) { // This function will look at the state access inside for-loop contents. // If there's state, the default building functions will have created // terms that look like this: // // input() :state -> unpack_state -> pack_state -> output() :state // // We want each loop iteration to have its own state container. So we'll // insert pack/unpack_state_list_n terms so that each iteration accesses // state from a list. The result will look like: // // input() :state -> unpack_state_list_n(index) -> unpack_state -> pack_state // -> pack_state_list_n(index) -> output() :state // First insert the unpack_state_list_n call Term* stateInput = find_state_input(contents); // Nothing to do if there's no state input if (stateInput == NULL) return; // Nothing to do if unpack_state_list_n term already exists if (find_user_with_function(stateInput, FUNCS.unpack_state_list_n) != NULL) return; Term* unpackState = find_user_with_function(stateInput, FUNCS.unpack_state); ca_assert(unpackState != NULL); Term* index = for_loop_find_index(contents); Term* unpackStateList = apply(contents, FUNCS.unpack_state_list_n, TermList(stateInput, index)); transfer_users(stateInput, unpackStateList); move_before(unpackStateList, unpackState); set_input(unpackState, 0, unpackStateList); // Now insert the pack_state_list_n call Term* stateResult = find_open_state_result(contents, contents->length()); Term* packStateList = apply(contents, FUNCS.pack_state_list_n, TermList(stateInput, stateResult, index)); packStateList->setBoolProp("final", true); move_after(packStateList, stateResult); // Make sure the state output uses this result Term* stateOutput = append_state_output(contents); set_input(stateOutput, 0, packStateList); }
Term* find_or_create_state_input(Branch* branch) { // check if there is already a stateful input Term* existing = find_state_input(branch); if (existing != NULL) return existing; // None yet, insert one Term* input = append_state_input(branch); // Add a final pack_state call too append_final_pack_state(branch); return input; }
Term* find_active_state_container(Branch* branch) { // Check if there is already a stateful input // Special case for if-block: Look for a unpack_state_from_list call if (is_case_branch(branch)) { Term* existing = find_term_with_function(branch, FUNCS.unpack_state_from_list); if (existing != NULL) return existing; } // Special case for for-block: Look for a unpack_state_from_list call Term* existing = find_state_input(branch); if (existing != NULL) return existing; return NULL; }