mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-05 23:31:49 +02:00
* fix #40390: implement support for handling parameter names (including __SELF and __HIGH(<identifier>)) that resolve directly to registers
+ added tests
This commit is contained in:
parent
7f290c27ed
commit
3b455c1cf2
@ -207,7 +207,105 @@ Implementation
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure Consume_Index;
|
||||
|
||||
procedure Check_Scaling;
|
||||
begin
|
||||
{ check for scaling ... }
|
||||
case actasmtoken of
|
||||
AS_RPAREN:
|
||||
Begin
|
||||
Consume_RParen;
|
||||
exit;
|
||||
end;
|
||||
AS_COMMA:
|
||||
Begin
|
||||
Consume(AS_COMMA);
|
||||
Consume_Scale;
|
||||
Consume_RParen;
|
||||
end;
|
||||
else
|
||||
Begin
|
||||
Message(asmr_e_invalid_reference_syntax);
|
||||
RecoverConsume(false);
|
||||
end;
|
||||
end; { end case }
|
||||
end;
|
||||
|
||||
var
|
||||
tmp : tx86operand;
|
||||
expr : string;
|
||||
begin
|
||||
if actasmtoken=AS_REGISTER then
|
||||
Begin
|
||||
oper.opr.ref.index:=actasmregister;
|
||||
Consume(AS_REGISTER);
|
||||
Check_Scaling;
|
||||
end
|
||||
else if actasmtoken=AS_ID then
|
||||
begin
|
||||
expr:=actasmpattern;
|
||||
Consume(AS_ID);
|
||||
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 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
|
||||
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 (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.index:=tmp.opr.ref.base;
|
||||
tmp.free;
|
||||
Check_Scaling;
|
||||
end
|
||||
else
|
||||
begin
|
||||
message(asmr_e_invalid_reference_syntax);
|
||||
RecoverConsume(false);
|
||||
tmp.free;
|
||||
Exit;
|
||||
end;
|
||||
end
|
||||
else
|
||||
Begin
|
||||
Message(asmr_e_invalid_reference_syntax);
|
||||
RecoverConsume(false);
|
||||
end;
|
||||
end;
|
||||
|
||||
var
|
||||
expr : string;
|
||||
begin
|
||||
oper.InitRef;
|
||||
Consume(AS_LPAREN);
|
||||
@ -244,7 +342,7 @@ Implementation
|
||||
oper.opr.ref.refaddr:=addr_pic_no_got;
|
||||
{$endif x86_64}
|
||||
Consume(AS_REGISTER);
|
||||
{ can either be a register or a right parenthesis }
|
||||
{ can either be a register, an identifier or a right parenthesis }
|
||||
{ (reg) }
|
||||
if actasmtoken=AS_RPAREN then
|
||||
Begin
|
||||
@ -253,36 +351,53 @@ Implementation
|
||||
end;
|
||||
{ (reg,reg .. }
|
||||
Consume(AS_COMMA);
|
||||
if actasmtoken=AS_REGISTER then
|
||||
Begin
|
||||
oper.opr.ref.index:=actasmregister;
|
||||
Consume(AS_REGISTER);
|
||||
{ check for scaling ... }
|
||||
case actasmtoken of
|
||||
AS_RPAREN:
|
||||
Begin
|
||||
Consume_Index;
|
||||
end; {end case }
|
||||
AS_ID: { identifier (parameter, variable, ...), but only those that might be in a register }
|
||||
begin
|
||||
expr:=actasmpattern;
|
||||
Consume(AS_ID);
|
||||
if not oper.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
|
||||
Message1(sym_e_unknown_id,'high'+actasmpattern);
|
||||
consume(AS_ID);
|
||||
consume(AS_RPAREN);
|
||||
end
|
||||
else
|
||||
if expr = '__SELF' then
|
||||
oper.SetupSelf
|
||||
else
|
||||
begin
|
||||
message1(sym_e_unknown_id,expr);
|
||||
RecoverConsume(false);
|
||||
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
|
||||
else
|
||||
begin
|
||||
message(asmr_e_invalid_reference_syntax);
|
||||
RecoverConsume(false);
|
||||
Exit;
|
||||
end;
|
||||
{ can either be a register, an identifier or a right parenthesis }
|
||||
{ (reg) }
|
||||
if actasmtoken=AS_RPAREN then
|
||||
begin
|
||||
Consume_RParen;
|
||||
exit;
|
||||
end;
|
||||
AS_COMMA:
|
||||
Begin
|
||||
Consume(AS_COMMA);
|
||||
Consume_Scale;
|
||||
Consume_RParen;
|
||||
Consume_Index;
|
||||
end;
|
||||
else
|
||||
Begin
|
||||
Message(asmr_e_invalid_reference_syntax);
|
||||
RecoverConsume(false);
|
||||
end;
|
||||
end; { end case }
|
||||
end
|
||||
else
|
||||
Begin
|
||||
Message(asmr_e_invalid_reference_syntax);
|
||||
RecoverConsume(false);
|
||||
end;
|
||||
end; {end case }
|
||||
AS_COMMA: { (, ... can either be scaling, or index }
|
||||
Begin
|
||||
Consume(AS_COMMA);
|
||||
|
17
tests/test/tasm28.pp
Normal file
17
tests/test/tasm28.pp
Normal file
@ -0,0 +1,17 @@
|
||||
{ %NORUN }
|
||||
{ %CPU=i386,x86_64 }
|
||||
|
||||
program tasm28;
|
||||
|
||||
{$mode objfpc}
|
||||
|
||||
{$asmmode att}
|
||||
procedure Test(aArr: array of LongInt); {$ifdef cpu386}register;{$endif} assembler; nostackframe;
|
||||
asm
|
||||
movb $5, (aArr, __HIGH(aArr))
|
||||
movb $5, (__HIGH(aArr), aArr)
|
||||
end;
|
||||
|
||||
begin
|
||||
|
||||
end.
|
22
tests/test/tasm29.pp
Normal file
22
tests/test/tasm29.pp
Normal file
@ -0,0 +1,22 @@
|
||||
{ %NORUN }
|
||||
{ %CPU=i386,x86_64 }
|
||||
|
||||
program tasm29;
|
||||
|
||||
{$mode objfpc}
|
||||
|
||||
type
|
||||
|
||||
TTest = class
|
||||
procedure Test(aArg: Pointer); {$ifdef cpu386}register;{$endif} assembler; nostackframe;
|
||||
end;
|
||||
|
||||
procedure TTest.Test(aArg: Pointer); {$ifdef cpu386}register;{$endif} assembler; nostackframe;
|
||||
asm
|
||||
movb $5, (__SELF, aArg)
|
||||
movb $5, (aArg, __SELF)
|
||||
end;
|
||||
|
||||
begin
|
||||
|
||||
end.
|
23
tests/webtbs/tw40390.pp
Normal file
23
tests/webtbs/tw40390.pp
Normal file
@ -0,0 +1,23 @@
|
||||
{ %NORUN }
|
||||
{ %CPU=i386,x86_64 }
|
||||
|
||||
program tw40390;
|
||||
|
||||
{$asmmode att}
|
||||
procedure SetMiddleTo5(p: pointer; n: SizeUint); {$ifdef cpu386}register;{$endif} assembler; nostackframe;
|
||||
asm
|
||||
{$ifdef cpu386}
|
||||
shrl $1, n // becomes “shrq $1, %rdx” (Win64) or “shrq $1, %rsi” (System V)
|
||||
movb $5, (p,n) // Invalid reference syntax.
|
||||
movb $5, (%edx,n)
|
||||
movb $5, (p,%edx)
|
||||
{$elseif defined(cpux86_64)}
|
||||
shrq $1, n // becomes “shrq $1, %rdx” (Win64) or “shrq $1, %rsi” (System V)
|
||||
movb $5, (p,n) // Invalid reference syntax.
|
||||
movb $5, (%rdx,n)
|
||||
movb $5, (p,%rdx)
|
||||
{$endif}
|
||||
end;
|
||||
|
||||
begin
|
||||
end.
|
Loading…
Reference in New Issue
Block a user