#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"
#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/OperandTraits.h"
#include "llvm/IR/Operator.h"
#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 {
}
// Create and return a placeholder, which will later be RAUW'd.
- Value *V = MDNode::getTemporary(Context, ArrayRef<Value*>());
+ Value *V = MDNode::getTemporary(Context, None);
MDValuePtrs[Idx] = V;
return V;
}
if (Alignment)
B.addAlignmentAttr(Alignment);
- B.addRawValue(((EncodedAttrs & (0xffffULL << 32)) >> 11) |
+ B.addRawValue(((EncodedAttrs & (0xfffffULL << 32)) >> 11) |
(EncodedAttrs & 0xffff));
}
Attrs.clear();
break;
}
+ case bitc::PARAMATTR_CODE_ENTRY: { // ENTRY: [attrgrp0, attrgrp1, ...]
+ for (unsigned i = 0, e = Record.size(); i != e; ++i)
+ Attrs.push_back(MAttributeGroups[Record[i]]);
+
+ MAttributes.push_back(AttributeSet::get(Context, Attrs));
+ Attrs.clear();
+ break;
+ }
+ }
+ }
+}
+
+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_OPTIMIZE_NONE:
+ *Kind = Attribute::OptimizeNone;
+ 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");
+
+ if (!MAttributeGroups.empty())
+ return Error("Multiple PARAMATTR_GROUP blocks found!");
+
+ SmallVector<uint64_t, 64> Record;
+
+ // Read all the records.
+ while (1) {
+ BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+
+ switch (Entry.Kind) {
+ case BitstreamEntry::SubBlock: // Handled for us already.
+ case BitstreamEntry::Error:
+ return Error("Error at end of PARAMATTR_GROUP block");
+ case BitstreamEntry::EndBlock:
+ return false;
+ case BitstreamEntry::Record:
+ // The interesting case.
+ break;
+ }
+
+ // Read a record.
+ Record.clear();
+ switch (Stream.readRecord(Entry.ID, Record)) {
+ default: // Default behavior: ignore.
+ break;
+ case bitc::PARAMATTR_GRP_CODE_ENTRY: { // ENTRY: [grpid, idx, a0, a1, ...]
+ if (Record.size() < 3)
+ return Error("Invalid ENTRY record");
+
+ uint64_t GrpID = Record[0];
+ uint64_t Idx = Record[1]; // Index of the object this attribute refers to.
+
+ AttrBuilder B;
+ for (unsigned i = 2, e = Record.size(); i != e; ++i) {
+ if (Record[i] == 0) { // Enum attribute
+ Attribute::AttrKind Kind;
+ if (ParseAttrKind(Record[++i], &Kind))
+ return true;
+
+ B.addAttribute(Kind);
+ } else if (Record[i] == 1) { // Align attribute
+ Attribute::AttrKind Kind;
+ if (ParseAttrKind(Record[++i], &Kind))
+ return true;
+ if (Kind == Attribute::Alignment)
+ B.addAlignmentAttr(Record[++i]);
+ else
+ B.addStackAlignmentAttr(Record[++i]);
+ } else { // String attribute
+ assert((Record[i] == 3 || Record[i] == 4) &&
+ "Invalid attribute group entry");
+ bool HasValue = (Record[i++] == 4);
+ SmallString<64> KindStr;
+ SmallString<64> ValStr;
+
+ while (Record[i] != 0 && i != e)
+ KindStr += Record[i++];
+ assert(Record[i] == 0 && "Kind string not null terminated");
+
+ if (HasValue) {
+ // Has a value associated with it.
+ ++i; // Skip the '0' that terminates the "kind" string.
+ while (Record[i] != 0 && i != e)
+ ValStr += Record[i++];
+ assert(Record[i] == 0 && "Value string not null terminated");
+ }
+
+ B.addAttribute(KindStr.str(), ValStr.str());
+ }
+ }
+
+ MAttributeGroups[GrpID] = AttributeSet::get(Context, Idx, B);
+ break;
+ }
}
}
}
bool BitcodeReader::ResolveGlobalAndAliasInits() {
std::vector<std::pair<GlobalVariable*, unsigned> > GlobalInitWorklist;
std::vector<std::pair<GlobalAlias*, unsigned> > AliasInitWorklist;
+ std::vector<std::pair<Function*, unsigned> > FunctionPrefixWorklist;
GlobalInitWorklist.swap(GlobalInits);
AliasInitWorklist.swap(AliasInits);
+ FunctionPrefixWorklist.swap(FunctionPrefixes);
while (!GlobalInitWorklist.empty()) {
unsigned ValID = GlobalInitWorklist.back().second;
}
AliasInitWorklist.pop_back();
}
+
+ while (!FunctionPrefixWorklist.empty()) {
+ unsigned ValID = FunctionPrefixWorklist.back().second;
+ if (ValID >= ValueList.size()) {
+ FunctionPrefixes.push_back(FunctionPrefixWorklist.back());
+ } else {
+ if (Constant *C = dyn_cast<Constant>(ValueList[ValID]))
+ FunctionPrefixWorklist.back().first->setPrefixData(C);
+ else
+ return Error("Function prefix is not a constant!");
+ }
+ FunctionPrefixWorklist.pop_back();
+ }
+
return false;
}
bitc::CST_CODE_CE_INBOUNDS_GEP);
break;
}
- case bitc::CST_CODE_CE_SELECT: // CE_SELECT: [opval#, opval#, opval#]
+ case bitc::CST_CODE_CE_SELECT: { // CE_SELECT: [opval#, opval#, opval#]
if (Record.size() < 3) return Error("Invalid CE_SELECT record");
- V = ConstantExpr::getSelect(
- ValueList.getConstantFwdRef(Record[0],
- Type::getInt1Ty(Context)),
- ValueList.getConstantFwdRef(Record[1],CurTy),
- ValueList.getConstantFwdRef(Record[2],CurTy));
+
+ Type *SelectorTy = Type::getInt1Ty(Context);
+
+ // If CurTy is a vector of length n, then Record[0] must be a <n x i1>
+ // vector. Otherwise, it must be a single bit.
+ if (VectorType *VTy = dyn_cast<VectorType>(CurTy))
+ SelectorTy = VectorType::get(Type::getInt1Ty(Context),
+ VTy->getNumElements());
+
+ V = ConstantExpr::getSelect(ValueList.getConstantFwdRef(Record[0],
+ SelectorTy),
+ ValueList.getConstantFwdRef(Record[1],CurTy),
+ ValueList.getConstantFwdRef(Record[2],CurTy));
break;
+ }
case bitc::CST_CODE_CE_EXTRACTELT: { // CE_EXTRACTELT: [opty, opval, opval]
if (Record.size() < 3) return Error("Invalid CE_EXTRACTELT record");
VectorType *OpTy =
if (ParseAttributeBlock())
return true;
break;
+ case bitc::PARAMATTR_GROUP_BLOCK_ID:
+ if (ParseAttributeGroupBlock())
+ return true;
+ break;
case bitc::TYPE_BLOCK_ID_NEW:
if (ParseTypeTable())
return true;
if (Record.size() > 9)
UnnamedAddr = Record[9];
Func->setUnnamedAddr(UnnamedAddr);
+ if (Record.size() > 10 && Record[10] != 0)
+ FunctionPrefixes.push_back(std::make_pair(Func, Record[10]-1));
ValueList.push_back(Func);
// If this is a function with a body, remember the prototype we are
return Error("Invalid metadata kind ID");
Value *Node = MDValueList.getValueFwdRef(Record[i+1]);
Inst->setMetadata(I->second, cast<MDNode>(Node));
+ if (I->second == LLVMContext::MD_tbaa)
+ InstsWithTBAATag.push_back(Inst);
}
break;
}
case bitc::FUNC_CODE_INST_SWITCH: { // SWITCH: [opty, op0, op1, ...]
// Check magic
if ((Record[0] >> 16) == SWITCH_INST_MAGIC) {
- // New SwitchInst format with case ranges.
+ // "New" SwitchInst format with case ranges. The changes to write this
+ // format were reverted but we still recognize bitcode that uses it.
+ // Hopefully someday we will have support for case ranges and can use
+ // this format again.
Type *OpTy = getTypeByID(Record[1]);
unsigned ValueBitWidth = cast<IntegerType>(OpTy)->getBitWidth();
unsigned CurIdx = 5;
for (unsigned i = 0; i != NumCases; ++i) {
- IntegersSubsetToBB CaseBuilder;
+ SmallVector<ConstantInt*, 1> CaseVals;
unsigned NumItems = Record[CurIdx++];
for (unsigned ci = 0; ci != NumItems; ++ci) {
bool isSingleNumber = Record[CurIdx++];
APInt High =
ReadWideAPInt(makeArrayRef(&Record[CurIdx], ActiveWords),
ValueBitWidth);
-
- CaseBuilder.add(IntItem::fromType(OpTy, Low),
- IntItem::fromType(OpTy, High));
CurIdx += ActiveWords;
+
+ // FIXME: It is not clear whether values in the range should be
+ // compared as signed or unsigned values. The partially
+ // implemented changes that used this format in the past used
+ // unsigned comparisons.
+ for ( ; Low.ule(High); ++Low)
+ CaseVals.push_back(ConstantInt::get(Context, Low));
} else
- CaseBuilder.add(IntItem::fromType(OpTy, Low));
+ CaseVals.push_back(ConstantInt::get(Context, Low));
}
BasicBlock *DestBB = getBasicBlock(Record[CurIdx++]);
- IntegersSubset Case = CaseBuilder.getCase();
- SI->addCase(Case, DestBB);
+ for (SmallVector<ConstantInt*, 1>::iterator cvi = CaseVals.begin(),
+ cve = CaseVals.end(); cvi != cve; ++cvi)
+ SI->addCase(*cvi, DestBB);
}
- uint16_t Hash = SI->hash();
- if (Hash != (Record[0] & 0xFFFF))
- return Error("Invalid SWITCH record");
I = SI;
break;
}
}
std::vector<std::pair<Function*, Function*> >().swap(UpgradedIntrinsics);
+ for (unsigned I = 0, E = InstsWithTBAATag.size(); I < E; I++)
+ UpgradeInstWithTBAATag(InstsWithTBAATag[I]);
+
return false;
}
Stream.init(*StreamFile);
unsigned char buf[16];
- if (Bytes->readBytes(0, 16, buf, NULL) == -1)
+ if (Bytes->readBytes(0, 16, buf) == -1)
return Error("Bitcode stream must be at least 16 bytes in length");
if (!isBitcode(buf, buf + 16))