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