This is an archive of the discontinued LLVM Phabricator instance.

[SystemZ] Allow symbols in immediate asm operands
ClosedPublic

Authored by iii on Jul 10 2023, 2:57 PM.

Details

Summary

Currently mentioning any symbols in immediate asm operands is not
supported, for example:

error: invalid operand for instruction
lghi %r4,foo_end-foo

The immediate problem is that is*Imm() and print*Operand() functions do
not accept MCExprs, but simply relaxing these checks is not enough:
after symbol addresses are computed, range checks need to run against
resolved values.

Add a number of SystemZ::FixupKind members for each kind of immediate
value and process them in SystemZMCAsmBackend::applyFixup(). Only
perform the range checks, do not change anything.

In order to create fixups, one needs to know the operand offsets.
Unfortunately the existing LLVM infrastructure does not provide this
information. Implement generating getOperandBitOffset(), which provides
this information. It does not return useful values for multi-lit
operands, such as SystemZ vector registers, but this is not important
for its intended use case.

Finally, adjust the tests: move previously failing cases like the
one shown above out of insn-bad.s.

Diff Detail

Event Timeline

iii created this revision.Jul 10 2023, 2:57 PM
Herald added a project: Restricted Project. · View Herald TranscriptJul 10 2023, 2:57 PM
Herald added a subscriber: hiraditya. · View Herald Transcript
iii requested review of this revision.Jul 10 2023, 2:57 PM
Herald added a project: Restricted Project. · View Herald TranscriptJul 10 2023, 2:57 PM
iii updated this revision to Diff 538846.Jul 10 2023, 3:06 PM
  • Remove an unused variable.
  • Remove an irrelevant whitespace change.

Thanks for working on that, Ilya! If we do allow symbols in immediates (and I agree we should), we should then also handle the case where they don't completely resolve, but result in relocations. This should be straightforward to add once we already have fixups. In addition to R_S390_12 (which is already emitted, and should be used for the U12Imm cases as well), we do support 1-, 2-, 4-, and 8-byte relocations. The sub-byte (U1Imm, U2Imm, U3Imm, U4Imm) and .insn opcode (U48Imm) cases don't have corresponding relocations, but I believe for those we should not allow any symbolic expressions anyway.

Also, it would be good to have tests for the PC-relative cases (symbol-.), both where those resolve at assemble time (symbol in the current section), and where a PC-relative reloc is required (symbol in another section).

Finally, for the tablegen changes I'd prefer to have someone more familiar with that code base to review it. Maybe we can split this off into a separate diff (possibly combined with a getDispOpValue change to make use of it for displacements)?

llvm/lib/Target/SystemZ/MCTargetDesc/SystemZInstPrinter.cpp
88

I don't think we should have the "imm" markup for expressions.

llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp
207

I think this should rather go into getDispOpValue ... a displacement is in fact simply an immediate.

The getOperandBitOffset logic should allow us to replace the MemOpsEmitted hack we currently have there, and then generalize it to all immediates.

The getMachineOpValue will then be only used for registers.

iii updated this revision to Diff 542478.Jul 20 2023, 6:07 AM
iii marked 2 inline comments as done.
  • Emit relocations.
  • Add various tests.
  • Remove "imm" markup for expressions.
  • Move the isExpr() logic to getDispOpValue().
iii added a comment.EditedJul 20 2023, 6:14 AM

I've added pc-relative tests, but only for PC32. For PC32DBL I tried (src-.)/2, but the common code does not recognize division as a relocatable expression, and does not let the backend to handle it either. GAS does not handle it either though, so it's probably fine:

lgfi %r0,(foo-.)/2
1.s:1: Error: invalid operands (*UND* and .text sections) for `-'

Thanks for the updates, looking really good now. Just a few cosmetic comments inline.

llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp
82

Can we rename this to something like getImmOpValue - it's no longer just displacements. Also the comment should be updated.

llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCFixups.h
24

Can we integrate the handling of displacements into the new scheme and use FK_390_U12Imm and FK_390_S20Imm here (and elsewhere)? In generals, displacements should just be a type of immediates.

llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCObjectWriter.cpp
60 ↗(On Diff #542478)

Would be nicer to reformat those cases as well so that all use the same style.

llvm/test/MC/SystemZ/fixups.s
8

Would it make sense to add CHECK-DIS lines to the existing tests as well?

I've added pc-relative tests, but only for PC32. For PC32DBL I tried (src-.)/2, but the common code does not recognize division as a relocatable expression, and does not let the backend to handle it either. GAS does not handle it either though, so it's probably fine:

Agreed, I think this is fine. The DBL relocations really are intended for the LARL-type instructions, where the /2 is implicit.

iii updated this revision to Diff 542630.Jul 20 2023, 12:39 PM
iii marked 3 inline comments as done.
  • Rename getDispOpValue() to getImmOpValue().
  • Rename FK_390_12 to FK_390_U12Imm and FK_390_20 to FK_390_S20Imm.
  • Reformat.
llvm/test/MC/SystemZ/fixups.s
8

For the new tests it's important, because it allows us to check the resolved immediate value. The existing tests depend relocations, so it's going to be only zeroes anyway.

uweigand accepted this revision.Jul 21 2023, 12:34 AM

LGTM, thanks!

llvm/test/MC/SystemZ/fixups.s
8

OK, makes sense.

This revision is now accepted and ready to land.Jul 21 2023, 12:34 AM
This revision was landed with ongoing or failed builds.Jul 21 2023, 2:09 AM
This revision was automatically updated to reflect the committed changes.