2
0

nllvmld.pas 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. {
  2. Copyright (c) 2012 by Jonas Maebe
  3. Generate LLVM bytecode for nodes that handle loads and assignments
  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 nllvmld;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. globtype,
  22. cgutils,
  23. symtype,
  24. node,ncgld,ncgnstld;
  25. type
  26. tllvmloadnode = class(tcgnestloadnode)
  27. function pass_1: tnode; override;
  28. procedure pass_generate_code; override;
  29. end;
  30. { tllvmarrayconstructornode }
  31. tllvmarrayconstructornode = class(tcgarrayconstructornode)
  32. protected
  33. procedure makearrayref(var ref: treference; eledef: tdef); override;
  34. end;
  35. implementation
  36. uses
  37. systems,
  38. aasmbase,aasmdata,aasmllvm,
  39. nld,
  40. symtable,symconst,symdef,symsym,defutil,
  41. procinfo,tgobj,
  42. llvmbase,cgbase,hlcgobj;
  43. function tllvmloadnode.pass_1: tnode;
  44. begin
  45. result:=inherited;
  46. if assigned(result) then
  47. exit;
  48. case symtableentry.typ of
  49. procsym:
  50. begin
  51. if assigned(left) then
  52. expectloc:=LOC_REFERENCE;
  53. end;
  54. end;
  55. end;
  56. procedure tllvmloadnode.pass_generate_code;
  57. var
  58. pvdef: tprocvardef;
  59. href, mpref: treference;
  60. field: tfieldvarsym;
  61. procreg, selfreg: tregister;
  62. selfdef: tdef;
  63. ai: taillvm;
  64. begin
  65. inherited;
  66. case symtableentry.typ of
  67. procsym:
  68. begin
  69. { if the result is returned in two registers, force it to memory into
  70. a single memory location, as we don't use the registerhi/register
  71. location hack for llvm (llvm will put it back into registers itself)
  72. }
  73. if assigned(left) and
  74. (resultdef.typ in [symconst.procdef,procvardef]) and
  75. not tabstractprocdef(resultdef).is_addressonly then
  76. begin
  77. pvdef:=tprocvardef(procdef.getcopyas(procvardef,pc_normal,''));
  78. { on little endian, location.register contains proc and
  79. location.registerhi contains self; on big endian, it's the
  80. other way around }
  81. tg.gethltemp(current_asmdata.CurrAsmList,pvdef,pvdef.size,tt_normal,href);
  82. if target_info.endian=endian_little then
  83. begin
  84. procreg:=location.register;
  85. selfreg:=location.registerhi
  86. end
  87. else
  88. begin
  89. procreg:=location.registerhi;
  90. selfreg:=location.register
  91. end;
  92. { left can be a pointerdef when we take the address of a nested
  93. procedure, as left will then be a pointer to the nestedfpstruct
  94. }
  95. if is_implicit_pointer_object_type(left.resultdef) or
  96. (left.resultdef.typ in [classrefdef,pointerdef]) then
  97. selfdef:=left.resultdef
  98. else
  99. selfdef:=cpointerdef.getreusable(left.resultdef);
  100. mpref:=href;
  101. hlcg.g_ptrtypecast_ref(current_asmdata.CurrAsmList,cpointerdef.getreusable(pvdef),cpointerdef.getreusable(methodpointertype),mpref);
  102. hlcg.g_load_reg_field_by_name(current_asmdata.CurrAsmList,cprocvardef.getreusableprocaddr(procdef),trecorddef(methodpointertype),procreg,'proc',mpref);
  103. hlcg.g_load_reg_field_by_name(current_asmdata.CurrAsmList,selfdef,trecorddef(methodpointertype),selfreg,'self',mpref);
  104. location_reset_ref(location,LOC_REFERENCE,location.size,href.alignment,href.volatility);
  105. location.reference:=href;
  106. end;
  107. end;
  108. labelsym:
  109. begin
  110. selfreg:=hlcg.getaddressregister(current_asmdata.CurrAsmList,voidcodepointertype);
  111. ai:=taillvm.blockaddress(
  112. current_asmdata.RefAsmSymbol(current_procinfo.procdef.mangledname,AT_FUNCTION),
  113. location.reference.symbol
  114. );
  115. current_asmdata.CurrAsmList.concat(
  116. taillvm.op_reg_tai_size(la_bitcast,selfreg,ai,voidcodepointertype)
  117. );
  118. reference_reset_base(location.reference,selfreg,0,ctempposinvalid,location.reference.alignment,location.reference.volatility);
  119. end;
  120. end;
  121. end;
  122. { tllvmarrayconstructornode }
  123. procedure tllvmarrayconstructornode.makearrayref(var ref: treference; eledef: tdef);
  124. begin
  125. { the array elements are addressed as pointer to the individual elements ->
  126. convert }
  127. hlcg.g_ptrtypecast_ref(current_asmdata.CurrAsmList,cpointerdef.getreusable(resultdef),cpointerdef.getreusable(eledef),ref);
  128. end;
  129. begin
  130. cloadnode:=tllvmloadnode;
  131. carrayconstructornode:=tllvmarrayconstructornode;
  132. end.