Handle TOC offsets by giving them to the linker.

An offset > 2^15 would exceed the range of an addi immediate on ppc64le.
Thus, rather than add the offset after loading the TOC reference, have
different tocloader functions for each (symbol, offset) pair. In this
case, the linker can handle large offsets by changing the value of
foo+offset@toc@ha accordingly.

Change-Id: Iac1481bccaf55fb0c2b080eedebaf11befdae465
Reviewed-on: https://boringssl-review.googlesource.com/16784
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
This commit is contained in:
Adam Langley 2017-05-31 17:02:42 -07:00 committed by CQ bot account: commit-bot@chromium.org
parent 733f46e84f
commit cd334a54ca
3 changed files with 71 additions and 30 deletions

View File

@ -479,13 +479,27 @@ func establishTOC(w stringWriter) {
}
// loadTOCFuncName returns the name of a synthesized function that sets r3 to
// the value of “symbol”.
func loadTOCFuncName(symbol string) string {
return ".Lbcm_loadtoc_" + strings.Replace(symbol, ".", "_dot_", -1)
// the value of “symbol+offset”.
func loadTOCFuncName(symbol, offset string) string {
ret := ".Lbcm_loadtoc_" + strings.Replace(symbol, ".", "_dot_", -1)
switch {
case len(offset) == 0:
break
case offset[0] == '+':
ret += "__plus_" + offset[1:]
case offset[0] == '-':
ret += "__minus_" + offset[1:]
default:
// parseMemRef will prepend a plus to bare offsets.
panic("bad offset: " + offset)
}
return ret
}
func (d *delocation) loadFromTOC(w stringWriter, symbol, dest string) wrapperFunc {
d.tocLoaders[symbol] = struct{}{}
func (d *delocation) loadFromTOC(w stringWriter, symbol, offset, dest string) wrapperFunc {
d.tocLoaders[symbol + "\x00" + offset] = struct{}{}
return func(k func()) {
w.WriteString("\taddi 1, 1, -288\n") // Clear the red zone.
w.WriteString("\tmflr " + dest + "\n") // Stash the link register.
@ -497,7 +511,7 @@ func (d *delocation) loadFromTOC(w stringWriter, symbol, dest string) wrapperFun
// Because loadTOCFuncName returns a “.L” name, we don't need a
// nop after this call.
w.WriteString("\tbl " + loadTOCFuncName(symbol) + "\n")
w.WriteString("\tbl " + loadTOCFuncName(symbol, offset) + "\n")
// Cycle registers around. We need r3 -> destReg, -8(1) ->
// lr and, optionally, -16(1) -> r3.
@ -672,26 +686,20 @@ Args:
// destination register is the first argument.
destReg := args[0]
wrappers = append(wrappers, d.loadFromTOC(d.output, symbol, destReg))
wrappers = append(wrappers, d.loadFromTOC(d.output, symbol, offset, destReg))
switch instructionName {
case "addi":
// The original instruction was:
// addi destReg, tocHaReg, offset+symbol@toc@l
//
// All that is left is adding the offset, if any.
instructionName = ""
if len(offset) != 0 {
wrappers = append(wrappers, func(k func()) {
d.output.WriteString("\taddi " + destReg + ", " + destReg + ", " + offset + "\n")
})
}
case "ld", "lhz", "lwz":
// The original instruction was:
// l?? destReg, offset+symbol@toc@l(tocHaReg)
//
// We transform that into the
// equivalent dereference of destReg:
// l?? destReg, offset(destReg)
// l?? destReg, 0(destReg)
origInstructionName := instructionName
instructionName = ""
@ -702,11 +710,7 @@ Args:
}
wrappers = append(wrappers, func(k func()) {
fixedOffset := offset
if len(fixedOffset) == 0 {
fixedOffset = "0"
}
d.output.WriteString("\t" + origInstructionName + " " + destReg + ", " + fixedOffset + "(" + destReg + ")\n")
d.output.WriteString("\t" + origInstructionName + " " + destReg + ", 0(" + destReg + ")\n")
})
default:
return nil, fmt.Errorf("can't process TOC argument to %q", instructionName)
@ -1212,14 +1216,18 @@ func transform(w stringWriter, inputs []inputFile) error {
if d.processor == ppc64le {
loadTOCNames := sortedSet(d.tocLoaders)
for _, symbol := range loadTOCNames {
funcName := loadTOCFuncName(symbol)
for _, symbolAndOffset := range loadTOCNames {
parts := strings.SplitN(symbolAndOffset, "\x00", 2)
symbol, offset := parts[0], parts[1]
funcName := loadTOCFuncName(symbol, offset)
ref := symbol + offset
w.WriteString(".type " + funcName[2:] + ", @function\n")
w.WriteString(funcName[2:] + ":\n")
w.WriteString(funcName + ":\n")
w.WriteString("\taddis 3, 2, " + symbol + "@toc@ha\n")
w.WriteString("\taddi 3, 3, " + symbol + "@toc@l\n")
w.WriteString("\taddis 3, 2, " + ref + "@toc@ha\n")
w.WriteString("\taddi 3, 3, " + ref + "@toc@l\n")
w.WriteString("\tblr\n")
}

View File

@ -12,3 +12,6 @@ foo:
addis 5, 2, 5+foo@toc@ha
ld 5, 10+foo@toc@l(5)
addis 4, 2, foo-10@toc@ha
addi 4, 4, foo-10@toc@l

View File

@ -9,26 +9,24 @@ foo:
addi 1, 1, -288
mflr 3
std 3, -8(1)
bl .Lbcm_loadtoc__dot_Lfoo_local_target
bl .Lbcm_loadtoc__dot_Lfoo_local_target__plus_10
std 3, -24(1)
ld 3, -8(1)
mtlr 3
ld 3, -24(1)
addi 1, 1, 288
addi 3, 3, +10
# WAS addis 3, 2, 15+foo@toc@ha
# WAS addi 3, 3, 20+foo@toc@l
addi 1, 1, -288
mflr 3
std 3, -8(1)
bl .Lbcm_loadtoc__dot_Lfoo_local_target
bl .Lbcm_loadtoc__dot_Lfoo_local_target__plus_20
std 3, -24(1)
ld 3, -8(1)
mtlr 3
ld 3, -24(1)
addi 1, 1, 288
addi 3, 3, +20
# WAS addis 4, 2, foo@toc@ha
# WAS addi 4, 4, foo@toc@l
@ -50,14 +48,28 @@ foo:
mflr 5
std 5, -8(1)
std 3, -16(1)
bl .Lbcm_loadtoc__dot_Lfoo_local_target
bl .Lbcm_loadtoc__dot_Lfoo_local_target__plus_10
std 3, -24(1)
ld 3, -8(1)
mtlr 3
ld 5, -24(1)
ld 3, -16(1)
addi 1, 1, 288
ld 5, +10(5)
ld 5, 0(5)
# WAS addis 4, 2, foo-10@toc@ha
# WAS addi 4, 4, foo-10@toc@l
addi 1, 1, -288
mflr 4
std 4, -8(1)
std 3, -16(1)
bl .Lbcm_loadtoc__dot_Lfoo_local_target__minus_10
std 3, -24(1)
ld 3, -8(1)
mtlr 3
ld 4, -24(1)
ld 3, -16(1)
addi 1, 1, 288
.text
BORINGSSL_bcm_text_end:
.type bcm_loadtoc__dot_Lfoo_local_target, @function
@ -66,6 +78,24 @@ bcm_loadtoc__dot_Lfoo_local_target:
addis 3, 2, .Lfoo_local_target@toc@ha
addi 3, 3, .Lfoo_local_target@toc@l
blr
.type bcm_loadtoc__dot_Lfoo_local_target__plus_10, @function
bcm_loadtoc__dot_Lfoo_local_target__plus_10:
.Lbcm_loadtoc__dot_Lfoo_local_target__plus_10:
addis 3, 2, .Lfoo_local_target+10@toc@ha
addi 3, 3, .Lfoo_local_target+10@toc@l
blr
.type bcm_loadtoc__dot_Lfoo_local_target__plus_20, @function
bcm_loadtoc__dot_Lfoo_local_target__plus_20:
.Lbcm_loadtoc__dot_Lfoo_local_target__plus_20:
addis 3, 2, .Lfoo_local_target+20@toc@ha
addi 3, 3, .Lfoo_local_target+20@toc@l
blr
.type bcm_loadtoc__dot_Lfoo_local_target__minus_10, @function
bcm_loadtoc__dot_Lfoo_local_target__minus_10:
.Lbcm_loadtoc__dot_Lfoo_local_target__minus_10:
addis 3, 2, .Lfoo_local_target-10@toc@ha
addi 3, 3, .Lfoo_local_target-10@toc@l
blr
.LBORINGSSL_external_toc:
.quad .TOC.-.LBORINGSSL_external_toc
.type BORINGSSL_bcm_text_hash, @object