xref: /llvm-project/llvm/lib/ExecutionEngine/JITLink/i386.cpp (revision 026fb0487523fec61c23643f8f78bb3c1a401682)
129fe204bSKshitij Jain //===---- i386.cpp - Generic JITLink i386 edge kinds, utilities -----===//
229fe204bSKshitij Jain //
329fe204bSKshitij Jain // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
429fe204bSKshitij Jain // See https://llvm.org/LICENSE.txt for license information.
529fe204bSKshitij Jain // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
629fe204bSKshitij Jain //
729fe204bSKshitij Jain //===----------------------------------------------------------------------===//
829fe204bSKshitij Jain //
929fe204bSKshitij Jain // Generic utilities for graphs representing i386 objects.
1029fe204bSKshitij Jain //
1129fe204bSKshitij Jain //===----------------------------------------------------------------------===//
1229fe204bSKshitij Jain 
1329fe204bSKshitij Jain #include "llvm/ExecutionEngine/JITLink/i386.h"
1429fe204bSKshitij Jain 
1529fe204bSKshitij Jain #define DEBUG_TYPE "jitlink"
1629fe204bSKshitij Jain 
172a3b257aSKshitij Jain namespace llvm::jitlink::i386 {
1829fe204bSKshitij Jain 
getEdgeKindName(Edge::Kind K)1929fe204bSKshitij Jain const char *getEdgeKindName(Edge::Kind K) {
2029fe204bSKshitij Jain   switch (K) {
2129fe204bSKshitij Jain   case None:
2229fe204bSKshitij Jain     return "None";
232a3b257aSKshitij Jain   case Pointer32:
242a3b257aSKshitij Jain     return "Pointer32";
252a3b257aSKshitij Jain   case PCRel32:
262a3b257aSKshitij Jain     return "PCRel32";
272a3b257aSKshitij Jain   case Pointer16:
282a3b257aSKshitij Jain     return "Pointer16";
292a3b257aSKshitij Jain   case PCRel16:
302a3b257aSKshitij Jain     return "PCRel16";
311b123d9fSKshitij Jain   case Delta32:
321b123d9fSKshitij Jain     return "Delta32";
331b123d9fSKshitij Jain   case Delta32FromGOT:
341b123d9fSKshitij Jain     return "Delta32FromGOT";
351b123d9fSKshitij Jain   case RequestGOTAndTransformToDelta32FromGOT:
361b123d9fSKshitij Jain     return "RequestGOTAndTransformToDelta32FromGOT";
37cd9fd425SKshitij Jain   case BranchPCRel32:
38cd9fd425SKshitij Jain     return "BranchPCRel32";
39cd9fd425SKshitij Jain   case BranchPCRel32ToPtrJumpStub:
40cd9fd425SKshitij Jain     return "BranchPCRel32ToPtrJumpStub";
41cd9fd425SKshitij Jain   case BranchPCRel32ToPtrJumpStubBypassable:
42cd9fd425SKshitij Jain     return "BranchPCRel32ToPtrJumpStubBypassable";
4329fe204bSKshitij Jain   }
441b123d9fSKshitij Jain 
4529fe204bSKshitij Jain   return getGenericEdgeKindName(K);
4629fe204bSKshitij Jain }
472a3b257aSKshitij Jain 
481b123d9fSKshitij Jain const char NullPointerContent[PointerSize] = {0x00, 0x00, 0x00, 0x00};
49cd9fd425SKshitij Jain 
50cd9fd425SKshitij Jain const char PointerJumpStubContent[6] = {
51cd9fd425SKshitij Jain     static_cast<char>(0xFFu), 0x25, 0x00, 0x00, 0x00, 0x00};
52cd9fd425SKshitij Jain 
optimizeGOTAndStubAccesses(LinkGraph & G)53cd9fd425SKshitij Jain Error optimizeGOTAndStubAccesses(LinkGraph &G) {
54cd9fd425SKshitij Jain   LLVM_DEBUG(dbgs() << "Optimizing GOT entries and stubs:\n");
55cd9fd425SKshitij Jain 
56cd9fd425SKshitij Jain   for (auto *B : G.blocks())
57cd9fd425SKshitij Jain     for (auto &E : B->edges()) {
58cd9fd425SKshitij Jain       if (E.getKind() == i386::BranchPCRel32ToPtrJumpStubBypassable) {
59cd9fd425SKshitij Jain         auto &StubBlock = E.getTarget().getBlock();
60cd9fd425SKshitij Jain         assert(StubBlock.getSize() == sizeof(PointerJumpStubContent) &&
61cd9fd425SKshitij Jain                "Stub block should be stub sized");
62cd9fd425SKshitij Jain         assert(StubBlock.edges_size() == 1 &&
63cd9fd425SKshitij Jain                "Stub block should only have one outgoing edge");
64cd9fd425SKshitij Jain 
65cd9fd425SKshitij Jain         auto &GOTBlock = StubBlock.edges().begin()->getTarget().getBlock();
66cd9fd425SKshitij Jain         assert(GOTBlock.getSize() == G.getPointerSize() &&
67cd9fd425SKshitij Jain                "GOT block should be pointer sized");
68cd9fd425SKshitij Jain         assert(GOTBlock.edges_size() == 1 &&
69cd9fd425SKshitij Jain                "GOT block should only have one outgoing edge");
70cd9fd425SKshitij Jain 
71cd9fd425SKshitij Jain         auto &GOTTarget = GOTBlock.edges().begin()->getTarget();
72cd9fd425SKshitij Jain         orc::ExecutorAddr EdgeAddr = B->getAddress() + E.getOffset();
73cd9fd425SKshitij Jain         orc::ExecutorAddr TargetAddr = GOTTarget.getAddress();
74cd9fd425SKshitij Jain 
75cd9fd425SKshitij Jain         int64_t Displacement = TargetAddr - EdgeAddr + 4;
76*026fb048SLang Hames         if (isInt<32>(Displacement)) {
77cd9fd425SKshitij Jain           E.setKind(i386::BranchPCRel32);
78cd9fd425SKshitij Jain           E.setTarget(GOTTarget);
79cd9fd425SKshitij Jain           LLVM_DEBUG({
80cd9fd425SKshitij Jain             dbgs() << "  Replaced stub branch with direct branch:\n    ";
81cd9fd425SKshitij Jain             printEdge(dbgs(), *B, E, getEdgeKindName(E.getKind()));
82cd9fd425SKshitij Jain             dbgs() << "\n";
83cd9fd425SKshitij Jain           });
84cd9fd425SKshitij Jain         }
85cd9fd425SKshitij Jain       }
86cd9fd425SKshitij Jain     }
87cd9fd425SKshitij Jain 
88cd9fd425SKshitij Jain   return Error::success();
89cd9fd425SKshitij Jain }
90cd9fd425SKshitij Jain 
912a3b257aSKshitij Jain } // namespace llvm::jitlink::i386
92