rautils.pas 59 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975
  1. {
  2. Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
  3. This unit implements some support routines for assembler parsing
  4. independent of the processor
  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. Unit RAUtils;
  18. {$i fpcdefs.inc}
  19. Interface
  20. Uses
  21. cutils,cclasses,
  22. globtype,aasmbase,aasmtai,aasmdata,cpubase,cpuinfo,cgbase,cgutils,
  23. symconst,symbase,symtype,symdef,symsym,constexp,symcpu;
  24. Const
  25. RPNMax = 10; { I think you only need 4, but just to be safe }
  26. OpMax = 25;
  27. Function SearchLabel(const s: string; var hl: tasmlabel;emit:boolean): boolean;
  28. {---------------------------------------------------------------------
  29. Instruction management
  30. ---------------------------------------------------------------------}
  31. type
  32. TOprType=(OPR_NONE,OPR_CONSTANT,OPR_SYMBOL,OPR_LOCAL,
  33. OPR_REFERENCE,OPR_REGISTER,OPR_COND,OPR_REGSET,
  34. OPR_SHIFTEROP,OPR_MODEFLAGS,OPR_SPECIALREG,
  35. OPR_REGPAIR,OPR_FENCEFLAGS,OPR_INDEXEDREG,OPR_FLOATCONSTANT,
  36. OPR_FUNCTYPE);
  37. TOprRec = record
  38. case typ:TOprType of
  39. OPR_NONE : ();
  40. {$if defined(AVR)}
  41. OPR_CONSTANT : (val:longint);
  42. {$elseif defined(i8086)}
  43. OPR_CONSTANT : (val:longint);
  44. {$elseif defined(Z80)}
  45. OPR_CONSTANT : (val:longint);
  46. {$elseif defined(MOS6502)}
  47. OPR_CONSTANT : (val:longint);
  48. {$else}
  49. OPR_CONSTANT : (val:aint);
  50. {$endif}
  51. OPR_SYMBOL : (symbol:tasmsymbol;symofs:aint;symseg:boolean;sym_farproc_entry:boolean);
  52. OPR_REFERENCE : (varsize:asizeint; constoffset: asizeint;ref_farproc_entry:boolean;ref:treference);
  53. OPR_LOCAL : (localvarsize, localconstoffset: asizeint;localsym:tabstractnormalvarsym;localsymofs:aint;localsegment,localindexreg:tregister;localscale:byte;localgetoffset,localforceref:boolean);
  54. OPR_REGISTER : (reg:tregister);
  55. {$ifdef m68k}
  56. OPR_REGSET : (regsetdata,regsetaddr,regsetfpu : tcpuregisterset);
  57. OPR_REGPAIR : (reghi,reglo: tregister);
  58. {$endif m68k}
  59. {$ifdef powerpc}
  60. OPR_COND : (cond : tasmcond);
  61. {$endif powerpc}
  62. {$ifdef POWERPC64}
  63. OPR_COND : (cond : tasmcond);
  64. {$endif POWERPC64}
  65. {$ifdef arm}
  66. OPR_REGSET : (regset : tcpuregisterset; regtype: tregistertype; subreg: tsubregister; usermode: boolean);
  67. OPR_SHIFTEROP : (shifterop : tshifterop);
  68. OPR_COND : (cc : tasmcond);
  69. OPR_MODEFLAGS : (flags : tcpumodeflags);
  70. OPR_SPECIALREG: (specialreg : tregister; specialregflags : tspecialregflags);
  71. {$endif arm}
  72. {$ifdef aarch64}
  73. OPR_REGSET : (basereg: tregister; nregs, regsetindex: byte);
  74. OPR_INDEXEDREG: (indexedreg: tregister; regindex: byte);
  75. OPR_SHIFTEROP : (shifterop : tshifterop);
  76. OPR_COND : (cc : tasmcond);
  77. {$endif aarch64}
  78. {$if defined(riscv32) or defined(riscv64)}
  79. OPR_FENCEFLAGS: (fenceflags : TFenceFlags);
  80. {$endif aarch64}
  81. {$ifdef wasm32}
  82. OPR_FLOATCONSTANT: (floatval:double);
  83. OPR_FUNCTYPE : (functype: TWasmFuncType);
  84. {$endif wasm32}
  85. end;
  86. TInstruction = class;
  87. TOperand = class
  88. opr : TOprRec;
  89. typesize : byte;
  90. haslabelref, { if the operand has a label, used in a reference like a
  91. var (e.g. 'mov ax, word ptr [label+5]', but *not*
  92. e.g. 'jmp label') }
  93. hasproc, { if the operand has a procedure/function reference }
  94. hastype, { if the operand has typecasted variable }
  95. hasvar : boolean; { if the operand is loaded with a variable }
  96. size : TCGSize;
  97. constructor create;virtual;
  98. destructor destroy;override;
  99. Procedure SetSize(_size:longint;force:boolean);virtual;
  100. Procedure SetCorrectSize(opcode:tasmop);virtual;
  101. Function SetupResult:boolean;virtual;
  102. Function SetupSelf:boolean;
  103. Function SetupOldEBP:boolean;
  104. Function SetupVar(const s:string;GetOffset : boolean): Boolean;
  105. function CheckOperand(ins : TInstruction): boolean; virtual;
  106. Procedure InitRef;
  107. Procedure InitRefConvertLocal;
  108. protected
  109. Procedure InitRefError;
  110. end;
  111. TCOperand = class of TOperand;
  112. TInstruction = class
  113. operands : array[1..max_operands] of toperand;
  114. opcode : tasmop;
  115. condition : tasmcond;
  116. ops : byte;
  117. labeled : boolean;
  118. filepos : tfileposinfo;
  119. constructor create(optype : tcoperand);virtual;
  120. destructor destroy;override;
  121. { converts the instruction to an instruction how it's used by the assembler writer
  122. and concats it to the passed list. The newly created item is returned if the
  123. instruction was valid, otherwise nil is returned }
  124. function ConcatInstruction(p:TAsmList) : tai;virtual;
  125. end;
  126. {---------------------------------------------------------------------}
  127. { Expression parser types }
  128. {---------------------------------------------------------------------}
  129. TExprOperator = record
  130. ch: char; { operator }
  131. is_prefix: boolean; { was it a prefix, possible prefixes are +,- and not }
  132. end;
  133. {**********************************************************************}
  134. { The following operators are supported: }
  135. { '+' : addition }
  136. { '-' : subtraction }
  137. { '*' : multiplication }
  138. { '/' : modulo division }
  139. { '^' : exclusive or }
  140. { '<' : shift left }
  141. { '>' : shift right }
  142. { '&' : bitwise and }
  143. { '|' : bitwise or }
  144. { '~' : bitwise complement }
  145. { '%' : modulo division }
  146. { nnn: longint numbers }
  147. { ( and ) parenthesis }
  148. { [ and ] another kind of parenthesis }
  149. {**********************************************************************}
  150. TExprParse = class
  151. public
  152. Constructor create;
  153. Destructor Destroy;override;
  154. Function Evaluate(Expr: String): tcgint;
  155. Function Priority(_Operator: Char): aint;
  156. private
  157. RPNStack : Array[1..RPNMax] of tcgint; { Stack For RPN calculator }
  158. RPNTop : tcgint;
  159. OpStack : Array[1..OpMax] of TExprOperator; { Operator stack For conversion }
  160. OpTop : tcgint;
  161. Procedure RPNPush(Num: tcgint);
  162. Function RPNPop: tcgint;
  163. Procedure RPNCalc(const token: String; prefix: boolean);
  164. Procedure OpPush(_Operator: char; prefix: boolean);
  165. { In reality returns TExprOperaotr }
  166. Procedure OpPop(var _Operator:TExprOperator);
  167. end;
  168. { Evaluate an expression string to a tcgint }
  169. Function CalculateExpression(const expression: string): tcgint;
  170. {---------------------------------------------------------------------}
  171. { String routines }
  172. {---------------------------------------------------------------------}
  173. Function ParseVal(const S:String;base:byte):tcgint;
  174. Function PadZero(Var s: String; n: byte): Boolean;
  175. Function EscapeToPascal(const s:string): string;
  176. {---------------------------------------------------------------------
  177. Symbol helper routines
  178. ---------------------------------------------------------------------}
  179. procedure AsmSearchSym(const s:string;out srsym:tsym;out srsymtable:TSymtable);
  180. Function GetRecordOffsetSize(s:string;out Offset: tcgint;out Size:tcgint; out mangledname: string; needvmtofs: boolean; out hastypecast: boolean):boolean;
  181. Function SearchType(const hs:string;out size:tcgint): Boolean;
  182. Function SearchRecordType(const s:string): boolean;
  183. Function SearchIConstant(const s:string; var l:tcgint): boolean;
  184. Function AsmRegisterPara(sym: tabstractnormalvarsym): boolean;
  185. {---------------------------------------------------------------------
  186. Instruction generation routines
  187. ---------------------------------------------------------------------}
  188. Procedure ConcatLabel(p: TAsmList;var l : tasmlabel);
  189. Procedure ConcatConstant(p : TAsmList;value: tcgint; constsize:byte);
  190. Procedure ConcatConstSymbol(p : TAsmList;const sym,endsym:string;symtyp:tasmsymtype;l:tcgint;constsize:byte;isofs:boolean);
  191. Procedure ConcatRealConstant(p : TAsmList;value: bestreal; real_typ : tfloattype);
  192. Procedure ConcatString(p : TAsmList;s:string);
  193. procedure ConcatAlign(p:TAsmList;l:tcgint);
  194. Procedure ConcatPublic(p:TAsmList;const s : string);
  195. Procedure ConcatLocal(p:TAsmList;const s : string);
  196. Implementation
  197. uses
  198. SysUtils,
  199. defutil,systems,verbose,globals,
  200. symtable,paramgr,
  201. aasmcpu,
  202. procinfo,ngenutil;
  203. {*************************************************************************
  204. TExprParse
  205. *************************************************************************}
  206. Constructor TExprParse.create;
  207. Begin
  208. end;
  209. Procedure TExprParse.RPNPush(Num : tcgint);
  210. { Add an operand to the top of the RPN stack }
  211. begin
  212. if RPNTop < RPNMax then
  213. begin
  214. Inc(RPNTop);
  215. RPNStack[RPNTop]:=Num;
  216. end
  217. else
  218. Message(asmr_e_expr_illegal);
  219. end;
  220. Function TExprParse.RPNPop : tcgint;
  221. { Get the operand at the top of the RPN stack }
  222. begin
  223. RPNPop:=0;
  224. if RPNTop > 0 then
  225. begin
  226. RPNPop:=RPNStack[RPNTop];
  227. Dec(RPNTop);
  228. end
  229. else
  230. Message(asmr_e_expr_illegal);
  231. end;
  232. Procedure TExprParse.RPNCalc(const Token : String; prefix:boolean); { RPN Calculator }
  233. Var
  234. Temp : tcgint;
  235. n1,n2 : tcgint;
  236. LocalError : Integer;
  237. begin
  238. { Handle operators }
  239. if (Length(Token) = 1) and (Token[1] in ['+', '-', '*', '/','&','|','%','^','~','<','>']) then
  240. Case Token[1] of
  241. '+' :
  242. Begin
  243. if not prefix then
  244. RPNPush(RPNPop + RPNPop);
  245. end;
  246. '-' :
  247. Begin
  248. if prefix then
  249. RPNPush(-(RPNPop))
  250. else
  251. begin
  252. n1:=RPNPop;
  253. n2:=RPNPop;
  254. RPNPush(n2 - n1);
  255. end;
  256. end;
  257. '*' : RPNPush(RPNPop * RPNPop);
  258. '&' :
  259. begin
  260. n1:=RPNPop;
  261. n2:=RPNPop;
  262. RPNPush(n2 and n1);
  263. end;
  264. '|' :
  265. begin
  266. n1:=RPNPop;
  267. n2:=RPNPop;
  268. RPNPush(n2 or n1);
  269. end;
  270. '~' : RPNPush(NOT RPNPop);
  271. '<' :
  272. begin
  273. n1:=RPNPop;
  274. n2:=RPNPop;
  275. RPNPush(n2 SHL n1);
  276. end;
  277. '>' :
  278. begin
  279. n1:=RPNPop;
  280. n2:=RPNPop;
  281. RPNPush(n2 SHR n1);
  282. end;
  283. '%' :
  284. begin
  285. Temp:=RPNPop;
  286. if Temp <> 0 then
  287. RPNPush(RPNPop mod Temp)
  288. else
  289. begin
  290. Message(asmr_e_expr_zero_divide);
  291. { push 1 for error recovery }
  292. RPNPush(1);
  293. end;
  294. end;
  295. '^' : RPNPush(RPNPop XOR RPNPop);
  296. '/' :
  297. begin
  298. Temp:=RPNPop;
  299. if Temp <> 0 then
  300. RPNPush(RPNPop div Temp)
  301. else
  302. begin
  303. Message(asmr_e_expr_zero_divide);
  304. { push 1 for error recovery }
  305. RPNPush(1);
  306. end;
  307. end;
  308. end
  309. else
  310. begin
  311. { Convert String to number and add to stack }
  312. Val(Token, Temp, LocalError);
  313. if LocalError = 0 then
  314. RPNPush(Temp)
  315. else
  316. begin
  317. Message(asmr_e_expr_illegal);
  318. { push 1 for error recovery }
  319. RPNPush(1);
  320. end;
  321. end;
  322. end;
  323. Procedure TExprParse.OpPush(_Operator : char;prefix: boolean);
  324. { Add an operator onto top of the stack }
  325. begin
  326. if OpTop < OpMax then
  327. begin
  328. Inc(OpTop);
  329. OpStack[OpTop].ch:=_Operator;
  330. OpStack[OpTop].is_prefix:=prefix;
  331. end
  332. else
  333. Message(asmr_e_expr_illegal);
  334. end;
  335. Procedure TExprParse.OpPop(var _Operator:TExprOperator);
  336. { Get operator at the top of the stack }
  337. begin
  338. if OpTop > 0 then
  339. begin
  340. _Operator:=OpStack[OpTop];
  341. Dec(OpTop);
  342. end
  343. else
  344. Message(asmr_e_expr_illegal);
  345. end;
  346. Function TExprParse.Priority(_Operator : Char) : aint;
  347. { Return priority of operator }
  348. { The greater the priority, the higher the precedence }
  349. begin
  350. Priority:=0;
  351. Case _Operator OF
  352. '(','[' :
  353. Priority:=0;
  354. '|','^','~' : // the lowest priority: OR, XOR, NOT
  355. Priority:=0;
  356. '&' : // bigger priority: AND
  357. Priority:=1;
  358. '+', '-' : // bigger priority: +, -
  359. Priority:=2;
  360. '*', '/','%','<','>' : // the highest priority: *, /, MOD, SHL, SHR
  361. Priority:=3;
  362. else
  363. Message(asmr_e_expr_illegal);
  364. end;
  365. end;
  366. Function TExprParse.Evaluate(Expr : String):tcgint;
  367. Var
  368. I : longint;
  369. Token : String;
  370. opr : TExprOperator;
  371. begin
  372. Evaluate:=0;
  373. { Reset stacks }
  374. OpTop :=0;
  375. RPNTop:=0;
  376. Token :='';
  377. { nothing to do ? }
  378. if Expr='' then
  379. exit;
  380. For I:=1 to Length(Expr) DO
  381. begin
  382. if Expr[I] in ['0'..'9'] then
  383. begin { Build multi-digit numbers }
  384. Token:=Token + Expr[I];
  385. if I = Length(Expr) then { Send last one to calculator }
  386. RPNCalc(Token,false);
  387. end
  388. else
  389. if Expr[I] in ['+', '-', '*', '/', '(', ')','[',']','^','&','|','%','~','<','>'] then
  390. begin
  391. if Token <> '' then
  392. begin { Send last built number to calc. }
  393. RPNCalc(Token,false);
  394. Token:='';
  395. end;
  396. Case Expr[I] OF
  397. '[' : OpPush('[',false);
  398. ']' : begin
  399. While (OpTop>0) and (OpStack[OpTop].ch <> '[') DO
  400. Begin
  401. OpPop(opr);
  402. RPNCalc(opr.ch,opr.is_prefix);
  403. end;
  404. OpPop(opr); { Pop off and ignore the '[' }
  405. end;
  406. '(' : OpPush('(',false);
  407. ')' : begin
  408. While (OpTop>0) and (OpStack[OpTop].ch <> '(') DO
  409. Begin
  410. OpPop(opr);
  411. RPNCalc(opr.ch,opr.is_prefix);
  412. end;
  413. OpPop(opr); { Pop off and ignore the '(' }
  414. end;
  415. '+','-','~' : Begin
  416. { workaround for -2147483648 }
  417. if (expr[I]='-') and (expr[i+1] in ['0'..'9']) then
  418. begin
  419. token:='-';
  420. expr[i]:='+';
  421. end;
  422. { if start of expression then surely a prefix }
  423. { or if previous char was also an operator }
  424. if (I = 1) or (not (Expr[I-1] in ['0'..'9',')'])) then
  425. OpPush(Expr[I],true)
  426. else
  427. Begin
  428. { Evaluate all higher priority operators }
  429. While (OpTop > 0) AND (Priority(Expr[I]) <= Priority(OpStack[OpTop].ch)) DO
  430. Begin
  431. OpPop(opr);
  432. RPNCalc(opr.ch,opr.is_prefix);
  433. end;
  434. OpPush(Expr[I],false);
  435. End;
  436. end;
  437. '*', '/',
  438. '^','|','&',
  439. '%','<','>' : begin
  440. While (OpTop > 0) and (Priority(Expr[I]) <= Priority(OpStack[OpTop].ch)) DO
  441. Begin
  442. OpPop(opr);
  443. RPNCalc(opr.ch,opr.is_prefix);
  444. end;
  445. OpPush(Expr[I],false);
  446. end;
  447. end; { Case }
  448. end
  449. else
  450. Message(asmr_e_expr_illegal); { Handle bad input error }
  451. end;
  452. { Pop off the remaining operators }
  453. While OpTop > 0 do
  454. Begin
  455. OpPop(opr);
  456. RPNCalc(opr.ch,opr.is_prefix);
  457. end;
  458. { The result is stored on the top of the stack }
  459. Evaluate:=RPNPop;
  460. end;
  461. Destructor TExprParse.Destroy;
  462. Begin
  463. end;
  464. Function CalculateExpression(const expression: string): tcgint;
  465. var
  466. expr: TExprParse;
  467. Begin
  468. expr:=TExprParse.create;
  469. CalculateExpression:=expr.Evaluate(expression);
  470. expr.Free;
  471. end;
  472. {*************************************************************************}
  473. { String conversions/utils }
  474. {*************************************************************************}
  475. Function EscapeToPascal(const s:string): string;
  476. { converts a C styled string - which contains escape }
  477. { characters to a pascal style string. }
  478. var
  479. i,len : asizeint;
  480. hs : string;
  481. temp : string;
  482. c : char;
  483. Begin
  484. hs:='';
  485. len:=0;
  486. i:=0;
  487. while (i<length(s)) and (len<255) do
  488. begin
  489. Inc(i);
  490. if (s[i]='\') and (i<length(s)) then
  491. Begin
  492. inc(i);
  493. case s[i] of
  494. '\' :
  495. c:='\';
  496. 'b':
  497. c:=#8;
  498. 'f':
  499. c:=#12;
  500. 'n':
  501. c:=#10;
  502. 'r':
  503. c:=#13;
  504. 't':
  505. c:=#9;
  506. '"':
  507. c:='"';
  508. '0'..'7':
  509. Begin
  510. temp:=s[i];
  511. temp:=temp+s[i+1];
  512. temp:=temp+s[i+2];
  513. inc(i,2);
  514. c:=chr(ParseVal(temp,8));
  515. end;
  516. 'x':
  517. Begin
  518. temp:=s[i+1];
  519. temp:=temp+s[i+2];
  520. inc(i,2);
  521. c:=chr(ParseVal(temp,16));
  522. end;
  523. else
  524. Begin
  525. Message1(asmr_e_escape_seq_ignored,s[i]);
  526. c:=s[i];
  527. end;
  528. end;
  529. end
  530. else
  531. c:=s[i];
  532. inc(len);
  533. hs[len]:=c;
  534. end;
  535. hs[0]:=chr(len);
  536. EscapeToPascal:=hs;
  537. end;
  538. Function ParseVal(const S:String;base:byte):tcgint;
  539. { Converts a decimal string to tcgint }
  540. var
  541. code : integer;
  542. errmsg : word;
  543. prefix : string[2];
  544. Begin
  545. case base of
  546. 2 :
  547. begin
  548. errmsg:=asmr_e_error_converting_binary;
  549. prefix:='%';
  550. end;
  551. 8 :
  552. begin
  553. errmsg:=asmr_e_error_converting_octal;
  554. prefix:='&';
  555. end;
  556. 10 :
  557. begin
  558. errmsg:=asmr_e_error_converting_decimal;
  559. prefix:='';
  560. end;
  561. 16 :
  562. begin
  563. errmsg:=asmr_e_error_converting_hexadecimal;
  564. prefix:='$';
  565. end;
  566. else
  567. internalerror(200501202);
  568. end;
  569. val(prefix+s,result,code);
  570. if code<>0 then
  571. begin
  572. val(prefix+s,result,code);
  573. if code<>0 then
  574. begin
  575. Message1(errmsg,s);
  576. result:=0;
  577. end;
  578. end;
  579. end;
  580. Function PadZero(Var s: String; n: byte): Boolean;
  581. Begin
  582. PadZero:=TRUE;
  583. { Do some error checking first }
  584. if Length(s) = n then
  585. exit
  586. else
  587. if Length(s) > n then
  588. Begin
  589. PadZero:=FALSE;
  590. delete(s,n+1,length(s));
  591. exit;
  592. end
  593. else
  594. PadZero:=TRUE;
  595. { Fill it up with the specified character }
  596. fillchar(s[length(s)+1],n-1,#0);
  597. s[0]:=chr(n);
  598. end;
  599. {****************************************************************************
  600. TOperand
  601. ****************************************************************************}
  602. constructor TOperand.Create;
  603. begin
  604. size:=OS_NO;
  605. hasproc:=false;
  606. hastype:=false;
  607. hasvar:=false;
  608. FillChar(Opr,sizeof(Opr),0);
  609. end;
  610. destructor TOperand.destroy;
  611. begin
  612. end;
  613. Procedure TOperand.SetSize(_size:longint;force:boolean);
  614. begin
  615. if force or
  616. ((size = OS_NO) and (_size<=16)) then
  617. Begin
  618. case _size of
  619. 1 : size:=OS_8;
  620. 2 : size:=OS_16{ could be S_IS};
  621. 4 : size:=OS_32{ could be S_IL or S_FS};
  622. 8 : size:=OS_64{ could be S_D or S_FL};
  623. 10 : size:=OS_F80;
  624. 16 : size:=OS_128;
  625. end;
  626. end;
  627. end;
  628. Procedure TOperand.SetCorrectSize(opcode:tasmop);
  629. begin
  630. end;
  631. function TOperand.SetupResult:boolean;
  632. begin
  633. SetupResult:=false;
  634. { replace by correct offset. }
  635. with current_procinfo.procdef do
  636. if (not is_void(returndef)) then
  637. begin
  638. if (m_tp7 in current_settings.modeswitches) and
  639. not (df_generic in defoptions) and
  640. (po_assembler in procoptions) and
  641. (not paramanager.ret_in_param(returndef,current_procinfo.procdef)) then
  642. begin
  643. message(asmr_e_cannot_use_RESULT_here);
  644. exit;
  645. end;
  646. SetupResult:=setupvar('result',false)
  647. end
  648. else
  649. message(asmr_e_void_function);
  650. end;
  651. Function TOperand.SetupSelf:boolean;
  652. Begin
  653. SetupSelf:=false;
  654. if assigned(current_structdef) then
  655. SetupSelf:=setupvar('self',false)
  656. else
  657. Message(asmr_e_cannot_use_SELF_outside_a_method);
  658. end;
  659. Function TOperand.SetupOldEBP:boolean;
  660. Begin
  661. SetupOldEBP:=false;
  662. if current_procinfo.procdef.parast.symtablelevel>normal_function_level then
  663. SetupOldEBP:=setupvar('parentframe',false)
  664. else
  665. Message(asmr_e_cannot_use_OLDEBP_outside_nested_procedure);
  666. end;
  667. Function TOperand.SetupVar(const s:string;GetOffset : boolean): Boolean;
  668. function symtable_has_localvarsyms(st:TSymtable):boolean;
  669. var
  670. sym : tsym;
  671. i : longint;
  672. begin
  673. result:=false;
  674. for i:=0 to st.SymList.Count-1 do
  675. begin
  676. sym:=tsym(st.SymList[i]);
  677. if sym.typ=localvarsym then
  678. begin
  679. result:=true;
  680. exit;
  681. end;
  682. end;
  683. end;
  684. procedure setconst(l:aint);
  685. begin
  686. { We return the address of the field, just like Delphi/TP }
  687. case opr.typ of
  688. OPR_NONE :
  689. begin
  690. opr.typ:=OPR_CONSTANT;
  691. opr.val:=l;
  692. end;
  693. OPR_CONSTANT :
  694. inc(opr.val,l);
  695. OPR_REFERENCE :
  696. inc(opr.ref.offset,l);
  697. OPR_LOCAL :
  698. inc(opr.localsymofs,l);
  699. else
  700. Message(asmr_e_invalid_operand_type);
  701. end;
  702. end;
  703. procedure setvarsize(sym: tabstractvarsym);
  704. var
  705. harrdef: tarraydef;
  706. l: asizeint;
  707. begin
  708. case sym.vardef.typ of
  709. orddef,
  710. enumdef,
  711. pointerdef,
  712. procvardef,
  713. floatdef :
  714. SetSize(sym.getsize,false);
  715. arraydef :
  716. begin
  717. { for arrays try to get the element size, take care of
  718. multiple indexes }
  719. harrdef:=tarraydef(sym.vardef);
  720. { calc array size }
  721. if is_special_array(harrdef) then
  722. l := -1
  723. else
  724. l := harrdef.size;
  725. case opr.typ of
  726. OPR_REFERENCE: opr.varsize := l;
  727. OPR_LOCAL: opr.localvarsize := l;
  728. else
  729. ;
  730. end;
  731. while assigned(harrdef.elementdef) and
  732. (harrdef.elementdef.typ=arraydef) do
  733. harrdef:=tarraydef(harrdef.elementdef);
  734. if not is_packed_array(harrdef) then
  735. SetSize(harrdef.elesize,false)
  736. else
  737. if (harrdef.elepackedbitsize mod 8) = 0 then
  738. SetSize(harrdef.elepackedbitsize div 8,false);
  739. end;
  740. recorddef:
  741. case opr.typ of
  742. OPR_REFERENCE: opr.varsize := sym.getsize;
  743. OPR_LOCAL: opr.localvarsize := sym.getsize;
  744. else
  745. ;
  746. end;
  747. else
  748. ;
  749. end;
  750. end;
  751. { search and sets up the correct fields in the Instr record }
  752. { for the NON-constant identifier passed to the routine. }
  753. { if not found returns FALSE. }
  754. var
  755. sym : tsym;
  756. srsymtable : TSymtable;
  757. {$ifdef x86}
  758. segreg,
  759. {$endif x86}
  760. indexreg : tregister;
  761. plist : ppropaccesslistitem;
  762. size_set_from_absolute : boolean = false;
  763. { offset fixup (in bytes), coming from an absolute declaration with an index
  764. (e.g. var tralala: word absolute moo[5]; ) }
  765. absoffset: asizeint=0;
  766. harrdef: tarraydef;
  767. tmpprocinfo: tprocinfo;
  768. Begin
  769. SetupVar:=false;
  770. asmsearchsym(s,sym,srsymtable);
  771. if sym = nil then
  772. exit;
  773. if sym.typ=absolutevarsym then
  774. begin
  775. case tabsolutevarsym(sym).abstyp of
  776. tovar:
  777. begin
  778. { Only support simple loads }
  779. plist:=tabsolutevarsym(sym).ref.firstsym;
  780. if assigned(plist) and
  781. (plist^.sltype=sl_load) then
  782. begin
  783. setvarsize(tabstractvarsym(sym));
  784. size_set_from_absolute:=true;
  785. sym:=plist^.sym;
  786. { Check if address can be resolved, but only if not an array }
  787. if (sym.typ=absolutevarsym) and (tabsolutevarsym(sym).abstyp=toaddr) and not
  788. (assigned(plist^.next) and (plist^.next^.sltype=sl_vec)) then
  789. begin
  790. initref;
  791. opr.ref.offset:=tabsolutevarsym(sym).addroffset;
  792. hasvar:=true;
  793. Result:=true;
  794. exit;
  795. end;
  796. { resolve the chain of array indexes (if there are any) }
  797. harrdef:=nil;
  798. while assigned(plist^.next) do
  799. begin
  800. plist:=plist^.next;
  801. if (plist^.sltype=sl_vec) and (tabstractvarsym(sym).vardef.typ=arraydef) then
  802. begin
  803. if harrdef=nil then
  804. harrdef:=tarraydef(tabstractvarsym(sym).vardef)
  805. else if harrdef.elementdef.typ=arraydef then
  806. harrdef:=tarraydef(harrdef.elementdef)
  807. else
  808. begin
  809. Message(asmr_e_unsupported_symbol_type);
  810. exit;
  811. end;
  812. if is_special_array(harrdef) then
  813. begin
  814. Message(asmr_e_unsupported_symbol_type);
  815. exit;
  816. end;
  817. if not is_packed_array(harrdef) then
  818. Inc(absoffset,asizeint(Int64(plist^.value-harrdef.lowrange))*harrdef.elesize)
  819. else if (Int64(plist^.value-harrdef.lowrange)*harrdef.elepackedbitsize mod 8)=0 then
  820. Inc(absoffset,asizeint(Int64(plist^.value-harrdef.lowrange)*harrdef.elepackedbitsize div 8))
  821. else
  822. Message(asmr_e_packed_element);
  823. end
  824. else
  825. begin
  826. Message(asmr_e_unsupported_symbol_type);
  827. exit;
  828. end;
  829. end;
  830. end
  831. else
  832. begin
  833. Message(asmr_e_unsupported_symbol_type);
  834. exit;
  835. end;
  836. end;
  837. toaddr:
  838. begin
  839. initref;
  840. opr.ref.offset:=tabsolutevarsym(sym).addroffset;
  841. setvarsize(tabstractvarsym(sym));
  842. size_set_from_absolute:=true;
  843. hasvar:=true;
  844. Result:=true;
  845. exit;
  846. end;
  847. else
  848. begin
  849. Message(asmr_e_unsupported_symbol_type);
  850. exit;
  851. end;
  852. end;
  853. end;
  854. case sym.typ of
  855. fieldvarsym :
  856. begin
  857. if not tabstractrecordsymtable(sym.owner).is_packed then
  858. setconst(absoffset+tfieldvarsym(sym).fieldoffset)
  859. else if tfieldvarsym(sym).fieldoffset mod 8 = 0 then
  860. setconst(absoffset+tfieldvarsym(sym).fieldoffset div 8)
  861. else
  862. Message(asmr_e_packed_element);
  863. if not size_set_from_absolute then
  864. setvarsize(tabstractvarsym(sym));
  865. hasvar:=true;
  866. SetupVar:=true;
  867. end;
  868. staticvarsym,
  869. localvarsym,
  870. paravarsym :
  871. begin
  872. { we always assume in asm statements that }
  873. { that the variable is valid. }
  874. tabstractvarsym(sym).varstate:=vs_readwritten;
  875. inc(tabstractvarsym(sym).refs);
  876. { variable can't be placed in a register }
  877. tabstractvarsym(sym).varregable:=vr_none;
  878. { and anything may happen with its address }
  879. tabstractvarsym(sym).addr_taken:=true;
  880. case sym.typ of
  881. staticvarsym :
  882. begin
  883. initref;
  884. opr.ref.symbol:=current_asmdata.RefAsmSymbol(tstaticvarsym(sym).mangledname,AT_DATA);
  885. Inc(opr.ref.offset,absoffset);
  886. end;
  887. paravarsym,
  888. localvarsym :
  889. begin
  890. tmpprocinfo:=current_procinfo;
  891. while assigned(tmpprocinfo) do
  892. begin
  893. if (sym.owner=tmpprocinfo.procdef.localst) or
  894. (sym.owner=tmpprocinfo.procdef.parast) then
  895. begin
  896. tmpprocinfo.procdef.init_paraloc_info(calleeside);
  897. break;
  898. end;
  899. tmpprocinfo:=tmpprocinfo.parent;
  900. end;
  901. if opr.typ=OPR_REFERENCE then
  902. begin
  903. {$ifdef x86}
  904. segreg:=opr.ref.segment;
  905. {$endif x86}
  906. indexreg:=opr.ref.base;
  907. if opr.ref.index<>NR_NO then
  908. begin
  909. if indexreg=NR_NO then
  910. indexreg:=opr.ref.index
  911. else
  912. Message(asmr_e_multiple_index);
  913. end;
  914. end
  915. else
  916. begin
  917. {$ifdef x86}
  918. segreg:=NR_NO;
  919. {$endif x86}
  920. indexreg:=NR_NO;
  921. end;
  922. opr.typ:=OPR_LOCAL;
  923. if assigned(current_procinfo.parent) and
  924. not(po_inline in current_procinfo.procdef.procoptions) and
  925. (sym.owner<>current_procinfo.procdef.localst) and
  926. (sym.owner<>current_procinfo.procdef.parast) and
  927. (current_procinfo.procdef.localst.symtablelevel>normal_function_level) and
  928. symtable_has_localvarsyms(current_procinfo.procdef.localst) then
  929. message1(asmr_e_local_para_unreachable,s);
  930. opr.localsym:=tabstractnormalvarsym(sym);
  931. opr.localsymofs:=absoffset;
  932. {$ifdef x86}
  933. opr.localsegment:=segreg;
  934. {$endif x86}
  935. opr.localindexreg:=indexreg;
  936. opr.localscale:=0;
  937. opr.localgetoffset:=GetOffset;
  938. if paramanager.push_addr_param(tabstractvarsym(sym).varspez,tabstractvarsym(sym).vardef,current_procinfo.procdef.proccalloption) then
  939. SetSize(sizeof(pint),false);
  940. end;
  941. else
  942. ;
  943. end;
  944. if not size_set_from_absolute then
  945. setvarsize(tabstractvarsym(sym));
  946. hasvar:=true;
  947. SetupVar:=true;
  948. Exit;
  949. end;
  950. constsym :
  951. begin
  952. if tconstsym(sym).consttyp=constord then
  953. begin
  954. setconst(tconstsym(sym).value.valueord.svalue);
  955. SetupVar:=true;
  956. Exit;
  957. end;
  958. end;
  959. typesym :
  960. begin
  961. if ttypesym(sym).typedef.typ in [recorddef,objectdef] then
  962. begin
  963. setconst(0);
  964. SetupVar:=TRUE;
  965. Exit;
  966. end;
  967. end;
  968. procsym :
  969. begin
  970. if Tprocsym(sym).ProcdefList.Count>1 then
  971. Message(asmr_w_calling_overload_func);
  972. case opr.typ of
  973. OPR_REFERENCE:
  974. begin
  975. opr.ref.symbol:=current_asmdata.RefAsmSymbol(tprocdef(tprocsym(sym).ProcdefList[0]).mangledname,AT_FUNCTION);
  976. Inc(opr.ref.offset,absoffset);
  977. {$ifdef i8086}
  978. opr.ref_farproc_entry:=is_proc_far(tprocdef(tprocsym(sym).ProcdefList[0]))
  979. and not (po_interrupt in tprocdef(tprocsym(sym).ProcdefList[0]).procoptions);
  980. {$endif i8086}
  981. end;
  982. OPR_NONE:
  983. begin
  984. opr.typ:=OPR_SYMBOL;
  985. opr.symbol:=current_asmdata.RefAsmSymbol(tprocdef(tprocsym(sym).ProcdefList[0]).mangledname,AT_FUNCTION);
  986. {$ifdef i8086}
  987. opr.sym_farproc_entry:=is_proc_far(tprocdef(tprocsym(sym).ProcdefList[0]))
  988. and not (po_interrupt in tprocdef(tprocsym(sym).ProcdefList[0]).procoptions);
  989. {$endif i8086}
  990. opr.symofs:=absoffset;
  991. end;
  992. else
  993. Message(asmr_e_invalid_operand_type);
  994. end;
  995. hasproc:=true;
  996. hasvar:=true;
  997. SetupVar:=TRUE;
  998. Exit;
  999. end;
  1000. {$ifdef i8086}
  1001. labelsym :
  1002. begin
  1003. case opr.typ of
  1004. OPR_REFERENCE:
  1005. begin
  1006. opr.ref.symbol:=current_asmdata.RefAsmSymbol(tlabelsym(sym).mangledname,AT_FUNCTION);
  1007. Inc(opr.ref.offset,absoffset);
  1008. if opr.ref.segment=NR_NO then
  1009. opr.ref.segment:=NR_CS;
  1010. end;
  1011. else
  1012. begin
  1013. Message(asmr_e_unsupported_symbol_type);
  1014. exit;
  1015. end;
  1016. end;
  1017. haslabelref:=true;
  1018. hasvar:=true;
  1019. SetupVar:=TRUE;
  1020. Exit;
  1021. end
  1022. {$endif i8086}
  1023. else
  1024. begin
  1025. Message(asmr_e_unsupported_symbol_type);
  1026. exit;
  1027. end;
  1028. end;
  1029. end;
  1030. procedure TOperand.InitRef;
  1031. {*********************************************************************}
  1032. { Description: This routine first check if the opcode is of }
  1033. { type OPR_NONE, or OPR_REFERENCE , if not it gives out an error. }
  1034. { If the operandtype = OPR_NONE or <> OPR_REFERENCE then it sets up }
  1035. { the operand type to OPR_REFERENCE, as well as setting up the ref }
  1036. { to point to the default segment. }
  1037. {*********************************************************************}
  1038. var
  1039. l : aint;
  1040. hsymofs : aint;
  1041. hsymbol : tasmsymbol;
  1042. reg : tregister;
  1043. hsym_farprocentry: Boolean;
  1044. Begin
  1045. case opr.typ of
  1046. OPR_REFERENCE :
  1047. exit;
  1048. OPR_CONSTANT :
  1049. begin
  1050. l:=opr.val;
  1051. opr.typ:=OPR_REFERENCE;
  1052. Fillchar(opr.ref,sizeof(treference),0);
  1053. opr.Ref.Offset:=l;
  1054. opr.varsize:=0;
  1055. opr.constoffset:=0;
  1056. opr.ref_farproc_entry:=false;
  1057. end;
  1058. OPR_NONE :
  1059. begin
  1060. opr.typ:=OPR_REFERENCE;
  1061. opr.varsize:=0;
  1062. opr.constoffset:=0;
  1063. opr.ref_farproc_entry:=false;
  1064. Fillchar(opr.ref,sizeof(treference),0);
  1065. end;
  1066. OPR_REGISTER :
  1067. begin
  1068. reg:=opr.reg;
  1069. opr.typ:=OPR_REFERENCE;
  1070. opr.varsize:=0;
  1071. opr.constoffset:=0;
  1072. opr.ref_farproc_entry:=false;
  1073. Fillchar(opr.ref,sizeof(treference),0);
  1074. opr.Ref.base:=reg;
  1075. end;
  1076. OPR_SYMBOL :
  1077. begin
  1078. hsymbol:=opr.symbol;
  1079. hsymofs:=opr.symofs;
  1080. hsym_farprocentry:=opr.sym_farproc_entry;
  1081. opr.typ:=OPR_REFERENCE;
  1082. opr.varsize:=0;
  1083. opr.constoffset:=0;
  1084. Fillchar(opr.ref,sizeof(treference),0);
  1085. opr.ref.symbol:=hsymbol;
  1086. opr.ref.offset:=hsymofs;
  1087. opr.ref_farproc_entry:=hsym_farprocentry;
  1088. end;
  1089. else
  1090. InitRefError;
  1091. end;
  1092. end;
  1093. procedure TOperand.InitRefConvertLocal;
  1094. var
  1095. localvarsize,localconstoffset: asizeint;
  1096. localsym:tabstractnormalvarsym;
  1097. localsymofs:aint;
  1098. {$ifdef x86}
  1099. localsegment,
  1100. {$endif x86}
  1101. localindexreg:tregister;
  1102. localscale:byte;
  1103. begin
  1104. if opr.typ=OPR_LOCAL then
  1105. begin
  1106. if AsmRegisterPara(opr.localsym) and
  1107. not opr.localgetoffset then
  1108. begin
  1109. localvarsize:=opr.localvarsize;
  1110. localconstoffset:=opr.localconstoffset;
  1111. localsym:=opr.localsym;
  1112. localsymofs:=opr.localsymofs;
  1113. {$ifdef x86}
  1114. localsegment:=opr.localsegment;
  1115. {$endif x86}
  1116. localindexreg:=opr.localindexreg;
  1117. localscale:=opr.localscale;
  1118. opr.typ:=OPR_REFERENCE;
  1119. hasvar:=false;
  1120. Fillchar(opr.ref,sizeof(treference),0);
  1121. opr.varsize:=localvarsize;
  1122. opr.constoffset:=localconstoffset;
  1123. opr.ref_farproc_entry:=false;
  1124. opr.ref.base:=tparavarsym(localsym).paraloc[calleeside].Location^.register;
  1125. opr.ref.offset:=localsymofs;
  1126. {$ifdef x86}
  1127. opr.ref.segment:=localsegment;
  1128. {$endif x86}
  1129. opr.ref.index:=localindexreg;
  1130. opr.ref.scalefactor:=localscale;
  1131. end
  1132. else
  1133. InitRefError;
  1134. end
  1135. else
  1136. InitRef;
  1137. end;
  1138. procedure TOperand.InitRefError;
  1139. begin
  1140. Message(asmr_e_invalid_operand_type);
  1141. { Recover }
  1142. opr.typ:=OPR_REFERENCE;
  1143. opr.varsize:=0;
  1144. opr.constoffset:=0;
  1145. opr.ref_farproc_entry:=false;
  1146. Fillchar(opr.ref,sizeof(treference),0);
  1147. end;
  1148. Function TOperand.CheckOperand(ins : TInstruction): boolean;
  1149. {*********************************************************************}
  1150. { Description: This routine checks if the operand is of }
  1151. { valid, and returns false if it isn't. Does nothing by default. }
  1152. {*********************************************************************}
  1153. begin
  1154. result:=true;
  1155. end;
  1156. {****************************************************************************
  1157. TInstruction
  1158. ****************************************************************************}
  1159. constructor TInstruction.create(optype : tcoperand);
  1160. var
  1161. i : longint;
  1162. Begin
  1163. { these field are set to 0 anyways by the constructor helper (FK)
  1164. Opcode:=A_NONE;
  1165. Condition:=C_NONE;
  1166. Ops:=0;
  1167. }
  1168. filepos:=current_filepos;
  1169. for i:=1 to max_operands do
  1170. Operands[i]:=optype.create;
  1171. Labeled:=false;
  1172. end;
  1173. destructor TInstruction.destroy;
  1174. var
  1175. i : longint;
  1176. Begin
  1177. for i:=1 to max_operands do
  1178. Operands[i].free;
  1179. end;
  1180. function TInstruction.ConcatInstruction(p:TAsmList) : tai;
  1181. var
  1182. ai : taicpu;
  1183. i : longint;
  1184. begin
  1185. for i:=1 to Ops do
  1186. operands[i].CheckOperand(self);
  1187. ai:=taicpu.op_none(opcode);
  1188. ai.fileinfo:=filepos;
  1189. ai.Ops:=Ops;
  1190. ai.Allocate_oper(Ops);
  1191. for i:=1 to Ops do
  1192. with operands[i].opr do
  1193. begin
  1194. case typ of
  1195. OPR_CONSTANT :
  1196. ai.loadconst(i-1,val);
  1197. OPR_REGISTER:
  1198. ai.loadreg(i-1,reg);
  1199. OPR_SYMBOL:
  1200. ai.loadsymbol(i-1,symbol,symofs);
  1201. OPR_LOCAL :
  1202. begin
  1203. ai.loadlocal(i-1,localsym,localsymofs,localindexreg,
  1204. localscale,localgetoffset,localforceref);
  1205. {$ifdef x86}
  1206. ai.oper[i-1]^.localoper^.localsegment:=localsegment;
  1207. {$endif x86}
  1208. end;
  1209. OPR_REFERENCE:
  1210. ai.loadref(i-1,ref);
  1211. {$ifdef m68k}
  1212. OPR_REGSET:
  1213. ai.loadregset(i-1,regsetdata,regsetaddr,regsetfpu);
  1214. OPR_REGPAIR:
  1215. ai.loadregpair(i-1,reghi,reglo);
  1216. {$endif}
  1217. {$ifdef ARM}
  1218. OPR_REGSET:
  1219. ai.loadregset(i-1,regtype,subreg,regset,usermode);
  1220. OPR_MODEFLAGS:
  1221. ai.loadmodeflags(i-1,flags);
  1222. OPR_SPECIALREG:
  1223. ai.loadspecialreg(i-1,specialreg,specialregflags);
  1224. {$endif ARM}
  1225. {$if defined(arm) or defined(aarch64)}
  1226. OPR_SHIFTEROP:
  1227. ai.loadshifterop(i-1,shifterop);
  1228. OPR_COND:
  1229. ai.loadconditioncode(i-1,cc);
  1230. {$endif arm or aarch64}
  1231. {$ifdef aarch64}
  1232. OPR_REGSET:
  1233. ai.loadregset(i-1,basereg,nregs,regsetindex);
  1234. OPR_INDEXEDREG:
  1235. ai.loadindexedreg(i-1,indexedreg,regindex);
  1236. {$endif aarch64}
  1237. {$if defined(riscv32) or defined(riscv64)}
  1238. OPR_FENCEFLAGS:
  1239. ai.loadfenceflags(i-1,fenceflags);
  1240. {$endif riscv32 or riscv64}
  1241. {$ifdef wasm32}
  1242. OPR_FLOATCONSTANT:
  1243. case opcode of
  1244. a_f32_const:
  1245. ai.loadsingle(i-1,floatval);
  1246. a_f64_const:
  1247. ai.loaddouble(i-1,floatval);
  1248. else
  1249. internalerror(2024072001);
  1250. end;
  1251. OPR_FUNCTYPE:
  1252. ai.loadfunctype(i-1,functype);
  1253. {$endif wasm32}
  1254. { ignore wrong operand }
  1255. OPR_NONE:
  1256. ;
  1257. else
  1258. internalerror(200501051);
  1259. end;
  1260. end;
  1261. ai.SetCondition(condition);
  1262. { Concat the opcode or give an error }
  1263. if assigned(ai) then
  1264. p.concat(ai)
  1265. else
  1266. Message(asmr_e_invalid_opcode_and_operand);
  1267. result:=ai;
  1268. end;
  1269. {****************************************************************************
  1270. Symbol table helper routines
  1271. ****************************************************************************}
  1272. procedure AddAbsoluteSymRefs(sym: tabsolutevarsym); forward;
  1273. procedure MaybeAddSymRef(sym: tsym);
  1274. begin
  1275. case sym.typ of
  1276. absolutevarsym:
  1277. AddAbsoluteSymRefs(tabsolutevarsym(sym));
  1278. staticvarsym:
  1279. if not(vo_is_external in tstaticvarsym(sym).varoptions) then
  1280. cnodeutils.RegisterUsedAsmSym(current_asmdata.RefAsmSymbol(sym.mangledname,AT_DATA),tstaticvarsym(sym).vardef,true);
  1281. procsym:
  1282. begin
  1283. { if it's a pure assembler routine, the definition of the symbol will also
  1284. be in assembler and it can't be removed by the compiler (and if we mark
  1285. it as used anyway, clang will get into trouble) }
  1286. if not(po_assembler in tprocdef(tprocsym(sym).ProcdefList[0]).procoptions) and
  1287. not(po_external in tprocdef(tprocsym(sym).ProcdefList[0]).procoptions) then
  1288. cnodeutils.RegisterUsedAsmSym(current_asmdata.RefAsmSymbol(tprocdef(tprocsym(sym).ProcdefList[0]).mangledname,AT_FUNCTION),tprocdef(tprocsym(sym).ProcdefList[0]),true);
  1289. end;
  1290. else
  1291. ;
  1292. end;
  1293. end;
  1294. procedure AddAbsoluteSymRefs(sym: tabsolutevarsym);
  1295. var
  1296. symlist: ppropaccesslistitem;
  1297. begin
  1298. case sym.abstyp of
  1299. toaddr:
  1300. ;
  1301. toasm:
  1302. begin
  1303. cnodeutils.RegisterUsedAsmSym(current_asmdata.RefAsmSymbol(sym.mangledname,AT_DATA),sym.vardef,true);
  1304. end;
  1305. tovar:
  1306. begin
  1307. symlist:=tabsolutevarsym(sym).ref.firstsym;
  1308. repeat
  1309. case symlist^.sltype of
  1310. sl_load:
  1311. MaybeAddSymRef(symlist^.sym);
  1312. sl_subscript,
  1313. sl_absolutetype,
  1314. sl_typeconv,
  1315. sl_vec:
  1316. ;
  1317. else
  1318. internalerror(2009031401);
  1319. end;
  1320. symlist:=symlist^.next;
  1321. until not assigned(symlist);
  1322. end;
  1323. end;
  1324. end;
  1325. procedure AsmSearchSym(const s:string;out srsym:tsym;out srsymtable:TSymtable);
  1326. var
  1327. i : integer;
  1328. begin
  1329. i:=pos('.',s);
  1330. { allow unit.identifier }
  1331. if i>1 then
  1332. begin
  1333. searchsym(Copy(s,1,i-1),srsym,srsymtable);
  1334. if assigned(srsym) then
  1335. begin
  1336. if (srsym.typ=unitsym) and
  1337. (srsym.owner.symtabletype in [staticsymtable,globalsymtable]) and
  1338. srsym.owner.iscurrentunit then
  1339. searchsym_in_module(tunitsym(srsym).module,Copy(s,i+1,255),srsym,srsymtable)
  1340. else
  1341. begin
  1342. srsym:=nil;
  1343. srsymtable:=nil;
  1344. end;
  1345. end;
  1346. end
  1347. else
  1348. searchsym(s,srsym,srsymtable);
  1349. { in asm routines, the function result variable, that matches the function
  1350. name should be avoided, because:
  1351. 1) there's already a @Result directive (even in TP7) that can be used, if
  1352. you want to access the function result
  1353. 2) there's no other way to disambiguate between the function result variable
  1354. and the function's address (using asm syntax only)
  1355. This fixes code, such as:
  1356. function test1: word;
  1357. begin
  1358. asm
  1359. mov ax, offset test1
  1360. end;
  1361. end;
  1362. and makes it work in a consistent manner as this code:
  1363. procedure test2;
  1364. begin
  1365. asm
  1366. mov ax, offset test2
  1367. end;
  1368. end; }
  1369. if assigned(srsym) and
  1370. assigned(srsymtable) and
  1371. (srsym.typ=absolutevarsym) and
  1372. (vo_is_funcret in tabsolutevarsym(srsym).varoptions) and
  1373. (srsymtable.symtabletype=localsymtable) and
  1374. assigned(srsymtable.defowner) and
  1375. (srsymtable.defowner.typ=procdef) and
  1376. (tprocdef(srsymtable.defowner).procsym.name=tabsolutevarsym(srsym).Name) then
  1377. begin
  1378. srsym:=tprocdef(srsymtable.defowner).procsym;
  1379. srsymtable:=srsym.Owner;
  1380. end;
  1381. { llvm can't catch symbol references from inline assembler blocks }
  1382. if assigned(srsym) then
  1383. MaybeAddSymRef(srsym);
  1384. end;
  1385. Function SearchType(const hs:string;out size:tcgint): Boolean;
  1386. var
  1387. srsym : tsym;
  1388. srsymtable : TSymtable;
  1389. begin
  1390. result:=false;
  1391. size:=0;
  1392. asmsearchsym(hs,srsym,srsymtable);
  1393. if assigned(srsym) and
  1394. (srsym.typ=typesym) then
  1395. begin
  1396. size:=ttypesym(srsym).typedef.size;
  1397. result:=true;
  1398. end;
  1399. end;
  1400. Function SearchRecordType(const s:string): boolean;
  1401. var
  1402. srsym : tsym;
  1403. srsymtable : TSymtable;
  1404. Begin
  1405. SearchRecordType:=false;
  1406. { Check the constants in symtable }
  1407. asmsearchsym(s,srsym,srsymtable);
  1408. if srsym <> nil then
  1409. Begin
  1410. case srsym.typ of
  1411. typesym :
  1412. begin
  1413. if ttypesym(srsym).typedef.typ in [recorddef,objectdef] then
  1414. begin
  1415. SearchRecordType:=true;
  1416. exit;
  1417. end;
  1418. end;
  1419. fieldvarsym :
  1420. begin
  1421. if (tfieldvarsym(srsym).vardef.typ in [recorddef,objectdef]) then
  1422. begin
  1423. SearchRecordType:=true;
  1424. exit;
  1425. end;
  1426. end;
  1427. else
  1428. ;
  1429. end;
  1430. end;
  1431. end;
  1432. Function SearchIConstant(const s:string; var l:tcgint): boolean;
  1433. {**********************************************************************}
  1434. { Description: Searches for a CONSTANT of name s in either the local }
  1435. { symbol list, then in the global symbol list, and returns the value }
  1436. { of that constant in l. Returns TRUE if successfull, if not found, }
  1437. { or if the constant is not of correct type, then returns FALSE }
  1438. { Remarks: Also handle TRUE and FALSE returning in those cases 1 and 0 }
  1439. { respectively. }
  1440. {**********************************************************************}
  1441. var
  1442. srsym : tsym;
  1443. srsymtable : TSymtable;
  1444. Begin
  1445. SearchIConstant:=false;
  1446. { check for TRUE or FALSE reserved words first }
  1447. if s = 'TRUE' then
  1448. Begin
  1449. SearchIConstant:=TRUE;
  1450. l:=1;
  1451. exit;
  1452. end;
  1453. if s = 'FALSE' then
  1454. Begin
  1455. SearchIConstant:=TRUE;
  1456. l:=0;
  1457. exit;
  1458. end;
  1459. { Check the constants in symtable }
  1460. asmsearchsym(s,srsym,srsymtable);
  1461. if srsym <> nil then
  1462. Begin
  1463. case srsym.typ of
  1464. constsym :
  1465. begin
  1466. if tconstsym(srsym).consttyp=constord then
  1467. Begin
  1468. l:=tconstsym(srsym).value.valueord.svalue;
  1469. SearchIConstant:=TRUE;
  1470. exit;
  1471. end;
  1472. end;
  1473. enumsym:
  1474. Begin
  1475. l:=tenumsym(srsym).value;
  1476. SearchIConstant:=TRUE;
  1477. exit;
  1478. end;
  1479. else
  1480. ;
  1481. end;
  1482. end;
  1483. end;
  1484. function AsmRegisterPara(sym: tabstractnormalvarsym): boolean;
  1485. begin
  1486. result:=
  1487. (po_assembler in current_procinfo.procdef.procoptions) and
  1488. (sym.typ=paravarsym) and
  1489. (tparavarsym(sym).paraloc[calleeside].Location^.Loc=LOC_REGISTER);
  1490. end;
  1491. Function GetRecordOffsetSize(s:string;out Offset: tcgint;out Size:tcgint; out mangledname: string; needvmtofs: boolean; out hastypecast: boolean):boolean;
  1492. { search and returns the offset and size of records/objects of the base }
  1493. { with field name setup in field. }
  1494. { returns FALSE if not found. }
  1495. { used when base is a variable or a typed constant name. }
  1496. var
  1497. st : TSymtable;
  1498. harrdef : tarraydef;
  1499. sym : tsym;
  1500. srsymtable : TSymtable;
  1501. i : longint;
  1502. base : string;
  1503. procdef: tprocdef;
  1504. Begin
  1505. GetRecordOffsetSize:=FALSE;
  1506. Offset:=0;
  1507. Size:=0;
  1508. mangledname:='';
  1509. hastypecast:=false;
  1510. i:=pos('.',s);
  1511. if i=0 then
  1512. i:=255;
  1513. base:=Copy(s,1,i-1);
  1514. delete(s,1,i);
  1515. if base='SELF' then
  1516. st:=current_structdef.symtable
  1517. else
  1518. begin
  1519. asmsearchsym(base,sym,srsymtable);
  1520. { allow unitname.identifier }
  1521. if assigned(sym) and (sym.typ=unitsym) then
  1522. begin
  1523. i:=pos('.',s);
  1524. if i=0 then
  1525. i:=255;
  1526. base:=base+'.'+Copy(s,1,i-1);
  1527. delete(s,1,i);
  1528. asmsearchsym(base,sym,srsymtable);
  1529. end;
  1530. st:=nil;
  1531. { we can start with a var,type,typedconst }
  1532. if assigned(sym) then
  1533. case sym.typ of
  1534. staticvarsym,
  1535. localvarsym,
  1536. paravarsym :
  1537. st:=Tabstractvarsym(sym).vardef.GetSymtable(gs_record);
  1538. typesym :
  1539. st:=Ttypesym(sym).typedef.GetSymtable(gs_record);
  1540. else
  1541. ;
  1542. end
  1543. else
  1544. s:='';
  1545. end;
  1546. { now walk all recordsymtables }
  1547. while assigned(st) and (s<>'') do
  1548. begin
  1549. { load next field in base }
  1550. i:=pos('.',s);
  1551. if i=0 then
  1552. i:=255;
  1553. base:=Copy(s,1,i-1);
  1554. delete(s,1,i);
  1555. sym:=search_struct_member(tabstractrecorddef(st.defowner),base);
  1556. if not assigned(sym) then
  1557. begin
  1558. Message(asmr_e_unknown_field);
  1559. GetRecordOffsetSize:=false;
  1560. exit;
  1561. end;
  1562. st:=nil;
  1563. case sym.typ of
  1564. fieldvarsym :
  1565. with Tfieldvarsym(sym) do
  1566. begin
  1567. if not tabstractrecordsymtable(sym.owner).is_packed then
  1568. inc(Offset,fieldoffset)
  1569. else if tfieldvarsym(sym).fieldoffset mod 8 = 0 then
  1570. inc(Offset,fieldoffset div 8)
  1571. else
  1572. Message(asmr_e_packed_element);
  1573. size:=getsize;
  1574. case vardef.typ of
  1575. arraydef :
  1576. begin
  1577. { for arrays try to get the element size, take care of
  1578. multiple indexes }
  1579. harrdef:=tarraydef(vardef);
  1580. while assigned(harrdef.elementdef) and
  1581. (harrdef.elementdef.typ=arraydef) do
  1582. harrdef:=tarraydef(harrdef.elementdef);
  1583. if not is_packed_array(harrdef) then
  1584. size:=harrdef.elesize
  1585. else
  1586. begin
  1587. if (harrdef.elepackedbitsize mod 8) <> 0 then
  1588. Message(asmr_e_packed_element);
  1589. size := (harrdef.elepackedbitsize + 7) div 8;
  1590. end;
  1591. end;
  1592. recorddef :
  1593. st:=trecorddef(vardef).symtable;
  1594. objectdef :
  1595. st:=tobjectdef(vardef).symtable;
  1596. else
  1597. ;
  1598. end;
  1599. end;
  1600. procsym:
  1601. begin
  1602. st:=nil;
  1603. if Tprocsym(sym).ProcdefList.Count>1 then
  1604. Message(asmr_w_calling_overload_func);
  1605. procdef:=tprocdef(tprocsym(sym).ProcdefList[0]);
  1606. if (not needvmtofs) then
  1607. begin
  1608. mangledname:=procdef.mangledname;
  1609. end
  1610. else
  1611. begin
  1612. { can only get the vmtoffset of virtual methods }
  1613. if not(po_virtualmethod in procdef.procoptions) or
  1614. is_objectpascal_helper(procdef.struct) then
  1615. Message1(asmr_e_no_vmtoffset_possible,FullTypeName(procdef,nil))
  1616. else
  1617. begin
  1618. { size = sizeof(target_system_pointer) }
  1619. size:=sizeof(pint);
  1620. offset:=tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber)
  1621. end;
  1622. end;
  1623. { if something comes after the procsym, it's invalid assembler syntax }
  1624. GetRecordOffsetSize:=(s='');
  1625. exit;
  1626. end;
  1627. else
  1628. ;
  1629. end;
  1630. end;
  1631. { Support Field.Type as typecasting }
  1632. if (st=nil) and (s<>'') then
  1633. begin
  1634. asmsearchsym(s,sym,srsymtable);
  1635. if assigned(sym) and (sym.typ=typesym) then
  1636. begin
  1637. size:=ttypesym(sym).typedef.size;
  1638. s:='';
  1639. hastypecast:=true;
  1640. end;
  1641. end;
  1642. GetRecordOffsetSize:=(s='');
  1643. end;
  1644. Function SearchLabel(const s: string; var hl: tasmlabel;emit:boolean): boolean;
  1645. var
  1646. sym : tsym;
  1647. srsymtable : TSymtable;
  1648. hs : string;
  1649. Begin
  1650. hl:=nil;
  1651. SearchLabel:=false;
  1652. { Check for pascal labels, which are case insensetive }
  1653. hs:=upper(s);
  1654. asmsearchsym(hs,sym,srsymtable);
  1655. if sym=nil then
  1656. exit;
  1657. case sym.typ of
  1658. labelsym :
  1659. begin
  1660. if symtablestack.top.symtablelevel<>srsymtable.symtablelevel then
  1661. begin
  1662. {$ifndef LLVM}
  1663. { LLVM compiler requires that the static label RawThunkEnd
  1664. in packages/rtl-objpas/src/rtti.pp unit is set to nonlocal }
  1665. if (srsymtable.symtabletype=globalsymtable) or create_smartlink_library then
  1666. {$endif LLVM}
  1667. Tlabelsym(sym).nonlocal:=true;
  1668. if emit then
  1669. include(current_procinfo.flags,pi_has_interproclabel);
  1670. end;
  1671. if not(assigned(tlabelsym(sym).asmblocklabel)) then
  1672. if Tlabelsym(sym).nonlocal then
  1673. current_asmdata.getglobaljumplabel(tlabelsym(sym).asmblocklabel)
  1674. else
  1675. current_asmdata.getjumplabel(tlabelsym(sym).asmblocklabel);
  1676. hl:=tlabelsym(sym).asmblocklabel;
  1677. if emit then
  1678. begin
  1679. if tlabelsym(sym).defined then
  1680. Message(sym_e_label_already_defined);
  1681. tlabelsym(sym).defined:=true;
  1682. hl.defined_in_asmstatement:=true
  1683. end
  1684. else
  1685. tlabelsym(sym).used:=true;
  1686. SearchLabel:=true;
  1687. end;
  1688. else
  1689. ;
  1690. end;
  1691. end;
  1692. {*************************************************************************}
  1693. { Instruction Generation Utilities }
  1694. {*************************************************************************}
  1695. Procedure ConcatString(p : TAsmList;s:string);
  1696. {*********************************************************************}
  1697. { PROCEDURE ConcatString(s:string); }
  1698. { Description: This routine adds the character chain pointed to in }
  1699. { s to the instruction linked list. }
  1700. {*********************************************************************}
  1701. Begin
  1702. p.concat(Tai_string.Create(s));
  1703. end;
  1704. Procedure ConcatConstant(p: TAsmList; value: tcgint; constsize:byte);
  1705. {*********************************************************************}
  1706. { Description: This routine adds the value constant to the current }
  1707. { instruction linked list. }
  1708. {*********************************************************************}
  1709. var
  1710. rangelo,rangehi : int64;
  1711. Begin
  1712. case constsize of
  1713. 1 :
  1714. begin
  1715. p.concat(Tai_const.Create_8bit(byte(value)));
  1716. rangelo:=low(shortint);
  1717. rangehi:=high(byte);
  1718. end;
  1719. 2 :
  1720. begin
  1721. p.concat(Tai_const.Create_16bit(word(value)));
  1722. rangelo:=low(smallint);
  1723. rangehi:=high(word);
  1724. end;
  1725. 4 :
  1726. begin
  1727. p.concat(Tai_const.Create_32bit(longint(value)));
  1728. rangelo:=low(longint);
  1729. rangehi:=high(cardinal);
  1730. end;
  1731. 8 :
  1732. begin
  1733. p.concat(Tai_const.Create_64bit(int64(value)));
  1734. rangelo:=0;
  1735. rangehi:=0;
  1736. end;
  1737. else
  1738. internalerror(200405011);
  1739. end;
  1740. { check for out of bounds }
  1741. if (rangelo<>0) and
  1742. ((value>rangehi) or (value<rangelo)) then
  1743. Message(asmr_e_constant_out_of_bounds);
  1744. end;
  1745. Procedure ConcatConstSymbol(p : TAsmList;const sym,endsym:string;symtyp:tasmsymtype;l:tcgint;constsize:byte;isofs:boolean);
  1746. begin
  1747. {$ifdef i8086}
  1748. { 'DW xx' as well as 'DW OFFSET xx' are just near pointers }
  1749. if constsize=2 then
  1750. p.concat(Tai_const.Createname_near(sym,l))
  1751. else if constsize=4 then
  1752. begin
  1753. if isofs then
  1754. begin
  1755. { 'DD OFFSET xx' is a 32-bit offset; since we don't produce 32-bit
  1756. relocations yet, just do a 16-bit one and set the high word to 0 }
  1757. p.concat(Tai_const.Createname_near(sym,l));
  1758. p.concat(Tai_const.Create_16bit(0));
  1759. end
  1760. else
  1761. { 'DD xx' is a far pointer }
  1762. p.concat(Tai_const.Createname_far(sym,l));
  1763. end
  1764. else
  1765. internalerror(2018020701);
  1766. {$else i8086}
  1767. p.concat(Tai_const.Createname(sym,l));
  1768. {$endif i8086}
  1769. end;
  1770. Procedure ConcatRealConstant(p : TAsmList;value: bestreal; real_typ : tfloattype);
  1771. {***********************************************************************}
  1772. { PROCEDURE ConcatRealConstant(value: bestreal; real_typ : tfloattype); }
  1773. { Description: This routine adds the value constant to the current }
  1774. { instruction linked list. }
  1775. { real_typ -> indicates the type of the real data to initialize: }
  1776. { s32real -> create a single node. }
  1777. { s64real -> create a double node. }
  1778. { s80real -> create an extended node. }
  1779. { s64bit -> create a comp node. }
  1780. { f32bit -> create a fixed node. (not used normally) }
  1781. {***********************************************************************}
  1782. Begin
  1783. case real_typ of
  1784. s32real : p.concat(tai_realconst.create_s32real(value));
  1785. s64real :
  1786. {$ifdef ARM}
  1787. if is_double_hilo_swapped then
  1788. p.concat(tai_realconst.create_s64real_hiloswapped(value))
  1789. else
  1790. {$endif ARM}
  1791. p.concat(tai_realconst.create_s64real(value));
  1792. s80real : p.concat(tai_realconst.create_s80real(value,s80floattype.size));
  1793. sc80real : p.concat(tai_realconst.create_s80real(value,sc80floattype.size));
  1794. s64comp : p.concat(tai_realconst.create_s64compreal(trunc(value)));
  1795. else
  1796. internalerror(2014050608);
  1797. end;
  1798. end;
  1799. Procedure ConcatLabel(p: TAsmList;var l : tasmlabel);
  1800. {*********************************************************************}
  1801. { PROCEDURE ConcatLabel }
  1802. { Description: This routine either emits a label or a labeled }
  1803. { instruction to the linked list of instructions. }
  1804. {*********************************************************************}
  1805. begin
  1806. p.concat(Tai_label.Create(l));
  1807. end;
  1808. procedure ConcatAlign(p:TAsmList;l:tcgint);
  1809. {*********************************************************************}
  1810. { PROCEDURE ConcatPublic }
  1811. { Description: This routine emits an global definition to the }
  1812. { linked list of instructions.(used by AT&T styled asm) }
  1813. {*********************************************************************}
  1814. begin
  1815. p.concat(Tai_align.Create(l));
  1816. end;
  1817. procedure ConcatPublic(p:TAsmList;const s : string);
  1818. {*********************************************************************}
  1819. { PROCEDURE ConcatPublic }
  1820. { Description: This routine emits an global definition to the }
  1821. { linked list of instructions.(used by AT&T styled asm) }
  1822. {*********************************************************************}
  1823. begin
  1824. p.concat(Tai_symbol.Createname_global(s,AT_LABEL,0,voidcodepointertype));
  1825. end;
  1826. procedure ConcatLocal(p:TAsmList;const s : string);
  1827. {*********************************************************************}
  1828. { PROCEDURE ConcatLocal }
  1829. { Description: This routine emits an local definition to the }
  1830. { linked list of instructions. }
  1831. {*********************************************************************}
  1832. begin
  1833. p.concat(Tai_symbol.Createname(s,AT_LABEL,0,voidcodepointertype));
  1834. end;
  1835. end.