Skip to content

Computation of locals' offsets is wrong when stack size exceeds 2G #48911

@nagisa

Description

@nagisa
Bugzilla Link 49567
Version trunk
OS All
CC @topperc,@cuviper,@jdm,@RKSimon,@phoebewang,@rotateright,@oToToT

Extended Description

Given the following test case:

; RUN: llc -O0 -mtriple=x86_64 < %s
; RUN: llc -O0 -mtriple=i686 < %s

%large = type [2148000000 x i8]

define void @banana() unnamed_addr #0 {
  %1 = alloca %large, align 1
  %2 = alloca %large, align 1
  %3 = getelementptr inbounds %large, %large* %1, i64 0, i64 0
  store i8 42, i8* %3, align 1
  %4 = getelementptr inbounds %large, %large* %2, i64 0, i64 0
  store i8 43, i8* %4, align 1
  ret void
}

Will produce the following assembly:

movabsq	$4295999872, %rax               # imm = 0x1000FC180
subq	%rax, %rsp
.cfi_def_cfa_offset 1032584
movb	$42, -2146967424(%rsp)
movb	$43, -128(%rsp)
movabsq	$4295999872, %rax               # imm = 0x1000FC180
addq	%rax, %rsp
.cfi_def_cfa_offset 8
retq

You will notice that both the variables allocad in this function are considered to be below the already adjusted stack pointer, rather than above it, where they ought to be.

This looks like a basic signed 32-bit integer overflow somewhere in prologepilog:

# *** IR Dump Before Prologue/Epilogue Insertion & Frame Finalization (prologepilog) ***:
# Machine code for function banana: NoPHIs, TracksLiveness, NoVRegs, TiedOpsRewritten
Frame Objects:
  fi#0: size=2148000000, align=1, at location [SP+8]
  fi#1: size=2148000000, align=1, at location [SP+8]

bb.0 (%ir-block.0):
  MOV8mi %stack.0, 1, $noreg, 0, $noreg, 42 :: (store 1 into %ir.3)
  MOV8mi %stack.1, 1, $noreg, 0, $noreg, 43 :: (store 1 into %ir.4)
  RET 0

# *** IR Dump After Prologue/Epilogue Insertion & Frame Finalization (prologepilog) ***:
# Machine code for function banana: NoPHIs, TracksLiveness, NoVRegs, TiedOpsRewritten
Frame Objects:
  fi#0: size=2148000000, align=1, at location [SP-2148000000]
  fi#1: size=2148000000, align=1, at location [SP-4296000000]

bb.0 (%ir-block.0):
  $rax = frame-setup MOV64ri 4295999872
  $rsp = SUB64rr $rsp(tied-def 0), $rax, implicit-def dead $eflags
  CFI_INSTRUCTION def_cfa_offset 1032584
  MOV8mi $rsp, 1, $noreg, -2146967424, $noreg, 42 :: (store 1 into %ir.3)
  MOV8mi $rsp, 1, $noreg, -128, $noreg, 43 :: (store 1 into %ir.4)
  $rax = frame-destroy MOV64ri 4295999872
  $rsp = ADD64rr $rsp(tied-def 0), $rax, implicit-def dead $eflags
  CFI_INSTRUCTION def_cfa_offset 8
  RET 0

Worth noting that the the def_cfa_offset directive also overflowed in this reproducer here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions