Reland "[ir-to-program] Fix issue converting int32_t min."

This reverts commit d386c8472b73f0e3255c705fffcd4ecf3bbff145.

Reason for revert: Fixed UBSAN issue

Original change's description:
> Revert "[ir-to-program] Fix issue converting int32_t min."
>
> This reverts commit 2e5296af62b62fee638a3d5ff5f0ae95e683d774.
>
> Reason for revert: Breaking UBSAN
>
> Original change's description:
> > [ir-to-program] Fix issue converting int32_t min.
> >
> > When converting an `i32` minimum value from IR back to WGSL, we can't
> > just emit the number as it won't parse in WGSL. We need to emit it as an
> > abstract and convert that to an i32 value.
> >
> > Change-Id: I173d1a78f78c8af8ab9791c8b72f879b67520276
> > Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/252954
> > Commit-Queue: David Neto <dneto@google.com>
> > Reviewed-by: David Neto <dneto@google.com>
> > Commit-Queue: dan sinclair <dsinclair@chromium.org>
>
> TBR=dneto@google.com,dsinclair@chromium.org,dawn-scoped@luci-project-accounts.iam.gserviceaccount.com
>
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Change-Id: If3228b76993f181b31573154811d2091ca26ef42
> Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/253234
> Reviewed-by: dan sinclair <dsinclair@chromium.org>
> Reviewed-by: Kai Ninomiya <kainino@chromium.org>
> Commit-Queue: Kai Ninomiya <kainino@chromium.org>

# Not skipping CQ checks because this is a reland.

Change-Id: Icc8a60915c71faccc882a8afef2aae826aafdfa2
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/253315
Auto-Submit: dan sinclair <dsinclair@chromium.org>
Commit-Queue: David Neto <dneto@google.com>
Reviewed-by: David Neto <dneto@google.com>
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
index 48be5d6..a9078b7 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
+++ b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
@@ -27,6 +27,7 @@
 
 #include "src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.h"
 
+#include <limits>
 #include <string>
 #include <tuple>
 #include <utility>
@@ -962,7 +963,15 @@
         };
         return tint::Switch(
             c->Type(),  //
-            [&](const core::type::I32*) { return b.Expr(c->ValueAs<i32>()); },
+            [&](const core::type::I32*) -> const ast::Expression* {
+                auto val = c->ValueAs<i32>();
+                if (val == std::numeric_limits<int32_t>::min()) {
+                    return b.Call(b.ty.i32(), b.create<ast::IntLiteralExpression>(
+                                                  val, ast::IntLiteralExpression::Suffix::kNone));
+                }
+
+                return b.Expr(val);
+            },
             [&](const core::type::U32*) { return b.Expr(c->ValueAs<u32>()); },
             [&](const core::type::F32*) { return b.Expr(c->ValueAs<f32>()); },
             [&](const core::type::F16*) {
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
index 95d0c11..d90dc0b 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
+++ b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
@@ -27,6 +27,7 @@
 
 // GEN_BUILD:CONDITION(tint_build_wgsl_writer)
 
+#include <limits>
 #include <sstream>
 #include <string>
 
@@ -117,6 +118,18 @@
 )");
 }
 
+TEST_F(IRToProgramTest, SingleFunction_Return_min_i32) {
+    auto* fn = b.Function("f", ty.i32());
+
+    fn->Block()->Append(b.Return(fn, i32(std::numeric_limits<int32_t>::min())));
+
+    EXPECT_WGSL(R"(
+fn f() -> i32 {
+  return i32(-2147483648);
+}
+)");
+}
+
 TEST_F(IRToProgramTest, SingleFunction_Parameters) {
     auto* fn = b.Function("f", ty.i32());
     auto* i = b.FunctionParam("i", ty.i32());