Index: llvm/trunk/docs/LangRef.rst =================================================================== --- llvm/trunk/docs/LangRef.rst +++ llvm/trunk/docs/LangRef.rst @@ -6978,12 +6978,12 @@ Arguments: """""""""" -The argument to the ``load`` instruction specifies the memory address -from which to load. The type specified must be a :ref:`first -class ` type. If the ``load`` is marked as ``volatile``, -then the optimizer is not allowed to modify the number or order of -execution of this ``load`` with other :ref:`volatile -operations `. +The argument to the ``load`` instruction specifies the memory address from which +to load. The type specified must be a :ref:`first class ` type of +known size (i.e. not containing an :ref:`opaque structural type `). If +the ``load`` is marked as ``volatile``, then the optimizer is not allowed to +modify the number or order of execution of this ``load`` with other +:ref:`volatile operations `. If the ``load`` is marked as ``atomic``, it takes an extra :ref:`ordering ` and optional ``singlethread`` argument. The ``release`` and @@ -7101,13 +7101,14 @@ Arguments: """""""""" -There are two arguments to the ``store`` instruction: a value to store -and an address at which to store it. The type of the ```` -operand must be a pointer to the :ref:`first class ` type of -the ```` operand. If the ``store`` is marked as ``volatile``, -then the optimizer is not allowed to modify the number or order of -execution of this ``store`` with other :ref:`volatile -operations `. +There are two arguments to the ``store`` instruction: a value to store and an +address at which to store it. The type of the ```` operand must be a +pointer to the :ref:`first class ` type of the ```` +operand. If the ``store`` is marked as ``volatile``, then the optimizer is not +allowed to modify the number or order of execution of this ``store`` with other +:ref:`volatile operations `. Only values of :ref:`first class +` types of known size (i.e. not containing an :ref:`opaque +structural type `) can be stored. If the ``store`` is marked as ``atomic``, it takes an extra :ref:`ordering ` and optional ``singlethread`` argument. The ``acquire`` and Index: llvm/trunk/lib/IR/Verifier.cpp =================================================================== --- llvm/trunk/lib/IR/Verifier.cpp +++ llvm/trunk/lib/IR/Verifier.cpp @@ -2963,6 +2963,7 @@ Type *ElTy = LI.getType(); Assert(LI.getAlignment() <= Value::MaximumAlignment, "huge alignment values are unsupported", &LI); + Assert(ElTy->isSized(), "loading unsized types is not allowed", &LI); if (LI.isAtomic()) { Assert(LI.getOrdering() != AtomicOrdering::Release && LI.getOrdering() != AtomicOrdering::AcquireRelease, @@ -2991,6 +2992,7 @@ "Stored value type does not match pointer operand type!", &SI, ElTy); Assert(SI.getAlignment() <= Value::MaximumAlignment, "huge alignment values are unsupported", &SI); + Assert(ElTy->isSized(), "storing unsized types is not allowed", &SI); if (SI.isAtomic()) { Assert(SI.getOrdering() != AtomicOrdering::Acquire && SI.getOrdering() != AtomicOrdering::AcquireRelease, Index: llvm/trunk/test/Verifier/unsized-types.ll =================================================================== --- llvm/trunk/test/Verifier/unsized-types.ll +++ llvm/trunk/test/Verifier/unsized-types.ll @@ -0,0 +1,24 @@ +; RUN: not opt -verify < %s 2>&1 | FileCheck %s + +%X = type opaque + +define void @f_0(%X* %ptr) { + %t = load %X, %X* %ptr + ret void +; CHECK: loading unsized types is not allowed +; CHECK-NEXT: %t = load %X, %X* %ptr +} + +define void @f_1(%X %val, %X* %ptr) { + store %X %val, %X* %ptr + ret void +; CHECK: storing unsized types is not allowed +; CHECK-NEXT: store %X %val, %X* %ptr +} + +define void @f_2() { + %t = alloca %X + ret void +; CHECK: Cannot allocate unsized type +; CHECK-NEXT: %t = alloca %X +}