mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-05-02 20:33:40 +02:00

pasbool8type for this results in too much trouble (we mustn't use i1 for parameters, because then LLVM will try to apply the ABI convention for passing "1 bit" values, or in records because then this may result in unwanted bitpacking). Downside: the new LLVMBool1 type is also exposed in the system unit, because we need it to define LLVM intrinsics... git-svn-id: trunk@33726 -
159 lines
5.8 KiB
ObjectPascal
159 lines
5.8 KiB
ObjectPascal
{
|
|
Copyright (c) 2014 Jonas Maebe
|
|
|
|
Generate LLVM IR for math nodes
|
|
|
|
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 nllvmmat;
|
|
|
|
{$i fpcdefs.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
symtype,
|
|
node, nmat, ncgmat, ncghlmat, cgbase;
|
|
|
|
type
|
|
tllvmmoddivnode = class(tcgmoddivnode)
|
|
procedure pass_generate_code; override;
|
|
end;
|
|
|
|
Tllvmunaryminusnode = class(tcgunaryminusnode)
|
|
procedure emit_float_sign_change(r: tregister; _size : tdef);override;
|
|
end;
|
|
|
|
tllvmnotnode = class(tcghlnotnode)
|
|
end;
|
|
|
|
implementation
|
|
|
|
uses
|
|
globtype, systems, constexp,
|
|
cutils, verbose, globals,
|
|
symconst, symdef,
|
|
aasmbase, aasmllvm, aasmtai, aasmdata,
|
|
defutil,
|
|
procinfo,
|
|
hlcgobj, pass_2,
|
|
ncon,
|
|
llvmbase,
|
|
ncgutil, cgutils;
|
|
|
|
{*****************************************************************************
|
|
tllvmmoddivnode
|
|
*****************************************************************************}
|
|
|
|
procedure tllvmmoddivnode.pass_generate_code;
|
|
var
|
|
op: tllvmop;
|
|
hl: tasmlabel;
|
|
tmpovreg1,
|
|
tmpovreg2: tregister;
|
|
ovloc: tlocation;
|
|
begin
|
|
secondpass(left);
|
|
secondpass(right);
|
|
if is_signed(left.resultdef) then
|
|
if nodetype=divn then
|
|
op:=la_sdiv
|
|
else
|
|
op:=la_srem
|
|
else if nodetype=divn then
|
|
op:=la_udiv
|
|
else
|
|
op:=la_urem;
|
|
hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,resultdef,true);
|
|
if right.location.loc<>LOC_CONSTANT then
|
|
begin
|
|
hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,resultdef,true);
|
|
{ in llvm, div-by-zero is undefined on all platforms -> need explicit
|
|
check }
|
|
current_asmdata.getjumplabel(hl);
|
|
hlcg.a_cmp_const_loc_label(current_asmdata.CurrAsmList,resultdef,OC_NE,0,right.location,hl);
|
|
hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_divbyzero',[],nil).resetiftemp;
|
|
hlcg.a_label(current_asmdata.CurrAsmList,hl);
|
|
end;
|
|
if (cs_check_overflow in current_settings.localswitches) and
|
|
is_signed(left.resultdef) and
|
|
((right.nodetype<>ordconstn) or
|
|
(tordconstnode(right).value=-1)) then
|
|
begin
|
|
current_asmdata.getjumplabel(hl);
|
|
location_reset(ovloc,LOC_REGISTER,OS_8);
|
|
ovloc.register:=hlcg.getintregister(current_asmdata.CurrAsmList,llvmbool1type);
|
|
if right.nodetype=ordconstn then
|
|
current_asmdata.CurrAsmList.concat(taillvm.op_reg_cond_size_reg_const(la_icmp,ovloc.register,OC_EQ,resultdef,left.location.register,low(int64)))
|
|
else
|
|
begin
|
|
tmpovreg1:=hlcg.getintregister(current_asmdata.CurrAsmList,llvmbool1type);
|
|
tmpovreg2:=hlcg.getintregister(current_asmdata.CurrAsmList,llvmbool1type);
|
|
current_asmdata.CurrAsmList.concat(taillvm.op_reg_cond_size_reg_const(la_icmp,tmpovreg1,OC_EQ,resultdef,left.location.register,low(int64)));
|
|
current_asmdata.CurrAsmList.concat(taillvm.op_reg_cond_size_reg_const(la_icmp,tmpovreg2,OC_EQ,resultdef,right.location.register,-1));
|
|
hlcg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_AND,llvmbool1type,tmpovreg1,tmpovreg2,ovloc.register);
|
|
end;
|
|
hlcg.g_overflowCheck_loc(current_asmdata.CurrAsmList,location,resultdef,ovloc);
|
|
end;
|
|
location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
|
|
location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
|
|
if right.location.loc=LOC_CONSTANT then
|
|
current_asmdata.CurrAsmList.concat(taillvm.op_reg_size_reg_const(op,location.register,resultdef,left.location.register,right.location.value))
|
|
else
|
|
current_asmdata.CurrAsmList.concat(taillvm.op_reg_size_reg_reg(op,location.register,resultdef,left.location.register,right.location.register))
|
|
end;
|
|
|
|
{*****************************************************************************
|
|
Tllvmunaryminusnode
|
|
*****************************************************************************}
|
|
|
|
procedure Tllvmunaryminusnode.emit_float_sign_change(r: tregister; _size : tdef);
|
|
var
|
|
zeroreg: tregister;
|
|
begin
|
|
if _size.typ<>floatdef then
|
|
internalerror(2014012212);
|
|
zeroreg:=hlcg.getfpuregister(current_asmdata.CurrAsmList,_size);
|
|
case tfloatdef(_size).floattype of
|
|
s32real,s64real:
|
|
current_asmdata.CurrAsmList.concat(taillvm.op_reg_size_fpconst_size(la_bitcast,zeroreg,_size,0,_size));
|
|
{ comp and currency are handled as int64 at the llvm level }
|
|
s64comp,
|
|
s64currency:
|
|
begin
|
|
{ sc80floattype instead of _size, see comment in thlcgllvm.a_loadfpu_ref_reg }
|
|
_size:=sc80floattype;
|
|
current_asmdata.CurrAsmList.concat(taillvm.op_reg_size_const_size(la_sitofp,zeroreg,s64inttype,0,_size));
|
|
end;
|
|
{$ifdef cpuextended}
|
|
s80real,sc80real:
|
|
current_asmdata.CurrAsmList.concat(taillvm.op_reg_size_fpconst80_size(la_bitcast,zeroreg,_size,0.0,_size));
|
|
{$endif cpuextended}
|
|
end;
|
|
current_asmdata.CurrAsmList.Concat(taillvm.op_reg_size_reg_reg(la_fsub,r,_size,zeroreg,r));
|
|
end;
|
|
|
|
|
|
begin
|
|
cmoddivnode := tllvmmoddivnode;
|
|
(*
|
|
cshlshrnode := tllvmshlshrnode;
|
|
*)
|
|
cnotnode := tllvmnotnode;
|
|
cunaryminusnode := Tllvmunaryminusnode;
|
|
end.
|