* fix #40451: load the assembly symbol into a separate operand so that an offset already contained in oper isn't discarded + added test

This commit is contained in:
Sven/Sarah Barth 2023-10-20 15:48:32 +02:00
parent b003828d26
commit f88ee7b2d8
2 changed files with 49 additions and 6 deletions

View File

@ -306,6 +306,7 @@ Implementation
var
expr : string;
tmp : tx86operand;
begin
oper.InitRef;
Consume(AS_LPAREN);
@ -357,35 +358,53 @@ Implementation
begin
expr:=actasmpattern;
Consume(AS_ID);
if not oper.SetupVar(expr,false) then
tmp:=Tx86Operand.create;
if not tmp.SetupVar(expr,false) then
begin
{ look for special symbols ... }
if expr= '__HIGH' then
begin
consume(AS_LPAREN);
if not oper.setupvar('high'+actasmpattern,false) then
if not tmp.setupvar('high'+actasmpattern,false) then
Message1(sym_e_unknown_id,'high'+actasmpattern);
consume(AS_ID);
consume(AS_RPAREN);
end
else
if expr = '__SELF' then
oper.SetupSelf
tmp.SetupSelf
else
begin
message1(sym_e_unknown_id,expr);
RecoverConsume(false);
tmp.free;
Exit;
end;
end;
{ convert OPR_LOCAL register para into a reference base }
if (oper.opr.typ=OPR_LOCAL) and
AsmRegisterPara(oper.opr.localsym) then
oper.InitRefConvertLocal
if (tmp.opr.typ=OPR_LOCAL) and
AsmRegisterPara(tmp.opr.localsym) then
begin
tmp.InitRefConvertLocal;
if (tmp.opr.ref.index<>NR_NO) or
(tmp.opr.ref.offset<>0) or
(tmp.opr.ref.scalefactor<>0) or
(tmp.opr.ref.segment<>NR_NO) or
(tmp.opr.ref.base=NR_NO) then
begin
message(asmr_e_invalid_reference_syntax);
RecoverConsume(false);
tmp.free;
Exit;
end;
oper.opr.ref.base:=tmp.opr.ref.base;
tmp.free;
end
else
begin
message(asmr_e_invalid_reference_syntax);
RecoverConsume(false);
tmp.free;
Exit;
end;
{ can either be a register, an identifier or a right parenthesis }

24
tests/webtbs/tw40451.pp Normal file
View File

@ -0,0 +1,24 @@
{ %CPU=x86_64,i386 }
program tw40451;
{$mode objfpc}
{$asmmode att}
procedure DoubleUint32ToTheLeft(x: pointer); {$ifdef cpu386}register;{$endif} assembler; nostackframe;
asm
movl -4(x), %edx // Becomes "movl (x), %edx"
shl $1, %edx
movl %edx, -4(x) // Becomes "movl %edx, (x)"
end;
var
a: array[0 .. 2] of uint32 = (10, 11, 12);
begin
DoubleUint32ToTheLeft(@a[1]);
writeln('Got: ', a[0], ' ', a[1], ' ', a[2]);
writeln('Expected: 20 11 12');
if (a[0] <> 20) or (a[1] <> 11) or (a[2] <> 12) then
Halt(1);
end.