parabase.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. {
  2. Copyright (c) 2002 by Florian Klaempfl
  3. Generic calling convention handling
  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 parabase;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. cclasses,globtype,
  22. cpubase,cgbase,cgutils,
  23. symtype, ppu;
  24. type
  25. TCGParaReference = record
  26. index : tregister;
  27. offset : aint;
  28. end;
  29. PCGParaLocation = ^TCGParaLocation;
  30. TCGParaLocation = record
  31. Next : PCGParaLocation;
  32. Size : TCGSize; { size of this location }
  33. Loc : TCGLoc;
  34. case TCGLoc of
  35. LOC_REFERENCE : (reference : TCGParaReference);
  36. LOC_FPUREGISTER,
  37. LOC_CFPUREGISTER,
  38. LOC_MMREGISTER,
  39. LOC_CMMREGISTER,
  40. LOC_REGISTER,
  41. LOC_CREGISTER : (
  42. {
  43. * If shiftval > 0:
  44. The number of bits the value in the register must be shifted to the left before
  45. it can be stored to memory in the function prolog.
  46. This is used for passing OS_NO memory blocks less than register size and of "odd"
  47. (3, 5, 6, 7) size on big endian machines, so that small memory blocks passed via
  48. registers are properly aligned.
  49. E.g. the value $5544433 is passed in bits 40-63 of the register (others are zero),
  50. but they should actually be stored in the first bits of the stack location reserved
  51. for this value. So they have to be shifted left by this amount of bits before.
  52. * if shiftval < 0:
  53. Similar as above, but the shifting must always be done and
  54. 1) for all parameter sizes < regsize
  55. 2) on the caller side
  56. }
  57. shiftval : shortint;
  58. register : tregister);
  59. end;
  60. TCGPara = object
  61. Def : tdef; { Type of the parameter }
  62. Location : PCGParalocation;
  63. IntSize : tcgint; { size of the total location in bytes }
  64. DefDeref : tderef;
  65. Alignment : ShortInt;
  66. Size : TCGSize; { Size of the parameter included in all locations }
  67. Temporary : boolean; { created on the fly, no permanent references exist to this somewhere that will cause it to be disposed }
  68. {$ifdef powerpc}
  69. composite: boolean; { under the AIX abi, how certain parameters are passed depends on whether they are composite or not }
  70. {$endif powerpc}
  71. constructor init;
  72. destructor done;
  73. procedure reset;
  74. procedure resetiftemp; { reset if Temporary }
  75. function getcopy:tcgpara;
  76. procedure check_simple_location;
  77. function add_location:pcgparalocation;
  78. procedure get_location(var newloc:tlocation);
  79. procedure buildderef;
  80. procedure deref;
  81. procedure ppuwrite(ppufile:tcompilerppufile);
  82. procedure ppuload(ppufile:tcompilerppufile);
  83. end;
  84. tvarargsinfo = (
  85. va_uses_float_reg
  86. );
  87. tparalist = class(TFPObjectList)
  88. procedure SortParas;
  89. end;
  90. tvarargsparalist = class(tparalist)
  91. varargsinfo : set of tvarargsinfo;
  92. {$ifdef x86_64}
  93. { x86_64 requires %al to contain the no. SSE regs passed }
  94. mmregsused : longint;
  95. {$endif x86_64}
  96. end;
  97. implementation
  98. uses
  99. systems,verbose,
  100. symsym;
  101. {****************************************************************************
  102. TCGPara
  103. ****************************************************************************}
  104. constructor tcgpara.init;
  105. begin
  106. alignment:=0;
  107. size:=OS_NO;
  108. intsize:=0;
  109. location:=nil;
  110. def:=nil;
  111. temporary:=false;
  112. {$ifdef powerpc}
  113. composite:=false;
  114. {$endif powerpc}
  115. end;
  116. destructor tcgpara.done;
  117. begin
  118. reset;
  119. end;
  120. procedure tcgpara.reset;
  121. var
  122. hlocation : pcgparalocation;
  123. begin
  124. while assigned(location) do
  125. begin
  126. hlocation:=location^.next;
  127. dispose(location);
  128. location:=hlocation;
  129. end;
  130. alignment:=0;
  131. size:=OS_NO;
  132. intsize:=0;
  133. {$ifdef powerpc}
  134. composite:=false;
  135. {$endif powerpc}
  136. end;
  137. procedure TCGPara.resetiftemp;
  138. begin
  139. if temporary then
  140. reset;
  141. end;
  142. function tcgpara.getcopy:tcgpara;
  143. var
  144. hlocation : pcgparalocation;
  145. begin
  146. result.init;
  147. while assigned(location) do
  148. begin
  149. hlocation:=result.add_location;
  150. hlocation^:=location^;
  151. hlocation^.next:=nil;
  152. location:=location^.next;
  153. end;
  154. result.alignment:=alignment;
  155. result.size:=size;
  156. result.intsize:=intsize;
  157. {$ifdef powerpc}
  158. result.composite:=composite;
  159. {$endif powerpc}
  160. end;
  161. function tcgpara.add_location:pcgparalocation;
  162. var
  163. prevlocation,
  164. hlocation : pcgparalocation;
  165. begin
  166. prevlocation:=nil;
  167. hlocation:=location;
  168. while assigned(hlocation) do
  169. begin
  170. prevlocation:=hlocation;
  171. hlocation:=hlocation^.next;
  172. end;
  173. new(hlocation);
  174. Fillchar(hlocation^,sizeof(tcgparalocation),0);
  175. if assigned(prevlocation) then
  176. prevlocation^.next:=hlocation
  177. else
  178. location:=hlocation;
  179. result:=hlocation;
  180. end;
  181. procedure tcgpara.check_simple_location;
  182. begin
  183. if not assigned(location) then
  184. internalerror(200408161);
  185. if assigned(location^.next) then
  186. internalerror(200408162);
  187. end;
  188. procedure tcgpara.get_location(var newloc:tlocation);
  189. begin
  190. if not assigned(location) then
  191. internalerror(200408205);
  192. fillchar(newloc,sizeof(newloc),0);
  193. newloc.loc:=location^.loc;
  194. newloc.size:=size;
  195. case location^.loc of
  196. LOC_REGISTER :
  197. begin
  198. {$ifndef cpu64bitalu}
  199. if size in [OS_64,OS_S64] then
  200. begin
  201. if not assigned(location^.next) then
  202. internalerror(200408206);
  203. if (location^.next^.loc<>LOC_REGISTER) then
  204. internalerror(200408207);
  205. if (target_info.endian = ENDIAN_BIG) then
  206. begin
  207. newloc.register64.reghi:=location^.register;
  208. newloc.register64.reglo:=location^.next^.register;
  209. end
  210. else
  211. begin
  212. newloc.register64.reglo:=location^.register;
  213. newloc.register64.reghi:=location^.next^.register;
  214. end;
  215. end
  216. else
  217. {$endif}
  218. newloc.register:=location^.register;
  219. end;
  220. LOC_FPUREGISTER,
  221. LOC_MMREGISTER :
  222. newloc.register:=location^.register;
  223. LOC_REFERENCE :
  224. begin
  225. newloc.reference.base:=location^.reference.index;
  226. newloc.reference.offset:=location^.reference.offset;
  227. newloc.reference.alignment:=alignment;
  228. end;
  229. end;
  230. end;
  231. procedure TCGPara.buildderef;
  232. begin
  233. defderef.build(def);
  234. end;
  235. procedure TCGPara.deref;
  236. begin
  237. def:=tdef(defderef.resolve);
  238. end;
  239. procedure TCGPara.ppuwrite(ppufile: tcompilerppufile);
  240. var
  241. hparaloc: PCGParaLocation;
  242. nparaloc: byte;
  243. begin
  244. ppufile.putbyte(byte(Alignment));
  245. ppufile.putbyte(ord(Size));
  246. ppufile.putaint(IntSize);
  247. {$ifdef powerpc}
  248. ppufile.putbyte(byte(composite));
  249. {$endif}
  250. ppufile.putderef(defderef);
  251. nparaloc:=0;
  252. hparaloc:=location;
  253. while assigned(hparaloc) do
  254. begin
  255. inc(nparaloc);
  256. hparaloc:=hparaloc^.Next;
  257. end;
  258. ppufile.putbyte(nparaloc);
  259. hparaloc:=location;
  260. while assigned(hparaloc) do
  261. begin
  262. ppufile.putbyte(byte(hparaloc^.Size));
  263. ppufile.putbyte(byte(hparaloc^.loc));
  264. case hparaloc^.loc of
  265. LOC_REFERENCE:
  266. begin
  267. ppufile.putlongint(longint(hparaloc^.reference.index));
  268. ppufile.putaint(hparaloc^.reference.offset);
  269. end;
  270. LOC_FPUREGISTER,
  271. LOC_CFPUREGISTER,
  272. LOC_MMREGISTER,
  273. LOC_CMMREGISTER,
  274. LOC_REGISTER,
  275. LOC_CREGISTER :
  276. begin
  277. ppufile.putbyte(hparaloc^.shiftval);
  278. ppufile.putlongint(longint(hparaloc^.register));
  279. end;
  280. { This seems to be required for systems using explicitparaloc (eg. MorphOS)
  281. or otherwise it hits the internalerror below. I don't know if this is
  282. the proper way to fix this, someone else with clue might want to take a
  283. look. The compiler cycles on the affected systems with this enabled. (KB) }
  284. LOC_VOID:
  285. begin end
  286. else
  287. internalerror(2010053115);
  288. end;
  289. hparaloc:=hparaloc^.next;
  290. end;
  291. end;
  292. procedure TCGPara.ppuload(ppufile: tcompilerppufile);
  293. var
  294. hparaloc: PCGParaLocation;
  295. nparaloc: byte;
  296. begin
  297. reset;
  298. Alignment:=shortint(ppufile.getbyte);
  299. Size:=TCgSize(ppufile.getbyte);
  300. IntSize:=ppufile.getaint;
  301. {$ifdef powerpc}
  302. composite:=boolean(ppufile.getbyte);
  303. {$endif}
  304. ppufile.getderef(defderef);
  305. nparaloc:=ppufile.getbyte;
  306. while nparaloc>0 do
  307. begin
  308. hparaloc:=add_location;
  309. hparaloc^.size:=TCGSize(ppufile.getbyte);
  310. hparaloc^.loc:=TCGLoc(ppufile.getbyte);
  311. case hparaloc^.loc of
  312. LOC_REFERENCE:
  313. begin
  314. hparaloc^.reference.index:=tregister(ppufile.getlongint);
  315. hparaloc^.reference.offset:=ppufile.getaint;
  316. end;
  317. LOC_FPUREGISTER,
  318. LOC_CFPUREGISTER,
  319. LOC_MMREGISTER,
  320. LOC_CMMREGISTER,
  321. LOC_REGISTER,
  322. LOC_CREGISTER :
  323. begin
  324. hparaloc^.shiftval:=ppufile.getbyte;
  325. hparaloc^.register:=tregister(ppufile.getlongint);
  326. end;
  327. { This seems to be required for systems using explicitparaloc (eg. MorphOS)
  328. or otherwise it hits the internalerror below. I don't know if this is
  329. the proper way to fix this, someone else with clue might want to take a
  330. look. The compiler cycles on the affected systems with this enabled. (KB) }
  331. LOC_VOID:
  332. begin end
  333. else
  334. internalerror(2010051301);
  335. end;
  336. dec(nparaloc);
  337. end;
  338. end;
  339. {****************************************************************************
  340. TParaList
  341. ****************************************************************************}
  342. function ParaNrCompare(Item1, Item2: Pointer): Integer;
  343. var
  344. I1 : tparavarsym absolute Item1;
  345. I2 : tparavarsym absolute Item2;
  346. begin
  347. Result:=longint(I1.paranr)-longint(I2.paranr);
  348. end;
  349. procedure TParaList.SortParas;
  350. begin
  351. Sort(@ParaNrCompare);
  352. end;
  353. end.