{ Copyright (c) 2010-2013 by Jonas Maebe This unit implements the code generator for LLVM 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 cgllvm; {$i fpcdefs.inc} interface uses globtype,parabase, cgbase,cgutils,cgobj,cghlcpu, llvmbase,llvminfo,aasmbase,aasmtai,aasmdata,aasmllvm; type tcgllvm=class(thlbasecgcpu) public procedure a_label(list : TAsmList;l : tasmlabel);override; procedure a_jmp_always(list: TAsmList; l: tasmlabel); override; procedure init_register_allocators;override; procedure done_register_allocators;override; function getintregister(list:TAsmList;size:Tcgsize):Tregister;override; function getfpuregister(list:TAsmList;size:Tcgsize):Tregister;override; end; procedure create_codegen; implementation uses globals,verbose,systems,cutils, paramgr,fmodule, tgobj,rgllvm,cpubase, procinfo,cpupi; {**************************************************************************** Assembler code ****************************************************************************} procedure tcgllvm.a_label(list: TAsmList; l: tasmlabel); begin { in llvm, every block must end with a terminator instruction, such as a branch -> if the previous instruction is not a terminator instruction, add an unconditional branch to the next block (= the one starting with this label) } if not assigned(list.last) or (tai(list.Last).typ<>ait_llvmins) or not(taillvm(list.Last).llvmopcode in llvmterminatoropcodes) then a_jmp_always(list,l); inherited; end; procedure tcgllvm.a_jmp_always(list: TAsmList; l: tasmlabel); begin list.concat(taillvm.op_lab(la_br,l)); end; procedure tcgllvm.init_register_allocators; begin inherited init_register_allocators; rg[R_INTREGISTER]:=Trgllvm.create(R_INTREGISTER,R_SUBWHOLE, [0],first_int_imreg,[]); rg[R_FPUREGISTER]:=Trgllvm.create(R_FPUREGISTER,R_SUBWHOLE, [0],first_fpu_imreg,[]); rg[R_MMREGISTER]:=Trgllvm.create(R_MMREGISTER,R_SUBWHOLE, [0],first_mm_imreg,[]); { every temp gets its own "base register" to uniquely identify it } rg[R_TEMPREGISTER]:=trgllvm.Create(R_TEMPREGISTER,R_SUBWHOLE, [0],1,[]); end; procedure tcgllvm.done_register_allocators; begin rg[R_INTREGISTER].free; rg[R_FPUREGISTER].free; rg[R_MMREGISTER].free; rg[R_TEMPREGISTER].free; inherited done_register_allocators; end; function tcgllvm.getintregister(list:TAsmList;size:Tcgsize):Tregister; begin { all size determinations are based on tdef, subregisters are irrelevant } result:=rg[R_INTREGISTER].getregister(list,R_SUBWHOLE) end; function tcgllvm.getfpuregister(list:TAsmList;size:Tcgsize):Tregister; begin { all size determinations are based on tdef, subregisters are irrelevant } result:=rg[R_FPUREGISTER].getregister(list,R_SUBWHOLE); end; procedure create_codegen; begin cg:=tcgllvm.Create; end; end.