Browse Source

chore: cherry-pick 3 changes from 0-M125 (#42221)

* chore: [28-x-y] cherry-pick 3 changes from 0-M125

* 6503a987d966 from v8
* 2a434fd0af6b from DirectXShaderCompiler
* 03609e39be8c from chromium

* chore: update patches

---------

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
Pedro Pontes 11 months ago
parent
commit
db688056d8

+ 1 - 0
patches/DirectXShaderCompiler/.patches

@@ -2,3 +2,4 @@ fix_hlmatrixlowerpass_leaving_call_to_dangling_functionval.patch
 cherry-pick-a65e511a14b4.patch
 cherry-pick-bc18aec94c82.patch
 cherry-pick-bd7aa9779873.patch
+cherry-pick-2a434fd0af6b.patch

+ 419 - 0
patches/DirectXShaderCompiler/cherry-pick-2a434fd0af6b.patch

@@ -0,0 +1,419 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Antonio Maiorano <[email protected]>
+Date: Wed, 8 May 2024 13:38:38 -0400
+Subject: Fix invalid IR from scalarrepl-param-hlsl in ReplaceConstantWithInst
+ (#6556)
+
+ReplaceConstantWithInst(C, V) replaces uses of C in the current function
+with V. If such a use C is an instruction I, the it replaces uses of C
+in I with V. However, this function did not make sure to only perform
+this replacement if V dominates I. As a result, it may end up replacing
+uses of C in instructions before the definition of V.
+
+The fix is to lazily compute the dominator tree in
+ReplaceConstantWithInst so that we can guard the replacement with that
+dominance check.
+
+Bug: chromium:333414294
+Change-Id: I2a8bf64094298b49a1887cc7c1334e91a745c396
+Reviewed-on: https://chromium-review.googlesource.com/c/external/github.com/microsoft/DirectXShaderCompiler/+/5525429
+Reviewed-by: James Price <[email protected]>
+Reviewed-by: dan sinclair <[email protected]>
+
+diff --git a/lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp b/lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp
+index bd429ae98b0e11bbb2b95c68392b82eb222f64a4..1ef9a002a46f3acd14be6e1cb456efcbd398b416 100644
+--- a/lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp
++++ b/lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp
+@@ -3271,15 +3271,34 @@ bool SROA_Helper::DoScalarReplacement(GlobalVariable *GV,
+   return true;
+ }
+ 
+-static void ReplaceConstantWithInst(Constant *C, Value *V,
++// Replaces uses of constant C in the current function
++// with V, when those uses are dominated by V.
++// Returns true if it was completely replaced.
++static bool ReplaceConstantWithInst(Constant *C, Value *V,
+                                     IRBuilder<> &Builder) {
++  bool bReplacedAll = true;
+   Function *F = Builder.GetInsertBlock()->getParent();
++  Instruction *VInst = dyn_cast<Instruction>(V);
++  // Lazily calculate dominance
++  DominatorTree DT;
++  bool Calculated = false;
++  auto Dominates = [&](llvm::Instruction *Def, llvm::Instruction *User) {
++    if (!Calculated) {
++      DT.recalculate(*F);
++      Calculated = true;
++    }
++    return DT.dominates(Def, User);
++  };
++
+   for (auto it = C->user_begin(); it != C->user_end();) {
+     User *U = *(it++);
+     if (Instruction *I = dyn_cast<Instruction>(U)) {
+       if (I->getParent()->getParent() != F)
+         continue;
+-      I->replaceUsesOfWith(C, V);
++      if (VInst && Dominates(VInst, I))
++        I->replaceUsesOfWith(C, V);
++      else
++        bReplacedAll = false;
+     } else {
+       // Skip unused ConstantExpr.
+       if (U->user_empty())
+@@ -3288,10 +3307,12 @@ static void ReplaceConstantWithInst(Constant *C, Value *V,
+       Instruction *Inst = CE->getAsInstruction();
+       Builder.Insert(Inst);
+       Inst->replaceUsesOfWith(C, V);
+-      ReplaceConstantWithInst(CE, Inst, Builder);
++      if (!ReplaceConstantWithInst(CE, Inst, Builder))
++        bReplacedAll = false;
+     }
+   }
+   C->removeDeadConstantUsers();
++  return bReplacedAll;
+ }
+ 
+ static void ReplaceUnboundedArrayUses(Value *V, Value *Src) {
+@@ -3531,7 +3552,8 @@ static bool ReplaceMemcpy(Value *V, Value *Src, MemCpyInst *MC,
+       } else {
+         // Replace Constant with a non-Constant.
+         IRBuilder<> Builder(MC);
+-        ReplaceConstantWithInst(C, Src, Builder);
++        if (!ReplaceConstantWithInst(C, Src, Builder))
++          return false;
+       }
+     } else {
+       // Try convert special pattern for cbuffer which copy array of float4 to
+@@ -3539,7 +3561,8 @@ static bool ReplaceMemcpy(Value *V, Value *Src, MemCpyInst *MC,
+       if (!tryToReplaceCBVec4ArrayToScalarArray(V, TyV, Src, TySrc, MC, DL)) {
+         IRBuilder<> Builder(MC);
+         Src = Builder.CreateBitCast(Src, V->getType());
+-        ReplaceConstantWithInst(C, Src, Builder);
++        if (!ReplaceConstantWithInst(C, Src, Builder))
++          return false;
+       }
+     }
+   } else {
+@@ -5443,9 +5466,9 @@ void SROA_Parameter_HLSL::flattenArgument(
+         if (Ty->isPointerTy())
+           Ty = Ty->getPointerElementType();
+         unsigned size = DL.getTypeAllocSize(Ty);
+-#if 0  // HLSL Change
++#if 0 // HLSL Change
+         DIExpression *DDIExp = DIB.createBitPieceExpression(debugOffset, size);
+-#else  // HLSL Change
++#else // HLSL Change
+         Type *argTy = Arg->getType();
+         if (argTy->isPointerTy())
+           argTy = argTy->getPointerElementType();
+diff --git a/tools/clang/test/DXC/Passes/ScalarReplHLSL/scalarrepl-param-hlsl-const-to-local-and-back.hlsl b/tools/clang/test/DXC/Passes/ScalarReplHLSL/scalarrepl-param-hlsl-const-to-local-and-back.hlsl
+new file mode 100644
+index 0000000000000000000000000000000000000000..0f30050e69decaf7da3f2ae645611c1a49a4a719
+--- /dev/null
++++ b/tools/clang/test/DXC/Passes/ScalarReplHLSL/scalarrepl-param-hlsl-const-to-local-and-back.hlsl
+@@ -0,0 +1,45 @@
++// RUN: not %dxc -T ps_6_2 %s 2>&1 | FileCheck %s
++
++// Validate that copying from static array to local, then back to static
++// array does not crash the compiler. This was resulting in an invalid
++// ReplaceConstantWithInst from ScalarReplAggregatesHLSL, which would
++// result in referenced deleted instruction in a later pass.
++
++// CHECK: error: Loop must have break.
++
++static int arr1[10] = (int[10])0;
++static int arr2[10] = (int[10])0;
++static float result = 0;
++ByteAddressBuffer buff : register(t0);
++
++void foo() {
++  int i = 0;
++  if (buff.Load(0u)) {
++    return;
++  }
++  arr2[i] = arr1[i];
++  result = float(arr1[0]);
++}
++
++struct tint_symbol {
++  float4 value : SV_Target0;
++};
++
++float main_inner() {
++  foo();
++  bool cond = false;
++  while (true) {
++    if (cond) { break; }
++  }
++  int arr1_copy[10] = arr1; // constant to local
++  arr1 = arr1_copy; // local to constant
++  foo();
++  return result;
++}
++
++tint_symbol main() {
++  float inner_result = main_inner();
++  tint_symbol wrapper_result = (tint_symbol)0;
++  wrapper_result.value.x = inner_result;
++  return wrapper_result;
++}
+diff --git a/tools/clang/test/DXC/Passes/ScalarReplHLSL/scalarrepl-param-hlsl-const-to-local-and-back.ll b/tools/clang/test/DXC/Passes/ScalarReplHLSL/scalarrepl-param-hlsl-const-to-local-and-back.ll
+new file mode 100644
+index 0000000000000000000000000000000000000000..6ca08ab3a9c500cacb715f63ee407c7add4fc51c
+--- /dev/null
++++ b/tools/clang/test/DXC/Passes/ScalarReplHLSL/scalarrepl-param-hlsl-const-to-local-and-back.ll
+@@ -0,0 +1,253 @@
++; RUN: %dxopt %s -hlsl-passes-resume -scalarrepl-param-hlsl -S | FileCheck %s
++
++; The first memcpy, from arr1 to arr1_copy.i, should be replaced by a series of 10 loads and stores,
++; while the second memcpy, from arr1_copy.i back to arr1, should be removed:
++;   %19 = bitcast [10 x i32]* %arr1_copy.i to i8*, !dbg !33 ; line:25 col:23
++;   call void @llvm.memcpy.p0i8.p0i8.i64(i8* %19, i8* bitcast ([10 x i32]* @arr1 to i8*), i64 40, i32 1, i1 false) #0, !dbg !33 ; line:25 col:23
++;   %20 = bitcast [10 x i32]* %arr1_copy.i to i8*, !dbg !34 ; line:26 col:10
++;   call void @llvm.memcpy.p0i8.p0i8.i64(i8* bitcast ([10 x i32]* @arr1 to i8*), i8* %20, i64 40, i32 1, i1 false) #0, !dbg !34 ; line:26 col:10
++;   store i32 0, i32* %i.i.1.i, align 4, !dbg !35, !tbaa !12 ; line:7 col:7
++
++; CHECK:  [[DEST0:%[a-z0-9\.]+]] = getelementptr inbounds [10 x i32], [10 x i32]* %arr1_copy.i, i32 0, i32 0
++; CHECK-NEXT:  [[SRC0:%[a-z0-9\.]+]] = load i32, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @arr1, i32 0, i32 0)
++; CHECK-NEXT:  store i32 [[SRC0:%[a-z0-9\.]+]], i32* [[DEST0:%[a-z0-9\.]+]]
++; CHECK-NEXT:  [[DEST1:%[a-z0-9\.]+]] = getelementptr inbounds [10 x i32], [10 x i32]* %arr1_copy.i, i32 0, i32 1
++; CHECK-NEXT:  [[SRC1:%[a-z0-9\.]+]] = load i32, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @arr1, i32 0, i32 1)
++; CHECK-NEXT:  store i32 [[SRC1:%[a-z0-9\.]+]], i32* [[DEST1:%[a-z0-9\.]+]]
++; CHECK-NEXT:  [[DEST2:%[a-z0-9\.]+]] = getelementptr inbounds [10 x i32], [10 x i32]* %arr1_copy.i, i32 0, i32 2
++; CHECK-NEXT:  [[SRC2:%[a-z0-9\.]+]] = load i32, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @arr1, i32 0, i32 2)
++; CHECK-NEXT:  store i32 [[SRC2:%[a-z0-9\.]+]], i32* [[DEST2:%[a-z0-9\.]+]]
++; CHECK-NEXT:  [[DEST3:%[a-z0-9\.]+]] = getelementptr inbounds [10 x i32], [10 x i32]* %arr1_copy.i, i32 0, i32 3
++; CHECK-NEXT:  [[SRC3:%[a-z0-9\.]+]] = load i32, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @arr1, i32 0, i32 3)
++; CHECK-NEXT:  store i32 [[SRC3:%[a-z0-9\.]+]], i32* [[DEST3:%[a-z0-9\.]+]]
++; CHECK-NEXT:  [[DEST4:%[a-z0-9\.]+]] = getelementptr inbounds [10 x i32], [10 x i32]* %arr1_copy.i, i32 0, i32 4
++; CHECK-NEXT:  [[SRC4:%[a-z0-9\.]+]] = load i32, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @arr1, i32 0, i32 4)
++; CHECK-NEXT:  store i32 [[SRC4:%[a-z0-9\.]+]], i32* [[DEST4:%[a-z0-9\.]+]]
++; CHECK-NEXT:  [[DEST5:%[a-z0-9\.]+]] = getelementptr inbounds [10 x i32], [10 x i32]* %arr1_copy.i, i32 0, i32 5
++; CHECK-NEXT:  [[SRC5:%[a-z0-9\.]+]] = load i32, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @arr1, i32 0, i32 5)
++; CHECK-NEXT:  store i32 [[SRC5:%[a-z0-9\.]+]], i32* [[DEST5:%[a-z0-9\.]+]]
++; CHECK-NEXT:  [[DEST6:%[a-z0-9\.]+]] = getelementptr inbounds [10 x i32], [10 x i32]* %arr1_copy.i, i32 0, i32 6
++; CHECK-NEXT:  [[SRC6:%[a-z0-9\.]+]] = load i32, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @arr1, i32 0, i32 6)
++; CHECK-NEXT:  store i32 [[SRC6:%[a-z0-9\.]+]], i32* [[DEST6:%[a-z0-9\.]+]]
++; CHECK-NEXT:  [[DEST7:%[a-z0-9\.]+]] = getelementptr inbounds [10 x i32], [10 x i32]* %arr1_copy.i, i32 0, i32 7
++; CHECK-NEXT:  [[SRC7:%[a-z0-9\.]+]] = load i32, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @arr1, i32 0, i32 7)
++; CHECK-NEXT:  store i32 [[SRC7:%[a-z0-9\.]+]], i32* [[DEST7:%[a-z0-9\.]+]]
++; CHECK-NEXT:  [[DEST8:%[a-z0-9\.]+]] = getelementptr inbounds [10 x i32], [10 x i32]* %arr1_copy.i, i32 0, i32 8
++; CHECK-NEXT:  [[SRC8:%[a-z0-9\.]+]] = load i32, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @arr1, i32 0, i32 8)
++; CHECK-NEXT:  store i32 [[SRC8:%[a-z0-9\.]+]], i32* [[DEST8:%[a-z0-9\.]+]]
++; CHECK-NEXT:  [[DEST9:%[a-z0-9\.]+]] = getelementptr inbounds [10 x i32], [10 x i32]* %arr1_copy.i, i32 0, i32 9
++; CHECK-NEXT:  [[SRC9:%[a-z0-9\.]+]] = load i32, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @arr1, i32 0, i32 9)
++; CHECK-NEXT:  store i32 [[SRC9:%[a-z0-9\.]+]], i32* [[DEST9:%[a-z0-9\.]+]]
++
++;
++; Buffer Definitions:
++;
++; cbuffer $Globals
++; {
++;
++;   [0 x i8] (type annotation not present)
++;
++; }
++;
++;
++; Resource Bindings:
++;
++; Name                                 Type  Format         Dim      ID      HLSL Bind  Count
++; ------------------------------ ---------- ------- ----------- ------- -------------- ------
++; $Globals                          cbuffer      NA          NA     CB0   cb4294967295     1
++; buff                              texture    byte         r/o      T0             t0     1
++;
++target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64"
++target triple = "dxil-ms-dx"
++
++%struct.ByteAddressBuffer = type { i32 }
++%ConstantBuffer = type opaque
++%struct.tint_symbol = type { <4 x float> }
++%dx.types.Handle = type { i8* }
++%dx.types.ResourceProperties = type { i32, i32 }
++
++@"\01?buff@@3UByteAddressBuffer@@A" = external global %struct.ByteAddressBuffer, align 4
++@arr1 = internal global [10 x i32] zeroinitializer, align 4
++@arr2 = internal global [10 x i32] zeroinitializer, align 4
++@"$Globals" = external constant %ConstantBuffer
++
++; Function Attrs: nounwind
++define void @main(%struct.tint_symbol* noalias sret %agg.result) #0 {
++  %1 = alloca float
++  store float 0.000000e+00, float* %1
++  %i.i.1.i = alloca i32, align 4
++  %i.i.i = alloca i32, align 4
++  %cond.i = alloca i32, align 4
++  %arr1_copy.i = alloca [10 x i32], align 4
++  %inner_result = alloca float, align 4
++  %wrapper_result = alloca %struct.tint_symbol, align 4
++  store i32 0, i32* %i.i.i, align 4, !dbg !23, !tbaa !31 ; line:7 col:7
++  %2 = load %struct.ByteAddressBuffer, %struct.ByteAddressBuffer* @"\01?buff@@3UByteAddressBuffer@@A", !dbg !35 ; line:8 col:7
++  %3 = call %dx.types.Handle @"dx.hl.createhandle..%dx.types.Handle (i32, %struct.ByteAddressBuffer)"(i32 0, %struct.ByteAddressBuffer %2) #0, !dbg !35 ; line:8 col:7
++  %4 = call %dx.types.Handle @"dx.hl.annotatehandle..%dx.types.Handle (i32, %dx.types.Handle, %dx.types.ResourceProperties, %struct.ByteAddressBuffer)"(i32 14, %dx.types.Handle %3, %dx.types.ResourceProperties { i32 11, i32 0 }, %struct.ByteAddressBuffer undef) #0, !dbg !35 ; line:8 col:7
++  %5 = call i32 @"dx.hl.op.ro.i32 (i32, %dx.types.Handle, i32)"(i32 231, %dx.types.Handle %4, i32 0) #0, !dbg !35 ; line:8 col:7
++  %6 = icmp ne i32 %5, 0, !dbg !35 ; line:8 col:7
++  br i1 %6, label %"\01?foo@@YAXXZ.exit.i", label %7, !dbg !35 ; line:8 col:7
++
++; <label>:7                                       ; preds = %0
++  %8 = load i32, i32* %i.i.i, align 4, !dbg !36, !tbaa !31 ; line:11 col:18
++  %9 = getelementptr inbounds [10 x i32], [10 x i32]* @arr1, i32 0, i32 %8, !dbg !37 ; line:11 col:13
++  %10 = load i32, i32* %9, align 4, !dbg !37, !tbaa !31 ; line:11 col:13
++  %11 = load i32, i32* %i.i.i, align 4, !dbg !38, !tbaa !31 ; line:11 col:8
++  %12 = getelementptr inbounds [10 x i32], [10 x i32]* @arr2, i32 0, i32 %11, !dbg !39 ; line:11 col:3
++  store i32 %10, i32* %12, align 4, !dbg !40, !tbaa !31 ; line:11 col:11
++  %13 = load i32, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @arr1, i32 0, i32 0), align 4, !dbg !41, !tbaa !31 ; line:12 col:18
++  %14 = sitofp i32 %13 to float, !dbg !41 ; line:12 col:18
++  store float %14, float* %1, align 4, !dbg !42, !tbaa !43 ; line:12 col:10
++  br label %"\01?foo@@YAXXZ.exit.i", !dbg !45 ; line:13 col:1
++
++"\01?foo@@YAXXZ.exit.i":                          ; preds = %7, %0
++  store i32 0, i32* %cond.i, align 4, !dbg !46, !tbaa !47 ; line:21 col:8
++  br label %15, !dbg !49 ; line:22 col:3
++
++; <label>:15                                      ; preds = %15, %"\01?foo@@YAXXZ.exit.i"
++  %16 = load i32, i32* %cond.i, align 4, !dbg !50, !tbaa !47, !range !51 ; line:23 col:9
++  %17 = icmp ne i32 %16, 0, !dbg !50 ; line:23 col:9
++  br i1 %17, label %18, label %15, !dbg !50 ; line:23 col:9
++
++; <label>:18                                      ; preds = %15
++  %19 = bitcast [10 x i32]* %arr1_copy.i to i8*, !dbg !52 ; line:25 col:23
++  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %19, i8* bitcast ([10 x i32]* @arr1 to i8*), i64 40, i32 1, i1 false) #0, !dbg !52 ; line:25 col:23
++  %20 = bitcast [10 x i32]* %arr1_copy.i to i8*, !dbg !53 ; line:26 col:10
++  call void @llvm.memcpy.p0i8.p0i8.i64(i8* bitcast ([10 x i32]* @arr1 to i8*), i8* %20, i64 40, i32 1, i1 false) #0, !dbg !53 ; line:26 col:10
++  store i32 0, i32* %i.i.1.i, align 4, !dbg !54, !tbaa !31 ; line:7 col:7
++  %21 = load %struct.ByteAddressBuffer, %struct.ByteAddressBuffer* @"\01?buff@@3UByteAddressBuffer@@A", !dbg !56 ; line:8 col:7
++  %22 = call %dx.types.Handle @"dx.hl.createhandle..%dx.types.Handle (i32, %struct.ByteAddressBuffer)"(i32 0, %struct.ByteAddressBuffer %21) #0, !dbg !56 ; line:8 col:7
++  %23 = call %dx.types.Handle @"dx.hl.annotatehandle..%dx.types.Handle (i32, %dx.types.Handle, %dx.types.ResourceProperties, %struct.ByteAddressBuffer)"(i32 14, %dx.types.Handle %22, %dx.types.ResourceProperties { i32 11, i32 0 }, %struct.ByteAddressBuffer undef) #0, !dbg !56 ; line:8 col:7
++  %24 = call i32 @"dx.hl.op.ro.i32 (i32, %dx.types.Handle, i32)"(i32 231, %dx.types.Handle %23, i32 0) #0, !dbg !56 ; line:8 col:7
++  %25 = icmp ne i32 %24, 0, !dbg !56 ; line:8 col:7
++  br i1 %25, label %"\01?main_inner@@YAMXZ.exit", label %26, !dbg !56 ; line:8 col:7
++
++; <label>:26                                      ; preds = %18
++  %27 = load i32, i32* %i.i.1.i, align 4, !dbg !57, !tbaa !31 ; line:11 col:18
++  %28 = getelementptr inbounds [10 x i32], [10 x i32]* @arr1, i32 0, i32 %27, !dbg !58 ; line:11 col:13
++  %29 = load i32, i32* %28, align 4, !dbg !58, !tbaa !31 ; line:11 col:13
++  %30 = load i32, i32* %i.i.1.i, align 4, !dbg !59, !tbaa !31 ; line:11 col:8
++  %31 = getelementptr inbounds [10 x i32], [10 x i32]* @arr2, i32 0, i32 %30, !dbg !60 ; line:11 col:3
++  store i32 %29, i32* %31, align 4, !dbg !61, !tbaa !31 ; line:11 col:11
++  %32 = load i32, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @arr1, i32 0, i32 0), align 4, !dbg !62, !tbaa !31 ; line:12 col:18
++  %33 = sitofp i32 %32 to float, !dbg !62 ; line:12 col:18
++  store float %33, float* %1, align 4, !dbg !63, !tbaa !43 ; line:12 col:10
++  br label %"\01?main_inner@@YAMXZ.exit", !dbg !64 ; line:13 col:1
++
++"\01?main_inner@@YAMXZ.exit":                     ; preds = %18, %26
++  %34 = load float, float* %1, align 4, !dbg !65, !tbaa !43 ; line:28 col:10
++  store float %34, float* %inner_result, align 4, !dbg !66, !tbaa !43 ; line:32 col:9
++  %35 = getelementptr inbounds %struct.tint_symbol, %struct.tint_symbol* %wrapper_result, i32 0, i32 0, !dbg !67 ; line:33 col:45
++  store <4 x float> zeroinitializer, <4 x float>* %35, !dbg !67 ; line:33 col:45
++  %36 = load float, float* %inner_result, align 4, !dbg !68, !tbaa !43 ; line:34 col:28
++  %37 = getelementptr inbounds %struct.tint_symbol, %struct.tint_symbol* %wrapper_result, i32 0, i32 0, !dbg !69 ; line:34 col:18
++  %38 = load <4 x float>, <4 x float>* %37, align 4, !dbg !70 ; line:34 col:26
++  %39 = getelementptr <4 x float>, <4 x float>* %37, i32 0, i32 0, !dbg !70 ; line:34 col:26
++  store float %36, float* %39, !dbg !70 ; line:34 col:26
++  %40 = bitcast %struct.tint_symbol* %agg.result to i8*, !dbg !71 ; line:35 col:10
++  %41 = bitcast %struct.tint_symbol* %wrapper_result to i8*, !dbg !71 ; line:35 col:10
++  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %40, i8* %41, i64 16, i32 1, i1 false), !dbg !71 ; line:35 col:10
++  ret void, !dbg !72 ; line:35 col:3
++}
++
++; Function Attrs: nounwind
++declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1) #0
++
++; Function Attrs: nounwind readonly
++declare i32 @"dx.hl.op.ro.i32 (i32, %dx.types.Handle, i32)"(i32, %dx.types.Handle, i32) #1
++
++; Function Attrs: nounwind readnone
++declare %dx.types.Handle @"dx.hl.createhandle..%dx.types.Handle (i32, %struct.ByteAddressBuffer)"(i32, %struct.ByteAddressBuffer) #2
++
++; Function Attrs: nounwind readnone
++declare %dx.types.Handle @"dx.hl.annotatehandle..%dx.types.Handle (i32, %dx.types.Handle, %dx.types.ResourceProperties, %struct.ByteAddressBuffer)"(i32, %dx.types.Handle, %dx.types.ResourceProperties, %struct.ByteAddressBuffer) #2
++
++attributes #0 = { nounwind }
++attributes #1 = { nounwind readonly }
++attributes #2 = { nounwind readnone }
++
++!llvm.module.flags = !{!0}
++!pauseresume = !{!1}
++!llvm.ident = !{!2}
++!dx.version = !{!3}
++!dx.valver = !{!4}
++!dx.shaderModel = !{!5}
++!dx.typeAnnotations = !{!6, !9}
++!dx.entryPoints = !{!14}
++!dx.fnprops = !{!20}
++!dx.options = !{!21, !22}
++
++!0 = !{i32 2, !"Debug Info Version", i32 3}
++!1 = !{!"hlsl-hlemit", !"hlsl-hlensure"}
++!2 = !{!"dxc(private) 1.8.0.4547 (14ec4b49d)"}
++!3 = !{i32 1, i32 2}
++!4 = !{i32 1, i32 8}
++!5 = !{!"ps", i32 6, i32 2}
++!6 = !{i32 0, %struct.tint_symbol undef, !7}
++!7 = !{i32 16, !8}
++!8 = !{i32 6, !"value", i32 3, i32 0, i32 4, !"SV_Target0", i32 7, i32 9}
++!9 = !{i32 1, void (%struct.tint_symbol*)* @main, !10}
++!10 = !{!11, !13}
++!11 = !{i32 0, !12, !12}
++!12 = !{}
++!13 = !{i32 1, !12, !12}
++!14 = !{void (%struct.tint_symbol*)* @main, !"main", null, !15, null}
++!15 = !{!16, null, !18, null}
++!16 = !{!17}
++!17 = !{i32 0, %struct.ByteAddressBuffer* @"\01?buff@@3UByteAddressBuffer@@A", !"buff", i32 0, i32 0, i32 1, i32 11, i32 0, null}
++!18 = !{!19}
++!19 = !{i32 0, %ConstantBuffer* @"$Globals", !"$Globals", i32 0, i32 -1, i32 1, i32 0, null}
++!20 = !{void (%struct.tint_symbol*)* @main, i32 0, i1 false}
++!21 = !{i32 144}
++!22 = !{i32 -1}
++!23 = !DILocation(line: 7, column: 7, scope: !24, inlinedAt: !27)
++!24 = !DISubprogram(name: "foo", scope: !25, file: !25, line: 6, type: !26, isLocal: false, isDefinition: true, scopeLine: 6, flags: DIFlagPrototyped, isOptimized: false)
++!25 = !DIFile(filename: "333414294_simplifed.hlsl", directory: "")
++!26 = !DISubroutineType(types: !12)
++!27 = distinct !DILocation(line: 20, column: 3, scope: !28, inlinedAt: !29)
++!28 = !DISubprogram(name: "main_inner", scope: !25, file: !25, line: 19, type: !26, isLocal: false, isDefinition: true, scopeLine: 19, flags: DIFlagPrototyped, isOptimized: false)
++!29 = distinct !DILocation(line: 32, column: 24, scope: !30)
++!30 = !DISubprogram(name: "main", scope: !25, file: !25, line: 31, type: !26, isLocal: false, isDefinition: true, scopeLine: 31, flags: DIFlagPrototyped, isOptimized: false, function: void (%struct.tint_symbol*)* @main)
++!31 = !{!32, !32, i64 0}
++!32 = !{!"int", !33, i64 0}
++!33 = !{!"omnipotent char", !34, i64 0}
++!34 = !{!"Simple C/C++ TBAA"}
++!35 = !DILocation(line: 8, column: 7, scope: !24, inlinedAt: !27)
++!36 = !DILocation(line: 11, column: 18, scope: !24, inlinedAt: !27)
++!37 = !DILocation(line: 11, column: 13, scope: !24, inlinedAt: !27)
++!38 = !DILocation(line: 11, column: 8, scope: !24, inlinedAt: !27)
++!39 = !DILocation(line: 11, column: 3, scope: !24, inlinedAt: !27)
++!40 = !DILocation(line: 11, column: 11, scope: !24, inlinedAt: !27)
++!41 = !DILocation(line: 12, column: 18, scope: !24, inlinedAt: !27)
++!42 = !DILocation(line: 12, column: 10, scope: !24, inlinedAt: !27)
++!43 = !{!44, !44, i64 0}
++!44 = !{!"float", !33, i64 0}
++!45 = !DILocation(line: 13, column: 1, scope: !24, inlinedAt: !27)
++!46 = !DILocation(line: 21, column: 8, scope: !28, inlinedAt: !29)
++!47 = !{!48, !48, i64 0}
++!48 = !{!"bool", !33, i64 0}
++!49 = !DILocation(line: 22, column: 3, scope: !28, inlinedAt: !29)
++!50 = !DILocation(line: 23, column: 9, scope: !28, inlinedAt: !29)
++!51 = !{i32 0, i32 2}
++!52 = !DILocation(line: 25, column: 23, scope: !28, inlinedAt: !29)
++!53 = !DILocation(line: 26, column: 10, scope: !28, inlinedAt: !29)
++!54 = !DILocation(line: 7, column: 7, scope: !24, inlinedAt: !55)
++!55 = distinct !DILocation(line: 27, column: 3, scope: !28, inlinedAt: !29)
++!56 = !DILocation(line: 8, column: 7, scope: !24, inlinedAt: !55)
++!57 = !DILocation(line: 11, column: 18, scope: !24, inlinedAt: !55)
++!58 = !DILocation(line: 11, column: 13, scope: !24, inlinedAt: !55)
++!59 = !DILocation(line: 11, column: 8, scope: !24, inlinedAt: !55)
++!60 = !DILocation(line: 11, column: 3, scope: !24, inlinedAt: !55)
++!61 = !DILocation(line: 11, column: 11, scope: !24, inlinedAt: !55)
++!62 = !DILocation(line: 12, column: 18, scope: !24, inlinedAt: !55)
++!63 = !DILocation(line: 12, column: 10, scope: !24, inlinedAt: !55)
++!64 = !DILocation(line: 13, column: 1, scope: !24, inlinedAt: !55)
++!65 = !DILocation(line: 28, column: 10, scope: !28, inlinedAt: !29)
++!66 = !DILocation(line: 32, column: 9, scope: !30)
++!67 = !DILocation(line: 33, column: 45, scope: !30)
++!68 = !DILocation(line: 34, column: 28, scope: !30)
++!69 = !DILocation(line: 34, column: 18, scope: !30)
++!70 = !DILocation(line: 34, column: 26, scope: !30)
++!71 = !DILocation(line: 35, column: 10, scope: !30)
++!72 = !DILocation(line: 35, column: 3, scope: !30)

+ 1 - 0
patches/chromium/.patches

@@ -157,3 +157,4 @@ cherry-pick-013961609785.patch
 a11y_avoid_clearing_resetting_focus_on_an_already_focus_event.patch
 cherry-pick-b2cc7b7ac538.patch
 m120-lts_merge_fix_domarraybuffer_isdetached_and_comment_out.patch
+cherry-pick-03609e39be8c.patch

+ 117 - 0
patches/chromium/cherry-pick-03609e39be8c.patch

@@ -0,0 +1,117 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: David Benjamin <[email protected]>
+Date: Fri, 10 May 2024 15:10:48 +0000
+Subject: Fix size calculations in V8StringToUTF8
+
+While I'm here, remove the unnecessary use of base::WriteInto, which is
+a remnant of C++03 copy-on-write strings. Also ask V8 not to write a
+NUL terminator because std::(u16)string already owns that byte.
+
+(cherry picked from commit f414dc31032a453f4a6c88977d7894fcb3cba44e)
+
+Bug: 338574384
+Change-Id: I5c6eaa99093925db799736f321eab92d35f5acbb
+Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5515743
+Reviewed-by: mmenke <[email protected]>
+Commit-Queue: David Benjamin <[email protected]>
+Reviewed-by: Michael Lippautz <[email protected]>
+Cr-Original-Commit-Position: refs/heads/main@{#1297196}
+Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5527764
+Auto-Submit: David Benjamin <[email protected]>
+Commit-Queue: mmenke <[email protected]>
+Cr-Commit-Position: refs/branch-heads/6367@{#1148}
+Cr-Branched-From: d158c6dc6e3604e6f899041972edf26087a49740-refs/heads/main@{#1274542}
+
+diff --git a/services/proxy_resolver/proxy_resolver_v8.cc b/services/proxy_resolver/proxy_resolver_v8.cc
+index e5f8b501b7122c92b82bd2b7586c20af2560b177..1fdda1c5238e6876ec3905a8593742d618387535 100644
+--- a/services/proxy_resolver/proxy_resolver_v8.cc
++++ b/services/proxy_resolver/proxy_resolver_v8.cc
+@@ -17,6 +17,7 @@
+ #include "base/memory/raw_ptr.h"
+ #include "base/memory/raw_ptr_exclusion.h"
+ #include "base/notreached.h"
++#include "base/numerics/safe_conversions.h"
+ #include "base/strings/string_tokenizer.h"
+ #include "base/strings/string_util.h"
+ #include "base/strings/utf_string_conversions.h"
+@@ -148,25 +149,22 @@ const size_t kMaxStringBytesForCopy = 256;
+ 
+ // Converts a V8 String to a UTF8 std::string.
+ std::string V8StringToUTF8(v8::Isolate* isolate, v8::Local<v8::String> s) {
+-  int len = s->Length();
+-  std::string result;
+-  if (len > 0)
+-    s->WriteUtf8(isolate, base::WriteInto(&result, len + 1));
+-  return result;
++  int len = s->Utf8Length(isolate);
++  std::string str(base::checked_cast<size_t>(len), '\0');
++  s->WriteUtf8(isolate, str.data(), len, /*nchars_ref=*/nullptr,
++               v8::String::NO_NULL_TERMINATION);
++  return str;
+ }
+ 
+ // Converts a V8 String to a UTF16 std::u16string.
+ std::u16string V8StringToUTF16(v8::Isolate* isolate, v8::Local<v8::String> s) {
+   int len = s->Length();
+-  std::u16string result;
+-  // Note that the reinterpret cast is because on Windows string16 is an alias
+-  // to wstring, and hence has character type wchar_t not uint16_t.
+-  if (len > 0) {
+-    s->Write(isolate,
+-             reinterpret_cast<uint16_t*>(base::WriteInto(&result, len + 1)), 0,
+-             len);
+-  }
+-  return result;
++  std::u16string str(base::checked_cast<size_t>(len), '\0');
++  // `char16_t` and `uint16_t` are not the same type, but we build with strict
++  // aliasing off. See https://crbug.com/42209752.
++  s->Write(isolate, reinterpret_cast<uint16_t*>(str.data()), /*start=*/0, len,
++           v8::String::NO_NULL_TERMINATION);
++  return str;
+ }
+ 
+ // Converts an ASCII std::string to a V8 string.
+diff --git a/services/proxy_resolver/test/data/proxy_resolver_v8_unittest/pac_library_unittest.js b/services/proxy_resolver/test/data/proxy_resolver_v8_unittest/pac_library_unittest.js
+index 3414dc0b4a33a64c8fe09b0d2a5cd48123a5d9ac..1b8bc17862f0c3cfa4fdc97121619afac8777a9d 100644
+--- a/services/proxy_resolver/test/data/proxy_resolver_v8_unittest/pac_library_unittest.js
++++ b/services/proxy_resolver/test/data/proxy_resolver_v8_unittest/pac_library_unittest.js
+@@ -69,6 +69,11 @@ Tests.testIsPlainHostName = function(t) {
+   t.expectFalse(isPlainHostName("."));
+   t.expectFalse(isPlainHostName(".:"));
+ 
++  // These are not really hostnames, but `isPlainHostName` accepts any dotless,
++  // non-IP string.
++  t.expectTrue(isPlainHostName("\uffff".repeat(256)));
++  t.expectTrue(isPlainHostName(""));
++
+   // Valid IPv6 address
+   t.expectFalse(isPlainHostName("::1"));
+ 
+@@ -178,6 +183,7 @@ Tests.testSortIpAddressList = function(t) {
+   t.expectEquals(null, sortIpAddressList());
+   t.expectEquals(null, sortIpAddressList(null));
+   t.expectEquals(null, sortIpAddressList(null, null));
++  t.expectEquals(null, sortIpAddressList("\uffff".repeat(256)));
+ };
+ 
+ Tests.testIsInNetEx = function(t) {
+@@ -223,10 +229,14 @@ Tests.testIsInNetEx = function(t) {
+   // Invalid IP address.
+   t.expectFalse(isInNetEx("256.0.0.1", "198.95.249.79"));
+   t.expectFalse(isInNetEx("127.0.0.1 ", "127.0.0.1/32"));  // Extra space.
++  t.expectFalse(isInNetEx("\uffff".repeat(256), "127.0.0.1/32"));
++  t.expectFalse(isInNetEx("", "127.0.0.1/32"));
+ 
+   // Invalid prefix.
+   t.expectFalse(isInNetEx("198.95.115.10", "198.95.0.0/34"));
+   t.expectFalse(isInNetEx("127.0.0.1", "127.0.0.1"));  // Missing '/' in prefix.
++  t.expectFalse(isInNetEx("127.0.0.1", "\uffff".repeat(256)));
++  t.expectFalse(isInNetEx("127.0.0.1", ""));
+ };
+ 
+ Tests.testWeekdayRange = function(t) {
+@@ -465,4 +475,3 @@ MockDate.setCurrent = function(currentDateString) {
+ 
+ // Bind the methods to proxy requests to the wrapped Date().
+ MockDate.init();
+-

+ 1 - 0
patches/v8/.patches

@@ -8,3 +8,4 @@ merged_wasm_check_for_type-definition_count_limit.patch
 merged_runtime_recreate_enum_cache_on_map_update_if_any_previous.patch
 cherry-pick-f320600cd1f4.patch
 cherry-pick-b3c01ac1e60a.patch
+cherry-pick-6503a987d966.patch

+ 56 - 0
patches/v8/cherry-pick-6503a987d966.patch

@@ -0,0 +1,56 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Victor Gomes <[email protected]>
+Date: Thu, 21 Mar 2024 09:59:19 +0100
+Subject: Deal with large strings in NoSideEffectsErrorToString
+
+If name is too big, StringBuilder will fail to even add
+"<a very large string>" suffix.
+
+In this case, we truncate name first.
+
+Bug: 329699609
+Change-Id: I6e4440c07eae84371f44b54f88127e2c70af0db5
+Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/5378286
+Commit-Queue: Victor Gomes <[email protected]>
+Reviewed-by: Patrick Thier <[email protected]>
+Auto-Submit: Victor Gomes <[email protected]>
+Cr-Commit-Position: refs/heads/main@{#92932}
+
+diff --git a/src/objects/objects.cc b/src/objects/objects.cc
+index a05fe442f5a0d0a341cf8053e86d810c1a196fa4..a20fc42daaeba10244a43170be9aa08f4fb7a4cc 100644
+--- a/src/objects/objects.cc
++++ b/src/objects/objects.cc
+@@ -470,14 +470,27 @@ Handle<String> NoSideEffectsErrorToString(Isolate* isolate,
+   if (name_str->length() == 0) return msg_str;
+   if (msg_str->length() == 0) return name_str;
+ 
+-  IncrementalStringBuilder builder(isolate);
+-  builder.AppendString(name_str);
+-  builder.AppendCStringLiteral(": ");
++  constexpr const char error_suffix[] = "<a very large string>";
++  constexpr int error_suffix_size = sizeof(error_suffix);
++  int suffix_size = std::min(error_suffix_size, msg_str->length());
+ 
+-  if (builder.Length() + msg_str->length() <= String::kMaxLength) {
+-    builder.AppendString(msg_str);
++  IncrementalStringBuilder builder(isolate);
++  if (name_str->length() + suffix_size + 2 /* ": " */ > String::kMaxLength) {
++    constexpr const char connector[] = "... : ";
++    int connector_size = sizeof(connector);
++    Handle<String> truncated_name = isolate->factory()->NewProperSubString(
++        name_str, 0, name_str->length() - error_suffix_size - connector_size);
++    builder.AppendString(truncated_name);
++    builder.AppendCStringLiteral(connector);
++    builder.AppendCStringLiteral(error_suffix);
+   } else {
+-    builder.AppendCStringLiteral("<a very large string>");
++    builder.AppendString(name_str);
++    builder.AppendCStringLiteral(": ");
++    if (builder.Length() + msg_str->length() <= String::kMaxLength) {
++      builder.AppendString(msg_str);
++    } else {
++      builder.AppendCStringLiteral(error_suffix);
++    }
+   }
+ 
+   return builder.Finish().ToHandleChecked();