<div dir="ltr">Do we want to pull this into the release branch? The segfault has apparently existed since LLVM 3.0.<br><div class="gmail_extra"><br><br><div class="gmail_quote">On Fri, Dec 6, 2013 at 4:13 PM, Kaelyn Uhrain <span dir="ltr"><<a href="mailto:rikka@google.com" target="_blank">rikka@google.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rikka<br>
Date: Fri Dec 6 18:13:34 2013<br>
New Revision: 196626<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=196626&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=196626&view=rev</a><br>
Log:<br>
Fix the segfault reported in PR 11990.<br>
<br>
The sefault occurs due to an infinite loop when the verifier tries to<br>
determine the size of a type of the form "%rt = type { %rt }" while<br>
checking an alloca of the type.<br>
<br>
Added:<br>
llvm/trunk/test/Verifier/recursive-type-1.ll<br>
llvm/trunk/test/Verifier/recursive-type-2.ll<br>
llvm/trunk/test/Verifier/recursive-type-3.ll<br>
Modified:<br>
llvm/trunk/include/llvm/IR/DerivedTypes.h<br>
llvm/trunk/include/llvm/IR/Type.h<br>
llvm/trunk/lib/IR/Type.cpp<br>
llvm/trunk/lib/IR/Verifier.cpp<br>
<br>
Modified: llvm/trunk/include/llvm/IR/DerivedTypes.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/DerivedTypes.h?rev=196626&r1=196625&r2=196626&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/DerivedTypes.h?rev=196626&r1=196625&r2=196626&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/IR/DerivedTypes.h (original)<br>
+++ llvm/trunk/include/llvm/IR/DerivedTypes.h Fri Dec 6 18:13:34 2013<br>
@@ -249,7 +249,7 @@ public:<br>
bool isOpaque() const { return (getSubclassData() & SCDB_HasBody) == 0; }<br>
<br>
/// isSized - Return true if this is a sized type.<br>
- bool isSized() const;<br>
+ bool isSized(SmallPtrSet<const Type*, 4> *Visited = 0) const;<br>
<br>
/// hasName - Return true if this is a named struct that has a non-empty name.<br>
bool hasName() const { return SymbolTableEntry != 0; }<br>
<br>
Modified: llvm/trunk/include/llvm/IR/Type.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Type.h?rev=196626&r1=196625&r2=196626&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Type.h?rev=196626&r1=196625&r2=196626&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/IR/Type.h (original)<br>
+++ llvm/trunk/include/llvm/IR/Type.h Fri Dec 6 18:13:34 2013<br>
@@ -16,6 +16,7 @@<br>
#define LLVM_IR_TYPE_H<br>
<br>
#include "llvm/ADT/APFloat.h"<br>
+#include "llvm/ADT/SmallPtrSet.h"<br>
#include "llvm/Support/Casting.h"<br>
#include "llvm/Support/CBindingWrapping.h"<br>
#include "llvm/Support/DataTypes.h"<br>
@@ -275,7 +276,7 @@ public:<br>
/// get the actual size for a particular target, it is reasonable to use the<br>
/// DataLayout subsystem to do this.<br>
///<br>
- bool isSized() const {<br>
+ bool isSized(SmallPtrSet<const Type*, 4> *Visited = 0) const {<br>
// If it's a primitive, it is always sized.<br>
if (getTypeID() == IntegerTyID || isFloatingPointTy() ||<br>
getTypeID() == PointerTyID ||<br>
@@ -287,7 +288,7 @@ public:<br>
getTypeID() != VectorTyID)<br>
return false;<br>
// Otherwise we have to try harder to decide.<br>
- return isSizedDerivedType();<br>
+ return isSizedDerivedType(Visited);<br>
}<br>
<br>
/// getPrimitiveSizeInBits - Return the basic size of this type if it is a<br>
@@ -429,7 +430,7 @@ private:<br>
/// isSizedDerivedType - Derived types like structures and arrays are sized<br>
/// iff all of the members of the type are sized as well. Since asking for<br>
/// their size is relatively uncommon, move this operation out of line.<br>
- bool isSizedDerivedType() const;<br>
+ bool isSizedDerivedType(SmallPtrSet<const Type*, 4> *Visited = 0) const;<br>
};<br>
<br>
// Printing of types.<br>
<br>
Modified: llvm/trunk/lib/IR/Type.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Type.cpp?rev=196626&r1=196625&r2=196626&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Type.cpp?rev=196626&r1=196625&r2=196626&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/IR/Type.cpp (original)<br>
+++ llvm/trunk/lib/IR/Type.cpp Fri Dec 6 18:13:34 2013<br>
@@ -155,14 +155,14 @@ int Type::getFPMantissaWidth() const {<br>
/// isSizedDerivedType - Derived types like structures and arrays are sized<br>
/// iff all of the members of the type are sized as well. Since asking for<br>
/// their size is relatively uncommon, move this operation out of line.<br>
-bool Type::isSizedDerivedType() const {<br>
+bool Type::isSizedDerivedType(SmallPtrSet<const Type*, 4> *Visited) const {<br>
if (const ArrayType *ATy = dyn_cast<ArrayType>(this))<br>
- return ATy->getElementType()->isSized();<br>
+ return ATy->getElementType()->isSized(Visited);<br>
<br>
if (const VectorType *VTy = dyn_cast<VectorType>(this))<br>
- return VTy->getElementType()->isSized();<br>
+ return VTy->getElementType()->isSized(Visited);<br>
<br>
- return cast<StructType>(this)->isSized();<br>
+ return cast<StructType>(this)->isSized(Visited);<br>
}<br>
<br>
//===----------------------------------------------------------------------===//<br>
@@ -550,17 +550,20 @@ StructType *StructType::create(StringRef<br>
return llvm::StructType::create(Ctx, StructFields, Name);<br>
}<br>
<br>
-bool StructType::isSized() const {<br>
+bool StructType::isSized(SmallPtrSet<const Type*, 4> *Visited) const {<br>
if ((getSubclassData() & SCDB_IsSized) != 0)<br>
return true;<br>
if (isOpaque())<br>
return false;<br>
<br>
+ if (Visited && !Visited->insert(this))<br>
+ return false;<br>
+<br>
// Okay, our struct is sized if all of the elements are, but if one of the<br>
// elements is opaque, the struct isn't sized *yet*, but may become sized in<br>
// the future, so just bail out without caching.<br>
for (element_iterator I = element_begin(), E = element_end(); I != E; ++I)<br>
- if (!(*I)->isSized())<br>
+ if (!(*I)->isSized(Visited))<br>
return false;<br>
<br>
// Here we cheat a bit and cast away const-ness. The goal is to memoize when<br>
<br>
Modified: llvm/trunk/lib/IR/Verifier.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Verifier.cpp?rev=196626&r1=196625&r2=196626&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Verifier.cpp?rev=196626&r1=196625&r2=196626&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/IR/Verifier.cpp (original)<br>
+++ llvm/trunk/lib/IR/Verifier.cpp Fri Dec 6 18:13:34 2013<br>
@@ -1861,11 +1861,12 @@ void Verifier::visitStoreInst(StoreInst<br>
}<br>
<br>
void Verifier::visitAllocaInst(AllocaInst &AI) {<br>
+ SmallPtrSet<const Type*, 4> Visited;<br>
PointerType *PTy = AI.getType();<br>
Assert1(PTy->getAddressSpace() == 0,<br>
"Allocation instruction pointer not in the generic address space!",<br>
&AI);<br>
- Assert1(PTy->getElementType()->isSized(), "Cannot allocate unsized type",<br>
+ Assert1(PTy->getElementType()->isSized(&Visited), "Cannot allocate unsized type",<br>
&AI);<br>
Assert1(AI.getArraySize()->getType()->isIntegerTy(),<br>
"Alloca array size must have integer type", &AI);<br>
<br>
Added: llvm/trunk/test/Verifier/recursive-type-1.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/recursive-type-1.ll?rev=196626&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/recursive-type-1.ll?rev=196626&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/Verifier/recursive-type-1.ll (added)<br>
+++ llvm/trunk/test/Verifier/recursive-type-1.ll Fri Dec 6 18:13:34 2013<br>
@@ -0,0 +1,12 @@<br>
+; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s<br>
+<br>
+%rt2 = type { i32, { i8, %rt2, i8 }, i32 }<br>
+<br>
+define i32 @main() nounwind {<br>
+entry:<br>
+ ; Check that recursive types trigger an error instead of segfaulting, when<br>
+ ; the recursion isn't through a pointer to the type.<br>
+ ; CHECK: Cannot allocate unsized type<br>
+ %0 = alloca %rt2<br>
+ ret i32 0<br>
+}<br>
<br>
Added: llvm/trunk/test/Verifier/recursive-type-2.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/recursive-type-2.ll?rev=196626&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/recursive-type-2.ll?rev=196626&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/Verifier/recursive-type-2.ll (added)<br>
+++ llvm/trunk/test/Verifier/recursive-type-2.ll Fri Dec 6 18:13:34 2013<br>
@@ -0,0 +1,14 @@<br>
+; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s<br>
+<br>
+%rt1 = type { i32, { i8, %rt2, i8 }, i32 }<br>
+%rt2 = type { i64, { i6, %rt3 } }<br>
+%rt3 = type { %rt1 }<br>
+<br>
+define i32 @main() nounwind {<br>
+entry:<br>
+ ; Check that mutually recursive types trigger an error instead of segfaulting,<br>
+ ; when the recursion isn't through a pointer to the type.<br>
+ ; CHECK: Cannot allocate unsized type<br>
+ %0 = alloca %rt2<br>
+ ret i32 0<br>
+}<br>
<br>
Added: llvm/trunk/test/Verifier/recursive-type-3.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/recursive-type-3.ll?rev=196626&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/recursive-type-3.ll?rev=196626&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/Verifier/recursive-type-3.ll (added)<br>
+++ llvm/trunk/test/Verifier/recursive-type-3.ll Fri Dec 6 18:13:34 2013<br>
@@ -0,0 +1,11 @@<br>
+; RUN: llvm-as %s -o /dev/null 2>&1<br>
+<br>
+%rt2 = type { i32, { i8, %rt2*, i8 }, i32 }<br>
+<br>
+define i32 @main() nounwind {<br>
+entry:<br>
+ ; Check that linked-list-style recursive types where the recursion is through<br>
+ ; a pointer of the type is valid for an alloca.<br>
+ %0 = alloca %rt2<br>
+ ret i32 0<br>
+}<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu" target="_blank">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank" rel="noreferrer">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div></div>