add bitcode reader support for blockaddress. We can now fully
authorChris Lattner <sabre@nondot.org>
Wed, 28 Oct 2009 05:53:48 +0000 (05:53 +0000)
committerChris Lattner <sabre@nondot.org>
Wed, 28 Oct 2009 05:53:48 +0000 (05:53 +0000)
round trip blockaddress through .ll and .bc files, so add a testcase.

There are still a bunch of places in the optimizer and other places
that need to be updated to work with these constructs, but at least
the basics are in now.

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

lib/Bitcode/Reader/BitcodeReader.cpp
lib/Bitcode/Reader/BitcodeReader.h
test/Feature/terminators.ll

index 1326b68ac59680cb696416a26e52d21f2d613f0f..68527e3d474992102661fe95bb111ef951888fac 100644 (file)
@@ -1192,6 +1192,22 @@ bool BitcodeReader::ParseConstants() {
                          AsmStr, ConstrStr, HasSideEffects, IsAlignStack);
       break;
     }
+    case bitc::CST_CODE_BLOCKADDRESS:{
+      if (Record.size() < 3) return Error("Invalid CE_BLOCKADDRESS record");
+      const Type *FnTy = getTypeByID(Record[0]);
+      if (FnTy == 0) return Error("Invalid CE_BLOCKADDRESS record");
+      Function *Fn =
+        dyn_cast_or_null<Function>(ValueList.getConstantFwdRef(Record[1],FnTy));
+      if (Fn == 0) return Error("Invalid CE_BLOCKADDRESS record");
+      
+      GlobalVariable *FwdRef = new GlobalVariable(*Fn->getParent(),
+                                                  Type::getInt8Ty(Context),
+                                            false, GlobalValue::InternalLinkage,
+                                                  0, "");
+      BlockAddrFwdRefs[Fn].push_back(std::make_pair(Record[2], FwdRef));
+      V = FwdRef;
+      break;
+    }  
     }
 
     ValueList.AssignValue(V, NextCstNo);
@@ -2248,6 +2264,27 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
     }
   }
 
+  // See if anything took the address of blocks in this function.  If so,
+  // resolve them now.
+  /// BlockAddrFwdRefs - These are blockaddr references to basic blocks.  These
+  /// are resolved lazily when functions are loaded.
+  DenseMap<Function*, std::vector<BlockAddrRefTy> >::iterator BAFRI =
+    BlockAddrFwdRefs.find(F);
+  if (BAFRI != BlockAddrFwdRefs.end()) {
+    std::vector<BlockAddrRefTy> &RefList = BAFRI->second;
+    for (unsigned i = 0, e = RefList.size(); i != e; ++i) {
+      unsigned BlockIdx = RefList[i].first;
+      if (BlockIdx >= FunctionBBs.size())
+        return Error("Invalid blockaddress block #");
+    
+      GlobalVariable *FwdRef = RefList[i].second;
+      FwdRef->replaceAllUsesWith(BlockAddress::get(F, FunctionBBs[BlockIdx]));
+      FwdRef->eraseFromParent();
+    }
+    
+    BlockAddrFwdRefs.erase(BAFRI);
+  }
+  
   // Trim the value list down to the size it was before we parsed this function.
   ValueList.shrinkTo(ModuleValueListSize);
   std::vector<BasicBlock*>().swap(FunctionBBs);
index eefc7bdc28a8ec77421a42f6b08c7416285a0739..7b3a1ae893c292c4aaebd25cecd8a8df92bcf423 100644 (file)
@@ -94,7 +94,7 @@ public:
 class BitcodeReaderMDValueList {
   std::vector<WeakVH> MDValuePtrs;
   
-  LLVMContextContext;
+  LLVMContext &Context;
 public:
   BitcodeReaderMDValueList(LLVMContext& C) : Context(C) {}
 
@@ -122,7 +122,7 @@ public:
 };
 
 class BitcodeReader : public ModuleProvider {
-  LLVMContextContext;
+  LLVMContext &Context;
   MemoryBuffer *Buffer;
   BitstreamReader StreamFile;
   BitstreamCursor Stream;
@@ -163,6 +163,12 @@ class BitcodeReader : public ModuleProvider {
   /// map contains info about where to find deferred function body (in the
   /// stream) and what linkage the original function had.
   DenseMap<Function*, std::pair<uint64_t, unsigned> > DeferredFunctionInfo;
+  
+  /// BlockAddrFwdRefs - These are blockaddr references to basic blocks.  These
+  /// are resolved lazily when functions are loaded.
+  typedef std::pair<unsigned, GlobalVariable*> BlockAddrRefTy;
+  DenseMap<Function*, std::vector<BlockAddrRefTy> > BlockAddrFwdRefs;
+  
 public:
   explicit BitcodeReader(MemoryBuffer *buffer, LLVMContext& C)
     : Context(C), Buffer(buffer), ErrorString(0), ValueList(C), MDValueList(C) {
index d3c68a71429375a4df90ea6f4aa095d02c5b4656..1bca2a842c5d2783ddbf856325a43eab71963972 100644 (file)
@@ -25,13 +25,19 @@ Case4:          ; preds = %0
 }
 
 
+@Addr = global i8* blockaddress(@indbrtest, %BB1)
+@Addr3 = global i8* blockaddress(@squared, %Case1)
+
 
 define i32 @indbrtest(i8* %P, i32* %Q) {
   indirectbr i8* %P, [label %BB1, label %BB2, label %BB3]
 BB1:
   indirectbr i32* %Q, []
 BB2:
-  indirectbr i32* %Q, [label %BB1, label %BB2]
+  %R = bitcast i8* blockaddress(@indbrtest, %BB3) to i8*
+  indirectbr i8* %R, [label %BB1, label %BB2, label %BB3]
 BB3:
   ret i32 2
 }
+
+