summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Gohman <gohman@apple.com>2010-07-28 20:12:04 +0000
committerDan Gohman <gohman@apple.com>2010-07-28 20:12:04 +0000
commit138aa2a82bc6de611f28e51332fb0a30262a58e3 (patch)
tree9457512df2e0e69b34681b03b8baede85785395c
parenta0c5bf19bff7d06faa3e039a0638806c9e5a8ff6 (diff)
downloadllvm-138aa2a82bc6de611f28e51332fb0a30262a58e3.tar.gz
llvm-138aa2a82bc6de611f28e51332fb0a30262a58e3.tar.bz2
llvm-138aa2a82bc6de611f28e51332fb0a30262a58e3.tar.xz
Define a maximum supported alignment value for load, store, and
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
-rw-r--r--include/llvm/Instructions.h4
-rw-r--r--lib/AsmParser/LLParser.cpp3
-rw-r--r--lib/Transforms/InstCombine/InstCombineCalls.cpp6
-rw-r--r--lib/VMCore/Instructions.cpp8
-rw-r--r--test/Assembler/align-inst-alloca.ll6
-rw-r--r--test/Assembler/align-inst-load.ll6
-rw-r--r--test/Assembler/align-inst-store.ll6
-rw-r--r--test/Assembler/align-inst.ll8
8 files changed, 46 insertions, 1 deletions
diff --git a/include/llvm/Instructions.h b/include/llvm/Instructions.h
index 273c9951c6..118a42d515 100644
--- a/include/llvm/Instructions.h
+++ b/include/llvm/Instructions.h
@@ -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
//===----------------------------------------------------------------------===//
diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp
index 61b1ae5e97..e581a69458 100644
--- a/lib/AsmParser/LLParser.cpp
+++ b/lib/AsmParser/LLParser.cpp
@@ -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;
}
diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 0d5e30205a..fdb2dd693d 100644
--- a/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -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);
diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp
index 57b7f3f3d6..e03cc82758 100644
--- a/lib/VMCore/Instructions.cpp
+++ b/lib/VMCore/Instructions.cpp
@@ -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
index 0000000000..0343bebf18
--- /dev/null
+++ b/test/Assembler/align-inst-alloca.ll
@@ -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
index 0000000000..3586be2d6e
--- /dev/null
+++ b/test/Assembler/align-inst-load.ll
@@ -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
index 0000000000..8c3b7124b4
--- /dev/null
+++ b/test/Assembler/align-inst-store.ll
@@ -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
index 0000000000..7bf0b6493b
--- /dev/null
+++ b/test/Assembler/align-inst.ll
@@ -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
+}