From 3aed2eb8ac4c5b09d3b2a68c17cf1215c20e7214 Mon Sep 17 00:00:00 2001 From: Stephen Heumann Date: Thu, 2 Nov 2017 00:45:47 -0500 Subject: [PATCH] Fix problem where array index computations involving a negative variable part of the index could be miscomputed when using the small memory model. This introduces a function to check whether the index portion of a pc_ixa intermediate code operation (used for array indexing) may be negative. This is also used when generating code for the large memory model, which can allow slightly more efficient code to be generated in some cases. This fixes #45. --- Gen.pas | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/Gen.pas b/Gen.pas index 88842c5..5ba94d7 100644 --- a/Gen.pas +++ b/Gen.pas @@ -2373,6 +2373,7 @@ case optype of end; {GenInd} + procedure GenIxa (op: icptr); { Generate code for a pc_ixa } @@ -2408,6 +2409,29 @@ var end; {Index} + function IndexCanBeNegative: boolean; + + { Check if the index value (right argument) of a pc_ixa } + { can validly be negative. Returns false if this is } + { precluded by the type of the operation or other available } + { information, or if any use of a negative index would be } + { undefined behavior. Otherwise, returns true. } + { } + { parameters: } + { op - pc_ixa operation } + + begin {IndexCanBeNegative} + IndexCanBeNegative := true; + if op^.optype in [cgUByte,cgUWord] then + IndexCanBeNegative := false + else if (op^.right^.opcode = pc_ldc) and (op^.right^.q >= 0) then + IndexCanBeNegative := false + else if (op^.left^.opcode in [pc_lao,pc_lda]) and (op^.left^.q = 0) then + {Can't index before start of array, so using a negative index would be UB} + IndexCanBeNegative := false; + end; {IndexCanBeNegative} + + begin {GenIxa} if smallMemoryModel then begin lLong := gLong; @@ -2507,6 +2531,14 @@ if smallMemoryModel then begin LoadX(op^.right); gLong.fixedDisp := false; end; {else} + if gLong.where = globalLabel then + if IndexCanBeNegative then begin + GenImplied(m_txa); + GenImplied(m_clc); + GenNative(m_adc_imm, immediate, gLong.disp, nil, 0); + GenImplied(m_tax); + gLong.disp := 0; + end; {if} if (lLong.preference & gLong.where) = 0 then begin if (lLong.preference & inPointer) <> 0 then begin if gLong.where = localAddress then begin @@ -2598,12 +2630,12 @@ if smallMemoryModel then begin otherwise: Error(cge1); end; {case} - end {if smallMemoryModel or (op^.right^.opcode = pc_ldc)} + end {if smallMemoryModel} else begin gLong.preference := onStack; GenTree(op^.left); GenTree(op^.right); - if op^.optype in [cgByte,cgWord] then begin + if IndexCanBeNegative then begin lab1 := GenLabel; GenNative(m_ldx_imm, immediate, $0000, nil, 0); GenImplied(m_tay);