ncginl.pas 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl and Carl Eric Codere
  4. Generate generic inline nodes
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit ncginl;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. node,ninl;
  23. type
  24. tcginlinenode = class(tinlinenode)
  25. procedure pass_2;override;
  26. procedure second_assigned;virtual; abstract;
  27. procedure second_assert;virtual;
  28. procedure second_sizeoftypeof;virtual;
  29. procedure second_length;virtual;
  30. procedure second_predsucc;virtual;
  31. procedure second_incdec;virtual;
  32. procedure second_typeinfo;virtual;
  33. procedure second_includeexclude;virtual; abstract;
  34. procedure second_pi; virtual;
  35. procedure second_arctan_real; virtual;
  36. procedure second_abs_real; virtual;
  37. procedure second_sqr_real; virtual;
  38. procedure second_sqrt_real; virtual;
  39. procedure second_ln_real; virtual;
  40. procedure second_cos_real; virtual;
  41. procedure second_sin_real; virtual;
  42. end;
  43. implementation
  44. uses
  45. globtype,systems,
  46. cutils,verbose,globals,fmodule,
  47. symconst,symdef,defbase,
  48. aasmbase,aasmtai,aasmcpu,
  49. cginfo,cgbase,pass_1,pass_2,
  50. cpubase,paramgr,
  51. nbas,ncon,ncal,ncnv,nld,
  52. cga,tgobj,ncgutil,cgobj,cg64f32,rgobj,rgcpu;
  53. {*****************************************************************************
  54. TCGINLINENODE
  55. *****************************************************************************}
  56. procedure tcginlinenode.pass_2;
  57. var
  58. asmop : tasmop;
  59. l : longint;
  60. oldpushedparasize : longint;
  61. begin
  62. { save & reset pushedparasize }
  63. oldpushedparasize:=pushedparasize;
  64. pushedparasize:=0;
  65. case inlinenumber of
  66. in_assert_x_y:
  67. begin
  68. second_Assert;
  69. end;
  70. in_sizeof_x,
  71. in_typeof_x :
  72. begin
  73. second_SizeofTypeOf;
  74. end;
  75. in_length_x :
  76. begin
  77. second_Length;
  78. end;
  79. in_pred_x,
  80. in_succ_x:
  81. begin
  82. second_PredSucc;
  83. end;
  84. in_dec_x,
  85. in_inc_x :
  86. begin
  87. second_IncDec;
  88. end;
  89. in_typeinfo_x:
  90. begin
  91. second_TypeInfo;
  92. end;
  93. in_assigned_x :
  94. begin
  95. second_Assigned;
  96. end;
  97. in_include_x_y,
  98. in_exclude_x_y:
  99. begin
  100. second_IncludeExclude;
  101. end;
  102. in_pi:
  103. begin
  104. second_pi;
  105. end;
  106. in_sin_extended:
  107. begin
  108. second_sin_real;
  109. end;
  110. in_arctan_extended:
  111. begin
  112. second_arctan_real;
  113. end;
  114. in_abs_extended:
  115. begin
  116. second_abs_real;
  117. end;
  118. in_sqr_extended:
  119. begin
  120. second_sqr_real;
  121. end;
  122. in_sqrt_extended:
  123. begin
  124. second_sqrt_real;
  125. end;
  126. in_ln_extended:
  127. begin
  128. second_ln_real;
  129. end;
  130. in_cos_extended:
  131. begin
  132. second_cos_real;
  133. end;
  134. {$ifdef SUPPORT_MMX}
  135. in_mmx_pcmpeqb..in_mmx_pcmpgtw:
  136. begin
  137. location_reset(location,LOC_MMXREGISTER,OS_NO);
  138. if left.location.loc=LOC_REGISTER then
  139. begin
  140. {!!!!!!!}
  141. end
  142. else if tcallparanode(left).left.location.loc=LOC_REGISTER then
  143. begin
  144. {!!!!!!!}
  145. end
  146. else
  147. begin
  148. {!!!!!!!}
  149. end;
  150. end;
  151. {$endif SUPPORT_MMX}
  152. else internalerror(9);
  153. end;
  154. { reset pushedparasize }
  155. pushedparasize:=oldpushedparasize;
  156. end;
  157. {*****************************************************************************
  158. ASSERT GENERIC HANDLING
  159. *****************************************************************************}
  160. procedure tcginlinenode.second_Assert;
  161. var
  162. hp2 : tstringconstnode;
  163. otlabel,oflabel{,l1} : tasmlabel;
  164. begin
  165. { the node should be removed in the firstpass }
  166. if not (cs_do_assertion in aktlocalswitches) then
  167. internalerror(7123458);
  168. otlabel:=truelabel;
  169. oflabel:=falselabel;
  170. getlabel(truelabel);
  171. getlabel(falselabel);
  172. secondpass(tcallparanode(left).left);
  173. maketojumpbool(exprasmlist,tcallparanode(left).left,lr_load_regvars);
  174. cg.a_label(exprasmlist,falselabel);
  175. { erroraddr }
  176. cg.a_param_reg(exprasmlist,OS_ADDR,FRAME_POINTER_REG,paramanager.getintparaloc(4));
  177. { lineno }
  178. cg.a_param_const(exprasmlist,OS_INT,aktfilepos.line,paramanager.getintparaloc(3));
  179. { filename string }
  180. hp2:=cstringconstnode.createstr(current_module.sourcefiles.get_file_name(aktfilepos.fileindex),st_shortstring);
  181. firstpass(hp2);
  182. secondpass(hp2);
  183. if codegenerror then
  184. exit;
  185. cg.a_paramaddr_ref(exprasmlist,hp2.location.reference,paramanager.getintparaloc(2));
  186. hp2.free;
  187. { push msg }
  188. secondpass(tcallparanode(tcallparanode(left).right).left);
  189. cg.a_paramaddr_ref(exprasmlist,tcallparanode(tcallparanode(left).right).left.location.reference,paramanager.getintparaloc(1));
  190. { call }
  191. cg.a_call_name(exprasmlist,'FPC_ASSERT');
  192. cg.a_label(exprasmlist,truelabel);
  193. truelabel:=otlabel;
  194. falselabel:=oflabel;
  195. end;
  196. {*****************************************************************************
  197. SIZEOF / TYPEOF GENERIC HANDLING
  198. *****************************************************************************}
  199. { second_handle_ the sizeof and typeof routines }
  200. procedure tcginlinenode.second_SizeOfTypeOf;
  201. var
  202. href : treference;
  203. hregister : tregister;
  204. begin
  205. location_reset(location,LOC_REGISTER,OS_ADDR);
  206. { for both cases load vmt }
  207. if left.nodetype=typen then
  208. begin
  209. hregister:=rg.getaddressregister(exprasmlist);
  210. reference_reset_symbol(href,newasmsymbol(tobjectdef(left.resulttype.def).vmt_mangledname),0);
  211. cg.a_loadaddr_ref_reg(exprasmlist,href,hregister);
  212. end
  213. else
  214. begin
  215. secondpass(left);
  216. location_release(exprasmlist,left.location);
  217. hregister:=rg.getaddressregister(exprasmlist);
  218. { load VMT pointer }
  219. inc(left.location.reference.offset,tobjectdef(left.resulttype.def).vmt_offset);
  220. cg.a_load_ref_reg(exprasmlist,OS_ADDR,left.location.reference,hregister);
  221. end;
  222. { in sizeof load size }
  223. if inlinenumber=in_sizeof_x then
  224. begin
  225. reference_reset_base(href,hregister,0);
  226. rg.ungetaddressregister(exprasmlist,hregister);
  227. hregister:=rg.getregisterint(exprasmlist);
  228. cg.a_load_ref_reg(exprasmlist,OS_INT,href,hregister);
  229. end;
  230. location.register:=hregister;
  231. end;
  232. {*****************************************************************************
  233. LENGTH GENERIC HANDLING
  234. *****************************************************************************}
  235. procedure tcginlinenode.second_Length;
  236. var
  237. lengthlab : tasmlabel;
  238. hregister : tregister;
  239. href : treference;
  240. begin
  241. secondpass(left);
  242. { length in ansi strings is at offset -8 }
  243. if is_ansistring(left.resulttype.def) or
  244. is_widestring(left.resulttype.def) then
  245. begin
  246. location_force_reg(exprasmlist,left.location,OS_ADDR,false);
  247. hregister:=left.location.register;
  248. getlabel(lengthlab);
  249. cg.a_cmp_const_reg_label(exprasmlist,OS_ADDR,OC_EQ,0,hregister,lengthlab);
  250. reference_reset_base(href,hregister,-8);
  251. cg.a_load_ref_reg(exprasmlist,OS_INT,href,hregister);
  252. cg.a_label(exprasmlist,lengthlab);
  253. location_reset(location,LOC_REGISTER,OS_INT);
  254. location.register:=hregister;
  255. end
  256. else
  257. begin
  258. location_copy(location,left.location);
  259. location.size:=OS_8;
  260. end;
  261. end;
  262. {*****************************************************************************
  263. PRED/SUCC GENERIC HANDLING
  264. *****************************************************************************}
  265. procedure tcginlinenode.second_PredSucc;
  266. var
  267. cgsize : TCGSize;
  268. cgop : topcg;
  269. begin
  270. secondpass(left);
  271. if inlinenumber=in_pred_x then
  272. cgop:=OP_SUB
  273. else
  274. cgop:=OP_ADD;
  275. cgsize:=def_cgsize(resulttype.def);
  276. { we need a value in a register }
  277. location_copy(location,left.location);
  278. location_force_reg(exprasmlist,location,cgsize,false);
  279. if cgsize in [OS_64,OS_S64] then
  280. cg64.a_op64_const_reg(exprasmlist,cgop,1,
  281. location.register64)
  282. else
  283. cg.a_op_const_reg(exprasmlist,cgop,1,location.register);
  284. cg.g_overflowcheck(exprasmlist,self);
  285. cg.g_rangecheck(exprasmlist,self,resulttype.def);
  286. end;
  287. {*****************************************************************************
  288. INC/DEC GENERIC HANDLING
  289. *****************************************************************************}
  290. procedure tcginlinenode.second_IncDec;
  291. const
  292. addsubop:array[in_inc_x..in_dec_x] of TOpCG=(OP_ADD,OP_SUB);
  293. var
  294. addvalue : longint;
  295. addconstant : boolean;
  296. hregisterhi,
  297. hregister : tregister;
  298. cgsize : tcgsize;
  299. pushedregs : tmaybesave;
  300. begin
  301. { set defaults }
  302. addconstant:=true;
  303. { load first parameter, must be a reference }
  304. secondpass(tcallparanode(left).left);
  305. cgsize:=def_cgsize(tcallparanode(left).left.resulttype.def);
  306. { get addvalue }
  307. case tcallparanode(left).left.resulttype.def.deftype of
  308. orddef,
  309. enumdef :
  310. addvalue:=1;
  311. pointerdef :
  312. begin
  313. if is_void(tpointerdef(tcallparanode(left).left.resulttype.def).pointertype.def) then
  314. addvalue:=1
  315. else
  316. addvalue:=tpointerdef(tcallparanode(left).left.resulttype.def).pointertype.def.size;
  317. end;
  318. else
  319. internalerror(10081);
  320. end;
  321. { second_ argument specified?, must be a s32bit in register }
  322. if assigned(tcallparanode(left).right) then
  323. begin
  324. maybe_save(exprasmlist,tcallparanode(tcallparanode(left).right).left.registers32,
  325. tcallparanode(left).left.location,pushedregs);
  326. secondpass(tcallparanode(tcallparanode(left).right).left);
  327. maybe_restore(exprasmlist,tcallparanode(left).left.location,pushedregs);
  328. { when constant, just multiply the addvalue }
  329. if is_constintnode(tcallparanode(tcallparanode(left).right).left) then
  330. addvalue:=addvalue*get_ordinal_value(tcallparanode(tcallparanode(left).right).left)
  331. else
  332. begin
  333. location_force_reg(exprasmlist,tcallparanode(tcallparanode(left).right).left.location,cgsize,false);
  334. hregister:=tcallparanode(tcallparanode(left).right).left.location.register;
  335. hregisterhi:=tcallparanode(tcallparanode(left).right).left.location.registerhigh;
  336. { insert multiply with addvalue if its >1 }
  337. if addvalue>1 then
  338. cg.a_op_const_reg(exprasmlist,OP_IMUL,addvalue,hregister);
  339. addconstant:=false;
  340. end;
  341. end;
  342. { write the add instruction }
  343. if addconstant then
  344. begin
  345. if cgsize in [OS_64,OS_S64] then
  346. cg64.a_op64_const_loc(exprasmlist,addsubop[inlinenumber],
  347. addvalue,tcallparanode(left).left.location)
  348. else
  349. cg.a_op_const_loc(exprasmlist,addsubop[inlinenumber],
  350. addvalue,tcallparanode(left).left.location);
  351. end
  352. else
  353. begin
  354. if cgsize in [OS_64,OS_S64] then
  355. cg64.a_op64_reg_loc(exprasmlist,addsubop[inlinenumber],
  356. joinreg64(hregister,hregisterhi),tcallparanode(left).left.location)
  357. else
  358. cg.a_op_reg_loc(exprasmlist,addsubop[inlinenumber],
  359. hregister,tcallparanode(left).left.location);
  360. location_release(exprasmlist,tcallparanode(tcallparanode(left).right).left.location);
  361. end;
  362. cg.g_overflowcheck(exprasmlist,tcallparanode(left).left);
  363. cg.g_rangecheck(exprasmlist,tcallparanode(left).left,tcallparanode(left).left.resulttype.def);
  364. end;
  365. {*****************************************************************************
  366. TYPEINFO GENERIC HANDLING
  367. *****************************************************************************}
  368. procedure tcginlinenode.second_typeinfo;
  369. var
  370. href : treference;
  371. begin
  372. location_reset(location,LOC_REGISTER,OS_ADDR);
  373. location.register:=rg.getaddressregister(exprasmlist);
  374. reference_reset_symbol(href,tstoreddef(ttypenode(tcallparanode(left).left).resulttype.def).get_rtti_label(fullrtti),0);
  375. cg.a_loadaddr_ref_reg(exprasmlist,href,location.register);
  376. end;
  377. {*****************************************************************************
  378. ASSIGNED GENERIC HANDLING
  379. *****************************************************************************}
  380. (*
  381. procedure tcginlinenode.second_Assigned;
  382. var
  383. hreg : tregister;
  384. ptrvalidlabel : tasmlabel;
  385. begin
  386. secondpass(tcallparanode(left).left);
  387. location_release(exprasmlist,tcallparanode(left).left.location);
  388. hreg := rg.getregisterint(exprasmlist);
  389. if (tcallparanode(left).left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  390. begin
  391. { if pointer is non-nil, and is in register, this directly the value we can use }
  392. cg.a_load_reg_reg(exprasmlist, OS_ADDR, tcallparanode(left).left.location.register, hreg);
  393. end
  394. else
  395. begin
  396. getlabel(ptrvalidlabel);
  397. cg.a_load_const_reg(exprasmlist, OS_INT, 1, hreg);
  398. cg.a_cmp_const_ref_label(exprasmlist, OS_ADDR, OC_NE, 0,
  399. tcallparanode(left).left.location.reference, ptrvalidlabel);
  400. cg.a_load_const_reg(exprasmlist, OS_INT, 0, hreg);
  401. cg.a_label(exprasmlist,ptrvalidlabel);
  402. end;
  403. location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def));
  404. location.register := rg.makeregsize(hreg,def_cgsize(resulttype.def));
  405. end;
  406. *)
  407. {*****************************************************************************
  408. FLOAT GENERIC HANDLING
  409. *****************************************************************************}
  410. {
  411. These routines all call internal RTL routines, so if they are
  412. called here, they give an internal error
  413. }
  414. procedure tcginlinenode.second_pi;
  415. begin
  416. internalerror(20020718);
  417. end;
  418. procedure tcginlinenode.second_arctan_real;
  419. begin
  420. internalerror(20020718);
  421. end;
  422. procedure tcginlinenode.second_abs_real;
  423. begin
  424. internalerror(20020718);
  425. end;
  426. procedure tcginlinenode.second_sqr_real;
  427. begin
  428. internalerror(20020718);
  429. end;
  430. procedure tcginlinenode.second_sqrt_real;
  431. begin
  432. internalerror(20020718);
  433. end;
  434. procedure tcginlinenode.second_ln_real;
  435. begin
  436. internalerror(20020718);
  437. end;
  438. procedure tcginlinenode.second_cos_real;
  439. begin
  440. internalerror(20020718);
  441. end;
  442. procedure tcginlinenode.second_sin_real;
  443. begin
  444. internalerror(20020718);
  445. end;
  446. begin
  447. { cinlinenode:=tcginlinenode;}
  448. end.
  449. {
  450. $Log$
  451. Revision 1.2 2002-07-25 17:55:41 carl
  452. + First working revision
  453. Revision 1.1 2002/07/24 04:07:49 carl
  454. + first revision (incomplete)
  455. }