Repository: carbon-language/carbon-lang
File: toolchain/sem_ir/inst_namer.cpp (C++)

Code before:
      }
      break;
    case BranchWithArg::Kind:
      if (branch_with_arg) {
        arg = *branch_with_arg;
      }
      break;
    default:
      break;
  }
  return llvm::formatv("{0}.{1}", prefix, arg);
}

// Finds and adds a suitable block label for the given SemIR instruction that
// represents some kind of branch.
auto InstNamer::AddBlockLabel(ScopeId scope_id, LocId loc_id, AnyBranch branch)
    -> void {
  loc_id = sem_ir_->insts().GetCanonicalLocId(loc_id);
  if (!loc_id.node_id().has_value()) {
    AddBlockLabel(scope_id, branch.target_id, "", loc_id);
    return;
  }
  std::string name;
  switch (sem_ir_->parse_tree().node_kind(loc_id.node_id())) {
    case Parse::NodeKind::IfExprIf:
      name = BranchKindToName("if.expr", branch.kind, "then", "else", "result");
      break;

    case Parse::NodeKind::IfCondition:
      name = BranchKindToName("if", branch.kind, "then", "else",
                              /*branch_with_arg=*/std::nullopt);
      break;

    case Parse::NodeKind::IfStatement:
      name = "if.done";
      break;

    case Parse::NodeKind::ShortCircuitOperandAnd:
      name = BranchKindToName("and", branch.kind, "rhs",
                              /*branch=*/std::nullopt, "result");
      break;
    case Parse::NodeKind::ShortCircuitOperandOr:
      name = BranchKindToName("or", branch.kind, "rhs", /*branch=*/std::nullopt,
                              "result");
      break;

    case Parse::NodeKind::WhileConditionStart:
      name = "while.cond";
      break;

    case Parse::NodeKind::WhileCondition:

Review comment (suggestion):
I think I'd want a comment on each of these last three arguments, not just the `nullopt` arguments, to understand what each of these calls means. The order of the three different kinds of branch seems arbitrary and I'd otherwise need to look it up to understand the call.

If we want argument labels, maybe we could avoid the comments and the `nullopt`s and pass a struct:
```
struct BranchNames {
  std::optional<const char*> branch_if = std::nullopt;
  std::optional<const char*> branch = std::nullopt;
  std::optional<const char*> branch_with_arg = std::nullopt;
};
// ...
name = BranchKindToName("if.expr", branch.kind, {.branch_if = "then", .branch = "else", .branch_with_arg = "result"});
````

Code after:
        return {{.prefix = "if", .branch = "done"}};

      case Parse::NodeKind::ShortCircuitOperandAnd:
        return {
            {.prefix = "and", .branch_if = "rhs", .branch_with_arg = "result"}};
      case Parse::NodeKind::ShortCircuitOperandOr:
        return {
            {.prefix = "or", .branch_if = "rhs", .branch_with_arg = "result"}};

      case Parse::NodeKind::WhileConditionStart:
        return {{.prefix = "while", .branch = "cond"}};

      case Parse::NodeKind::WhileCondition:
        return {{.prefix = "while", .branch_if = "body", .branch = "done"}};

      default:
        return std::nullopt;
    }
  }

  // Returns the provided suffix for the instruction kind, or an empty string.
  auto GetSuffix(InstKind inst_kind) -> llvm::StringLiteral {
    switch (inst_kind) {
      case BranchIf::Kind:
        return branch_if;
      case Branch::Kind:
        return branch;
      case BranchWithArg::Kind:
        return branch_with_arg;
      default:
        return "";
    }
  }

  // The kind of branch, based on the node kind.
  llvm::StringLiteral prefix;

  // For labeling branch instruction kinds. Only expected kinds need a value;
  // the empty string is for unexpected kinds.
  llvm::StringLiteral branch_if = "";
  llvm::StringLiteral branch = "";
  llvm::StringLiteral branch_with_arg = "";
};

// Finds and adds a suitable block label for the given SemIR instruction that
// represents some kind of branch.
auto InstNamer::AddBlockLabel(ScopeId scope_id, LocId loc_id, AnyBranch branch)
    -> void {
  std::string label;

  loc_id = sem_ir_->insts().GetCanonicalLocId(loc_id);