Fix --filetype=iasm non-pc-rel fixup offsets (double counted).

For pc-rel fixups, we have a ConstantRelocatable referring
to Foo+0, and and the offset "-4" is encoded in the code
buffer (but not the ConstantRelocatable object). Thus we
need to load from the code buffer in order to
get that "-4" instead of just taking the +0 from Foo+0.

For non-pc-rel fixups, we have the ConstantRelocatable
with a true offset, and we also write that offset into the
code buffer (for ELF REL and not RELA, it expects the
offset in the code buffer). In this case, we want to choose
one and not double-count.

BUG=none
176.gcc seemed to be failing when compiled with --filetype=iasm...
load address for 64-bit pointers were +8 instead of +4

R=stichnot@chromium.org

Review URL: https://codereview.chromium.org/1241313002 .
diff --git a/src/IceAssembler.cpp b/src/IceAssembler.cpp
index 48db036..5c1760b 100644
--- a/src/IceAssembler.cpp
+++ b/src/IceAssembler.cpp
@@ -132,6 +132,10 @@
       Str << "\n";
     }
     Str << "\t.long ";
+    // For PCRel fixups, we write the pc-offset from a symbol into the Buffer
+    // (e.g., -4), but we don't represent that in the fixup's offset.
+    // Otherwise the fixup holds the true offset, and so does the Buffer.
+    // Just load the offset from the buffer.
     NextFixup->emit(Ctx, Buffer.load<RelocOffsetT>(NextFixupLoc));
     if (fixupIsPCRel(NextFixup->kind()))
       Str << " - .";
diff --git a/src/IceELFSection.h b/src/IceELFSection.h
index 0ee3f03..5cf89a5 100644
--- a/src/IceELFSection.h
+++ b/src/IceELFSection.h
@@ -362,6 +362,8 @@
       llvm::report_fatal_error("Missing symbol mentioned in reloc");
 
     if (IsELF64) {
+      llvm_unreachable(
+          "Not tested -- check that Fixup.offset() is correct even for pc-rel");
       Elf64_Rela Rela;
       Rela.r_offset = Fixup.position();
       Rela.setSymbolAndType(Symbol->getNumber(), Fixup.kind());
diff --git a/src/IceFixups.cpp b/src/IceFixups.cpp
index de00d23..ff7916c 100644
--- a/src/IceFixups.cpp
+++ b/src/IceFixups.cpp
@@ -48,7 +48,8 @@
   return Str.str();
 }
 
-void AssemblerFixup::emit(GlobalContext *Ctx, RelocOffsetT BaseOffset) const {
+void AssemblerFixup::emit(GlobalContext *Ctx,
+                          RelocOffsetT OverrideOffset) const {
   if (!BuildDefs::dump())
     return;
   Ostream &Str = Ctx->getStrEmit();
@@ -56,7 +57,7 @@
     Str << "__Sz_AbsoluteZero";
   else
     Str << symbol(Ctx);
-  RelocOffsetT Offset = offset() + BaseOffset;
+  RelocOffsetT Offset = OverrideOffset;
   if (Offset)
     Str << " + " << Offset;
 }
diff --git a/src/IceFixups.h b/src/IceFixups.h
index f040918..3b79a92 100644
--- a/src/IceFixups.h
+++ b/src/IceFixups.h
@@ -45,7 +45,7 @@
 
   void set_value(const Constant *Value) { value_ = Value; }
 
-  void emit(GlobalContext *Ctx, RelocOffsetT BaseOffset) const;
+  void emit(GlobalContext *Ctx, RelocOffsetT OverrideOffset) const;
 
 private:
   intptr_t position_ = 0;
diff --git a/tests_lit/llvm2ice_tests/ias-data-reloc.ll b/tests_lit/llvm2ice_tests/ias-data-reloc.ll
new file mode 100644
index 0000000..d265d40
--- /dev/null
+++ b/tests_lit/llvm2ice_tests/ias-data-reloc.ll
@@ -0,0 +1,18 @@
+; Tests the integrated assembler for instructions with a reloc + offset.
+
+; RUN: %if --need=target_X8632 --need=allow_dump \
+; RUN:   --command %p2i --target x8632 -i %s --args -O2 \
+; RUN:   | %if --need=target_X8632 --need=allow_dump --command FileCheck %s
+
+@p_global_char = internal global [8 x i8] zeroinitializer, align 8
+
+define internal void @reloc_in_global(i64 %x) {
+entry:
+  %p_global_char.bc = bitcast [8 x i8]* @p_global_char to i64*
+  ; This 64-bit load is split into an i32 store to [p_global_char]
+  ; and an i32 store to [p_global_char + 4] on 32-bit architectures.
+  store i64 %x, i64* %p_global_char.bc, align 1
+  ret void
+}
+; CHECK-LABEL: reloc_in_global
+; CHECK: .long p_global_char + 4