nllvmcnv.pas 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. {
  2. Copyright (c) 2014 by Jonas Maebe
  3. Generate LLVM IR for type converting nodes
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit nllvmcnv;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. node,ncnv,ncgcnv,defcmp;
  22. type
  23. tllvmtypeconvnode = class(tcgtypeconvnode)
  24. protected
  25. function first_int_to_real: tnode; override;
  26. function first_int_to_bool: tnode; override;
  27. procedure second_int_to_int;override;
  28. { procedure second_string_to_string;override; }
  29. { procedure second_cstring_to_pchar;override; }
  30. { procedure second_string_to_chararray;override; }
  31. { procedure second_array_to_pointer;override; }
  32. procedure second_pointer_to_array;override;
  33. { procedure second_chararray_to_string;override; }
  34. { procedure second_char_to_string;override; }
  35. procedure second_int_to_real;override;
  36. { procedure second_real_to_real;override; }
  37. { procedure second_cord_to_pointer;override; }
  38. { procedure second_proc_to_procvar;override; }
  39. procedure second_bool_to_int;override;
  40. procedure second_int_to_bool;override;
  41. { procedure second_load_smallset;override; }
  42. { procedure second_ansistring_to_pchar;override; }
  43. { procedure second_pchar_to_string;override; }
  44. { procedure second_class_to_intf;override; }
  45. { procedure second_char_to_char;override; }
  46. procedure second_nothing; override;
  47. end;
  48. implementation
  49. uses
  50. globtype,globals,verbose,
  51. aasmbase,aasmdata,
  52. llvmbase,aasmllvm,
  53. procinfo,
  54. symconst,symtype,symdef,defutil,
  55. cgbase,cgutils,hlcgobj,pass_2;
  56. { tllvmtypeconvnode }
  57. function tllvmtypeconvnode.first_int_to_real: tnode;
  58. begin
  59. expectloc:=LOC_FPUREGISTER;
  60. result:=nil;
  61. end;
  62. function tllvmtypeconvnode.first_int_to_bool: tnode;
  63. begin
  64. result:=inherited;
  65. if not assigned(result) then
  66. begin
  67. if not((nf_explicit in flags) and
  68. not(left.location.loc in [LOC_FLAGS,LOC_JUMP])) then
  69. expectloc:=LOC_JUMP;
  70. end;
  71. end;
  72. procedure tllvmtypeconvnode.second_int_to_int;
  73. var
  74. fromsize, tosize: tcgint;
  75. hreg: tregister;
  76. begin
  77. if not(nf_explicit in flags) then
  78. hlcg.g_rangecheck(current_asmdata.CurrAsmList,left.location,left.resultdef,resultdef);
  79. fromsize:=left.resultdef.size;
  80. tosize:=resultdef.size;
  81. location_copy(location,left.location);
  82. if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) or
  83. (fromsize<>tosize) then
  84. begin
  85. hlcg.location_force_reg(current_asmdata.CurrAsmList,location,left.resultdef,resultdef,left.location.loc=LOC_CREGISTER);
  86. end
  87. else if left.resultdef<>resultdef then
  88. begin
  89. { just typecast the pointer type }
  90. hreg:=hlcg.getaddressregister(current_asmdata.CurrAsmList,cpointerdef.getreusable(resultdef));
  91. hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.resultdef,cpointerdef.getreusable(resultdef),left.location.reference,hreg);
  92. hlcg.reference_reset_base(location.reference,cpointerdef.getreusable(resultdef),hreg,0,location.reference.alignment);
  93. end;
  94. end;
  95. procedure tllvmtypeconvnode.second_pointer_to_array;
  96. var
  97. hreg: tregister;
  98. begin
  99. inherited;
  100. { insert type conversion }
  101. hreg:=hlcg.getaddressregister(current_asmdata.CurrAsmList,cpointerdef.getreusable(resultdef));
  102. hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,tpointerdef(left.resultdef).pointeddef,cpointerdef.getreusable(resultdef),location.reference,hreg);
  103. reference_reset_base(location.reference,hreg,0,location.reference.alignment);
  104. end;
  105. procedure tllvmtypeconvnode.second_int_to_real;
  106. var
  107. op: tllvmop;
  108. begin
  109. if is_signed(left.resultdef) then
  110. op:=la_sitofp
  111. else
  112. op:=la_uitofp;
  113. location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
  114. location.register:=hlcg.getfpuregister(current_asmdata.CurrAsmList,resultdef);
  115. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
  116. current_asmdata.CurrAsmList.concat(taillvm.op_reg_size_reg_size(op,location.register,left.resultdef,left.location.register,resultdef));
  117. end;
  118. procedure tllvmtypeconvnode.second_bool_to_int;
  119. var
  120. pdef: tdef;
  121. hreg: tregister;
  122. begin
  123. inherited;
  124. { all boolean/integer of the same size are represented using the same type
  125. by FPC in LLVM, except for Pascal booleans, which are i1 -> convert
  126. the type if necessary. This never has to be done for registers on the
  127. assignment side, because we make everything that's explicitly typecasted
  128. on the assignment side non regable for llvm }
  129. if is_pasbool(left.resultdef) and
  130. (nf_explicit in flags) and
  131. not(left.location.loc in [LOC_FLAGS,LOC_JUMP]) and
  132. (resultdef.size=1) then
  133. case location.loc of
  134. LOC_REFERENCE,LOC_CREFERENCE:
  135. begin
  136. pdef:=cpointerdef.getreusable(resultdef);
  137. hreg:=hlcg.getaddressregister(current_asmdata.CurrAsmList,pdef);
  138. hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.resultdef,pdef,location.reference,hreg);
  139. hlcg.reference_reset_base(location.reference,pdef,hreg,0,location.reference.alignment);
  140. end;
  141. LOC_REGISTER,LOC_CREGISTER:
  142. begin
  143. hreg:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  144. hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,left.resultdef,resultdef,location.register,hreg);
  145. location.register:=hreg;
  146. end;
  147. end;
  148. end;
  149. procedure tllvmtypeconvnode.second_int_to_bool;
  150. var
  151. truelabel,
  152. falselabel: tasmlabel;
  153. newsize : tcgsize;
  154. begin
  155. secondpass(left);
  156. if codegenerror then
  157. exit;
  158. { Explicit typecasts from any ordinal type to a boolean type }
  159. { must not change the ordinal value }
  160. if (nf_explicit in flags) and
  161. not(left.location.loc in [LOC_FLAGS,LOC_JUMP]) then
  162. begin
  163. location_copy(location,left.location);
  164. newsize:=def_cgsize(resultdef);
  165. { change of size? change sign only if location is LOC_(C)REGISTER? Then we have to sign/zero-extend }
  166. if (tcgsize2size[newsize]<>tcgsize2size[left.location.size]) or
  167. ((newsize<>left.location.size) and (location.loc in [LOC_REGISTER,LOC_CREGISTER])) then
  168. hlcg.location_force_reg(current_asmdata.CurrAsmList,location,left.resultdef,resultdef,true)
  169. else
  170. location.size:=newsize;
  171. exit;
  172. end;
  173. case left.location.loc of
  174. LOC_SUBSETREG,LOC_CSUBSETREG,LOC_SUBSETREF,LOC_CSUBSETREF,
  175. LOC_CREFERENCE,LOC_REFERENCE,LOC_REGISTER,LOC_CREGISTER:
  176. begin
  177. current_asmdata.getjumplabel(truelabel);
  178. current_asmdata.getjumplabel(falselabel);
  179. location_reset_jump(location,truelabel,falselabel);
  180. hlcg.a_cmp_const_loc_label(current_asmdata.CurrAsmList,left.resultdef,OC_EQ,0,left.location,location.falselabel);
  181. hlcg.a_jmp_always(current_asmdata.CurrAsmList,location.truelabel);
  182. end;
  183. LOC_JUMP :
  184. begin
  185. location:=left.location;
  186. end;
  187. else
  188. internalerror(10062);
  189. end;
  190. end;
  191. procedure tllvmtypeconvnode.second_nothing;
  192. var
  193. hreg: tregister;
  194. begin
  195. if left.resultdef<>resultdef then
  196. begin
  197. { handle sometype(voidptr^) }
  198. if not is_void(left.resultdef) and
  199. (left.resultdef.typ<>formaldef) and
  200. (left.resultdef.size<>resultdef.size) then
  201. internalerror(2014012216);
  202. hlcg.location_force_mem(current_asmdata.CurrAsmList,left.location,left.resultdef);
  203. hreg:=hlcg.getaddressregister(current_asmdata.CurrAsmList,cpointerdef.getreusable(resultdef));
  204. hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.resultdef,cpointerdef.getreusable(resultdef),left.location.reference,hreg);
  205. location_reset_ref(location,left.location.loc,left.location.size,left.location.reference.alignment);
  206. reference_reset_base(location.reference,hreg,0,location.reference.alignment);
  207. end
  208. else
  209. location_copy(location,left.location);
  210. end;
  211. begin
  212. ctypeconvnode:=tllvmtypeconvnode;
  213. end.