This is an archive of the discontinued LLVM Phabricator instance.

[mips] Support LA expansion in PIC mode
Needs RevisionPublic

Authored by sdardis on Feb 5 2016, 7:19 AM.

Details

Summary

Adds support for LA expansion in PIC mode.

Patch By: Srdjan Obucina

Event Timeline

obucina updated this revision to Diff 47016.Feb 5 2016, 7:19 AM
obucina retitled this revision from to [mips] Support LA expandsion in PIC mode.
obucina updated this object.
obucina added reviewers: dsanders, zoran.jovanovic.
obucina added a subscriber: llvm-commits.
obucina retitled this revision from [mips] Support LA expandsion in PIC mode to [mips] Support LA expansion in PIC mode.Feb 5 2016, 7:22 AM
obucina edited edge metadata.
dsanders requested changes to this revision.Feb 5 2016, 7:45 AM
dsanders edited edge metadata.

The code change looks right to me but I have some comments about the test case.

Rather than make a new test file, could you extend test/MC/Mips/macro-la.s? This is mostly to keep our test directories tidy but it will also allow us to test that the other cases (e.g. 'la $5, 1') are unaffected and we'll have better coverage of the variety of expressions (e.g. 'la $5, symbol+8($6)', 'la $6, symbol+8($6)', and 'la $5, 1f').

This revision now requires changes to proceed.Feb 5 2016, 7:45 AM
petarj edited edge metadata.Feb 5 2016, 8:02 AM
petarj added a subscriber: petarj.
obucina updated this revision to Diff 47453.Feb 10 2016, 7:49 AM
obucina edited edge metadata.

We couldn't extend test/MC/Mips/macro-la.s because some tests in it failed in pic mode. For example, 'la $5, symbol+8' gives: 'LLVM ERROR: unsupported reloc value'. Also, istruction la in the case 'la $5, 1f' does not expand properly because symbol 1 is defined at the end of the test file, so condition 'Sym->isInSection()' fails because of one pass structure of assembler.

mpf added a subscriber: mpf.Feb 29 2016, 12:47 PM
mpf added inline comments.
lib/Target/Mips/AsmParser/MipsAsmParser.cpp
2801

The problem here is that you do not know whether a symbol is going to have global or local linkage until the end of the module as the .global directive may appear later. In order to do this you will need to track which symbols are referred to during macro expansion and then at the end of the file check that all the symbols still have the same linkage. If any have changed then raise an error. The restriction you will end up with in LLVM is that a global symbol must be globalized before the first reference to it.

The test cases are:

global

.text
foo:
la $4, bar

local

.data
bar:
.word 1
.text
foo:
la $4, bar

global

.data
.global bar
bar:
.word 1
.text
foo:
la $4, bar

local (but an error for LLVM)

.text
foo:
la $4, bar
.data
bar:
.word 1

global (but an error for LLVM)

.data
bar:
.word 1
.text
foo:
la $4, bar
.global bar

If the cases which work are sufficient for the codebases you need to support then this is relatively easy to implement. If you need the last two cases to work then there will be a significant amount of framework required as I understand.

For example, 'la $5, symbol+8' gives: 'LLVM ERROR: unsupported reloc value'.

Whatever caused this seems to have been fixed. It emits this for me:

lw $6, %got(symbol)($gp)   # encoding: [A,A,0x86,0x8f]
lib/Target/Mips/AsmParser/MipsAsmParser.cpp
2801

The problem here is that you do not know whether a symbol is going to have global or local
linkage until the end of the module as the .global directive may appear later.

I should have noticed that given that we've recently had the same problem with jal.

In order to do this you will need to track which symbols are referred to during macro
expansion and then at the end of the file check that all the symbols still have the same
linkage. If any have changed then raise an error. The restriction you will end up with in LLVM
is that a global symbol must be globalized before the first reference to it.

I like this solution. There's some valid inputs to GAS that won't be supported but it only takes a trivial source change (inserting a '.global bar') to work around it.

I'd limit the 'reference' part of your last sentence to just references involved in this kind of linkage-specific expansion since things like:

  .data
foo:
  .word bar
bar:
  .word 1

aren't a problem.

We only need one of the two error cases to be an error don't we? I think we could assume local and error out if it turned out to be global, or assume global and error out if it turned out to be local.

If you need the last two cases to work then there will be a significant amount of framework required as I understand.

That's my understanding too. We don't have a way to see the whole input before we have to make a decision on how to expand.

test/MC/Mips/la.pic.s
15 ↗(On Diff #47453)

This instruction is incomplete

mpf added inline comments.Mar 1 2016, 4:38 AM
lib/Target/Mips/AsmParser/MipsAsmParser.cpp
2801

We only need one of the two error cases to be an error don't we?

No I think both ways round will happen. All symbols will need to start off presumed to be global to match gas and for the case where they are not defined in the current module at all. If they are defined without .global before being referenced then they are local but could become global later. If they are not declared before being referenced they are global but may become local if defined later.

Only if we assumed local could we eliminate one of the error cases but that would lead to all externally defined globals needing an explicit .global in each file that references them... which is contrary to gas behaviour.

Not sure if that description is too technically dense. I'll try again if it is impenetrable.

dsanders added inline comments.Mar 1 2016, 6:54 AM
lib/Target/Mips/AsmParser/MipsAsmParser.cpp
2801

I see what I've missed. The assumptions needed to make either of the latter two cases 'just work' directly contradict the assumptions needed to make the first three cases work.

The overall assumptions when processing the 'la $4, bar' are:

  • If the symbol has never been seen then assume global
  • If a .global/.local has been seen then it's known to be global/local
  • If the definition has been seen but no .local/.global has been seen then assume it's local
sdardis commandeered this revision.Feb 6 2017, 7:46 AM
sdardis added a reviewer: obucina.
sdardis added a subscriber: sdardis.

Commandeering this to repost.

sdardis updated this revision to Diff 87422.Feb 7 2017, 6:49 AM
sdardis edited the summary of this revision. (Show Details)
sdardis added a reviewer: slthakur.

Update to trunk, account in tests for difference between emitting assembly and objects.

Just removing a 3 year old patch from my queue. Feel free to re-add me if this is still needed and you want me to take another look

This revision now requires changes to proceed.Jul 12 2019, 1:26 PM
dsanders resigned from this revision.Jul 18 2019, 7:05 PM