[PATCH] D144083: [JITLink] Initial AArch32 backend
Peter Smith via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Tue Feb 28 01:39:37 PST 2023
peter.smith added inline comments.
================
Comment at: llvm/lib/ExecutionEngine/JITLink/aarch32.cpp:244
+ return makeUnexpectedOpcodeError(G, R, Kind);
+ if ((R.Lo & FixupInfo<Thumb_Call>::LoBitNoBlx) == 0 &&
+ (R.Lo & FixupInfo<Thumb_Call>::LoBitH) != 0)
----------------
sgraenitz wrote:
> peter.smith wrote:
> > Looking at the stub generation code, if there is a Thumb_Call to an external edge, then a stub with LoBitH will be set will be created. This won't be a problem if the code-generator never generates BLX to an external symbol, but would be if it does.
> Yes, I didn't catch a case like this yet. But I am also not sure I fully understand: If codegen wrote a BLX, then it would be T2 right? The docs say LoBitH must be empty here:
> ```
> if CurrentInstrSet() == InstrSet_ThumbEE || H == '1' then UNDEFINED;
> ```
>
> What is the stub generation code you mean? The one here in JITLink?
Yes, the code in visitEdge, quoted here. If there is a BLX instruction with a Thumb_Call relocation where the target isn't defined, it looks like a stub will be created.
```
bool visitEdge(LinkGraph &G, Block *B, Edge &E) {
if (E.getTarget().isDefined())
return false;
switch (E.getKind()) {
case Thumb_Call:
case Thumb_Jump24: {
DEBUG_WITH_TYPE("jitlink", {
dbgs() << " Fixing " << G.getEdgeKindName(E.getKind()) << " edge at "
<< B->getFixupAddress(E) << " (" << B->getAddress() << " + "
<< formatv("{0:x}", E.getOffset()) << ")\n";
});
E.setTarget(this->getEntryForTarget(G, E.getTarget()));
return true;
}
}
return false;
}
```
I would not expect a code-generator to generate a BLX in this situation as it has no idea whether the target is Arm or Thumb so I would expect a BL. It is possible to write in assembly language but I don't know how well that needs to be supported in a JIT.
In static linkers an R_ARM_CALL (Arm state) or R_ARM_THM_CALL (Thumb state) relocation can be associated with a BL or BLX. As the static linker always knows the (Arm/Thumb) state of the destination it can write a BL instruction if both source and target are the same state or a BLX if they are different. This property permits code-generators to only use BL with R_ARM_CALL/R_ARM_THM_CALL, with BLX reserved for assembler. It also permits Thumb code to reuse Arm stubs.
I don't know how often this would happen in a JIT though.
================
Comment at: llvm/lib/ExecutionEngine/JITLink/aarch32.cpp:261
+ StringRef(G.getEdgeKindName(Kind)));
+ return decodeImmBT4BlT1BlxT2_J1J2(R.Hi, R.Lo);
+
----------------
sgraenitz wrote:
> peter.smith wrote:
> > Is there a reason why this isn't
> > ```
> > LLVM_LIKELY(ArmCfg.J1J2BranchEncoding)
> > ? decodeImmBT4BlT1BlxT2_J1J2(R.Hi, R.Lo)
> > : decodeImmBT4BlT1BlxT2(R.Hi, R.Lo);
> > ```
> > The J1J2 would apply here in the same way as Thumb_Call.
> My understanding was that CPUs without J1J2 didn't have R_ARM_THM_JUMP24 yet, so it wouldn't every happen? (Maybe that would be worth an assertion.)
R_ARM_THM_JUMP24 is used for the wide unconditional branch regardless of whether J1J2 encoding is available. It was introduced when the BLX instruction was made available. BL <immediate> can be converted into BLX <immediate> but B.w <immediate> cannot be converted in BX <immediate> as BX <immediate> doesn't exist (only BX <register>).
In summary R_ARM_THM_CALL is for BL and BLX instructions, R_ARM_THM_JUMP24 is for B.w instructions. The J1J2 encoding applies to both BL, BLX and B.w.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D144083/new/
https://reviews.llvm.org/D144083
More information about the llvm-commits
mailing list