Fix computation of offset in arm64 compiler (#677)

* Fix computation of offset in arm64 compiler

Signed-off-by: Anuraag Agrawal <anuraaga@gmail.com>
This commit is contained in:
Anuraag Agrawal
2022-07-07 16:13:00 +09:00
committed by GitHub
parent 8c2f0928bc
commit 66d43a2a52
2 changed files with 190 additions and 136 deletions

View File

@@ -200,6 +200,14 @@ func (o operandTypes) String() string {
return fmt.Sprintf("from:%s,to:%s", o.src, o.dst)
}
const (
maxSignedInt26 int64 = 1<<25 - 1
minSignedInt26 int64 = -(1 << 25)
maxSignedInt19 int64 = 1<<19 - 1
minSignedInt19 int64 = -(1 << 19)
)
// AssemblerImpl implements Assembler.
type AssemblerImpl struct {
asm.BaseAssemblerImpl
@@ -756,9 +764,7 @@ func (a *AssemblerImpl) encodeRelativeBranch(n *nodeImpl) (err error) {
branchInst := code[branchInstOffset : branchInstOffset+4]
if condBits == condBitsUnconditional {
imm26 := offset / 4
const maxSignedInt26 int64 = 1<<25 - 1
const minSignedInt26 int64 = -(1 << 25)
if offset < minSignedInt26 || offset > maxSignedInt26 {
if imm26 < minSignedInt26 || imm26 > maxSignedInt26 {
// In theory this could happen if a Wasm binary has a huge single label (more than 128MB for a single block),
// and in that case, we use load the offset into a register and do the register jump, but to avoid the complexity,
// we impose this limit for now as that would be *unlikely* happen in practice.
@@ -771,9 +777,7 @@ func (a *AssemblerImpl) encodeRelativeBranch(n *nodeImpl) (err error) {
branchInst[3] = (byte(imm26 >> 24 & 0b000000_11)) | 0b000101_00
} else {
imm19 := offset / 4
const maxSignedInt19 int64 = 1<<19 - 1
const minSignedInt19 int64 = -(1 << 19)
if offset < minSignedInt19 || offset > maxSignedInt19 {
if imm19 < minSignedInt19 || imm19 > maxSignedInt19 {
// This should be a bug in our compiler as the conditional jumps are only used in the small offsets (~a few bytes),
// and if ever happens, compiler can be fixed.
return fmt.Errorf("BUG: relative jump offset %d/4(=%d) must be within %d and %d", offset, imm19, minSignedInt19, maxSignedInt19)

File diff suppressed because one or more lines are too long