[llvm] r187186 - Make .bc en/decoding of AttrKind stable

Tobias Grosser tobias at grosser.es
Thu Jul 25 21:16:56 PDT 2013


Author: grosser
Date: Thu Jul 25 23:16:55 2013
New Revision: 187186

URL: http://llvm.org/viewvc/llvm-project?rev=187186&view=rev
Log:
Make .bc en/decoding of AttrKind stable

The bitcode representation attribute kinds are encoded into / decoded from
should be independent of the current set of LLVM attributes and their position
in the AttrKind enum. This patch explicitly encodes attributes to fixed bitcode
values.

With this patch applied, LLVM does not silently misread attributes written by
LLVM 3.3. We also enhance the decoding slightly such that an error message is
printed if an unknown AttrKind encoding was dected.

Bonus: Dropping bitcode attributes from AttrKind is now easy, as old AttrKinds
       do not need to be kept to support the Bitcode reader.

Added:
    llvm/trunk/test/Bitcode/attributes-3.3.ll
    llvm/trunk/test/Bitcode/attributes-3.3.ll.bc
Modified:
    llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h
    llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
    llvm/trunk/lib/Bitcode/Reader/BitcodeReader.h
    llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp

Modified: llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h?rev=187186&r1=187185&r2=187186&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h (original)
+++ llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h Thu Jul 25 23:16:55 2013
@@ -330,6 +330,47 @@ namespace bitc {
   enum UseListCodes {
     USELIST_CODE_ENTRY = 1   // USELIST_CODE_ENTRY: TBD.
   };
+
+  enum AttributeKindCodes {
+    // = 0 is unused
+    ATTR_KIND_ALIGNMENT = 1,
+    ATTR_KIND_ALWAYS_INLINE = 2,
+    ATTR_KIND_BY_VAL = 3,
+    ATTR_KIND_INLINE_HINT = 4,
+    ATTR_KIND_IN_REG = 5,
+    ATTR_KIND_MIN_SIZE = 6,
+    ATTR_KIND_NAKED = 7,
+    ATTR_KIND_NEST = 8,
+    ATTR_KIND_NO_ALIAS = 9,
+    ATTR_KIND_NO_BUILTIN = 10,
+    ATTR_KIND_NO_CAPTURE = 11,
+    ATTR_KIND_NO_DUPLICATE = 12,
+    ATTR_KIND_NO_IMPLICIT_FLOAT = 13,
+    ATTR_KIND_NO_INLINE = 14,
+    ATTR_KIND_NON_LAZY_BIND = 15,
+    ATTR_KIND_NO_RED_ZONE = 16,
+    ATTR_KIND_NO_RETURN = 17,
+    ATTR_KIND_NO_UNWIND = 18,
+    ATTR_KIND_OPTIMIZE_FOR_SIZE = 19,
+    ATTR_KIND_READ_NONE = 20,
+    ATTR_KIND_READ_ONLY = 21,
+    ATTR_KIND_RETURNED = 22,
+    ATTR_KIND_RETURNS_TWICE = 23,
+    ATTR_KIND_S_EXT = 24,
+    ATTR_KIND_STACK_ALIGNMENT = 25,
+    ATTR_KIND_STACK_PROTECT = 26,
+    ATTR_KIND_STACK_PROTECT_REQ = 27,
+    ATTR_KIND_STACK_PROTECT_STRONG = 28,
+    ATTR_KIND_STRUCT_RET = 29,
+    ATTR_KIND_SANITIZE_ADDRESS = 30,
+    ATTR_KIND_SANITIZE_THREAD = 31,
+    ATTR_KIND_SANITIZE_MEMORY = 32,
+    ATTR_KIND_UW_TABLE = 33,
+    ATTR_KIND_Z_EXT = 34,
+    ATTR_KIND_BUILTIN = 35,
+    ATTR_KIND_COLD = 36
+  };
+
 } // End bitc namespace
 } // End llvm namespace
 

Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=187186&r1=187185&r2=187186&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)
+++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Thu Jul 25 23:16:55 2013
@@ -12,6 +12,7 @@
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/AutoUpgrade.h"
+#include "llvm/Bitcode/LLVMBitCodes.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/IR/InlineAsm.h"
@@ -22,6 +23,7 @@
 #include "llvm/Support/DataStream.h"
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
 using namespace llvm;
 
 enum {
@@ -506,6 +508,125 @@ bool BitcodeReader::ParseAttributeBlock(
   }
 }
 
+bool BitcodeReader::ParseAttrKind(uint64_t Code, Attribute::AttrKind *Kind) {
+  switch (Code) {
+  case bitc::ATTR_KIND_ALIGNMENT:
+    *Kind = Attribute::Alignment;
+    return false;
+  case bitc::ATTR_KIND_ALWAYS_INLINE:
+    *Kind = Attribute::AlwaysInline;
+    return false;
+  case bitc::ATTR_KIND_BUILTIN:
+    *Kind = Attribute::Builtin;
+    return false;
+  case bitc::ATTR_KIND_BY_VAL:
+    *Kind = Attribute::ByVal;
+    return false;
+  case bitc::ATTR_KIND_COLD:
+    *Kind = Attribute::Cold;
+    return false;
+  case bitc::ATTR_KIND_INLINE_HINT:
+    *Kind = Attribute::InlineHint;
+    return false;
+  case bitc::ATTR_KIND_IN_REG:
+    *Kind = Attribute::InReg;
+    return false;
+  case bitc::ATTR_KIND_MIN_SIZE:
+    *Kind = Attribute::MinSize;
+    return false;
+  case bitc::ATTR_KIND_NAKED:
+    *Kind = Attribute::Naked;
+    return false;
+  case bitc::ATTR_KIND_NEST:
+    *Kind = Attribute::Nest;
+    return false;
+  case bitc::ATTR_KIND_NO_ALIAS:
+    *Kind = Attribute::NoAlias;
+    return false;
+  case bitc::ATTR_KIND_NO_BUILTIN:
+    *Kind = Attribute::NoBuiltin;
+    return false;
+  case bitc::ATTR_KIND_NO_CAPTURE:
+    *Kind = Attribute::NoCapture;
+    return false;
+  case bitc::ATTR_KIND_NO_DUPLICATE:
+    *Kind = Attribute::NoDuplicate;
+    return false;
+  case bitc::ATTR_KIND_NO_IMPLICIT_FLOAT:
+    *Kind = Attribute::NoImplicitFloat;
+    return false;
+  case bitc::ATTR_KIND_NO_INLINE:
+    *Kind = Attribute::NoInline;
+    return false;
+  case bitc::ATTR_KIND_NON_LAZY_BIND:
+    *Kind = Attribute::NonLazyBind;
+    return false;
+  case bitc::ATTR_KIND_NO_RED_ZONE:
+    *Kind = Attribute::NoRedZone;
+    return false;
+  case bitc::ATTR_KIND_NO_RETURN:
+    *Kind = Attribute::NoReturn;
+    return false;
+  case bitc::ATTR_KIND_NO_UNWIND:
+    *Kind = Attribute::NoUnwind;
+    return false;
+  case bitc::ATTR_KIND_OPTIMIZE_FOR_SIZE:
+    *Kind = Attribute::OptimizeForSize;
+    return false;
+  case bitc::ATTR_KIND_READ_NONE:
+    *Kind = Attribute::ReadNone;
+    return false;
+  case bitc::ATTR_KIND_READ_ONLY:
+    *Kind = Attribute::ReadOnly;
+    return false;
+  case bitc::ATTR_KIND_RETURNED:
+    *Kind = Attribute::Returned;
+    return false;
+  case bitc::ATTR_KIND_RETURNS_TWICE:
+    *Kind = Attribute::ReturnsTwice;
+    return false;
+  case bitc::ATTR_KIND_S_EXT:
+    *Kind = Attribute::SExt;
+    return false;
+  case bitc::ATTR_KIND_STACK_ALIGNMENT:
+    *Kind = Attribute::StackAlignment;
+    return false;
+  case bitc::ATTR_KIND_STACK_PROTECT:
+    *Kind = Attribute::StackProtect;
+    return false;
+  case bitc::ATTR_KIND_STACK_PROTECT_REQ:
+    *Kind = Attribute::StackProtectReq;
+    return false;
+  case bitc::ATTR_KIND_STACK_PROTECT_STRONG:
+    *Kind = Attribute::StackProtectStrong;
+    return false;
+  case bitc::ATTR_KIND_STRUCT_RET:
+    *Kind = Attribute::StructRet;
+    return false;
+  case bitc::ATTR_KIND_SANITIZE_ADDRESS:
+    *Kind = Attribute::SanitizeAddress;
+    return false;
+  case bitc::ATTR_KIND_SANITIZE_THREAD:
+    *Kind = Attribute::SanitizeThread;
+    return false;
+  case bitc::ATTR_KIND_SANITIZE_MEMORY:
+    *Kind = Attribute::SanitizeMemory;
+    return false;
+  case bitc::ATTR_KIND_UW_TABLE:
+    *Kind = Attribute::UWTable;
+    return false;
+  case bitc::ATTR_KIND_Z_EXT:
+    *Kind = Attribute::ZExt;
+    return false;
+  default:
+    std::string Buf;
+    raw_string_ostream fmt(Buf);
+    fmt << "Unknown attribute kind (" << Code << ")";
+    fmt.flush();
+    return Error(Buf.c_str());
+  }
+}
+
 bool BitcodeReader::ParseAttributeGroupBlock() {
   if (Stream.EnterSubBlock(bitc::PARAMATTR_GROUP_BLOCK_ID))
     return Error("Malformed block record");
@@ -545,9 +666,16 @@ bool BitcodeReader::ParseAttributeGroupB
       AttrBuilder B;
       for (unsigned i = 2, e = Record.size(); i != e; ++i) {
         if (Record[i] == 0) {        // Enum attribute
-          B.addAttribute(Attribute::AttrKind(Record[++i]));
+          Attribute::AttrKind Kind;
+          if (ParseAttrKind(Record[++i], &Kind))
+            return true;
+
+          B.addAttribute(Kind);
         } else if (Record[i] == 1) { // Align attribute
-          if (Attribute::AttrKind(Record[++i]) == Attribute::Alignment)
+          Attribute::AttrKind Kind;
+          if (ParseAttrKind(Record[++i], &Kind))
+            return true;
+          if (Kind == Attribute::Alignment)
             B.addAlignmentAttr(Record[++i]);
           else
             B.addStackAlignmentAttr(Record[++i]);

Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.h?rev=187186&r1=187185&r2=187186&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.h (original)
+++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.h Thu Jul 25 23:16:55 2013
@@ -321,6 +321,7 @@ private:
     return getFnValueByID(ValNo, Ty);
   }
 
+  bool ParseAttrKind(uint64_t Code, Attribute::AttrKind *Kind);
   bool ParseModule(bool Resume);
   bool ParseAttributeBlock();
   bool ParseAttributeGroupBlock();

Modified: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp?rev=187186&r1=187185&r2=187186&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp (original)
+++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp Thu Jul 25 23:16:55 2013
@@ -161,6 +161,89 @@ static void WriteStringRecord(unsigned C
   Stream.EmitRecord(Code, Vals, AbbrevToUse);
 }
 
+static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) {
+  switch (Kind) {
+  case Attribute::Alignment:
+    return bitc::ATTR_KIND_ALIGNMENT;
+  case Attribute::AlwaysInline:
+    return bitc::ATTR_KIND_ALWAYS_INLINE;
+  case Attribute::Builtin:
+    return bitc::ATTR_KIND_BUILTIN;
+  case Attribute::ByVal:
+    return bitc::ATTR_KIND_BY_VAL;
+  case Attribute::Cold:
+    return bitc::ATTR_KIND_COLD;
+  case Attribute::InlineHint:
+    return bitc::ATTR_KIND_INLINE_HINT;
+  case Attribute::InReg:
+    return bitc::ATTR_KIND_IN_REG;
+  case Attribute::MinSize:
+    return bitc::ATTR_KIND_MIN_SIZE;
+  case Attribute::Naked:
+    return bitc::ATTR_KIND_NAKED;
+  case Attribute::Nest:
+    return bitc::ATTR_KIND_NEST;
+  case Attribute::NoAlias:
+    return bitc::ATTR_KIND_NO_ALIAS;
+  case Attribute::NoBuiltin:
+    return bitc::ATTR_KIND_NO_BUILTIN;
+  case Attribute::NoCapture:
+    return bitc::ATTR_KIND_NO_CAPTURE;
+  case Attribute::NoDuplicate:
+    return bitc::ATTR_KIND_NO_DUPLICATE;
+  case Attribute::NoImplicitFloat:
+    return bitc::ATTR_KIND_NO_IMPLICIT_FLOAT;
+  case Attribute::NoInline:
+    return bitc::ATTR_KIND_NO_INLINE;
+  case Attribute::NonLazyBind:
+    return bitc::ATTR_KIND_NON_LAZY_BIND;
+  case Attribute::NoRedZone:
+    return bitc::ATTR_KIND_NO_RED_ZONE;
+  case Attribute::NoReturn:
+    return bitc::ATTR_KIND_NO_RETURN;
+  case Attribute::NoUnwind:
+    return bitc::ATTR_KIND_NO_UNWIND;
+  case Attribute::OptimizeForSize:
+    return bitc::ATTR_KIND_OPTIMIZE_FOR_SIZE;
+  case Attribute::ReadNone:
+    return bitc::ATTR_KIND_READ_NONE;
+  case Attribute::ReadOnly:
+    return bitc::ATTR_KIND_READ_ONLY;
+  case Attribute::Returned:
+    return bitc::ATTR_KIND_RETURNED;
+  case Attribute::ReturnsTwice:
+    return bitc::ATTR_KIND_RETURNS_TWICE;
+  case Attribute::SExt:
+    return bitc::ATTR_KIND_S_EXT;
+  case Attribute::StackAlignment:
+    return bitc::ATTR_KIND_STACK_ALIGNMENT;
+  case Attribute::StackProtect:
+    return bitc::ATTR_KIND_STACK_PROTECT;
+  case Attribute::StackProtectReq:
+    return bitc::ATTR_KIND_STACK_PROTECT_REQ;
+  case Attribute::StackProtectStrong:
+    return bitc::ATTR_KIND_STACK_PROTECT_STRONG;
+  case Attribute::StructRet:
+    return bitc::ATTR_KIND_STRUCT_RET;
+  case Attribute::SanitizeAddress:
+    return bitc::ATTR_KIND_SANITIZE_ADDRESS;
+  case Attribute::SanitizeThread:
+    return bitc::ATTR_KIND_SANITIZE_THREAD;
+  case Attribute::SanitizeMemory:
+    return bitc::ATTR_KIND_SANITIZE_MEMORY;
+  case Attribute::UWTable:
+    return bitc::ATTR_KIND_UW_TABLE;
+  case Attribute::ZExt:
+    return bitc::ATTR_KIND_Z_EXT;
+  case Attribute::EndAttrKinds:
+    llvm_unreachable("Can not encode end-attribute kinds marker.");
+  case Attribute::None:
+    llvm_unreachable("Can not encode none-attribute.");
+  }
+
+  llvm_unreachable("Trying to encode unknown attribute");
+}
+
 static void WriteAttributeGroupTable(const ValueEnumerator &VE,
                                      BitstreamWriter &Stream) {
   const std::vector<AttributeSet> &AttrGrps = VE.getAttributeGroups();
@@ -182,10 +265,10 @@ static void WriteAttributeGroupTable(con
         Attribute Attr = *I;
         if (Attr.isEnumAttribute()) {
           Record.push_back(0);
-          Record.push_back(Attr.getKindAsEnum());
+          Record.push_back(getAttrKindEncoding(Attr.getKindAsEnum()));
         } else if (Attr.isAlignAttribute()) {
           Record.push_back(1);
-          Record.push_back(Attr.getKindAsEnum());
+          Record.push_back(getAttrKindEncoding(Attr.getKindAsEnum()));
           Record.push_back(Attr.getValueAsInt());
         } else {
           StringRef Kind = Attr.getKindAsString();

Added: llvm/trunk/test/Bitcode/attributes-3.3.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/attributes-3.3.ll?rev=187186&view=auto
==============================================================================
--- llvm/trunk/test/Bitcode/attributes-3.3.ll (added)
+++ llvm/trunk/test/Bitcode/attributes-3.3.ll Thu Jul 25 23:16:55 2013
@@ -0,0 +1,236 @@
+; RUN:  llvm-dis < %s.bc| FileCheck %s
+
+; attributes-3.3.ll.bc was generated by passing this file to llvm-as-3.3.
+; The test checks that LLVM does not silently misread attributes of
+; older bitcode files.
+
+define void @f1(i8 zeroext)
+; CHECK: define void @f1(i8 zeroext)
+{
+        ret void;
+}
+
+define void @f2(i8 signext)
+; CHECK: define void @f2(i8 signext)
+{
+        ret void;
+}
+
+define void @f3() noreturn
+; CHECK: define void @f3() #0
+{
+        ret void;
+}
+
+define void @f4(i8 inreg)
+; CHECK: define void @f4(i8 inreg)
+{
+        ret void;
+}
+
+define void @f5(i8* sret)
+; CHECK: define void @f5(i8* sret)
+{
+        ret void;
+}
+
+define void @f6() nounwind
+; CHECK: define void @f6() #1
+{
+        ret void;
+}
+
+define void @f7(i8* noalias)
+; CHECK: define void @f7(i8* noalias)
+{
+        ret void;
+}
+
+define void @f8(i8* byval)
+; CHECK: define void @f8(i8* byval)
+{
+        ret void;
+}
+
+define void @f9(i8* nest)
+; CHECK: define void @f9(i8* nest)
+{
+        ret void;
+}
+
+define void @f10() readnone
+; CHECK: define void @f10() #2
+{
+        ret void;
+}
+
+define void @f11() readonly
+; CHECK: define void @f11() #3
+{
+        ret void;
+}
+
+define void @f12() noinline
+; CHECK: define void @f12() #4
+{
+        ret void;
+}
+
+define void @f13() alwaysinline
+; CHECK: define void @f13() #5
+{
+        ret void;
+}
+
+define void @f14() optsize
+; CHECK: define void @f14() #6
+{
+        ret void;
+}
+
+define void @f15() ssp
+; CHECK: define void @f15() #7
+{
+        ret void;
+}
+
+define void @f16() sspreq
+; CHECK: define void @f16() #8
+{
+        ret void;
+}
+
+define void @f17(i8 align 4)
+; CHECK: define void @f17(i8 align 4)
+{
+        ret void;
+}
+
+define void @f18(i8* nocapture)
+; CHECK: define void @f18(i8* nocapture)
+{
+        ret void;
+}
+
+define void @f19() noredzone
+; CHECK: define void @f19() #9
+{
+        ret void;
+}
+
+define void @f20() noimplicitfloat
+; CHECK: define void @f20() #10
+{
+        ret void;
+}
+
+define void @f21() naked
+; CHECK: define void @f21() #11
+{
+        ret void;
+}
+
+define void @f22() inlinehint
+; CHECK: define void @f22() #12
+{
+        ret void;
+}
+
+define void @f23() alignstack(4)
+; CHECK: define void @f23() #13
+{
+        ret void;
+}
+
+define void @f24() returns_twice
+; CHECK: define void @f24() #14
+{
+        ret void;
+}
+
+define void @f25() uwtable
+; CHECK: define void @f25() #15
+{
+        ret void;
+}
+
+define void @f26() nonlazybind
+; CHECK: define void @f26() #16
+{
+        ret void;
+}
+
+define void @f27() sanitize_address
+; CHECK: define void @f27() #17
+{
+        ret void;
+}
+define void @f28() sanitize_thread
+; CHECK: define void @f28() #18
+{
+        ret void;
+}
+define void @f29() sanitize_memory
+; CHECK: define void @f29() #19
+{
+        ret void;
+}
+
+define void @f30() "cpu"="cortex-a8"
+; CHECK: define void @f30() #20
+{
+        ret void;
+}
+
+define i8 @f31(i8 returned %A)
+; CHECK: define i8 @f31(i8 returned %A)
+{
+        ret i8 %A;
+}
+
+define void @f32() sspstrong
+; CHECK: define void @f32() #21
+{
+        ret void;
+}
+
+define void @f33() minsize
+; CHECK: define void @f33() #22
+{
+        ret void;
+}
+
+declare void @nobuiltin()
+
+define void @f34()
+; CHECK: define void @f34()
+{
+        call void @nobuiltin() nobuiltin
+; CHECK: call void @nobuiltin() #23
+        ret void;
+}
+
+; CHECK: attributes #0 = { noreturn }
+; CHECK: attributes #1 = { nounwind }
+; CHECK: attributes #2 = { readnone }
+; CHECK: attributes #3 = { readonly }
+; CHECK: attributes #4 = { noinline }
+; CHECK: attributes #5 = { alwaysinline }
+; CHECK: attributes #6 = { optsize }
+; CHECK: attributes #7 = { ssp }
+; CHECK: attributes #8 = { sspreq }
+; CHECK: attributes #9 = { noredzone }
+; CHECK: attributes #10 = { noimplicitfloat }
+; CHECK: attributes #11 = { naked }
+; CHECK: attributes #12 = { inlinehint }
+; CHECK: attributes #13 = { alignstack=4 }
+; CHECK: attributes #14 = { returns_twice }
+; CHECK: attributes #15 = { uwtable }
+; CHECK: attributes #16 = { nonlazybind }
+; CHECK: attributes #17 = { sanitize_address }
+; CHECK: attributes #18 = { sanitize_thread }
+; CHECK: attributes #19 = { sanitize_memory }
+; CHECK: attributes #20 = { "cpu"="cortex-a8" }
+; CHECK: attributes #21 = { sspstrong }
+; CHECK: attributes #22 = { minsize }
+; CHECK: attributes #23 = { nobuiltin }

Added: llvm/trunk/test/Bitcode/attributes-3.3.ll.bc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/attributes-3.3.ll.bc?rev=187186&view=auto
==============================================================================
Binary files llvm/trunk/test/Bitcode/attributes-3.3.ll.bc (added) and llvm/trunk/test/Bitcode/attributes-3.3.ll.bc Thu Jul 25 23:16:55 2013 differ





More information about the llvm-commits mailing list