unit srBitcast; {$mode ObjFPC}{$H+} interface uses ginodes, srNode, srType, srConst, srReg; type PsrBitcastKey=^TsrBitcastKey; TsrBitcastKey=packed record dtype:TsrDataType; src:TsrRegNode; end; TsrBitcast=class pLeft,pRight:TsrBitcast; //---- key:TsrBitcastKey; dst:TsrRegNode; class function c(n1,n2:PsrBitcastKey):Integer; static; end; PsrBitcastList=^TsrBitcastList; TsrBitcastList=object type TNodeTree=specialize TNodeTreeClass; var FTree:TNodeTree; rSlot:TsrRegSlot; procedure Init(Emit:TCustomEmit); inline; function _Find(dtype:TsrDataType;src:TsrRegNode):TsrBitcast; function Find(dtype:TsrDataType;src:TsrRegNode):TsrRegNode; Procedure Save(dtype:TsrDataType;src,dst:TsrRegNode); function CastConst(dtype:TsrDataType;src:TsrRegNode):TsrRegNode; function FetchRead(dtype:TsrDataType;src:TsrRegNode):TsrRegNode; function FetchDstr(dtype:TsrDataType;src:TsrRegNode):TsrRegNode; function FetchCast(dtype:TsrDataType;src:TsrRegNode):TsrRegNode; end; implementation class function TsrBitcast.c(n1,n2:PsrBitcastKey):Integer; begin //first dtype Result:=ord(n1^.dtype>n2^.dtype)-ord(n1^.dtype0) then Exit; //second src (not need order sort) Result:=ord(ptruint(n1^.src)>ptruint(n2^.src))-ord(ptruint(n1^.src)nil) then begin Result:=node.dst; end; end; Procedure TsrBitcastList.Save(dtype:TsrDataType;src,dst:TsrRegNode); var node:TsrBitcast; begin node:=rSlot.Emit.specialize New; node.key:=Default(TsrBitcastKey); node.key.dtype:=dtype; node.key.src:=src; node.dst:=dst; FTree.Insert(node); end; function TsrBitcastList.CastConst(dtype:TsrDataType;src:TsrRegNode):TsrRegNode; var pConstList:PsrConstList; pConst:TsrConst; begin pConst:=src.AsConst; pConstList:=rSlot.Emit.GetConstList; pConst:=pConstList^.Bitcast(dtype,pConst); Result:=rSlot.New(dtype); Result.pWriter:=pConst; Result.CustomLine:=src.CustomLine; end; function TsrBitcastList.FetchRead(dtype:TsrDataType;src:TsrRegNode):TsrRegNode; var dst:TsrRegNode; begin Result:=src; if (src=nil) then Exit; if (dtype=dtUnknow) or (dtype=src.dtype) then Exit; Assert(TryBitcastType(src.dtype,dtype)); if src.is_const then begin //only from consts, first dst:=Find(dtype,src); if (dst<>nil) then Exit(dst); // dst:=CastConst(dtype,src); // Save(dtype,src,dst); end else begin dst:=rSlot.New(dtype); dst.pWriter:=src; end; Result:=dst; end; function TsrBitcastList.FetchDstr(dtype:TsrDataType;src:TsrRegNode):TsrRegNode; var dst:TsrRegNode; begin Result:=src; if (src=nil) then Exit; if (dtype=dtUnknow) or (dtype=src.dtype) then Exit; Assert(TryBitcastType(src.dtype,dtype)); dst:=rSlot.New(dtype); dst.pWriter:=src.pWriter; src.pWriter:=dst; Result:=dst; end; //post process function TsrBitcastList.FetchCast(dtype:TsrDataType;src:TsrRegNode):TsrRegNode; var dst:TsrRegNode; prv:TsrRegNode; begin Result:=src; if (src=nil) then Exit; if (dtype=dtUnknow) or (dtype=src.dtype) then Exit; dst:=nil; Assert(TryBitcastType(src.dtype,dtype)); // dst:=Find(dtype,src); if (dst<>nil) then Exit(dst); prv:=RegDown(src); if prv.is_const then begin dst:=CastConst(dtype,prv); end else begin if TryBitcastType(src.dtype,dtype) then begin dst:=rSlot.New(dtype); rSlot.Emit.OpCast(prv.pLine,dst,src); end else begin Writeln('bitcast:',src.dtype,'<>',dtype); Assert(false,'bitcast'); end; end; // Save(dtype,src,dst); Result:=dst; end; end.