Define a maximum supported alignment value for load, store, and
authorDan Gohman <gohman@apple.com>
Wed, 28 Jul 2010 20:12:04 +0000 (20:12 +0000)
committerDan Gohman <gohman@apple.com>
Wed, 28 Jul 2010 20:12:04 +0000 (20:12 +0000)
alloca instructions (constrained by their internal encoding),
and add error checking for it. Fix an instcombine bug which
generated huge alignment values (null is infinitely aligned).
This fixes undefined behavior noticed by John Regehr.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@109643 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Instructions.h
lib/AsmParser/LLParser.cpp
lib/Transforms/InstCombine/InstCombineCalls.cpp
lib/VMCore/Instructions.cpp
test/Assembler/align-inst-alloca.ll [new file with mode: 0644]
test/Assembler/align-inst-load.ll [new file with mode: 0644]
test/Assembler/align-inst-store.ll [new file with mode: 0644]
test/Assembler/align-inst.ll [new file with mode: 0644]

index 273c9951c6221b338653227a946e50012577d071..118a42d51539c94c48f1fec2c80d43374e22bccd 100644 (file)
@@ -31,6 +31,10 @@ class APInt;
 class LLVMContext;
 class DominatorTree;
 
+/// MaximumAlignment - This is the greatest alignment value supported by
+/// load, store, and alloca instructions.
+static const unsigned MaximumAlignment = 1u << 29;
+
 //===----------------------------------------------------------------------===//
 //                                AllocaInst Class
 //===----------------------------------------------------------------------===//
index 61b1ae5e97cc91a17d0a944518e569c50bef3129..e581a694586f44b124f0e686c9e4f28a147c996c 100644 (file)
@@ -1154,6 +1154,8 @@ bool LLParser::ParseOptionalAlignment(unsigned &Alignment) {
   if (ParseUInt32(Alignment)) return true;
   if (!isPowerOf2_32(Alignment))
     return Error(AlignLoc, "alignment is not a power of two");
+  if (Alignment > MaximumAlignment)
+    return Error(AlignLoc, "huge alignments are not supported yet");
   return false;
 }
 
@@ -1176,6 +1178,7 @@ bool LLParser::ParseOptionalCommaAlign(unsigned &Alignment,
     if (Lex.getKind() != lltok::kw_align)
       return Error(Lex.getLoc(), "expected metadata or 'align'");
     
+    LocTy AlignLoc = Lex.getLoc();
     if (ParseOptionalAlignment(Alignment)) return true;
   }
 
index 0d5e30205a09f71c18467e3c596210b8835bca79..fdb2dd693d96cffcd5618e319dfe833a461f9390 100644 (file)
@@ -104,11 +104,15 @@ unsigned InstCombiner::GetOrEnforceKnownAlignment(Value *V,
   ComputeMaskedBits(V, Mask, KnownZero, KnownOne);
   unsigned TrailZ = KnownZero.countTrailingOnes();
 
-  // LLVM doesn't support alignments larger than this currently.
+  // Avoid trouble with rediculously large TrailZ values, such as
+  // those computed from a null pointer.
   TrailZ = std::min(TrailZ, unsigned(sizeof(unsigned) * CHAR_BIT - 1));
 
   unsigned Align = 1u << std::min(BitWidth - 1, TrailZ);
 
+  // LLVM doesn't support alignments larger than this currently.
+  Align = std::min(Align, MaximumAlignment);
+
   if (PrefAlign > Align)
     Align = EnforceKnownAlignment(V, Align, PrefAlign);
   
index 57b7f3f3d649101d84d711f811ef1bff1e3d7930..e03cc827580e56a5c55db23e0493e6c3b8e018f4 100644 (file)
@@ -891,6 +891,8 @@ AllocaInst::~AllocaInst() {
 
 void AllocaInst::setAlignment(unsigned Align) {
   assert((Align & (Align-1)) == 0 && "Alignment is not a power of 2!");
+  assert(Align <= MaximumAlignment &&
+         "Alignment is greater than MaximumAlignment!");
   setInstructionSubclassData(Log2_32(Align) + 1);
   assert(getAlignment() == Align && "Alignment representation error!");
 }
@@ -1026,8 +1028,11 @@ LoadInst::LoadInst(Value *Ptr, const char *Name, bool isVolatile,
 
 void LoadInst::setAlignment(unsigned Align) {
   assert((Align & (Align-1)) == 0 && "Alignment is not a power of 2!");
+  assert(Align <= MaximumAlignment &&
+         "Alignment is greater than MaximumAlignment!");
   setInstructionSubclassData((getSubclassDataFromInstruction() & 1) |
                              ((Log2_32(Align)+1)<<1));
+  assert(getAlignment() == Align && "Alignment representation error!");
 }
 
 //===----------------------------------------------------------------------===//
@@ -1122,8 +1127,11 @@ StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
 
 void StoreInst::setAlignment(unsigned Align) {
   assert((Align & (Align-1)) == 0 && "Alignment is not a power of 2!");
+  assert(Align <= MaximumAlignment &&
+         "Alignment is greater than MaximumAlignment!");
   setInstructionSubclassData((getSubclassDataFromInstruction() & 1) |
                              ((Log2_32(Align)+1) << 1));
+  assert(getAlignment() == Align && "Alignment representation error!");
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/test/Assembler/align-inst-alloca.ll b/test/Assembler/align-inst-alloca.ll
new file mode 100644 (file)
index 0000000..0343beb
--- /dev/null
@@ -0,0 +1,6 @@
+; RUN: not llvm-as %s -o /dev/null 2>/dev/null
+
+define void @foo() {
+  %p = alloca i1, align 1073741824
+  ret void
+}
diff --git a/test/Assembler/align-inst-load.ll b/test/Assembler/align-inst-load.ll
new file mode 100644 (file)
index 0000000..3586be2
--- /dev/null
@@ -0,0 +1,6 @@
+; RUN: not llvm-as %s -o /dev/null 2>/dev/null
+
+define void @foo() {
+  load i1* %p, align 1073741824
+  ret void
+}
diff --git a/test/Assembler/align-inst-store.ll b/test/Assembler/align-inst-store.ll
new file mode 100644 (file)
index 0000000..8c3b712
--- /dev/null
@@ -0,0 +1,6 @@
+; RUN: not llvm-as %s -o /dev/null 2>/dev/null
+
+define void @foo() {
+  store i1 false, i1* %p, align 1073741824
+  ret void
+}
diff --git a/test/Assembler/align-inst.ll b/test/Assembler/align-inst.ll
new file mode 100644 (file)
index 0000000..7bf0b64
--- /dev/null
@@ -0,0 +1,8 @@
+; RUN: llvm-as %s -o /dev/null
+
+define void @foo() {
+  %p = alloca i1, align 536870912
+  load i1* %p, align 536870912
+  store i1 false, i1* %p, align 536870912
+  ret void
+}