[JITLink] Add a -slab-address option to llvm-jitlink.

This option can be used to for JITLink to link as-if the target memory slab were
allocated at a specific start address. This can be used to both verify that
cross-address space linking is working correctly, and to ensure that certain
address-sensitive optimizations (e.g. GOT and stub elimination) either do or do
not fire, depending on the requirements of the test case.

This argument is only valid for testing in conjunction with -noexec -slab-alloc,
and will produce an error if used without those arguments.
diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
index 3f40f7d..3e444e6 100644
--- a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
+++ b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
@@ -112,6 +112,11 @@
              "Kb)"),
     cl::init(""));
 
+static cl::opt<uint64_t> SlabAddress(
+    "slab-address",
+    cl::desc("Set slab target address (requires -slab-allocate and -noexec)"),
+    cl::init(~0ULL));
+
 static cl::opt<bool> ShowRelocatedSectionContents(
     "show-relocated-section-contents",
     cl::desc("show section contents after fixups have been applied"),
@@ -250,7 +255,8 @@
     // Local class for allocation.
     class IPMMAlloc : public Allocation {
     public:
-      IPMMAlloc(AllocationMap SegBlocks) : SegBlocks(std::move(SegBlocks)) {}
+      IPMMAlloc(JITLinkSlabAllocator &Parent, AllocationMap SegBlocks)
+          : Parent(Parent), SegBlocks(std::move(SegBlocks)) {}
       MutableArrayRef<char> getWorkingMemory(ProtectionFlags Seg) override {
         assert(SegBlocks.count(Seg) && "No allocation for segment");
         return {static_cast<char *>(SegBlocks[Seg].base()),
@@ -258,7 +264,8 @@
       }
       JITTargetAddress getTargetMemory(ProtectionFlags Seg) override {
         assert(SegBlocks.count(Seg) && "No allocation for segment");
-        return reinterpret_cast<JITTargetAddress>(SegBlocks[Seg].base());
+        return pointerToJITTargetAddress(SegBlocks[Seg].base()) +
+               Parent.TargetDelta;
       }
       void finalizeAsync(FinalizeContinuation OnFinalize) override {
         OnFinalize(applyProtections());
@@ -284,6 +291,7 @@
         return Error::success();
       }
 
+      JITLinkSlabAllocator &Parent;
       AllocationMap SegBlocks;
     };
 
@@ -329,7 +337,7 @@
       Blocks[KV.first] = std::move(SegMem);
     }
     return std::unique_ptr<InProcessMemoryManager::Allocation>(
-        new IPMMAlloc(std::move(Blocks)));
+        new IPMMAlloc(*this, std::move(Blocks)));
   }
 
 private:
@@ -359,10 +367,17 @@
       Err = errorCodeToError(EC);
       return;
     }
+
+    // Calculate the target address delta to link as-if slab were at
+    // SlabAddress.
+    if (SlabAddress != ~0ULL)
+      TargetDelta =
+          SlabAddress - pointerToJITTargetAddress(SlabRemaining.base());
   }
 
   sys::MemoryBlock SlabRemaining;
   uint64_t PageSize = 0;
+  int64_t TargetDelta = 0;
 };
 
 Expected<uint64_t> getSlabAllocSize(StringRef SizeString) {
@@ -566,6 +581,14 @@
   if (NoExec && !InputArgv.empty())
     outs() << "Warning: --args passed to -noexec run will be ignored.\n";
 
+  // If -slab-address is passed, require -slab-allocate and -noexec
+  if (SlabAddress != ~0ULL) {
+    if (SlabAllocateSizeString == "" || !NoExec)
+      return make_error<StringError>(
+          "-slab-address requires -slab-allocate and -noexec",
+          inconvertibleErrorCode());
+  }
+
   return Error::success();
 }