nllvminl.pas 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. {
  2. Copyright (c) 2014 by Jonas Maebe
  3. Generate LLVM bytecode for inline 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 nllvminl;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. node,
  22. ncginl;
  23. type
  24. tllvminlinenode = class(tcginlinenode)
  25. protected
  26. function first_get_frame: tnode; override;
  27. function first_abs_real: tnode; override;
  28. public
  29. procedure second_length; override;
  30. end;
  31. implementation
  32. uses
  33. verbose,globtype,constexp,
  34. aasmbase, aasmdata,
  35. symtype,symdef,defutil,
  36. nutils,nadd,nbas,ncal,ncon,nflw,ninl,nld,nmat,
  37. pass_2,
  38. cgbase,cgutils,tgobj,hlcgobj,
  39. cpubase;
  40. function tllvminlinenode.first_get_frame: tnode;
  41. begin
  42. result:=ccallnode.createintern('llvm_frameaddress',
  43. ccallparanode.create(genintconstnode(0),nil));
  44. end;
  45. { in general, generate regular expression rather than intrinsics: according
  46. to the "Performance Tips for Frontend Authors", "The optimizer is quite
  47. good at reasoning about general control flow and arithmetic, it is not
  48. anywhere near as strong at reasoning about the various intrinsics. If
  49. profitable for code generation purposes, the optimizer will likely form
  50. the intrinsics itself late in the optimization pipeline." }
  51. function tllvminlinenode.first_abs_real: tnode;
  52. var
  53. lefttemp,
  54. resulttemp: ttempcreatenode;
  55. stat: tstatementnode;
  56. begin
  57. result:=internalstatements(stat);
  58. lefttemp:=ctempcreatenode.create(left.resultdef,left.resultdef.size,tt_persistent,true);
  59. { assigned twice -> will be spilled if put in register }
  60. resulttemp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,false);
  61. addstatement(stat,lefttemp);
  62. addstatement(stat,resulttemp);
  63. { lefttemp:=left }
  64. addstatement(stat,
  65. cassignmentnode.create(ctemprefnode.create(lefttemp),left)
  66. );
  67. { if lefttemp>=0 then
  68. resulttemp:=lefttemp
  69. else
  70. resulttemp:=-lefttemp
  71. }
  72. addstatement(stat,
  73. cifnode.create(
  74. caddnode.create(
  75. gten,
  76. ctemprefnode.create(lefttemp),
  77. crealconstnode.create(0.0,left.resultdef)
  78. ),
  79. cassignmentnode.create(
  80. ctemprefnode.create(resulttemp),
  81. ctemprefnode.create(lefttemp)
  82. ),
  83. cassignmentnode.create(
  84. ctemprefnode.create(resulttemp),
  85. cunaryminusnode.create(ctemprefnode.create(lefttemp))
  86. )
  87. )
  88. );
  89. addstatement(stat,ctempdeletenode.create(lefttemp));
  90. addstatement(stat,ctempdeletenode.create_normal_temp(resulttemp));
  91. { return resulttemp }
  92. addstatement(stat,ctemprefnode.create(resulttemp));
  93. { reused }
  94. left:=nil;
  95. end;
  96. procedure tllvminlinenode.second_length;
  97. var
  98. lengthlab, nillab: tasmlabel;
  99. hregister: tregister;
  100. href, tempref: treference;
  101. lendef: tdef;
  102. begin
  103. secondpass(left);
  104. if is_shortstring(left.resultdef) then
  105. begin
  106. if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  107. internalerror(2014080806);
  108. { typecast the shortstring reference into a length byte reference }
  109. location_reset_ref(location,left.location.loc,def_cgsize(resultdef),left.location.reference.alignment);
  110. hregister:=hlcg.getaddressregister(current_asmdata.CurrAsmList,cpointerdef.getreusable(resultdef));
  111. hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.resultdef,cpointerdef.getreusable(resultdef),left.location.reference,hregister);
  112. hlcg.reference_reset_base(location.reference,cpointerdef.getreusable(resultdef),hregister,0,left.location.reference.alignment);
  113. end
  114. else
  115. begin
  116. tg.gethltemp(current_asmdata.CurrAsmList,resultdef,resultdef.size,tt_normal,tempref);
  117. { length in ansi/wide strings and high in dynamic arrays is at offset
  118. -sizeof(sizeint), for widestrings it's at -4 }
  119. if is_widestring(left.resultdef) then
  120. lendef:=u32inttype
  121. else
  122. lendef:=ossinttype;
  123. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,
  124. left.resultdef,cpointerdef.getreusable(lendef),true);
  125. current_asmdata.getjumplabel(nillab);
  126. current_asmdata.getjumplabel(lengthlab);
  127. hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,cpointerdef.getreusable(lendef),OC_EQ,0,left.location.register,nillab);
  128. hlcg.reference_reset_base(href,cpointerdef.getreusable(lendef),left.location.register,-lendef.size,lendef.alignment);
  129. hregister:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  130. hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,lendef,resultdef,href,hregister);
  131. if is_widestring(left.resultdef) then
  132. hlcg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SHR,resultdef,1,hregister);
  133. { Dynamic arrays do not have their length attached but their maximum index }
  134. if is_dynamic_array(left.resultdef) then
  135. hlcg.a_op_const_reg(current_asmdata.CurrAsmList,OP_ADD,resultdef,1,hregister);
  136. hlcg.a_load_reg_ref(current_asmdata.CurrAsmList,resultdef,resultdef,hregister,tempref);
  137. hlcg.a_jmp_always(current_asmdata.CurrAsmList,lengthlab);
  138. hlcg.a_label(current_asmdata.CurrAsmList,nillab);
  139. hlcg.a_load_const_ref(current_asmdata.CurrAsmList,resultdef,0,tempref);
  140. hlcg.a_label(current_asmdata.CurrAsmList,lengthlab);
  141. hregister:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  142. hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,resultdef,resultdef,tempref,hregister);
  143. tg.ungettemp(current_asmdata.CurrAsmList,tempref);
  144. location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
  145. location.register:=hregister;
  146. end;
  147. end;
  148. begin
  149. cinlinenode:=tllvminlinenode;
  150. end.