fpc/compiler/rasm.pas
florian 46fe2d486c * forgotten comment
git-svn-id: trunk@38142 -
2018-02-06 21:38:51 +00:00

193 lines
6.1 KiB
ObjectPascal

{
Copyright (c) 1998-2003 by Peter Vreman, Florian Klaempfl and Carl Eric Codere
Basic stuff for assembler readers
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
****************************************************************************
}
unit rasm;
{$i fpcdefs.inc}
interface
uses
cclasses,
symsym,
rabase,
aasmbase,
aasmdata,
cpubase,
cgbase;
type
tasmreader = class(tbaseasmreader)
firsttoken : boolean;
_asmsorted : boolean;
curlist : TAsmList;
c : char;
actasmpattern : string;
actopcode : tasmop;
actasmregister : tregister;
actcondition : tasmcond;
iasmops : TFPHashList;
locallabels : TFPHashObjectList;
constructor create;override;
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,
procinfo,
symconst,symdef,
paramgr;
type
TLocalLabel = class(TFPHashObject)
emitted: boolean;
lab: tasmlabel;
function Gettasmlabel: tasmlabel;
end;
function TLocalLabel.Gettasmlabel:tasmlabel;
begin
if not assigned(lab) then
begin
current_asmdata.getjumplabel(lab);
{ this label is forced to be used so it's always written }
lab.increfs;
end;
result:=lab;
end;
constructor tasmreader.create;
begin
inherited create;
firsttoken:=true;
locallabels:=TFPHashObjectList.create;
end;
destructor tasmreader.destroy;
begin
locallabels.Free;
iasmops.Free;
inherited destroy;
end;
function tasmreader.createlocallabel(const s: string; var hl: tasmlabel; emit:boolean):boolean;
var
lab: TLocalLabel;
begin
result:=true;
{ Check if it already is defined }
lab:=TLocalLabel(locallabels.Find(s));
if not assigned(lab) then
lab:=TLocalLabel.Create(locallabels,s);
{ set emitted flag and check for dup syms }
if emit then
begin
if lab.Emitted then
begin
Message1(asmr_e_dup_local_sym,lab.Name);
result:=false;
end;
lab.Emitted:=true;
end;
hl:=lab.Gettasmlabel;
end;
procedure tasmreader.checklocallabels;
var
i: longint;
lab: TLocalLabel;
begin
for i:=0 to locallabels.Count-1 do
begin
lab:=TLocalLabel(locallabels[i]);
if not lab.emitted then
Message1(asmr_e_unknown_label_identifier,lab.name);
end;
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
{ ... however this is only possible if the pointer takes only one register location }
not assigned(tparavarsym(sym).paraloc[calleeside].location^.Next) 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.