<div dir="ltr">Nice!<div><br></div><div>Thanks very much for working on this Juergen.</div><div><br></div><div>- Lang.</div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, Jul 22, 2014 at 2:42 PM, Juergen Ributzka <span dir="ltr"><<a href="mailto:juergen@apple.com" target="_blank">juergen@apple.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: ributzka<br>
Date: Tue Jul 22 16:42:55 2014<br>
New Revision: 213689<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=213689&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=213689&view=rev</a><br>
Log:<br>
[RuntimeDyld][MachO][AArch64] Add a helper function for encoding addends in instructions.<br>
<br>
Factor out the addend encoding into a helper function and simplify the<br>
processRelocationRef.<br>
<br>
Also add a few simple rtdyld tests. More tests to come once GOTs can be tested too.<br>
<br>
Related to <rdar://problem/17768539><br>
<br>
Added:<br>
    llvm/trunk/test/ExecutionEngine/RuntimeDyld/AArch64/<br>
    llvm/trunk/test/ExecutionEngine/RuntimeDyld/AArch64/MachO_ARM64_relocations.s<br>
    llvm/trunk/test/ExecutionEngine/RuntimeDyld/AArch64/lit.local.cfg<br>
Modified:<br>
    llvm/trunk/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h<br>
<br>
Modified: llvm/trunk/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h?rev=213689&r1=213688&r2=213689&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h?rev=213689&r1=213688&r2=213689&view=diff</a><br>

==============================================================================<br>
--- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h (original)<br>
+++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h Tue Jul 22 16:42:55 2014<br>
@@ -118,6 +118,109 @@ public:<br>
     return Addend;<br>
   }<br>
<br>
+  /// Extract the addend encoded in the instruction.<br>
+  void encodeAddend(uint8_t *LocalAddress, uint32_t RelType,<br>
+                    int64_t Addend) const {<br>
+    // Verify that the relocation has the correct alignment.<br>
+    switch (RelType) {<br>
+    default:<br>
+      llvm_unreachable("Unsupported relocation type!");<br>
+    case MachO::ARM64_RELOC_UNSIGNED:<br>
+      llvm_unreachable("Invalid relocation type for instruction.");<br>
+    case MachO::ARM64_RELOC_BRANCH26:<br>
+    case MachO::ARM64_RELOC_PAGE21:<br>
+    case MachO::ARM64_RELOC_PAGEOFF12:<br>
+    case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:<br>
+    case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12:<br>
+      assert((((uintptr_t)LocalAddress & 0x3) == 0) &&<br>
+             "Instruction address is not aligned to 4 bytes.");<br>
+      break;<br>
+    }<br>
+<br>
+    switch (RelType) {<br>
+    default:<br>
+      llvm_unreachable("Unsupported relocation type!");<br>
+    case MachO::ARM64_RELOC_BRANCH26: {<br>
+      // Verify that the relocation points to the expected branch instruction.<br>
+      uint32_t *p = (uint32_t *)LocalAddress;<br>
+      assert((*p & 0xFC000000) == 0x14000000 && "Expected branch instruction.");<br>
+<br>
+      // Verify addend value.<br>
+      assert((Addend & 0x3) == 0 && "Branch target is not aligned");<br>
+      assert(isInt<28>(Addend) && "Branch target is out of range.");<br>
+<br>
+      // Encode the addend as 26 bit immediate in the branch instruction.<br>
+      *p = (*p & 0xFC000000) | ((uint32_t)(Addend >> 2) & 0x03FFFFFF);<br>
+      break;<br>
+    }<br>
+    case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:<br>
+    case MachO::ARM64_RELOC_PAGE21: {<br>
+      // Verify that the relocation points to the expected adrp instruction.<br>
+      uint32_t *p = (uint32_t *)LocalAddress;<br>
+      assert((*p & 0x9F000000) == 0x90000000 && "Expected adrp instruction.");<br>
+<br>
+      // Check that the addend fits into 21 bits (+ 12 lower bits).<br>
+      assert((Addend & 0xFFF) == 0 && "ADRP target is not page aligned.");<br>
+      assert(isInt<33>(Addend) && "Invalid page reloc value.");<br>
+<br>
+      // Encode the addend into the instruction.<br>
+      uint32_t ImmLoValue = (uint32_t)(Addend << 17) & 0x60000000;<br>
+      uint32_t ImmHiValue = (uint32_t)(Addend >> 9) & 0x00FFFFE0;<br>
+      *p = (*p & 0x9F00001F) | ImmHiValue | ImmLoValue;<br>
+      break;<br>
+    }<br>
+    case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: {<br>
+      // Verify that the relocation points to one of the expected load / store<br>
+      // instructions.<br>
+      uint32_t *p = (uint32_t *)LocalAddress;<br>
+      assert((*p & 0x3B000000) == 0x39000000 &&<br>
+             "Only expected load / store instructions.");<br>
+    } // fall-through<br>
+    case MachO::ARM64_RELOC_PAGEOFF12: {<br>
+      // Verify that the relocation points to one of the expected load / store<br>
+      // or add / sub instructions.<br>
+      uint32_t *p = (uint32_t *)LocalAddress;<br>
+      assert((((*p & 0x3B000000) == 0x39000000) ||<br>
+              ((*p & 0x11C00000) == 0x11000000)   ) &&<br>
+             "Expected load / store  or add/sub instruction.");<br>
+<br>
+      // Check which instruction we are decoding to obtain the implicit shift<br>
+      // factor of the instruction and verify alignment.<br>
+      int ImplicitShift = 0;<br>
+      if ((*p & 0x3B000000) == 0x39000000) { // << load / store<br>
+        // For load / store instructions the size is encoded in bits 31:30.<br>
+        ImplicitShift = ((*p >> 30) & 0x3);<br>
+        switch (ImplicitShift) {<br>
+        case 0:<br>
+          // Check if this a vector op to get the correct shift value.<br>
+          if ((*p & 0x04800000) == 0x04800000) {<br>
+            ImplicitShift = 4;<br>
+            assert(((Addend & 0xF) == 0) &&<br>
+                   "128-bit LDR/STR not 16-byte aligned.");<br>
+          }<br>
+          break;<br>
+        case 1:<br>
+          assert(((Addend & 0x1) == 0) && "16-bit LDR/STR not 2-byte aligned.");<br>
+          break;<br>
+        case 2:<br>
+          assert(((Addend & 0x3) == 0) && "32-bit LDR/STR not 4-byte aligned.");<br>
+          break;<br>
+        case 3:<br>
+          assert(((Addend & 0x7) == 0) && "64-bit LDR/STR not 8-byte aligned.");<br>
+          break;<br>
+        }<br>
+      }<br>
+      // Compensate for implicit shift.<br>
+      Addend >>= ImplicitShift;<br>
+      assert(isUInt<12>(Addend) && "Addend cannot be encoded.");<br>
+<br>
+      // Encode the addend into the instruction.<br>
+      *p = (*p & 0xFFC003FF) | ((uint32_t)(Addend << 10) & 0x003FFC00);<br>
+      break;<br>
+    }<br>
+    }<br>
+  }<br>
+<br>
   relocation_iterator<br>
   processRelocationRef(unsigned SectionID, relocation_iterator RelI,<br>
                        ObjectImage &ObjImg, ObjSectionToIDMap &ObjSectionToID,<br>
@@ -196,105 +299,37 @@ public:<br>
     }<br>
     case MachO::ARM64_RELOC_BRANCH26: {<br>
       assert(RE.IsPCRel && "not PCRel and ARM64_RELOC_BRANCH26 not supported");<br>
-      // Mask the value into the target address. We know instructions are<br>
-      // 32-bit aligned, so we can do it all at once.<br>
-      uint32_t *p = (uint32_t *)LocalAddress;<br>
-      // Check if the addend is encoded in the instruction.<br>
-      uint32_t EncodedAddend = *p & 0x03FFFFFF;<br>
-      if (EncodedAddend != 0) {<br>
-        if (RE.Addend == 0)<br>
-          llvm_unreachable("branch26 instruction has embedded addend.");<br>
-        else<br>
-          llvm_unreachable("branch26 instruction has embedded addend and"<br>
-                           "ARM64_RELOC_ADDEND.");<br>
-      }<br>
       // Check if branch is in range.<br>
       uint64_t FinalAddress = Section.LoadAddress + RE.Offset;<br>
-      uint64_t PCRelVal = Value - FinalAddress + RE.Addend;<br>
-      assert(isInt<26>(PCRelVal) && "Branch target out of range!");<br>
-      // Insert the value into the instruction.<br>
-      *p = (*p & 0xFC000000) | ((uint32_t)(PCRelVal >> 2) & 0x03FFFFFF);<br>
+      int64_t PCRelVal = Value - FinalAddress + RE.Addend;<br>
+      encodeAddend(LocalAddress, RE.RelType, PCRelVal);<br>
       break;<br>
     }<br>
     case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:<br>
     case MachO::ARM64_RELOC_PAGE21: {<br>
       assert(RE.IsPCRel && "not PCRel and ARM64_RELOC_PAGE21 not supported");<br>
-      // Mask the value into the target address. We know instructions are<br>
-      // 32-bit aligned, so we can do it all at once.<br>
-      uint32_t *p = (uint32_t *)LocalAddress;<br>
-      // Check if the addend is encoded in the instruction.<br>
-      uint32_t EncodedAddend =<br>
-          ((*p & 0x60000000) >> 29) | ((*p & 0x01FFFFE0) >> 3);<br>
-      if (EncodedAddend != 0) {<br>
-        if (RE.Addend == 0)<br>
-          llvm_unreachable("adrp instruction has embedded addend.");<br>
-        else<br>
-          llvm_unreachable("adrp instruction has embedded addend and"<br>
-                           "ARM64_RELOC_ADDEND.");<br>
-      }<br>
       // Adjust for PC-relative relocation and offset.<br>
       uint64_t FinalAddress = Section.LoadAddress + RE.Offset;<br>
-      uint64_t PCRelVal =<br>
-          ((Value + RE.Addend) & (-4096)) - (FinalAddress & (-4096));<br>
-      // Check that the value fits into 21 bits (+ 12 lower bits).<br>
-      assert(isInt<33>(PCRelVal) && "Invalid page reloc value!");<br>
-      // Insert the value into the instruction.<br>
-      uint32_t ImmLoValue = (uint32_t)(PCRelVal << 17) & 0x60000000;<br>
-      uint32_t ImmHiValue = (uint32_t)(PCRelVal >> 9) & 0x00FFFFE0;<br>
-      *p = (*p & 0x9F00001F) | ImmHiValue | ImmLoValue;<br>
+      int64_t PCRelVal =<br>
+        ((Value + RE.Addend) & (-4096)) - (FinalAddress & (-4096));<br>
+      encodeAddend(LocalAddress, RE.RelType, PCRelVal);<br>
       break;<br>
     }<br>
     case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12:<br>
     case MachO::ARM64_RELOC_PAGEOFF12: {<br>
       assert(!RE.IsPCRel && "PCRel and ARM64_RELOC_PAGEOFF21 not supported");<br>
-      // Mask the value into the target address. We know instructions are<br>
-      // 32-bit aligned, so we can do it all at once.<br>
-      uint32_t *p = (uint32_t *)LocalAddress;<br>
-      // Check if the addend is encoded in the instruction.<br>
-      uint32_t EncodedAddend = *p & 0x003FFC00;<br>
-      if (EncodedAddend != 0) {<br>
-        if (RE.Addend == 0)<br>
-          llvm_unreachable("adrp instruction has embedded addend.");<br>
-        else<br>
-          llvm_unreachable("adrp instruction has embedded addend and"<br>
-                           "ARM64_RELOC_ADDEND.");<br>
-      }<br>
       // Add the offset from the symbol.<br>
       Value += RE.Addend;<br>
       // Mask out the page address and only use the lower 12 bits.<br>
       Value &= 0xFFF;<br>
-      // Check which instruction we are updating to obtain the implicit shift<br>
-      // factor from LDR/STR instructions.<br>
-      if (*p & 0x08000000) {<br>
-        uint32_t ImplicitShift = ((*p >> 30) & 0x3);<br>
-        switch (ImplicitShift) {<br>
-        case 0:<br>
-          // Check if this a vector op.<br>
-          if ((*p & 0x04800000) == 0x04800000) {<br>
-            ImplicitShift = 4;<br>
-            assert(((Value & 0xF) == 0) &&<br>
-                   "128-bit LDR/STR not 16-byte aligned.");<br>
-          }<br>
-          break;<br>
-        case 1:<br>
-          assert(((Value & 0x1) == 0) && "16-bit LDR/STR not 2-byte aligned.");<br>
-        case 2:<br>
-          assert(((Value & 0x3) == 0) && "32-bit LDR/STR not 4-byte aligned.");<br>
-        case 3:<br>
-          assert(((Value & 0x7) == 0) && "64-bit LDR/STR not 8-byte aligned.");<br>
-        }<br>
-        // Compensate for implicit shift.<br>
-        Value >>= ImplicitShift;<br>
-      }<br>
-      // Insert the value into the instruction.<br>
-      *p = (*p & 0xFFC003FF) | ((uint32_t)(Value << 10) & 0x003FFC00);<br>
+      encodeAddend(LocalAddress, RE.RelType, Value);<br>
       break;<br>
     }<br>
     case MachO::ARM64_RELOC_SUBTRACTOR:<br>
     case MachO::ARM64_RELOC_POINTER_TO_GOT:<br>
     case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21:<br>
     case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12:<br>
-      llvm_unreachable("Relocation type not implemented yet!");<br>
+      llvm_unreachable("Relocation type not yet implemented!");<br>
     case MachO::ARM64_RELOC_ADDEND:<br>
       llvm_unreachable("ARM64_RELOC_ADDEND should have been handeled by "<br>
                        "processRelocationRef!");<br>
<br>
Added: llvm/trunk/test/ExecutionEngine/RuntimeDyld/AArch64/MachO_ARM64_relocations.s<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ExecutionEngine/RuntimeDyld/AArch64/MachO_ARM64_relocations.s?rev=213689&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ExecutionEngine/RuntimeDyld/AArch64/MachO_ARM64_relocations.s?rev=213689&view=auto</a><br>

==============================================================================<br>
--- llvm/trunk/test/ExecutionEngine/RuntimeDyld/AArch64/MachO_ARM64_relocations.s (added)<br>
+++ llvm/trunk/test/ExecutionEngine/RuntimeDyld/AArch64/MachO_ARM64_relocations.s Tue Jul 22 16:42:55 2014<br>
@@ -0,0 +1,54 @@<br>
+# RUN: llvm-mc -triple=arm64-apple-ios7.0.0 -code-model=small -relocation-model=pic -filetype=obj -o %t.o %s<br>
+# RUN: llvm-rtdyld -triple=arm64-apple-ios7.0.0 -verify -check=%s %t.o<br>
+# RUN: rm %t.o<br>
+<br>
+# FIXME: Add GOT relocation tests once GOT testing is supported.<br>
+<br>
+    .section  __TEXT,__text,regular,pure_instructions<br>
+    .ios_version_min 7, 0<br>
+    .globl  foo<br>
+    .align  2<br>
+foo:<br>
+    movz  w0, #0<br>
+    ret<br>
+<br>
+    .globl  _test_branch_reloc<br>
+    .align  2<br>
+<br>
+<br>
+# Test ARM64_RELOC_BRANCH26 relocation. The branch instruction only encodes 26<br>
+# bits of the 28-bit possible branch range. The lower two bits are always zero<br>
+# and therefore ignored.<br>
+# rtdyld-check:  decode_operand(br1, 0)[25:0] = (foo-br1)[27:2]<br>
+_test_branch_reloc:<br>
+br1:<br>
+    b foo<br>
+    ret<br>
+<br>
+<br>
+# Test ARM64_RELOC_UNSIGNED relocation. The absolute 64-bit address of the<br>
+# function should be stored at the 8-byte memory location.<br>
+# rtdyld-check: *{8}ptr = foo<br>
+    .section  __DATA,__data<br>
+    .globl  ptr<br>
+    .align  3<br>
+    .fill 8192, 1, 0<br>
+ptr:<br>
+    .quad foo<br>
+<br>
+<br>
+# Test ARM64_RELOC_PAGE21 and ARM64_RELOC_PAGEOFF12 relocation. adrp encodes<br>
+# the PC-relative page (4 KiB) difference between the adrp instruction and the<br>
+# variable ptr. ldr encodes the offset of the variable within the page. The ldr<br>
+# instruction perfroms an implicit shift on the encoded immediate (imm<<3).<br>
+# rtdyld-check:  decode_operand(adrp1, 1) = (ptr[32:12]-adrp1[32:12])<br>
+# rtdyld-check:  decode_operand(ldr1, 2) = (ptr[11:3])<br>
+    .globl  _test_adrp_ldr<br>
+    .align  2<br>
+_test_adrp_ldr:<br>
+adrp1:<br>
+    adrp x0, ptr@PAGE<br>
+ldr1:<br>
+    ldr  x0, [x0, ptr@PAGEOFF]<br>
+    ret<br>
+    .fill 8192, 1, 0<br>
<br>
Added: llvm/trunk/test/ExecutionEngine/RuntimeDyld/AArch64/lit.local.cfg<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ExecutionEngine/RuntimeDyld/AArch64/lit.local.cfg?rev=213689&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ExecutionEngine/RuntimeDyld/AArch64/lit.local.cfg?rev=213689&view=auto</a><br>

==============================================================================<br>
--- llvm/trunk/test/ExecutionEngine/RuntimeDyld/AArch64/lit.local.cfg (added)<br>
+++ llvm/trunk/test/ExecutionEngine/RuntimeDyld/AArch64/lit.local.cfg Tue Jul 22 16:42:55 2014<br>
@@ -0,0 +1,3 @@<br>
+if not 'AArch64' in config.root.targets:<br>
+    config.unsupported = True<br>
+<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>