nllvminl.pas 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  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. ncginl;
  22. type
  23. tllvminlinenode = class(tcginlinenode)
  24. procedure second_length; override;
  25. end;
  26. implementation
  27. uses
  28. verbose,globtype,
  29. aasmbase, aasmdata,
  30. symtype,symdef,defutil,
  31. ninl,
  32. pass_2,
  33. cgbase,cgutils,tgobj,hlcgobj;
  34. procedure tllvminlinenode.second_length;
  35. var
  36. lengthlab, nillab: tasmlabel;
  37. hregister: tregister;
  38. href, tempref: treference;
  39. lendef: tdef;
  40. begin
  41. secondpass(left);
  42. if is_shortstring(left.resultdef) then
  43. begin
  44. if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  45. internalerror(2014080806);
  46. { typecast the shortstring reference into a length byte reference }
  47. location_reset_ref(location,left.location.loc,def_cgsize(resultdef),left.location.reference.alignment);
  48. hregister:=hlcg.getaddressregister(current_asmdata.CurrAsmList,getpointerdef(resultdef));
  49. hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.resultdef,getpointerdef(resultdef),left.location.reference,hregister);
  50. hlcg.reference_reset_base(location.reference,getpointerdef(resultdef),hregister,0,left.location.reference.alignment);
  51. end
  52. else
  53. begin
  54. tg.gethltemp(current_asmdata.CurrAsmList,resultdef,resultdef.size,tt_normal,tempref);
  55. { length in ansi/wide strings and high in dynamic arrays is at offset
  56. -sizeof(sizeint), for widestrings it's at -4 }
  57. if is_widestring(left.resultdef) then
  58. lendef:=u32inttype
  59. else
  60. lendef:=ossinttype;
  61. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,
  62. left.resultdef,getpointerdef(lendef),true);
  63. current_asmdata.getjumplabel(nillab);
  64. current_asmdata.getjumplabel(lengthlab);
  65. hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,getpointerdef(lendef),OC_EQ,0,left.location.register,nillab);
  66. hlcg.reference_reset_base(href,getpointerdef(lendef),left.location.register,-lendef.size,lendef.alignment);
  67. hregister:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  68. hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,lendef,resultdef,href,hregister);
  69. if is_widestring(left.resultdef) then
  70. hlcg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SHR,resultdef,1,hregister);
  71. { Dynamic arrays do not have their length attached but their maximum index }
  72. if is_dynamic_array(left.resultdef) then
  73. hlcg.a_op_const_reg(current_asmdata.CurrAsmList,OP_ADD,resultdef,1,hregister);
  74. hlcg.a_load_reg_ref(current_asmdata.CurrAsmList,resultdef,resultdef,hregister,tempref);
  75. hlcg.a_jmp_always(current_asmdata.CurrAsmList,lengthlab);
  76. hlcg.a_label(current_asmdata.CurrAsmList,nillab);
  77. hlcg.a_load_const_ref(current_asmdata.CurrAsmList,resultdef,0,tempref);
  78. hlcg.a_label(current_asmdata.CurrAsmList,lengthlab);
  79. hregister:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  80. hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,resultdef,resultdef,tempref,hregister);
  81. tg.ungettemp(current_asmdata.CurrAsmList,tempref);
  82. location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
  83. location.register:=hregister;
  84. end;
  85. end;
  86. begin
  87. cinlinenode:=tllvminlinenode;
  88. end.