|
@@ -26,9 +26,28 @@ unit nllvmbas;
|
|
|
interface
|
|
|
|
|
|
uses
|
|
|
- nbas,ncgbas;
|
|
|
+ globtype,cclasses,
|
|
|
+ aasmbase,aasmtai,aasmdata,
|
|
|
+ nbas,ncgbas,
|
|
|
+ symsym;
|
|
|
|
|
|
type
|
|
|
+ tllvmasmnode = class(tcgasmnode)
|
|
|
+ protected
|
|
|
+ { map a tasmsymbol to an index in fsymboldata }
|
|
|
+ fsymbollookup: THashSet;
|
|
|
+ { the LLVM symbolic inline assembly operands to which the ones in the
|
|
|
+ source code are mapped }
|
|
|
+ fsymboldata: tfplist;
|
|
|
+ function getllvmasmopindexforsym(sym: tabstractnormalvarsym): longint;
|
|
|
+ function getllvmasmparasym(sym: tabstractnormalvarsym): tasmsymbol;
|
|
|
+ procedure ResolveRef(const filepos: tfileposinfo; var op: toper); override;
|
|
|
+ public
|
|
|
+ constructor create(p : TAsmList); override;
|
|
|
+ destructor destroy; override;
|
|
|
+ procedure pass_generate_code; override;
|
|
|
+ end;
|
|
|
+
|
|
|
tllvmtempinfoaccessor = class(ttempinfoaccessor)
|
|
|
protected
|
|
|
class procedure settempinfoflags(tempinfo: ptempinfo; const flags: ttempinfoflags); override;
|
|
@@ -41,11 +60,168 @@ interface
|
|
|
implementation
|
|
|
|
|
|
uses
|
|
|
- aasmdata,
|
|
|
- cgbase,cgutils,
|
|
|
- llvmbase,aasmllvm
|
|
|
+ verbose,cutils,
|
|
|
+ cgbase,cgutils,paramgr,
|
|
|
+ symconst,symdef,procinfo,
|
|
|
+ node,
|
|
|
+ cpubase,llvmbase,aasmllvm
|
|
|
;
|
|
|
|
|
|
+{*****************************************************************************
|
|
|
+ TLLVMASMNODE
|
|
|
+*****************************************************************************}
|
|
|
+
|
|
|
+ function tllvmasmnode.getllvmasmopindexforsym(sym: tabstractnormalvarsym): longint;
|
|
|
+ var
|
|
|
+ key: record
|
|
|
+ sym: pointer;
|
|
|
+ end;
|
|
|
+ res: PHashSetItem;
|
|
|
+ callpara: pllvmcallpara;
|
|
|
+ begin
|
|
|
+ key.sym:=sym;
|
|
|
+ res:=fsymbollookup.FindOrAdd(@key,sizeof(key));
|
|
|
+ if not assigned(res^.Data) then
|
|
|
+ begin
|
|
|
+ new(callpara);
|
|
|
+ callpara^.def:=cpointerdef.getreusable(sym.vardef);
|
|
|
+ if (sym.typ=paravarsym) and
|
|
|
+ paramanager.push_addr_param(sym.varspez,sym.vardef,current_procinfo.procdef.proccalloption) then
|
|
|
+ callpara^.def:=cpointerdef.getreusable(callpara^.def);
|
|
|
+ callpara^.sret:=false;
|
|
|
+ callpara^.byval:=false;
|
|
|
+ callpara^.valueext:=lve_none;
|
|
|
+ callpara^.loc:=LOC_REGISTER;
|
|
|
+ { address must be a temp register }
|
|
|
+ if (sym.localloc.loc<>LOC_REFERENCE) or
|
|
|
+ (sym.localloc.reference.base=NR_NO) or
|
|
|
+ (sym.localloc.reference.index<>NR_NO) or
|
|
|
+ (sym.localloc.reference.offset<>0) or
|
|
|
+ assigned(sym.localloc.reference.symbol) then
|
|
|
+ internalerror(2016111001);
|
|
|
+ callpara^.reg:=sym.localloc.reference.base;
|
|
|
+ fsymboldata.add(callpara);
|
|
|
+ ptruint(res^.Data):=fsymboldata.count-1;
|
|
|
+ end;
|
|
|
+ result:=longint(ptruint(res^.Data));
|
|
|
+ end;
|
|
|
+
|
|
|
+
|
|
|
+ function tllvmasmnode.getllvmasmparasym(sym: tabstractnormalvarsym): tasmsymbol;
|
|
|
+ begin
|
|
|
+ result:=current_asmdata.RefAsmSymbol('$'+tostr(getllvmasmopindexforsym(sym)),AT_DATA,false);
|
|
|
+ end;
|
|
|
+
|
|
|
+
|
|
|
+ procedure tllvmasmnode.ResolveRef(const filepos: tfileposinfo; var op: toper);
|
|
|
+ var
|
|
|
+ sym: tabstractnormalvarsym;
|
|
|
+ ref: treference;
|
|
|
+ sofs: pint;
|
|
|
+ indexreg : tregister;
|
|
|
+ getoffset: boolean;
|
|
|
+{$ifdef x86}
|
|
|
+ scale : byte;
|
|
|
+{$endif x86}
|
|
|
+ begin
|
|
|
+ { pure assembler routines are handled by the regular code generator }
|
|
|
+ if po_assembler in current_procinfo.procdef.procoptions then
|
|
|
+ begin
|
|
|
+ inherited;
|
|
|
+ exit;
|
|
|
+ end;
|
|
|
+ { translate all symbolic references to "parameters" of the llvm
|
|
|
+ assembler statements }
|
|
|
+ case op.typ of
|
|
|
+ top_local:
|
|
|
+ begin
|
|
|
+ sofs:=op.localoper^.localsymofs;
|
|
|
+ indexreg:=op.localoper^.localindexreg;
|
|
|
+{$ifdef x86}
|
|
|
+ scale:=op.localoper^.localscale;
|
|
|
+{$endif x86}
|
|
|
+ getoffset:=op.localoper^.localgetoffset;
|
|
|
+ sym:=tabstractnormalvarsym(op.localoper^.localsym);
|
|
|
+ dispose(op.localoper);
|
|
|
+ case sym.localloc.loc of
|
|
|
+ LOC_REFERENCE:
|
|
|
+ begin
|
|
|
+ if getoffset then
|
|
|
+ begin
|
|
|
+ { todo: print proper error. You cannot get the offset
|
|
|
+ of a local variable since it may be in a register
|
|
|
+ outside the assembler block with llvm }
|
|
|
+ internalerror(2016102001);
|
|
|
+ end
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ op.typ:=top_ref;
|
|
|
+ new(op.ref);
|
|
|
+ reference_reset_symbol(op.ref^,getllvmasmparasym(sym),sofs,
|
|
|
+ newalignment(sym.localloc.reference.alignment,sofs));
|
|
|
+ op.ref^.index:=indexreg;
|
|
|
+{$ifdef x86}
|
|
|
+ op.ref^.scalefactor:=scale;
|
|
|
+{$endif x86}
|
|
|
+ end;
|
|
|
+ end
|
|
|
+ else
|
|
|
+ { all locals accessed from assembler are forced into memory
|
|
|
+ by FPC }
|
|
|
+ internalerror(2016101506);
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+
|
|
|
+
|
|
|
+ constructor tllvmasmnode.create(p: TAsmList);
|
|
|
+ begin
|
|
|
+ inherited;
|
|
|
+ end;
|
|
|
+
|
|
|
+
|
|
|
+ destructor tllvmasmnode.destroy;
|
|
|
+ begin
|
|
|
+ { normally already freed in pass_generate_code, but in case an error
|
|
|
+ occurred that may not have happened }
|
|
|
+ fsymboldata.free;
|
|
|
+ fsymbollookup.free;
|
|
|
+ inherited;
|
|
|
+ end;
|
|
|
+
|
|
|
+
|
|
|
+ procedure tllvmasmnode.pass_generate_code;
|
|
|
+ var
|
|
|
+ oldasmlist: tasmlist;
|
|
|
+ asmai: tai;
|
|
|
+ begin
|
|
|
+ oldasmlist:=nil;
|
|
|
+ if not(po_assembler in current_procinfo.procdef.procoptions) and
|
|
|
+ not(nf_get_asm_position in flags) then
|
|
|
+ begin
|
|
|
+ { store the assembler code in a separate list, so we can make it
|
|
|
+ the argument of an asmblock instruction }
|
|
|
+ oldasmlist:=current_asmdata.CurrAsmList;
|
|
|
+ current_asmdata.CurrAsmList:=tasmlist.create;
|
|
|
+ { record relation between parameters and replaced local assembler
|
|
|
+ operands }
|
|
|
+ fsymboldata:=tfplist.create;
|
|
|
+ fsymbollookup:=THashSet.Create(8,True,False);
|
|
|
+ end;
|
|
|
+ inherited;
|
|
|
+ if not(po_assembler in current_procinfo.procdef.procoptions) and
|
|
|
+ not(nf_get_asm_position in flags) then
|
|
|
+ begin
|
|
|
+ asmai:=taillvm.asm_paras(current_asmdata.CurrAsmList,fsymboldata);
|
|
|
+ fsymboldata:=nil;
|
|
|
+ fsymbollookup.free;
|
|
|
+ fsymbollookup:=nil;
|
|
|
+ oldasmlist.concat(asmai);
|
|
|
+ current_asmdata.CurrAsmList:=oldasmlist;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+
|
|
|
{*****************************************************************************
|
|
|
TLLVMTEMPINFOACCESSOR
|
|
|
*****************************************************************************}
|
|
@@ -85,6 +261,7 @@ interface
|
|
|
|
|
|
|
|
|
begin
|
|
|
+ casmnode:=tllvmasmnode;
|
|
|
ctempinfoaccessor:=tllvmtempinfoaccessor;
|
|
|
ctempcreatenode:=tllvmtempcreatenode;
|
|
|
end.
|