mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-23 08:49:38 +02:00
+ support for instruction operands that are tai themselves in the llvm
backend (required for inserting bitcasts/ptrtoint/... operations inside typed constant declarations) o taillvm constructors for creating bitcast-style and getlementptr operations that accept a tai as their source/base operand git-svn-id: branches/hlcgllvm@28112 -
This commit is contained in:
parent
7ebb1b813f
commit
1e7d9c9f0e
compiler
@ -262,6 +262,7 @@ interface
|
||||
{$ifdef cpuextended}
|
||||
,top_extended80
|
||||
{$endif cpuextended}
|
||||
,top_tai
|
||||
,top_def
|
||||
,top_fpcond
|
||||
,top_cond
|
||||
@ -283,49 +284,6 @@ interface
|
||||
end;
|
||||
plocaloper = ^tlocaloper;
|
||||
|
||||
{ please keep the size of this record <=12 bytes and keep it properly aligned }
|
||||
toper = record
|
||||
ot : longint;
|
||||
case typ : toptype of
|
||||
top_none : ();
|
||||
top_reg : (reg:tregister);
|
||||
top_ref : (ref:preference);
|
||||
top_const : (val:tcgint);
|
||||
top_bool : (b:boolean);
|
||||
{ local varsym that will be inserted in pass_generate_code }
|
||||
top_local : (localoper:plocaloper);
|
||||
{$ifdef arm}
|
||||
top_regset : (regset:^tcpuregisterset; regtyp: tregistertype; subreg: tsubregister; usermode: boolean);
|
||||
top_conditioncode : (cc : TAsmCond);
|
||||
top_modeflags : (modeflags : tcpumodeflags);
|
||||
top_specialreg : (specialreg:tregister; specialflags:tspecialregflags);
|
||||
{$endif arm}
|
||||
{$if defined(arm) or defined(aarch64)}
|
||||
top_shifterop : (shifterop : pshifterop);
|
||||
{$endif defined(arm) or defined(aarch64)}
|
||||
{$ifdef m68k}
|
||||
top_regset : (dataregset,addrregset:^tcpuregisterset);
|
||||
{$endif m68k}
|
||||
{$ifdef jvm}
|
||||
top_single : (sval:single);
|
||||
top_double : (dval:double);
|
||||
top_string : (pcvallen: aint; pcval: pchar);
|
||||
top_wstring : (pwstrval: pcompilerwidestring);
|
||||
{$endif jvm}
|
||||
{$ifdef llvm}
|
||||
top_single : (sval:single);
|
||||
top_double : (dval:double);
|
||||
{$ifdef cpuextended}
|
||||
top_extended80 : (eval:extended);
|
||||
{$endif cpuextended}
|
||||
top_def : (def: tdef);
|
||||
top_cond : (cond: topcmp);
|
||||
top_fpcond : (fpcond: tllvmfpcmp);
|
||||
top_para : (paras: tfplist);
|
||||
{$endif llvm}
|
||||
end;
|
||||
poper=^toper;
|
||||
|
||||
const
|
||||
{ ait_* types which don't result in executable code or which don't influence
|
||||
the way the program runs/behaves, but which may be encountered by the
|
||||
@ -438,6 +396,52 @@ interface
|
||||
);
|
||||
|
||||
type
|
||||
tai = class;
|
||||
|
||||
{ please keep the size of this record <=12 bytes and keep it properly aligned }
|
||||
toper = record
|
||||
ot : longint;
|
||||
case typ : toptype of
|
||||
top_none : ();
|
||||
top_reg : (reg:tregister);
|
||||
top_ref : (ref:preference);
|
||||
top_const : (val:tcgint);
|
||||
top_bool : (b:boolean);
|
||||
{ local varsym that will be inserted in pass_generate_code }
|
||||
top_local : (localoper:plocaloper);
|
||||
{$ifdef arm}
|
||||
top_regset : (regset:^tcpuregisterset; regtyp: tregistertype; subreg: tsubregister; usermode: boolean);
|
||||
top_conditioncode : (cc : TAsmCond);
|
||||
top_modeflags : (modeflags : tcpumodeflags);
|
||||
top_specialreg : (specialreg:tregister; specialflags:tspecialregflags);
|
||||
{$endif arm}
|
||||
{$if defined(arm) or defined(aarch64)}
|
||||
top_shifterop : (shifterop : pshifterop);
|
||||
{$endif defined(arm) or defined(aarch64)}
|
||||
{$ifdef m68k}
|
||||
top_regset : (dataregset,addrregset:^tcpuregisterset);
|
||||
{$endif m68k}
|
||||
{$ifdef jvm}
|
||||
top_single : (sval:single);
|
||||
top_double : (dval:double);
|
||||
top_string : (pcvallen: aint; pcval: pchar);
|
||||
top_wstring : (pwstrval: pcompilerwidestring);
|
||||
{$endif jvm}
|
||||
{$ifdef llvm}
|
||||
top_single : (sval:single);
|
||||
top_double : (dval:double);
|
||||
{$ifdef cpuextended}
|
||||
top_extended80 : (eval:extended);
|
||||
{$endif cpuextended}
|
||||
top_tai : (ai: tai);
|
||||
top_def : (def: tdef);
|
||||
top_cond : (cond: topcmp);
|
||||
top_fpcond : (fpcond: tllvmfpcmp);
|
||||
top_para : (paras: tfplist);
|
||||
{$endif llvm}
|
||||
end;
|
||||
poper=^toper;
|
||||
|
||||
{ abstract assembler item }
|
||||
tai = class(TLinkedListItem)
|
||||
{$ifndef NOOPT}
|
||||
@ -2807,6 +2811,8 @@ implementation
|
||||
{$ifdef llvm}
|
||||
top_para:
|
||||
paras.free;
|
||||
top_tai:
|
||||
ai.free;
|
||||
{$endif llvm}
|
||||
end;
|
||||
typ:=top_none;
|
||||
|
@ -68,6 +68,8 @@ interface
|
||||
{$endif cpuextended}
|
||||
{ e.g. dst = bitcast fromsize @globalvar to tosize }
|
||||
constructor op_reg_size_sym_size(op:tllvmop;dst:tregister;fromsize:tdef;src:TAsmSymbol;tosize:tdef);
|
||||
{ e.g. dst = bitcast fromsize <abstracttaidata> to tosize }
|
||||
constructor op_reg_size_tai_size(op:tllvmop;dst:tregister;fromsize:tdef;src:tai;tosize:tdef);
|
||||
|
||||
{ e.g. dst = bitcast fromsize src to tosize }
|
||||
constructor op_reg_size_ref_size(op:tllvmop;dst:tregister;fromsize:tdef;const src:treference;tosize:tdef);
|
||||
@ -97,10 +99,12 @@ interface
|
||||
{ e.g. dst = getelementptr ptrsize ref, i32 0 (if indirect), index1type index1 }
|
||||
constructor getelementptr_reg_size_ref_size_reg(dst:tregister;ptrsize:tdef;const ref:treference;indextype:tdef;index1:tregister;indirect:boolean);
|
||||
constructor getelementptr_reg_size_ref_size_const(dst:tregister;ptrsize:tdef;const ref:treference;indextype:tdef;index1:ptrint;indirect:boolean);
|
||||
constructor getelementptr_reg_tai_size_const(dst:tregister;const ai:taillvm;indextype:tdef;index1:ptrint;indirect:boolean);
|
||||
|
||||
{ e.g. dst = call retsize (paras) }
|
||||
constructor call_size_name_paras(dst: tregister;retsize: tdef;name:tasmsymbol;paras: tfplist);
|
||||
|
||||
procedure loadtai(opidx: longint; _ai: tai);
|
||||
procedure loaddef(opidx: longint; _def: tdef);
|
||||
procedure loadsingle(opidx: longint; _sval: single);
|
||||
procedure loaddouble(opidx: longint; _dval: double);
|
||||
@ -232,6 +236,19 @@ uses
|
||||
end;
|
||||
|
||||
|
||||
procedure taillvm.loadtai(opidx: longint; _ai: tai);
|
||||
begin
|
||||
allocate_oper(opidx+1);
|
||||
with oper[opidx]^ do
|
||||
begin
|
||||
if typ<>top_tai then
|
||||
clearop(opidx);
|
||||
ai:=_ai;
|
||||
typ:=top_tai;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure taillvm.loaddef(opidx:longint;_def: tdef);
|
||||
begin
|
||||
allocate_oper(opidx+1);
|
||||
@ -605,6 +622,17 @@ uses
|
||||
end;
|
||||
|
||||
|
||||
constructor taillvm.op_reg_size_tai_size(op:tllvmop;dst:tregister;fromsize:tdef;src:tai;tosize:tdef);
|
||||
begin
|
||||
create_llvm(op);
|
||||
ops:=4;
|
||||
loadreg(0,dst);
|
||||
loaddef(1,fromsize);
|
||||
loadtai(2,src);
|
||||
loaddef(3,tosize);
|
||||
end;
|
||||
|
||||
|
||||
constructor taillvm.op_reg_size_ref_size(op: tllvmop; dst: tregister; fromsize: tdef; const src: treference; tosize: tdef);
|
||||
begin
|
||||
create_llvm(op);
|
||||
@ -779,6 +807,31 @@ uses
|
||||
loadconst(index+1,index1);
|
||||
end;
|
||||
|
||||
|
||||
constructor taillvm.getelementptr_reg_tai_size_const(dst: tregister; const ai: taillvm; indextype: tdef; index1: ptrint; indirect: boolean);
|
||||
var
|
||||
index: longint;
|
||||
begin
|
||||
create_llvm(la_getelementptr);
|
||||
if indirect then
|
||||
ops:=6
|
||||
else
|
||||
ops:=4;
|
||||
loadreg(0,dst);
|
||||
loadtai(1,ai);
|
||||
if indirect then
|
||||
begin
|
||||
loaddef(2,s32inttype);
|
||||
loadconst(3,0);
|
||||
index:=4;
|
||||
end
|
||||
else
|
||||
index:=2;
|
||||
loaddef(index,indextype);
|
||||
loadconst(index+1,index1);
|
||||
end;
|
||||
|
||||
|
||||
constructor taillvm.call_size_name_paras(dst: tregister; retsize: tdef; name:tasmsymbol; paras: tfplist);
|
||||
begin
|
||||
create_llvm(la_call);
|
||||
|
@ -71,6 +71,9 @@ interface
|
||||
procedure WriteInstruction(hp : tai);
|
||||
protected
|
||||
owner: TLLVMAssember;
|
||||
|
||||
function InstructionToString(hp : tai): TSymStr;
|
||||
function getopstr(const o:toper; refwithalign: boolean) : TSymStr;
|
||||
end;
|
||||
|
||||
|
||||
@ -214,7 +217,7 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
function getopstr(const o:toper; refwithalign: boolean) : ansistring;
|
||||
function TLLVMInstrWriter.getopstr(const o:toper; refwithalign: boolean) : TSymStr;
|
||||
var
|
||||
hs : ansistring;
|
||||
doubleval: record
|
||||
@ -289,6 +292,10 @@ implementation
|
||||
begin
|
||||
result:=getparas(o);
|
||||
end;
|
||||
top_tai:
|
||||
begin
|
||||
result:=InstructionToString(o.ai);
|
||||
end;
|
||||
{$ifdef cpuextended}
|
||||
top_extended80:
|
||||
begin
|
||||
@ -303,12 +310,17 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
procedure TLlvmInstrWriter.WriteInstruction(hp: tai);
|
||||
procedure TLLVMInstrWriter.WriteInstruction(hp: tai);
|
||||
begin
|
||||
owner.AsmWriteLn(InstructionToString(hp));
|
||||
end;
|
||||
|
||||
|
||||
function TLLVMInstrWriter.InstructionToString(hp: tai): TSymStr;
|
||||
var
|
||||
op: tllvmop;
|
||||
s: string;
|
||||
s, sep: TSymStr;
|
||||
i, opstart: byte;
|
||||
sep: string[3];
|
||||
done: boolean;
|
||||
begin
|
||||
op:=taillvm(hp).llvmopcode;
|
||||
@ -345,8 +357,12 @@ implementation
|
||||
la_ptrtoint, la_inttoptr,
|
||||
la_bitcast:
|
||||
begin
|
||||
s:=s+getopstr(taillvm(hp).oper[0]^,false)+' = '+
|
||||
llvm_op2str[op]+' '+
|
||||
{ destination can be empty in case of nested constructs, or
|
||||
data initialisers }
|
||||
if (taillvm(hp).oper[0]^.typ<>top_reg) or
|
||||
(taillvm(hp).oper[0]^.reg<>NR_NO) then
|
||||
s:=s+getopstr(taillvm(hp).oper[0]^,false)+' = ';
|
||||
s:=s+llvm_op2str[op]+' '+
|
||||
getopstr(taillvm(hp).oper[1]^,false)+' '+
|
||||
getopstr(taillvm(hp).oper[2]^,false)+' to '+
|
||||
getopstr(taillvm(hp).oper[3]^,false);
|
||||
@ -380,7 +396,7 @@ implementation
|
||||
begin
|
||||
s:=s+getreferencealignstring(taillvm(hp).oper[0]^.ref^)
|
||||
end;
|
||||
owner.AsmWriteLn(s);
|
||||
result:=s;
|
||||
end;
|
||||
|
||||
{****************************************************************************}
|
||||
|
Loading…
Reference in New Issue
Block a user