| 158 | } |
| 159 | |
| 160 | Status FillFunctionBody( |
| 161 | const string& fn_name, const NodeNameMapping& node_names, |
| 162 | const std::vector<const Node*>& body_nodes, |
| 163 | const std::unordered_map<string, string>& tensor_renaming, |
| 164 | FunctionDef* fdef) { |
| 165 | std::unordered_set<string> func_attr_names; |
| 166 | for (const auto& func_attr : fdef->signature().attr()) { |
| 167 | func_attr_names.insert(func_attr.name()); |
| 168 | } |
| 169 | |
| 170 | std::vector<const Edge*> in_edges; |
| 171 | std::vector<const Edge*> control_edges; |
| 172 | for (const Node* node : body_nodes) { |
| 173 | NodeDef* node_def = fdef->add_node_def(); |
| 174 | // First, copy the node_def as is. We will patch it next. |
| 175 | *node_def = node->def(); |
| 176 | if (!node->assigned_device_name().empty()) { |
| 177 | node_def->set_device(node->assigned_device_name()); |
| 178 | } |
| 179 | node_def->set_name(node_names.Lookup(node->name())); |
| 180 | |
| 181 | // Input names must be set based on nested names in tensor_renaming. |
| 182 | // Clear the flat input names we got from the original node_def |
| 183 | // from the graph. |
| 184 | node_def->clear_input(); |
| 185 | |
| 186 | // Collect regular and control inputs. Regular inputs are indexed |
| 187 | // by the index at which they come into the `node`. Control inputs |
| 188 | // don't follow any order, and we sort control inputs to make sure generated |
| 189 | // NodeDef is deterministic. |
| 190 | in_edges.clear(); |
| 191 | in_edges.resize(node->num_inputs(), nullptr); |
| 192 | control_edges.clear(); |
| 193 | for (const Edge* edge : node->in_edges()) { |
| 194 | if (edge->src()->IsSource()) continue; |
| 195 | if (edge->IsControlEdge()) { |
| 196 | control_edges.push_back(edge); |
| 197 | } else { |
| 198 | in_edges[edge->dst_input()] = edge; |
| 199 | } |
| 200 | } |
| 201 | std::sort(control_edges.begin(), control_edges.end(), |
| 202 | [](const Edge* a, const Edge* b) { |
| 203 | return a->src()->name() < b->src()->name(); |
| 204 | }); |
| 205 | |
| 206 | // Add regular inputs. |
| 207 | for (size_t i = 0; i < in_edges.size(); ++i) { |
| 208 | const Edge* edge = in_edges[i]; |
| 209 | string original_input_name; |
| 210 | if (edge == nullptr) { |
| 211 | // A backedge might not appear as a regular Edge, but be only present |
| 212 | // in the node_def. Such edges are referred to as requested_inputs(). |
| 213 | if (i >= node->requested_inputs().size()) { |
| 214 | return InvalidArgument( |
| 215 | "Graph to be converted to function appears to be malformed. ", |
| 216 | "Node ", node->name(), " is missing input edge ", i); |
| 217 | } |
no test coverage detected