[llvm] [llubi] Implement memory manipulation intrinsics (PR #204932)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Sat Jun 20 08:05:09 PDT 2026


================
@@ -698,6 +699,120 @@ class InstExecutor : public InstVisitor<InstExecutor, void>,
     return V.asInteger();
   }
 
+  AnyValue callMemTransferIntrinsic(ArrayRef<AnyValue> Args,
+                                    Intrinsic::ID IID) {
+    if (Args[2].isPoison()) {
+      reportImmediateUB() << "Memory transfer intrinsic with poison length.";
+      return AnyValue::poison();
+    }
+
+    const APInt &Length = Args[2].asInteger();
+    if (Length.getActiveBits() > 64) {
+      reportImmediateUB()
+          << "Memory transfer intrinsic length overflows uint64_t.";
+      return AnyValue::poison();
+    }
+
+    const uint64_t Len = Length.getZExtValue();
+    if (Len == 0)
+      return AnyValue();
+
+    if (Args[0].isPoison()) {
+      reportImmediateUB()
+          << "Memory transfer intrinsic with poison destination pointer.";
+      return AnyValue::poison();
+    }
+
+    if (Args[1].isPoison()) {
+      reportImmediateUB()
+          << "Memory copy intrinsic with poison source pointer.";
+      return AnyValue::poison();
+    }
+
+    const Pointer &DstPtr = Args[0].asPointer();
+    const Pointer &SrcPtr = Args[1].asPointer();
+
+    auto [SrcMO, SrcOffset] =
+        verifyMemAccess(SrcPtr, Len, Align(1), /*IsStore=*/false);
+    if (!SrcMO)
+      return AnyValue();
+
+    auto [DstMO, DstOffset] =
+        verifyMemAccess(DstPtr, Len, Align(1), /*IsStore=*/true);
+    if (!DstMO)
+      return AnyValue();
+
+    if (DstMO->isConstant()) {
+      reportImmediateUB() << "Try to write to a constant memory object: "
+                          << DstPtr << ".";
+      return AnyValue::poison();
+    }
+
+    if (IID == Intrinsic::memcpy || IID == Intrinsic::memcpy_inline) {
+      if (SrcMO == DstMO && SrcOffset != DstOffset) {
+        const uint64_t SrcEnd = SrcOffset + Len;
+        const uint64_t DstEnd = DstOffset + Len;
+        if (SrcOffset < DstEnd && DstOffset < SrcEnd) {
+          reportImmediateUB()
+              << "memcpy with overlapping source and destination.";
+          return AnyValue::poison();
+        }
+      }
+    }
+
+    SmallVector<Byte, 16> Tmp;
+    if (SrcMO->getState() == MemoryObjectState::Dead) {
+      Tmp.assign(Len, Byte::poison());
+    } else {
+      ArrayRef<Byte> SrcBytes = SrcMO->getBytes().slice(SrcOffset, Len);
+      Tmp.assign(SrcBytes);
+    }
+    MutableArrayRef<Byte> DstBytes = DstMO->getBytes().slice(DstOffset, Len);
+    copy(Tmp, DstBytes.begin());
----------------
dtcxzyw wrote:

I guess memmove will handle the overlapping case, so we don't need a copy here, no?

https://github.com/llvm/llvm-project/pull/204932


More information about the llvm-commits mailing list