+ 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:
Jonas Maebe 2014-07-01 16:30:22 +00:00
parent 7ebb1b813f
commit 1e7d9c9f0e
3 changed files with 125 additions and 50 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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;
{****************************************************************************}