nllvmcal.pas 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. {
  2. Copyright (c) 2014 by Jonas Maebe
  3. Generate LLVM bytecode for call 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 nllvmcal;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. parabase,
  22. ncal,ncgcal,
  23. cgutils;
  24. type
  25. tllvmcallparanode = class(tcgcallparanode)
  26. end;
  27. tllvmcallnode = class(tcgcallnode)
  28. protected
  29. function paraneedsinlinetemp(para: tcallparanode; const pushconstaddr, complexpara: boolean): boolean; override;
  30. function can_call_ref(var ref: treference): boolean; override;
  31. procedure pushparas; override;
  32. procedure pass_generate_code; override;
  33. end;
  34. implementation
  35. uses
  36. verbose,
  37. aasmbase,aasmdata,aasmllvm,
  38. symconst,symdef;
  39. {*****************************************************************************
  40. TLLVMCALLNODE
  41. *****************************************************************************}
  42. function tllvmcallnode.paraneedsinlinetemp(para: tcallparanode; const pushconstaddr, complexpara: boolean): boolean;
  43. begin
  44. { We don't insert type conversions for self node trees to the type of
  45. the self parameter (and doing so is quite hard due to all kinds of
  46. ugly hacks with this parameter). This means that if we pass on a
  47. self parameter through multiple levels of inlining, it may no
  48. longer match the actual type of the parameter it has been passed to
  49. -> always store in a temp which by definition will have the right
  50. type (if it's a pointer-like type) }
  51. if (vo_is_self in para.parasym.varoptions) and
  52. (is_class_or_interface_or_dispinterface(para.parasym.vardef) or
  53. is_classhelper(para.parasym.vardef) or
  54. ((para.parasym.vardef.typ=classrefdef) and
  55. is_class(tclassrefdef(para.parasym.vardef).pointeddef))) then
  56. result:=true
  57. else
  58. result:=inherited;
  59. end;
  60. function tllvmcallnode.can_call_ref(var ref: treference): boolean;
  61. begin
  62. result:=false;
  63. end;
  64. procedure tllvmcallnode.pushparas;
  65. var
  66. n: tcgcallparanode;
  67. paraindex: longint;
  68. begin
  69. { we just pass the temp paralocs here }
  70. if not assigned(varargsparas) then
  71. setlength(paralocs,procdefinition.paras.count)
  72. else
  73. setlength(paralocs,procdefinition.paras.count+varargsparas.count);
  74. n:=tcgcallparanode(left);
  75. while assigned(n) do
  76. begin
  77. { TODO: check whether this is correct for left-to-right calling
  78. conventions, may also depend on whether or not llvm knows about
  79. the calling convention }
  80. if not(cpf_varargs_para in n.callparaflags) then
  81. paraindex:=procdefinition.paras.indexof(n.parasym)
  82. else
  83. paraindex:=procdefinition.paras.count+varargsparas.indexof(n.parasym);
  84. if paraindex=-1 then
  85. internalerror(2014010602);
  86. paralocs[paraindex]:[email protected];
  87. n:=tcgcallparanode(n.right);
  88. end;
  89. end;
  90. procedure tllvmcallnode.pass_generate_code;
  91. var
  92. asmsym: tasmsymbol;
  93. begin
  94. inherited;
  95. if assigned(overrideprocnamedef) and
  96. not overrideprocnamedef.in_currentunit then
  97. begin
  98. { insert an llvm declaration for this def if it's not defined in
  99. the current unit, because otherwise we will define it in the
  100. LLVM IR using the def for which this procdef's name is used
  101. first, which may be something completely different from the original
  102. def. LLVM can take the original def into account to load certain
  103. registers, so if we use a wrong def this can result in wrong code
  104. generation. }
  105. asmsym:=current_asmdata.RefAsmSymbol(overrideprocnamedef.mangledname,AT_FUNCTION);
  106. if not asmsym.declared then
  107. begin
  108. current_asmdata.AsmLists[al_imports].Concat(taillvmdecl.createdecl(asmsym,overrideprocnamedef,nil,sec_code,overrideprocnamedef.alignment));
  109. end;
  110. end;
  111. end;
  112. begin
  113. ccallnode:=tllvmcallnode;
  114. end.