mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-23 19:29:33 +02:00
* factored out check to determine whether a variable can be subscripted in
inline assembly, and fixed check after r35959 (mantis #32318) o can also subscript parameters passed by value on the stack o can also subscript local variables, the parameters passed by reference that are subsequently copied into a local git-svn-id: trunk@37886 -
This commit is contained in:
parent
dcac6b9c6f
commit
1b66995754
.gitattributes
compiler
tests/webtbs
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -15907,6 +15907,7 @@ tests/webtbs/tw3222.pp svneol=native#text/plain
|
||||
tests/webtbs/tw3226.pp svneol=native#text/plain
|
||||
tests/webtbs/tw3227.pp svneol=native#text/plain
|
||||
tests/webtbs/tw3227a.pp svneol=native#text/plain
|
||||
tests/webtbs/tw32318.pp svneol=native#text/plain
|
||||
tests/webtbs/tw3235.pp svneol=native#text/plain
|
||||
tests/webtbs/tw3235a.pp svneol=native#text/plain
|
||||
tests/webtbs/tw3241a.pp svneol=native#text/plain
|
||||
|
@ -607,13 +607,8 @@ Unit racpugas;
|
||||
{ don't allow direct access to fields of parameters, because that
|
||||
will generate buggy code. Allow it only for explicit typecasting }
|
||||
if hasdot and
|
||||
(not oper.hastype) and
|
||||
(oper.opr.localsym.typ=paravarsym) and
|
||||
(not(po_assembler in current_procinfo.procdef.procoptions) or
|
||||
(tparavarsym(oper.opr.localsym).paraloc[calleeside].location^.loc<>LOC_REGISTER) or
|
||||
(not is_implicit_pointer_object_type(oper.opr.localsym.vardef) and
|
||||
not paramanager.push_addr_param(oper.opr.localsym.varspez,oper.opr.localsym.vardef,current_procinfo.procdef.proccalloption))) then
|
||||
Message(asmr_e_cannot_access_field_directly_for_parameters);
|
||||
(not oper.hastype) then
|
||||
checklocalsubscript(oper.opr.localsym);
|
||||
inc(oper.opr.localsymofs,l)
|
||||
end;
|
||||
OPR_CONSTANT :
|
||||
|
@ -634,13 +634,8 @@ Unit raarmgas;
|
||||
{ don't allow direct access to fields of parameters, because that
|
||||
will generate buggy code. Allow it only for explicit typecasting }
|
||||
if hasdot and
|
||||
(not oper.hastype) and
|
||||
(oper.opr.localsym.typ=paravarsym) and
|
||||
(not(po_assembler in current_procinfo.procdef.procoptions) or
|
||||
(tparavarsym(oper.opr.localsym).paraloc[calleeside].location^.loc<>LOC_REGISTER) or
|
||||
(not is_implicit_pointer_object_type(oper.opr.localsym.vardef) and
|
||||
not paramanager.push_addr_param(oper.opr.localsym.varspez,oper.opr.localsym.vardef,current_procinfo.procdef.proccalloption))) then
|
||||
Message(asmr_e_cannot_access_field_directly_for_parameters);
|
||||
(not oper.hastype) then
|
||||
checklocalsubscript(oper.opr.localsym);
|
||||
inc(oper.opr.localsymofs,l)
|
||||
end;
|
||||
OPR_CONSTANT :
|
||||
|
@ -256,13 +256,8 @@ Unit raavrgas;
|
||||
{ don't allow direct access to fields of parameters, because that
|
||||
will generate buggy code. Allow it only for explicit typecasting }
|
||||
if hasdot and
|
||||
(not oper.hastype) and
|
||||
(oper.opr.localsym.typ=paravarsym) and
|
||||
(not(po_assembler in current_procinfo.procdef.procoptions) or
|
||||
(tparavarsym(oper.opr.localsym).paraloc[calleeside].location^.loc<>LOC_REGISTER) or
|
||||
(not is_implicit_pointer_object_type(oper.opr.localsym.vardef) and
|
||||
not paramanager.push_addr_param(oper.opr.localsym.varspez,oper.opr.localsym.vardef,current_procinfo.procdef.proccalloption))) then
|
||||
Message(asmr_e_cannot_access_field_directly_for_parameters);
|
||||
(not oper.hastype) then
|
||||
checklocalsubscript(oper.opr.localsym);
|
||||
inc(oper.opr.localsymofs,l)
|
||||
end;
|
||||
OPR_CONSTANT :
|
||||
|
@ -167,13 +167,8 @@ Interface
|
||||
{ don't allow direct access to fields of parameters, because that
|
||||
will generate buggy code. Allow it only for explicit typecasting }
|
||||
if hasdot and
|
||||
(not oper.hastype) and
|
||||
(oper.opr.localsym.typ=paravarsym) and
|
||||
(not(po_assembler in current_procinfo.procdef.procoptions) or
|
||||
(tparavarsym(oper.opr.localsym).paraloc[calleeside].location^.loc<>LOC_REGISTER) or
|
||||
(not is_implicit_pointer_object_type(oper.opr.localsym.vardef) and
|
||||
not paramanager.push_addr_param(oper.opr.localsym.varspez,oper.opr.localsym.vardef,current_procinfo.procdef.proccalloption))) then
|
||||
Message(asmr_e_cannot_access_field_directly_for_parameters);
|
||||
(not oper.hastype) then
|
||||
checklocalsubscript(oper.opr.localsym);
|
||||
inc(oper.opr.localsymofs,l)
|
||||
end;
|
||||
OPR_CONSTANT :
|
||||
|
@ -2652,7 +2652,7 @@ asmr_w_32bit_const_for_address=07079_W_32bit constant created for address
|
||||
asmr_n_align_is_target_specific=07080_N_.align is target specific, use .balign or .p2align
|
||||
% Using the .align directive is platform specific, and its meaning will vary
|
||||
% from one platform to another.
|
||||
asmr_e_cannot_access_field_directly_for_parameters=07081_E_Can't access fields directly for parameters
|
||||
asmr_e_cannot_access_field_directly_for_parameters=07081_E_Cannot directly access fields of pointer-based parameters
|
||||
% You should load the parameter first into a register and then access the
|
||||
% fields using that register.
|
||||
asmr_e_cannot_access_object_field_directly=07082_E_Can't access fields of objects/classes directly
|
||||
|
@ -1091,7 +1091,7 @@ const
|
||||
option_info=11024;
|
||||
option_help_pages=11025;
|
||||
|
||||
MsgTxtSize = 81026;
|
||||
MsgTxtSize = 81040;
|
||||
|
||||
MsgIdxMax : array[1..20] of longint=(
|
||||
27,105,347,124,96,58,139,33,221,67,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -339,13 +339,8 @@ Unit rappcgas;
|
||||
{ don't allow direct access to fields of parameters, because that
|
||||
will generate buggy code. Allow it only for explicit typecasting }
|
||||
if hasdot and
|
||||
(not oper.hastype) and
|
||||
(oper.opr.localsym.typ=paravarsym) and
|
||||
(not(po_assembler in current_procinfo.procdef.procoptions) or
|
||||
(tparavarsym(oper.opr.localsym).paraloc[calleeside].location^.loc<>LOC_REGISTER) or
|
||||
(not is_implicit_pointer_object_type(oper.opr.localsym.vardef) and
|
||||
not paramanager.push_addr_param(oper.opr.localsym.varspez,oper.opr.localsym.vardef,current_procinfo.procdef.proccalloption))) then
|
||||
Message(asmr_e_cannot_access_field_directly_for_parameters);
|
||||
(not oper.hastype) then
|
||||
checklocalsubscript(oper.opr.localsym);
|
||||
inc(oper.opr.localsymofs,l)
|
||||
end;
|
||||
OPR_CONSTANT :
|
||||
|
@ -349,13 +349,8 @@ var
|
||||
{ don't allow direct access to fields of parameters, because that
|
||||
will generate buggy code. Allow it only for explicit typecasting }
|
||||
if hasdot and
|
||||
(not oper.hastype) and
|
||||
(oper.opr.localsym.typ=paravarsym) and
|
||||
(not(po_assembler in current_procinfo.procdef.procoptions) or
|
||||
(tparavarsym(oper.opr.localsym).paraloc[calleeside].location^.loc<>LOC_REGISTER) or
|
||||
(not is_implicit_pointer_object_type(oper.opr.localsym.vardef) and
|
||||
not paramanager.push_addr_param(oper.opr.localsym.varspez,oper.opr.localsym.vardef,current_procinfo.procdef.proccalloption))) then
|
||||
Message(asmr_e_cannot_access_field_directly_for_parameters);
|
||||
(not oper.hastype) then
|
||||
checklocalsubscript(oper.opr.localsym);
|
||||
inc(oper.opr.localsymofs, l)
|
||||
end;
|
||||
OPR_CONSTANT:
|
||||
|
@ -27,6 +27,7 @@ unit rasm;
|
||||
|
||||
uses
|
||||
cclasses,
|
||||
symsym,
|
||||
rabase,
|
||||
aasmbase,
|
||||
aasmdata,
|
||||
@ -49,12 +50,21 @@ unit rasm;
|
||||
destructor destroy;override;
|
||||
function createlocallabel(const s: string; var hl: tasmlabel; emit: boolean): boolean;
|
||||
procedure checklocallabels;
|
||||
protected
|
||||
{ allow subscripting a local if it is a:
|
||||
1) pointer to a records/object, or a class instance pointer, passed in a register to a pure assembler routine
|
||||
2) record located on the stack (passed as parameter, or local variable)
|
||||
}
|
||||
procedure checklocalsubscript(sym: tabstractnormalvarsym); virtual;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
verbose;
|
||||
verbose,
|
||||
procinfo,
|
||||
symconst,symdef,
|
||||
paramgr;
|
||||
|
||||
type
|
||||
TLocalLabel = class(TFPHashObject)
|
||||
@ -129,4 +139,52 @@ unit rasm;
|
||||
locallabels.Clear;
|
||||
end;
|
||||
|
||||
|
||||
procedure tasmreader.checklocalsubscript(sym: tabstractnormalvarsym);
|
||||
var
|
||||
isimplicitpointer: boolean;
|
||||
begin
|
||||
isimplicitpointer:=
|
||||
(sym.typ=paravarsym) and
|
||||
(is_implicit_pointer_object_type(sym.vardef) or
|
||||
paramanager.push_addr_param(sym.varspez,sym.vardef,current_procinfo.procdef.proccalloption));
|
||||
|
||||
{ sym.initiallloc/localloc is not yet initialised here }
|
||||
|
||||
{ pointer parameter to aggregate passed in register to pure assembler routine }
|
||||
if (po_assembler in current_procinfo.procdef.procoptions) and
|
||||
(sym.typ=paravarsym) and
|
||||
(tparavarsym(sym).paraloc[calleeside].location^.loc=LOC_REGISTER) and
|
||||
isimplicitpointer then
|
||||
exit;
|
||||
|
||||
{ aggregate parameter passed on the stack to a pure assembler routine }
|
||||
if (po_assembler in current_procinfo.procdef.procoptions) and
|
||||
(sym.typ=paravarsym) and
|
||||
{ sym.localloc is not yet initialised here for pure assembler routines }
|
||||
(tparavarsym(sym).paraloc[calleeside].location^.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and
|
||||
not isimplicitpointer then
|
||||
exit;
|
||||
|
||||
{ aggregate parameter located on the stack for a non-assembler routine
|
||||
(locals accessed from assembler code are never kept in registers) }
|
||||
if not(po_assembler in current_procinfo.procdef.procoptions) and
|
||||
(sym.typ=paravarsym) and
|
||||
not isimplicitpointer then
|
||||
exit;
|
||||
|
||||
{ local aggregate located on the stack (locals accessed from assembler
|
||||
code are never kept in registers) }
|
||||
if ((sym.typ=localvarsym) or
|
||||
{ even if a parameter is passed by reference, it will be copied to
|
||||
a local if it's a value parameter to a non assembler routines }
|
||||
(not(po_assembler in current_procinfo.procdef.procoptions) and
|
||||
(sym.typ=paravarsym) and
|
||||
(sym.varspez=vs_value))) and
|
||||
not is_implicit_pointer_object_type(sym.vardef) then
|
||||
exit;
|
||||
|
||||
Message(asmr_e_cannot_access_field_directly_for_parameters);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
@ -226,13 +226,8 @@ Interface
|
||||
{ don't allow direct access to fields of parameters, because that
|
||||
will generate buggy code. Allow it only for explicit typecasting }
|
||||
if hasdot and
|
||||
(not oper.hastype) and
|
||||
(oper.opr.localsym.typ=paravarsym) and
|
||||
(not(po_assembler in current_procinfo.procdef.procoptions) or
|
||||
(tparavarsym(oper.opr.localsym).paraloc[calleeside].location^.loc<>LOC_REGISTER) or
|
||||
(not is_implicit_pointer_object_type(oper.opr.localsym.vardef) and
|
||||
not paramanager.push_addr_param(oper.opr.localsym.varspez,oper.opr.localsym.vardef,current_procinfo.procdef.proccalloption))) then
|
||||
Message(asmr_e_cannot_access_field_directly_for_parameters);
|
||||
(not oper.hastype) then
|
||||
checklocalsubscript(oper.opr.localsym);
|
||||
inc(oper.opr.localsymofs,l)
|
||||
end;
|
||||
OPR_CONSTANT :
|
||||
|
@ -459,13 +459,8 @@ Implementation
|
||||
{ don't allow direct access to fields of parameters, because that
|
||||
will generate buggy code. Allow it only for explicit typecasting }
|
||||
if hasdot and
|
||||
(not oper.hastype) and
|
||||
(oper.opr.localsym.typ=paravarsym) and
|
||||
(not(po_assembler in current_procinfo.procdef.procoptions) or
|
||||
(tparavarsym(oper.opr.localsym).paraloc[calleeside].location^.loc<>LOC_REGISTER) or
|
||||
(not is_implicit_pointer_object_type(oper.opr.localsym.vardef) and
|
||||
not paramanager.push_addr_param(oper.opr.localsym.varspez,oper.opr.localsym.vardef,current_procinfo.procdef.proccalloption))) then
|
||||
Message(asmr_e_cannot_access_field_directly_for_parameters);
|
||||
(not oper.hastype) then
|
||||
checklocalsubscript(oper.opr.localsym);
|
||||
inc(oper.opr.localsymofs,l);
|
||||
inc(oper.opr.localconstoffset,l);
|
||||
end;
|
||||
|
@ -1733,13 +1733,8 @@ Unit Rax86int;
|
||||
{ don't allow direct access to fields of parameters, because that
|
||||
will generate buggy code. Allow it only for explicit typecasting
|
||||
and when the parameter is in a register (delphi compatible) }
|
||||
if (not oper.hastype) and
|
||||
(oper.opr.localsym.typ=paravarsym) and
|
||||
(not(po_assembler in current_procinfo.procdef.procoptions) or
|
||||
(tparavarsym(oper.opr.localsym).paraloc[calleeside].location^.loc<>LOC_REGISTER) or
|
||||
(not is_implicit_pointer_object_type(oper.opr.localsym.vardef) and
|
||||
not paramanager.push_addr_param(oper.opr.localsym.varspez,oper.opr.localsym.vardef,current_procinfo.procdef.proccalloption))) then
|
||||
Message(asmr_e_cannot_access_field_directly_for_parameters);
|
||||
if (not oper.hastype) then
|
||||
checklocalsubscript(oper.opr.localsym);
|
||||
|
||||
oper.opr.localforceref:=true;
|
||||
inc(oper.opr.localsymofs,toffset);
|
||||
|
54
tests/webtbs/tw32318.pp
Normal file
54
tests/webtbs/tw32318.pp
Normal file
@ -0,0 +1,54 @@
|
||||
{ %cpu=i386}
|
||||
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$endif fpc}
|
||||
|
||||
function MakeProcInstanceData(M: TMethod): Pointer;
|
||||
begin
|
||||
asm
|
||||
MOV EAX, M.Data
|
||||
MOV @RESULT, EAX
|
||||
end;
|
||||
end;
|
||||
|
||||
function MakeProcInstanceCode(M: TMethod): Pointer;
|
||||
begin
|
||||
asm
|
||||
MOV EAX, M.Code
|
||||
MOV @RESULT, EAX
|
||||
end;
|
||||
end;
|
||||
|
||||
function MakeProcInstanceDataAsm(M: TMethod): Pointer; assembler;
|
||||
asm
|
||||
MOV EAX, M.Data
|
||||
MOV @RESULT, EAX
|
||||
end;
|
||||
|
||||
function MakeProcInstanceCodeAsm(M: TMethod): Pointer; assembler;
|
||||
asm
|
||||
MOV EAX, M.Code
|
||||
MOV @RESULT, EAX
|
||||
end;
|
||||
|
||||
var
|
||||
m: tmethod;
|
||||
begin
|
||||
m.code:=pointer(1);
|
||||
m.data:=pointer(2);
|
||||
if MAkeProcInstanceData(M)<>pointer(2) then
|
||||
halt(1);
|
||||
m.code:=pointer(1);
|
||||
m.data:=pointer(2);
|
||||
if MAkeProcInstanceCode(M)<>pointer(1) then
|
||||
halt(2);
|
||||
m.code:=pointer(1);
|
||||
m.data:=pointer(2);
|
||||
if MAkeProcInstanceDataAsm(M)<>pointer(2) then
|
||||
halt(3);
|
||||
m.code:=pointer(1);
|
||||
m.data:=pointer(2);
|
||||
if MAkeProcInstanceCodeAsm(M)<>pointer(1) then
|
||||
halt(4);
|
||||
end.
|
Loading…
Reference in New Issue
Block a user