assemble.pas 71 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188
  1. {
  2. Copyright (c) 1998-2004 by Peter Vreman
  3. This unit handles the assemblerfile write and assembler calls of FPC
  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. {# @abstract(This unit handles the assembler file write and assembler calls of FPC)
  18. Handles the calls to the actual external assemblers, as well as the generation
  19. of object files for smart linking. Also contains the base class for writing
  20. the assembler statements to file.
  21. }
  22. unit assemble;
  23. {$i fpcdefs.inc}
  24. interface
  25. uses
  26. SysUtils,
  27. systems,globtype,globals,aasmbase,aasmtai,aasmdata,ogbase,owbase,finput;
  28. const
  29. { maximum of aasmoutput lists there will be }
  30. maxoutputlists = ord(high(tasmlisttype))+1;
  31. { buffer size for writing the .s file }
  32. AsmOutSize=32768*4;
  33. type
  34. TAssembler=class(TObject)
  35. public
  36. {filenames}
  37. path : TPathStr;
  38. name : string;
  39. AsmFileName, { current .s and .o file }
  40. ObjFileName,
  41. ppufilename : TPathStr;
  42. asmprefix : string;
  43. SmartAsm : boolean;
  44. SmartFilesCount,
  45. SmartHeaderCount : longint;
  46. Constructor Create(smart:boolean);virtual;
  47. Destructor Destroy;override;
  48. procedure NextSmartName(place:tcutplace);
  49. procedure MakeObject;virtual;abstract;
  50. end;
  51. TExternalAssembler = class;
  52. IExternalAssemblerOutputFileDecorator=interface
  53. function LinePrefix: AnsiString;
  54. function LinePostfix: AnsiString;
  55. function LineFilter(const s: AnsiString): AnsiString;
  56. end;
  57. TExternalAssemblerOutputFile=class
  58. private
  59. fdecorator: IExternalAssemblerOutputFileDecorator;
  60. protected
  61. owner: TExternalAssembler;
  62. {outfile}
  63. AsmSize,
  64. AsmStartSize,
  65. outcnt : longint;
  66. outbuf : array[0..AsmOutSize-1] of char;
  67. outfile : file;
  68. fioerror : boolean;
  69. linestart: boolean;
  70. Procedure AsmClear;
  71. Procedure MaybeAddLinePrefix;
  72. Procedure MaybeAddLinePostfix;
  73. Procedure AsmWriteAnsiStringUnfiltered(const s: ansistring);
  74. public
  75. Constructor Create(_owner: TExternalAssembler);
  76. Procedure RemoveAsm;virtual;
  77. Procedure AsmFlush;
  78. { mark the current output as the "empty" state (i.e., it only contains
  79. headers/directives etc }
  80. Procedure MarkEmpty;
  81. { clears the assembler output if nothing was added since it was marked
  82. as empty, and returns whether it was empty }
  83. function ClearIfEmpty: boolean;
  84. { these routines will write the filtered version of their argument
  85. according to the current decorator }
  86. procedure AsmWriteFiltered(const c:char);
  87. procedure AsmWriteFiltered(const s:string);
  88. procedure AsmWriteFiltered(const s:ansistring);
  89. procedure AsmWriteFiltered(p:pchar; len: longint);
  90. {# Write a string to the assembler file }
  91. Procedure AsmWrite(const c:char);
  92. Procedure AsmWrite(const s:string);
  93. Procedure AsmWrite(const s:ansistring);
  94. {# Write a string to the assembler file }
  95. Procedure AsmWritePChar(p:pchar);
  96. {# Write a string to the assembler file followed by a new line }
  97. Procedure AsmWriteLn(const c:char);
  98. Procedure AsmWriteLn(const s:string);
  99. Procedure AsmWriteLn(const s:ansistring);
  100. {# Write a new line to the assembler file }
  101. Procedure AsmLn; virtual;
  102. procedure AsmCreate(Aplace:tcutplace);
  103. procedure AsmClose;
  104. property ioerror: boolean read fioerror;
  105. property decorator: IExternalAssemblerOutputFileDecorator read fdecorator write fdecorator;
  106. end;
  107. {# This is the base class which should be overridden for each each
  108. assembler writer. It is used to actually assembler a file,
  109. and write the output to the assembler file.
  110. }
  111. TExternalAssembler=class(TAssembler)
  112. private
  113. { output writer }
  114. fwriter: TExternalAssemblerOutputFile;
  115. ffreewriter: boolean;
  116. procedure CreateSmartLinkPath(const s:TPathStr);
  117. protected
  118. {input source info}
  119. lastfileinfo : tfileposinfo;
  120. infile,
  121. lastinfile : tinputfile;
  122. {last section type written}
  123. lastsectype : TAsmSectionType;
  124. procedure WriteSourceLine(hp: tailineinfo);
  125. procedure WriteTempalloc(hp: tai_tempalloc);
  126. procedure WriteRealConstAsBytes(hp: tai_realconst; const dbdir: string; do_line: boolean);
  127. function single2str(d : single) : string; virtual;
  128. function double2str(d : double) : string; virtual;
  129. function extended2str(e : extended) : string; virtual;
  130. Function DoPipe:boolean;
  131. public
  132. {# Returns the complete path and executable name of the assembler
  133. program.
  134. It first tries looking in the UTIL directory if specified,
  135. otherwise it searches in the free pascal binary directory, in
  136. the current working directory and then in the directories
  137. in the $PATH environment.}
  138. Function FindAssembler:string;
  139. {# Actually does the call to the assembler file. Returns false
  140. if the assembling of the file failed.}
  141. Function CallAssembler(const command:string; const para:TCmdStr):Boolean;
  142. Function DoAssemble:boolean;virtual;
  143. {# This routine should be overridden for each assembler, it is used
  144. to actually write the abstract assembler stream to file.}
  145. procedure WriteTree(p:TAsmList);virtual;
  146. {# This routine should be overridden for each assembler, it is used
  147. to actually write all the different abstract assembler streams
  148. by calling for each stream type, the @var(WriteTree) method.}
  149. procedure WriteAsmList;virtual;
  150. {# Constructs the command line for calling the assembler }
  151. function MakeCmdLine: TCmdStr; virtual;
  152. public
  153. Constructor Create(smart:boolean);override;
  154. Constructor CreateWithWriter(wr: TExternalAssemblerOutputFile; freewriter, smart: boolean);
  155. procedure MakeObject;override;
  156. destructor Destroy; override;
  157. property writer: TExternalAssemblerOutputFile read fwriter;
  158. end;
  159. TExternalAssemblerClass = class of TExternalAssembler;
  160. { TInternalAssembler }
  161. TInternalAssembler=class(TAssembler)
  162. private
  163. FCObjOutput : TObjOutputclass;
  164. FCInternalAr : TObjectWriterClass;
  165. { the aasmoutput lists that need to be processed }
  166. lists : byte;
  167. list : array[1..maxoutputlists] of TAsmList;
  168. { current processing }
  169. currlistidx : byte;
  170. currlist : TAsmList;
  171. procedure WriteStab(p:pchar);
  172. function MaybeNextList(var hp:Tai):boolean;
  173. function SetIndirectToSymbol(hp: Tai; const indirectname: string): Boolean;
  174. function TreePass0(hp:Tai):Tai;
  175. function TreePass1(hp:Tai):Tai;
  176. function TreePass2(hp:Tai):Tai;
  177. procedure writetree;
  178. procedure writetreesmart;
  179. protected
  180. ObjData : TObjData;
  181. ObjOutput : tObjOutput;
  182. property CObjOutput:TObjOutputclass read FCObjOutput write FCObjOutput;
  183. property CInternalAr : TObjectWriterClass read FCInternalAr write FCInternalAr;
  184. public
  185. constructor create(smart:boolean);override;
  186. destructor destroy;override;
  187. procedure MakeObject;override;
  188. end;
  189. TAssemblerClass = class of TAssembler;
  190. Procedure GenerateAsm(smart:boolean);
  191. Procedure OnlyAsm;
  192. procedure RegisterAssembler(const r:tasminfo;c:TAssemblerClass);
  193. Implementation
  194. uses
  195. {$ifdef hasunix}
  196. unix,
  197. {$endif}
  198. cutils,cfileutl,
  199. {$ifdef memdebug}
  200. cclasses,
  201. {$endif memdebug}
  202. script,fmodule,verbose,
  203. {$if defined(m68k) or defined(arm)}
  204. cpuinfo,
  205. {$endif m68k or arm}
  206. aasmcpu,
  207. owar,owomflib
  208. ;
  209. var
  210. CAssembler : array[tasm] of TAssemblerClass;
  211. function fixline(s:string):string;
  212. {
  213. return s with all leading and ending spaces and tabs removed
  214. }
  215. var
  216. i,j,k : integer;
  217. begin
  218. i:=length(s);
  219. while (i>0) and (s[i] in [#9,' ']) do
  220. dec(i);
  221. j:=1;
  222. while (j<i) and (s[j] in [#9,' ']) do
  223. inc(j);
  224. for k:=j to i do
  225. if s[k] in [#0..#31,#127..#255] then
  226. s[k]:='.';
  227. fixline:=Copy(s,j,i-j+1);
  228. end;
  229. {*****************************************************************************
  230. TAssembler
  231. *****************************************************************************}
  232. Constructor TAssembler.Create(smart:boolean);
  233. begin
  234. { load start values }
  235. AsmFileName:=current_module.AsmFilename;
  236. ObjFileName:=current_module.ObjFileName;
  237. name:=Lower(current_module.modulename^);
  238. path:=current_module.outputpath;
  239. asmprefix := current_module.asmprefix^;
  240. if current_module.outputpath = '' then
  241. ppufilename := ''
  242. else
  243. ppufilename := current_module.ppufilename;
  244. SmartAsm:=smart;
  245. SmartFilesCount:=0;
  246. SmartHeaderCount:=0;
  247. SmartLinkOFiles.Clear;
  248. end;
  249. Destructor TAssembler.Destroy;
  250. begin
  251. end;
  252. procedure TAssembler.NextSmartName(place:tcutplace);
  253. var
  254. s : string;
  255. begin
  256. inc(SmartFilesCount);
  257. if SmartFilesCount>999999 then
  258. Message(asmw_f_too_many_asm_files);
  259. case place of
  260. cut_begin :
  261. begin
  262. inc(SmartHeaderCount);
  263. s:=asmprefix+tostr(SmartHeaderCount)+'h';
  264. end;
  265. cut_normal :
  266. s:=asmprefix+tostr(SmartHeaderCount)+'s';
  267. cut_end :
  268. s:=asmprefix+tostr(SmartHeaderCount)+'t';
  269. end;
  270. AsmFileName:=Path+FixFileName(s+tostr(SmartFilesCount)+target_info.asmext);
  271. ObjFileName:=Path+FixFileName(s+tostr(SmartFilesCount)+target_info.objext);
  272. { insert in container so it can be cleared after the linking }
  273. SmartLinkOFiles.Insert(ObjFileName);
  274. end;
  275. {*****************************************************************************
  276. TAssemblerOutputFile
  277. *****************************************************************************}
  278. procedure TExternalAssemblerOutputFile.RemoveAsm;
  279. var
  280. g : file;
  281. begin
  282. if cs_asm_leave in current_settings.globalswitches then
  283. exit;
  284. if cs_asm_extern in current_settings.globalswitches then
  285. AsmRes.AddDeleteCommand(owner.AsmFileName)
  286. else
  287. begin
  288. assign(g,owner.AsmFileName);
  289. {$push} {$I-}
  290. erase(g);
  291. {$pop}
  292. if ioresult<>0 then;
  293. end;
  294. end;
  295. Procedure TExternalAssemblerOutputFile.AsmFlush;
  296. begin
  297. if outcnt>0 then
  298. begin
  299. { suppress i/o error }
  300. {$push} {$I-}
  301. BlockWrite(outfile,outbuf,outcnt);
  302. {$pop}
  303. fioerror:=fioerror or (ioresult<>0);
  304. outcnt:=0;
  305. end;
  306. end;
  307. procedure TExternalAssemblerOutputFile.MarkEmpty;
  308. begin
  309. AsmStartSize:=AsmSize
  310. end;
  311. function TExternalAssemblerOutputFile.ClearIfEmpty: boolean;
  312. begin
  313. result:=AsmSize=AsmStartSize;
  314. if result then
  315. AsmClear;
  316. end;
  317. procedure TExternalAssemblerOutputFile.AsmWriteFiltered(const c: char);
  318. begin
  319. MaybeAddLinePrefix;
  320. AsmWriteAnsiStringUnfiltered(decorator.LineFilter(c));
  321. end;
  322. procedure TExternalAssemblerOutputFile.AsmWriteFiltered(const s: string);
  323. begin
  324. MaybeAddLinePrefix;
  325. AsmWriteAnsiStringUnfiltered(decorator.LineFilter(s));
  326. end;
  327. procedure TExternalAssemblerOutputFile.AsmWriteFiltered(const s: ansistring);
  328. begin
  329. MaybeAddLinePrefix;
  330. AsmWriteAnsiStringUnfiltered(decorator.LineFilter(s));
  331. end;
  332. procedure TExternalAssemblerOutputFile.AsmWriteFiltered(p: pchar; len: longint);
  333. var
  334. s: ansistring;
  335. begin
  336. MaybeAddLinePrefix;
  337. setlength(s,len);
  338. move(p^,s[1],len);
  339. AsmWriteAnsiStringUnfiltered(decorator.LineFilter(s));
  340. end;
  341. Procedure TExternalAssemblerOutputFile.AsmClear;
  342. begin
  343. outcnt:=0;
  344. end;
  345. procedure TExternalAssemblerOutputFile.MaybeAddLinePrefix;
  346. begin
  347. if assigned(decorator) and
  348. linestart then
  349. begin
  350. AsmWriteAnsiStringUnfiltered(decorator.LinePrefix);
  351. linestart:=false;
  352. end;
  353. end;
  354. procedure TExternalAssemblerOutputFile.MaybeAddLinePostfix;
  355. begin
  356. if assigned(decorator) and
  357. not linestart then
  358. begin
  359. AsmWriteAnsiStringUnfiltered(decorator.LinePostfix);
  360. linestart:=true;
  361. end;
  362. end;
  363. procedure TExternalAssemblerOutputFile.AsmWriteAnsiStringUnfiltered(const s: ansistring);
  364. var
  365. StartIndex, ToWrite: longint;
  366. begin
  367. if s='' then
  368. exit;
  369. if OutCnt+length(s)>=AsmOutSize then
  370. AsmFlush;
  371. StartIndex:=1;
  372. ToWrite:=length(s);
  373. while ToWrite>AsmOutSize do
  374. begin
  375. Move(s[StartIndex],OutBuf[OutCnt],AsmOutSize);
  376. inc(OutCnt,AsmOutSize);
  377. inc(AsmSize,AsmOutSize);
  378. AsmFlush;
  379. inc(StartIndex,AsmOutSize);
  380. dec(ToWrite,AsmOutSize);
  381. end;
  382. Move(s[StartIndex],OutBuf[OutCnt],ToWrite);
  383. inc(OutCnt,ToWrite);
  384. inc(AsmSize,ToWrite);
  385. end;
  386. constructor TExternalAssemblerOutputFile.Create(_owner: TExternalAssembler);
  387. begin
  388. owner:=_owner;
  389. linestart:=true;
  390. end;
  391. Procedure TExternalAssemblerOutputFile.AsmWrite(const c: char);
  392. begin
  393. if assigned(decorator) then
  394. AsmWriteFiltered(c)
  395. else
  396. begin
  397. if OutCnt+1>=AsmOutSize then
  398. AsmFlush;
  399. OutBuf[OutCnt]:=c;
  400. inc(OutCnt);
  401. inc(AsmSize);
  402. end;
  403. end;
  404. Procedure TExternalAssemblerOutputFile.AsmWrite(const s:string);
  405. begin
  406. if s='' then
  407. exit;
  408. if assigned(decorator) then
  409. AsmWriteFiltered(s)
  410. else
  411. begin
  412. if OutCnt+length(s)>=AsmOutSize then
  413. AsmFlush;
  414. Move(s[1],OutBuf[OutCnt],length(s));
  415. inc(OutCnt,length(s));
  416. inc(AsmSize,length(s));
  417. end;
  418. end;
  419. Procedure TExternalAssemblerOutputFile.AsmWrite(const s:ansistring);
  420. begin
  421. if s='' then
  422. exit;
  423. if assigned(decorator) then
  424. AsmWriteFiltered(s)
  425. else
  426. AsmWriteAnsiStringUnfiltered(s);
  427. end;
  428. procedure TExternalAssemblerOutputFile.AsmWriteLn(const c: char);
  429. begin
  430. AsmWrite(c);
  431. AsmLn;
  432. end;
  433. Procedure TExternalAssemblerOutputFile.AsmWriteLn(const s:string);
  434. begin
  435. AsmWrite(s);
  436. AsmLn;
  437. end;
  438. Procedure TExternalAssemblerOutputFile.AsmWriteLn(const s: ansistring);
  439. begin
  440. AsmWrite(s);
  441. AsmLn;
  442. end;
  443. Procedure TExternalAssemblerOutputFile.AsmWritePChar(p:pchar);
  444. var
  445. i,j : longint;
  446. begin
  447. i:=StrLen(p);
  448. if i=0 then
  449. exit;
  450. if assigned(decorator) then
  451. AsmWriteFiltered(p,i)
  452. else
  453. begin
  454. j:=i;
  455. while j>0 do
  456. begin
  457. i:=min(j,AsmOutSize);
  458. if OutCnt+i>=AsmOutSize then
  459. AsmFlush;
  460. Move(p[0],OutBuf[OutCnt],i);
  461. inc(OutCnt,i);
  462. inc(AsmSize,i);
  463. dec(j,i);
  464. p:=pchar(@p[i]);
  465. end;
  466. end;
  467. end;
  468. Procedure TExternalAssemblerOutputFile.AsmLn;
  469. begin
  470. MaybeAddLinePostfix;
  471. if OutCnt>=AsmOutSize-2 then
  472. AsmFlush;
  473. if (cs_link_on_target in current_settings.globalswitches) then
  474. begin
  475. OutBuf[OutCnt]:=target_info.newline[1];
  476. inc(OutCnt);
  477. inc(AsmSize);
  478. if length(target_info.newline)>1 then
  479. begin
  480. OutBuf[OutCnt]:=target_info.newline[2];
  481. inc(OutCnt);
  482. inc(AsmSize);
  483. end;
  484. end
  485. else
  486. begin
  487. OutBuf[OutCnt]:=source_info.newline[1];
  488. inc(OutCnt);
  489. inc(AsmSize);
  490. if length(source_info.newline)>1 then
  491. begin
  492. OutBuf[OutCnt]:=source_info.newline[2];
  493. inc(OutCnt);
  494. inc(AsmSize);
  495. end;
  496. end;
  497. end;
  498. procedure TExternalAssemblerOutputFile.AsmCreate(Aplace:tcutplace);
  499. {$ifdef hasamiga}
  500. var
  501. tempFileName: TPathStr;
  502. {$endif}
  503. begin
  504. if owner.SmartAsm then
  505. owner.NextSmartName(Aplace);
  506. {$ifdef hasamiga}
  507. { on Amiga/MorphOS try to redirect .s files to the T: assign, which is
  508. for temp files, and usually (default setting) located in the RAM: drive.
  509. This highly improves assembling speed for complex projects like the
  510. compiler itself, especially on hardware with slow disk I/O.
  511. Consider this as a poor man's pipe on Amiga, because real pipe handling
  512. would be much more complex and error prone to implement. (KB) }
  513. if (([cs_asm_extern,cs_asm_leave,cs_link_on_target] * current_settings.globalswitches) = []) then
  514. begin
  515. { try to have an unique name for the .s file }
  516. tempFileName:=HexStr(GetProcessID shr 4,7)+ExtractFileName(owner.AsmFileName);
  517. {$ifndef morphos}
  518. { old Amiga RAM: handler only allows filenames up to 30 char }
  519. if Length(tempFileName) < 30 then
  520. {$endif}
  521. owner.AsmFileName:='T:'+tempFileName;
  522. end;
  523. {$endif}
  524. {$ifdef hasunix}
  525. if owner.DoPipe then
  526. begin
  527. if owner.SmartAsm then
  528. begin
  529. if (owner.SmartFilesCount<=1) then
  530. Message1(exec_i_assembling_smart,owner.name);
  531. end
  532. else
  533. Message1(exec_i_assembling_pipe,owner.AsmFileName);
  534. POpen(outfile,maybequoted(owner.FindAssembler)+' '+owner.MakeCmdLine,'W');
  535. end
  536. else
  537. {$endif}
  538. begin
  539. Assign(outfile,owner.AsmFileName);
  540. {$push} {$I-}
  541. Rewrite(outfile,1);
  542. {$pop}
  543. if ioresult<>0 then
  544. begin
  545. fioerror:=true;
  546. Message1(exec_d_cant_create_asmfile,owner.AsmFileName);
  547. end;
  548. end;
  549. outcnt:=0;
  550. AsmSize:=0;
  551. AsmStartSize:=0;
  552. end;
  553. procedure TExternalAssemblerOutputFile.AsmClose;
  554. var
  555. f : file;
  556. FileAge : longint;
  557. begin
  558. AsmFlush;
  559. {$ifdef hasunix}
  560. if owner.DoPipe then
  561. begin
  562. if PClose(outfile) <> 0 then
  563. GenerateError;
  564. end
  565. else
  566. {$endif}
  567. begin
  568. {Touch Assembler time to ppu time is there is a ppufilename}
  569. if owner.ppufilename<>'' then
  570. begin
  571. Assign(f,owner.ppufilename);
  572. {$push} {$I-}
  573. reset(f,1);
  574. {$pop}
  575. if ioresult=0 then
  576. begin
  577. FileAge := FileGetDate(GetFileHandle(f));
  578. close(f);
  579. reset(outfile,1);
  580. FileSetDate(GetFileHandle(outFile),FileAge);
  581. end;
  582. end;
  583. close(outfile);
  584. end;
  585. end;
  586. {*****************************************************************************
  587. TExternalAssembler
  588. *****************************************************************************}
  589. function TExternalAssembler.single2str(d : single) : string;
  590. var
  591. hs : string;
  592. begin
  593. str(d,hs);
  594. { replace space with + }
  595. if hs[1]=' ' then
  596. hs[1]:='+';
  597. single2str:='0d'+hs
  598. end;
  599. function TExternalAssembler.double2str(d : double) : string;
  600. var
  601. hs : string;
  602. begin
  603. str(d,hs);
  604. { replace space with + }
  605. if hs[1]=' ' then
  606. hs[1]:='+';
  607. double2str:='0d'+hs
  608. end;
  609. function TExternalAssembler.extended2str(e : extended) : string;
  610. var
  611. hs : string;
  612. begin
  613. str(e,hs);
  614. { replace space with + }
  615. if hs[1]=' ' then
  616. hs[1]:='+';
  617. extended2str:='0d'+hs
  618. end;
  619. Function TExternalAssembler.DoPipe:boolean;
  620. begin
  621. DoPipe:=(cs_asm_pipe in current_settings.globalswitches) and
  622. (([cs_asm_extern,cs_asm_leave,cs_link_on_target] * current_settings.globalswitches) = []) and
  623. ((target_asm.id in [as_gas,as_ggas,as_darwin,as_powerpc_xcoff]));
  624. end;
  625. Constructor TExternalAssembler.Create(smart:boolean);
  626. begin
  627. inherited create(smart);
  628. if not assigned(fwriter) then
  629. begin
  630. fwriter:=TExternalAssemblerOutputFile.Create(self);
  631. ffreewriter:=true;
  632. end;
  633. if SmartAsm then
  634. begin
  635. path:=FixPath(ChangeFileExt(AsmFileName,target_info.smartext),false);
  636. CreateSmartLinkPath(path);
  637. end;
  638. end;
  639. constructor TExternalAssembler.CreateWithWriter(wr: TExternalAssemblerOutputFile; freewriter,smart: boolean);
  640. begin
  641. fwriter:=wr;
  642. ffreewriter:=freewriter;
  643. Create(smart);
  644. end;
  645. procedure TExternalAssembler.CreateSmartLinkPath(const s:TPathStr);
  646. procedure DeleteFilesWithExt(const AExt:string);
  647. var
  648. dir : TRawByteSearchRec;
  649. begin
  650. if findfirst(FixPath(s,false)+'*'+AExt,faAnyFile,dir) = 0 then
  651. begin
  652. repeat
  653. DeleteFile(s+source_info.dirsep+dir.name);
  654. until findnext(dir) <> 0;
  655. end;
  656. findclose(dir);
  657. end;
  658. var
  659. hs : TPathStr;
  660. begin
  661. if PathExists(s,false) then
  662. begin
  663. { the path exists, now we clean only all the .o and .s files }
  664. DeleteFilesWithExt(target_info.objext);
  665. DeleteFilesWithExt(target_info.asmext);
  666. end
  667. else
  668. begin
  669. hs:=s;
  670. if hs[length(hs)] in ['/','\'] then
  671. delete(hs,length(hs),1);
  672. {$push} {$I-}
  673. mkdir(hs);
  674. {$pop}
  675. if ioresult<>0 then;
  676. end;
  677. end;
  678. const
  679. lastas : byte=255;
  680. var
  681. LastASBin : TCmdStr;
  682. Function TExternalAssembler.FindAssembler:string;
  683. var
  684. asfound : boolean;
  685. UtilExe : string;
  686. begin
  687. asfound:=false;
  688. if cs_link_on_target in current_settings.globalswitches then
  689. begin
  690. { If linking on target, don't add any path PM }
  691. FindAssembler:=utilsprefix+ChangeFileExt(target_asm.asmbin,target_info.exeext);
  692. exit;
  693. end
  694. else
  695. UtilExe:=utilsprefix+ChangeFileExt(target_asm.asmbin,source_info.exeext);
  696. if lastas<>ord(target_asm.id) then
  697. begin
  698. lastas:=ord(target_asm.id);
  699. { is an assembler passed ? }
  700. if utilsdirectory<>'' then
  701. asfound:=FindFile(UtilExe,utilsdirectory,false,LastASBin);
  702. if not AsFound then
  703. asfound:=FindExe(UtilExe,false,LastASBin);
  704. if (not asfound) and not(cs_asm_extern in current_settings.globalswitches) then
  705. begin
  706. Message1(exec_e_assembler_not_found,LastASBin);
  707. current_settings.globalswitches:=current_settings.globalswitches+[cs_asm_extern];
  708. end;
  709. if asfound then
  710. Message1(exec_t_using_assembler,LastASBin);
  711. end;
  712. FindAssembler:=LastASBin;
  713. end;
  714. Function TExternalAssembler.CallAssembler(const command:string; const para:TCmdStr):Boolean;
  715. var
  716. DosExitCode : Integer;
  717. begin
  718. result:=true;
  719. if (cs_asm_extern in current_settings.globalswitches) then
  720. begin
  721. if SmartAsm then
  722. AsmRes.AddAsmCommand(command,para,Name+'('+TosTr(SmartFilesCount)+')')
  723. else
  724. AsmRes.AddAsmCommand(command,para,name);
  725. exit;
  726. end;
  727. try
  728. FlushOutput;
  729. DosExitCode:=RequotedExecuteProcess(command,para);
  730. if DosExitCode<>0
  731. then begin
  732. Message1(exec_e_error_while_assembling,tostr(dosexitcode));
  733. result:=false;
  734. end;
  735. except on E:EOSError do
  736. begin
  737. Message1(exec_e_cant_call_assembler,tostr(E.ErrorCode));
  738. current_settings.globalswitches:=current_settings.globalswitches+[cs_asm_extern];
  739. result:=false;
  740. end;
  741. end;
  742. end;
  743. Function TExternalAssembler.DoAssemble:boolean;
  744. begin
  745. DoAssemble:=true;
  746. if DoPipe then
  747. exit;
  748. if not(cs_asm_extern in current_settings.globalswitches) then
  749. begin
  750. if SmartAsm then
  751. begin
  752. if (SmartFilesCount<=1) then
  753. Message1(exec_i_assembling_smart,name);
  754. end
  755. else
  756. Message1(exec_i_assembling,name);
  757. end;
  758. if CallAssembler(FindAssembler,MakeCmdLine) then
  759. writer.RemoveAsm
  760. else
  761. begin
  762. DoAssemble:=false;
  763. GenerateError;
  764. end;
  765. end;
  766. function TExternalAssembler.MakeCmdLine: TCmdStr;
  767. begin
  768. result:=target_asm.asmcmd;
  769. {$ifdef arm}
  770. if (target_info.system=system_arm_darwin) then
  771. Replace(result,'$ARCH',lower(cputypestr[current_settings.cputype]));
  772. {$endif arm}
  773. if (cs_link_on_target in current_settings.globalswitches) then
  774. begin
  775. Replace(result,'$ASM',maybequoted(ScriptFixFileName(AsmFileName)));
  776. Replace(result,'$OBJ',maybequoted(ScriptFixFileName(ObjFileName)));
  777. end
  778. else
  779. begin
  780. {$ifdef hasunix}
  781. if DoPipe then
  782. Replace(result,'$ASM','')
  783. else
  784. {$endif}
  785. Replace(result,'$ASM',maybequoted(AsmFileName));
  786. Replace(result,'$OBJ',maybequoted(ObjFileName));
  787. end;
  788. if (cs_create_pic in current_settings.moduleswitches) then
  789. Replace(result,'$PIC','-KPIC')
  790. else
  791. Replace(result,'$PIC','');
  792. if (cs_asm_source in current_settings.globalswitches) then
  793. Replace(result,'$NOWARN','')
  794. else
  795. Replace(result,'$NOWARN','-W');
  796. Replace(result,'$EXTRAOPT',asmextraopt);
  797. end;
  798. procedure TExternalAssembler.WriteSourceLine(hp: tailineinfo);
  799. var
  800. module : tmodule;
  801. begin
  802. { load infile }
  803. if (lastfileinfo.moduleindex<>hp.fileinfo.moduleindex) or
  804. (lastfileinfo.fileindex<>hp.fileinfo.fileindex) then
  805. begin
  806. { in case of a generic the module can be different }
  807. if current_module.unit_index=hp.fileinfo.moduleindex then
  808. module:=current_module
  809. else
  810. module:=get_module(hp.fileinfo.moduleindex);
  811. { during the compilation of the system unit there are cases when
  812. the fileinfo contains just zeros => invalid }
  813. if assigned(module) then
  814. infile:=module.sourcefiles.get_file(hp.fileinfo.fileindex)
  815. else
  816. infile:=nil;
  817. if assigned(infile) then
  818. begin
  819. { open only if needed !! }
  820. if (cs_asm_source in current_settings.globalswitches) then
  821. infile.open;
  822. end;
  823. { avoid unnecessary reopens of the same file !! }
  824. lastfileinfo.fileindex:=hp.fileinfo.fileindex;
  825. lastfileinfo.moduleindex:=hp.fileinfo.moduleindex;
  826. { be sure to change line !! }
  827. lastfileinfo.line:=-1;
  828. end;
  829. { write source }
  830. if (cs_asm_source in current_settings.globalswitches) and
  831. assigned(infile) then
  832. begin
  833. if (infile<>lastinfile) then
  834. begin
  835. writer.AsmWriteLn(target_asm.comment+'['+infile.name+']');
  836. if assigned(lastinfile) then
  837. lastinfile.close;
  838. end;
  839. if (hp.fileinfo.line<>lastfileinfo.line) and
  840. (hp.fileinfo.line<infile.maxlinebuf) then
  841. begin
  842. if (hp.fileinfo.line<>0) and
  843. (infile.linebuf^[hp.fileinfo.line]>=0) then
  844. writer.AsmWriteLn(target_asm.comment+'['+tostr(hp.fileinfo.line)+'] '+
  845. fixline(infile.GetLineStr(hp.fileinfo.line)));
  846. { set it to a negative value !
  847. to make that is has been read already !! PM }
  848. if (infile.linebuf^[hp.fileinfo.line]>=0) then
  849. infile.linebuf^[hp.fileinfo.line]:=-infile.linebuf^[hp.fileinfo.line]-1;
  850. end;
  851. end;
  852. lastfileinfo:=hp.fileinfo;
  853. lastinfile:=infile;
  854. end;
  855. procedure TExternalAssembler.WriteTempalloc(hp: tai_tempalloc);
  856. begin
  857. {$ifdef EXTDEBUG}
  858. if assigned(hp.problem) then
  859. writer.AsmWriteLn(target_asm.comment+'Temp '+tostr(hp.temppos)+','+
  860. tostr(hp.tempsize)+' '+hp.problem^)
  861. else
  862. {$endif EXTDEBUG}
  863. writer.AsmWriteLn(target_asm.comment+'Temp '+tostr(hp.temppos)+','+
  864. tostr(hp.tempsize)+' '+tempallocstr[hp.allocation]);
  865. end;
  866. procedure TExternalAssembler.WriteRealConstAsBytes(hp: tai_realconst; const dbdir: string; do_line: boolean);
  867. var
  868. pdata: pbyte;
  869. index, step, swapmask, count: longint;
  870. ssingle: single;
  871. ddouble: double;
  872. ccomp: comp;
  873. {$if defined(cpuextended) and defined(FPC_HAS_TYPE_EXTENDED)}
  874. eextended: extended;
  875. {$endif cpuextended}
  876. begin
  877. if do_line then
  878. begin
  879. case tai_realconst(hp).realtyp of
  880. aitrealconst_s32bit:
  881. writer.AsmWriteLn(target_asm.comment+'value: '+single2str(tai_realconst(hp).value.s32val));
  882. aitrealconst_s64bit:
  883. writer.AsmWriteLn(target_asm.comment+'value: '+double2str(tai_realconst(hp).value.s64val));
  884. {$if defined(cpuextended) and defined(FPC_HAS_TYPE_EXTENDED)}
  885. { can't write full 80 bit floating point constants yet on non-x86 }
  886. aitrealconst_s80bit:
  887. writer.AsmWriteLn(target_asm.comment+'value: '+extended2str(tai_realconst(hp).value.s80val));
  888. {$endif cpuextended}
  889. aitrealconst_s64comp:
  890. writer.AsmWriteLn(target_asm.comment+'value: '+extended2str(tai_realconst(hp).value.s64compval));
  891. else
  892. internalerror(2014050604);
  893. end;
  894. end;
  895. writer.AsmWrite(dbdir);
  896. { generic float writing code: get start address of value, then write
  897. byte by byte. Can't use fields directly, because e.g ts64comp is
  898. defined as extended on x86 }
  899. case tai_realconst(hp).realtyp of
  900. aitrealconst_s32bit:
  901. begin
  902. ssingle:=single(tai_realconst(hp).value.s32val);
  903. pdata:=@ssingle;
  904. end;
  905. aitrealconst_s64bit:
  906. begin
  907. ddouble:=double(tai_realconst(hp).value.s64val);
  908. pdata:=@ddouble;
  909. end;
  910. {$if defined(cpuextended) and defined(FPC_HAS_TYPE_EXTENDED)}
  911. { can't write full 80 bit floating point constants yet on non-x86 }
  912. aitrealconst_s80bit:
  913. begin
  914. eextended:=extended(tai_realconst(hp).value.s80val);
  915. pdata:=@eextended;
  916. end;
  917. {$endif cpuextended}
  918. aitrealconst_s64comp:
  919. begin
  920. ccomp:=comp(tai_realconst(hp).value.s64compval);
  921. pdata:=@ccomp;
  922. end;
  923. else
  924. internalerror(2014051001);
  925. end;
  926. count:=tai_realconst(hp).datasize;
  927. { write bytes in inverse order if source and target endianess don't
  928. match }
  929. if source_info.endian<>target_info.endian then
  930. begin
  931. { go from back to front }
  932. index:=count-1;
  933. step:=-1;
  934. end
  935. else
  936. begin
  937. index:=0;
  938. step:=1;
  939. end;
  940. {$ifdef ARM}
  941. { ARM-specific: low and high dwords of a double may be swapped }
  942. if tai_realconst(hp).formatoptions=fo_hiloswapped then
  943. begin
  944. { only supported for double }
  945. if tai_realconst(hp).datasize<>8 then
  946. internalerror(2014050605);
  947. { switch bit of the index so that the words are written in
  948. the opposite order }
  949. swapmask:=4;
  950. end
  951. else
  952. {$endif ARM}
  953. swapmask:=0;
  954. repeat
  955. writer.AsmWrite(tostr(pdata[index xor swapmask]));
  956. inc(index,step);
  957. dec(count);
  958. if count<>0 then
  959. writer.AsmWrite(',');
  960. until count=0;
  961. { padding }
  962. for count:=tai_realconst(hp).datasize+1 to tai_realconst(hp).savesize do
  963. writer.AsmWrite(',0');
  964. writer.AsmLn;
  965. end;
  966. procedure TExternalAssembler.WriteTree(p:TAsmList);
  967. begin
  968. end;
  969. procedure TExternalAssembler.WriteAsmList;
  970. begin
  971. end;
  972. procedure TExternalAssembler.MakeObject;
  973. begin
  974. writer.AsmCreate(cut_normal);
  975. FillChar(lastfileinfo, sizeof(lastfileinfo), 0);
  976. lastfileinfo.line := -1;
  977. lastinfile := nil;
  978. lastsectype := sec_none;
  979. WriteAsmList;
  980. writer.AsmClose;
  981. if not(writer.ioerror) then
  982. DoAssemble;
  983. end;
  984. destructor TExternalAssembler.Destroy;
  985. begin
  986. if ffreewriter then
  987. writer.Free;
  988. inherited;
  989. end;
  990. {*****************************************************************************
  991. TInternalAssembler
  992. *****************************************************************************}
  993. constructor TInternalAssembler.create(smart:boolean);
  994. begin
  995. inherited create(smart);
  996. ObjOutput:=nil;
  997. ObjData:=nil;
  998. SmartAsm:=smart;
  999. end;
  1000. destructor TInternalAssembler.destroy;
  1001. begin
  1002. if assigned(ObjData) then
  1003. ObjData.free;
  1004. if assigned(ObjOutput) then
  1005. ObjOutput.free;
  1006. end;
  1007. procedure TInternalAssembler.WriteStab(p:pchar);
  1008. function consumecomma(var p:pchar):boolean;
  1009. begin
  1010. while (p^=' ') do
  1011. inc(p);
  1012. result:=(p^=',');
  1013. inc(p);
  1014. end;
  1015. function consumenumber(var p:pchar;out value:longint):boolean;
  1016. var
  1017. hs : string;
  1018. len,
  1019. code : integer;
  1020. begin
  1021. value:=0;
  1022. while (p^=' ') do
  1023. inc(p);
  1024. len:=0;
  1025. while (p^ in ['0'..'9']) do
  1026. begin
  1027. inc(len);
  1028. hs[len]:=p^;
  1029. inc(p);
  1030. end;
  1031. if len>0 then
  1032. begin
  1033. hs[0]:=chr(len);
  1034. val(hs,value,code);
  1035. end
  1036. else
  1037. code:=-1;
  1038. result:=(code=0);
  1039. end;
  1040. function consumeoffset(var p:pchar;out relocsym:tobjsymbol;out value:longint):boolean;
  1041. var
  1042. hs : string;
  1043. len,
  1044. code : integer;
  1045. pstart : pchar;
  1046. sym : tobjsymbol;
  1047. exprvalue : longint;
  1048. gotmin,
  1049. have_first_symbol,
  1050. have_second_symbol,
  1051. dosub : boolean;
  1052. begin
  1053. result:=false;
  1054. value:=0;
  1055. relocsym:=nil;
  1056. gotmin:=false;
  1057. have_first_symbol:=false;
  1058. have_second_symbol:=false;
  1059. repeat
  1060. dosub:=false;
  1061. exprvalue:=0;
  1062. if gotmin then
  1063. begin
  1064. dosub:=true;
  1065. gotmin:=false;
  1066. end;
  1067. while (p^=' ') do
  1068. inc(p);
  1069. case p^ of
  1070. #0 :
  1071. break;
  1072. ' ' :
  1073. inc(p);
  1074. '0'..'9' :
  1075. begin
  1076. len:=0;
  1077. while (p^ in ['0'..'9']) do
  1078. begin
  1079. inc(len);
  1080. hs[len]:=p^;
  1081. inc(p);
  1082. end;
  1083. hs[0]:=chr(len);
  1084. val(hs,exprvalue,code);
  1085. if code<>0 then
  1086. internalerror(200702251);
  1087. end;
  1088. '.','_',
  1089. 'A'..'Z',
  1090. 'a'..'z' :
  1091. begin
  1092. pstart:=p;
  1093. while not(p^ in [#0,' ','-','+']) do
  1094. inc(p);
  1095. len:=p-pstart;
  1096. if len>255 then
  1097. internalerror(200509187);
  1098. move(pstart^,hs[1],len);
  1099. hs[0]:=chr(len);
  1100. sym:=objdata.symbolref(hs);
  1101. { Second symbol? }
  1102. if assigned(relocsym) then
  1103. begin
  1104. if have_second_symbol then
  1105. internalerror(2007032201);
  1106. have_second_symbol:=true;
  1107. if not have_first_symbol then
  1108. internalerror(2007032202);
  1109. { second symbol should substracted to first }
  1110. if not dosub then
  1111. internalerror(2007032203);
  1112. if (relocsym.objsection<>sym.objsection) then
  1113. internalerror(2005091810);
  1114. exprvalue:=relocsym.address-sym.address;
  1115. relocsym:=nil;
  1116. dosub:=false;
  1117. end
  1118. else
  1119. begin
  1120. relocsym:=sym;
  1121. if assigned(sym.objsection) then
  1122. begin
  1123. { first symbol should be + }
  1124. if not have_first_symbol and dosub then
  1125. internalerror(2007032204);
  1126. have_first_symbol:=true;
  1127. end;
  1128. end;
  1129. end;
  1130. '+' :
  1131. begin
  1132. { nothing, by default addition is done }
  1133. inc(p);
  1134. end;
  1135. '-' :
  1136. begin
  1137. gotmin:=true;
  1138. inc(p);
  1139. end;
  1140. else
  1141. internalerror(200509189);
  1142. end;
  1143. if dosub then
  1144. dec(value,exprvalue)
  1145. else
  1146. inc(value,exprvalue);
  1147. until false;
  1148. result:=true;
  1149. end;
  1150. var
  1151. stabstrlen,
  1152. ofs,
  1153. nline,
  1154. nidx,
  1155. nother,
  1156. i : longint;
  1157. stab : TObjStabEntry;
  1158. relocsym : TObjSymbol;
  1159. pstr,
  1160. pcurr,
  1161. pendquote : pchar;
  1162. oldsec : TObjSection;
  1163. begin
  1164. pcurr:=nil;
  1165. pstr:=nil;
  1166. pendquote:=nil;
  1167. relocsym:=nil;
  1168. ofs:=0;
  1169. { Parse string part }
  1170. if (p[0]='"') then
  1171. begin
  1172. pstr:=@p[1];
  1173. { Ignore \" inside the string }
  1174. i:=1;
  1175. while not((p[i]='"') and (p[i-1]<>'\')) and
  1176. (p[i]<>#0) do
  1177. inc(i);
  1178. pendquote:=@p[i];
  1179. pendquote^:=#0;
  1180. pcurr:=@p[i+1];
  1181. if not consumecomma(pcurr) then
  1182. internalerror(200509181);
  1183. end
  1184. else
  1185. pcurr:=p;
  1186. { When in pass 1 then only alloc and leave }
  1187. if ObjData.currpass=1 then
  1188. begin
  1189. ObjData.StabsSec.Alloc(sizeof(TObjStabEntry));
  1190. if assigned(pstr) and (pstr[0]<>#0) then
  1191. ObjData.StabStrSec.Alloc(strlen(pstr)+1);
  1192. end
  1193. else
  1194. begin
  1195. { Stabs format: nidx,nother,nline[,offset] }
  1196. if not consumenumber(pcurr,nidx) then
  1197. internalerror(200509182);
  1198. if not consumecomma(pcurr) then
  1199. internalerror(200509183);
  1200. if not consumenumber(pcurr,nother) then
  1201. internalerror(200509184);
  1202. if not consumecomma(pcurr) then
  1203. internalerror(200509185);
  1204. if not consumenumber(pcurr,nline) then
  1205. internalerror(200509186);
  1206. if consumecomma(pcurr) then
  1207. consumeoffset(pcurr,relocsym,ofs);
  1208. { Generate stab entry }
  1209. if assigned(pstr) and (pstr[0]<>#0) then
  1210. begin
  1211. stabstrlen:=strlen(pstr);
  1212. {$ifdef optimizestabs}
  1213. StabStrEntry:=nil;
  1214. if (nidx=N_SourceFile) or (nidx=N_IncludeFile) then
  1215. begin
  1216. hs:=strpas(pstr);
  1217. StabstrEntry:=StabStrDict.Find(hs);
  1218. if not assigned(StabstrEntry) then
  1219. begin
  1220. StabstrEntry:=TStabStrEntry.Create(hs);
  1221. StabstrEntry:=StabStrSec.Size;
  1222. StabStrDict.Insert(StabstrEntry);
  1223. { generate new stab }
  1224. StabstrEntry:=nil;
  1225. end;
  1226. end;
  1227. if assigned(StabstrEntry) then
  1228. stab.strpos:=StabstrEntry.strpos
  1229. else
  1230. {$endif optimizestabs}
  1231. begin
  1232. stab.strpos:=ObjData.StabStrSec.Size;
  1233. ObjData.StabStrSec.write(pstr^,stabstrlen+1);
  1234. end;
  1235. end
  1236. else
  1237. stab.strpos:=0;
  1238. stab.ntype:=byte(nidx);
  1239. stab.ndesc:=word(nline);
  1240. stab.nother:=byte(nother);
  1241. stab.nvalue:=ofs;
  1242. { Write the stab first without the value field. Then
  1243. write a the value field with relocation }
  1244. oldsec:=ObjData.CurrObjSec;
  1245. ObjData.SetSection(ObjData.StabsSec);
  1246. ObjData.Writebytes(stab,sizeof(TObjStabEntry)-4);
  1247. ObjData.Writereloc(stab.nvalue,4,relocsym,RELOC_ABSOLUTE32);
  1248. ObjData.setsection(oldsec);
  1249. end;
  1250. if assigned(pendquote) then
  1251. pendquote^:='"';
  1252. end;
  1253. function TInternalAssembler.MaybeNextList(var hp:Tai):boolean;
  1254. begin
  1255. { maybe end of list }
  1256. while not assigned(hp) do
  1257. begin
  1258. if currlistidx<lists then
  1259. begin
  1260. inc(currlistidx);
  1261. currlist:=list[currlistidx];
  1262. hp:=Tai(currList.first);
  1263. end
  1264. else
  1265. begin
  1266. MaybeNextList:=false;
  1267. exit;
  1268. end;
  1269. end;
  1270. MaybeNextList:=true;
  1271. end;
  1272. function TInternalAssembler.SetIndirectToSymbol(hp: Tai; const indirectname: string): Boolean;
  1273. var
  1274. objsym : TObjSymbol;
  1275. indsym : TObjSymbol;
  1276. begin
  1277. Result:=
  1278. Assigned(hp) and
  1279. (hp.typ=ait_symbol);
  1280. if not Result then
  1281. Exit;
  1282. objsym:=Objdata.SymbolRef(tai_symbol(hp).sym);
  1283. objsym.size:=0;
  1284. indsym := TObjSymbol(ObjData.ObjSymbolList.Find(indirectname));
  1285. if not Assigned(indsym) then
  1286. begin
  1287. { it's possible that indirect symbol is not present in the list,
  1288. so we must create it as undefined }
  1289. indsym:=ObjData.CObjSymbol.Create(ObjData.ObjSymbolList, indirectname);
  1290. indsym.typ:=AT_NONE;
  1291. indsym.bind:=AB_NONE;
  1292. end;
  1293. objsym.indsymbol:=indsym;
  1294. Result:=true;
  1295. end;
  1296. function TInternalAssembler.TreePass0(hp:Tai):Tai;
  1297. var
  1298. objsym,
  1299. objsymend : TObjSymbol;
  1300. begin
  1301. while assigned(hp) do
  1302. begin
  1303. case hp.typ of
  1304. ait_align :
  1305. begin
  1306. if tai_align_abstract(hp).aligntype>1 then
  1307. begin
  1308. { always use the maximum fillsize in this pass to avoid possible
  1309. short jumps to become out of range }
  1310. Tai_align_abstract(hp).fillsize:=Tai_align_abstract(hp).aligntype;
  1311. ObjData.alloc(Tai_align_abstract(hp).fillsize);
  1312. { may need to increase alignment of section }
  1313. if tai_align_abstract(hp).aligntype>ObjData.CurrObjSec.secalign then
  1314. ObjData.CurrObjSec.secalign:=tai_align_abstract(hp).aligntype;
  1315. end
  1316. else
  1317. Tai_align_abstract(hp).fillsize:=0;
  1318. end;
  1319. ait_datablock :
  1320. begin
  1321. {$ifdef USE_COMM_IN_BSS}
  1322. if writingpackages and
  1323. Tai_datablock(hp).is_global then
  1324. ObjData.SymbolDefine(Tai_datablock(hp).sym)
  1325. else
  1326. {$endif USE_COMM_IN_BSS}
  1327. begin
  1328. ObjData.allocalign(used_align(size_2_align(Tai_datablock(hp).size),0,ObjData.CurrObjSec.secalign));
  1329. ObjData.SymbolDefine(Tai_datablock(hp).sym);
  1330. ObjData.alloc(Tai_datablock(hp).size);
  1331. end;
  1332. end;
  1333. ait_realconst:
  1334. ObjData.alloc(tai_realconst(hp).savesize);
  1335. ait_const:
  1336. begin
  1337. { if symbols are provided we can calculate the value for relative symbols.
  1338. This is required for length calculation of leb128 constants }
  1339. if assigned(tai_const(hp).sym) then
  1340. begin
  1341. objsym:=Objdata.SymbolRef(tai_const(hp).sym);
  1342. { objsym already defined and there is endsym? }
  1343. if assigned(objsym.objsection) and assigned(tai_const(hp).endsym) then
  1344. begin
  1345. objsymend:=Objdata.SymbolRef(tai_const(hp).endsym);
  1346. { objsymend already defined? }
  1347. if assigned(objsymend.objsection) then
  1348. begin
  1349. if objsymend.objsection<>objsym.objsection then
  1350. begin
  1351. { leb128 relative constants are not relocatable, but other types are,
  1352. given that objsym belongs to the current section. }
  1353. if (Tai_const(hp).consttype in [aitconst_uleb128bit,aitconst_sleb128bit]) or
  1354. (objsym.objsection<>ObjData.CurrObjSec) then
  1355. InternalError(200404124);
  1356. end
  1357. else
  1358. Tai_const(hp).value:=objsymend.address-objsym.address+Tai_const(hp).symofs;
  1359. end;
  1360. end;
  1361. end;
  1362. ObjData.alloc(tai_const(hp).size);
  1363. end;
  1364. ait_directive:
  1365. begin
  1366. case tai_directive(hp).directive of
  1367. asd_indirect_symbol:
  1368. { handled in TreePass1 }
  1369. ;
  1370. asd_lazy_reference:
  1371. begin
  1372. if tai_directive(hp).name='' then
  1373. Internalerror(2009112101);
  1374. objsym:=ObjData.symbolref(tai_directive(hp).name);
  1375. objsym.bind:=AB_LAZY;
  1376. end;
  1377. asd_reference:
  1378. { ignore for now, but should be added}
  1379. ;
  1380. {$ifdef ARM}
  1381. asd_thumb_func:
  1382. ObjData.ThumbFunc:=true;
  1383. {$endif ARM}
  1384. else
  1385. internalerror(2010011101);
  1386. end;
  1387. end;
  1388. ait_section:
  1389. begin
  1390. ObjData.CreateSection(Tai_section(hp).sectype,Tai_section(hp).name^,Tai_section(hp).secorder);
  1391. Tai_section(hp).sec:=ObjData.CurrObjSec;
  1392. end;
  1393. ait_symbol :
  1394. begin
  1395. { needs extra support in the internal assembler }
  1396. { the value is just ignored }
  1397. {if tai_symbol(hp).has_value then
  1398. internalerror(2009090804); ;}
  1399. ObjData.SymbolDefine(Tai_symbol(hp).sym);
  1400. end;
  1401. ait_label :
  1402. ObjData.SymbolDefine(Tai_label(hp).labsym);
  1403. ait_string :
  1404. ObjData.alloc(Tai_string(hp).len);
  1405. ait_instruction :
  1406. begin
  1407. { reset instructions which could change in pass 2 }
  1408. Taicpu(hp).resetpass2;
  1409. ObjData.alloc(Taicpu(hp).Pass1(ObjData));
  1410. end;
  1411. ait_cutobject :
  1412. if SmartAsm then
  1413. break;
  1414. end;
  1415. hp:=Tai(hp.next);
  1416. end;
  1417. TreePass0:=hp;
  1418. end;
  1419. function TInternalAssembler.TreePass1(hp:Tai):Tai;
  1420. var
  1421. objsym,
  1422. objsymend : TObjSymbol;
  1423. begin
  1424. while assigned(hp) do
  1425. begin
  1426. case hp.typ of
  1427. ait_align :
  1428. begin
  1429. if tai_align_abstract(hp).aligntype>1 then
  1430. begin
  1431. { here we must determine the fillsize which is used in pass2 }
  1432. Tai_align_abstract(hp).fillsize:=align(ObjData.CurrObjSec.Size,Tai_align_abstract(hp).aligntype)-
  1433. ObjData.CurrObjSec.Size;
  1434. ObjData.alloc(Tai_align_abstract(hp).fillsize);
  1435. end;
  1436. end;
  1437. ait_datablock :
  1438. begin
  1439. if (oso_data in ObjData.CurrObjSec.secoptions) and
  1440. not (oso_sparse_data in ObjData.CurrObjSec.secoptions) then
  1441. Message(asmw_e_alloc_data_only_in_bss);
  1442. {$ifdef USE_COMM_IN_BSS}
  1443. if writingpackages and
  1444. Tai_datablock(hp).is_global then
  1445. begin
  1446. objsym:=ObjData.SymbolDefine(Tai_datablock(hp).sym);
  1447. objsym.size:=Tai_datablock(hp).size;
  1448. objsym.bind:=AB_COMMON;
  1449. objsym.alignment:=needtowritealignmentalsoforELF;
  1450. end
  1451. else
  1452. {$endif USE_COMM_IN_BSS}
  1453. begin
  1454. ObjData.allocalign(used_align(size_2_align(Tai_datablock(hp).size),0,ObjData.CurrObjSec.secalign));
  1455. objsym:=ObjData.SymbolDefine(Tai_datablock(hp).sym);
  1456. objsym.size:=Tai_datablock(hp).size;
  1457. ObjData.alloc(Tai_datablock(hp).size);
  1458. end;
  1459. end;
  1460. ait_realconst:
  1461. ObjData.alloc(tai_realconst(hp).savesize);
  1462. ait_const:
  1463. begin
  1464. { Recalculate relative symbols }
  1465. if assigned(tai_const(hp).sym) and
  1466. assigned(tai_const(hp).endsym) then
  1467. begin
  1468. objsym:=Objdata.SymbolRef(tai_const(hp).sym);
  1469. objsymend:=Objdata.SymbolRef(tai_const(hp).endsym);
  1470. if objsymend.objsection<>objsym.objsection then
  1471. begin
  1472. if (Tai_const(hp).consttype in [aitconst_uleb128bit,aitconst_sleb128bit]) or
  1473. (objsym.objsection<>ObjData.CurrObjSec) then
  1474. internalerror(200905042);
  1475. end
  1476. else
  1477. Tai_const(hp).value:=objsymend.address-objsym.address+Tai_const(hp).symofs;
  1478. end;
  1479. ObjData.alloc(tai_const(hp).size);
  1480. end;
  1481. ait_section:
  1482. begin
  1483. { use cached value }
  1484. ObjData.setsection(Tai_section(hp).sec);
  1485. end;
  1486. ait_stab :
  1487. begin
  1488. if assigned(Tai_stab(hp).str) then
  1489. WriteStab(Tai_stab(hp).str);
  1490. end;
  1491. ait_symbol :
  1492. ObjData.SymbolDefine(Tai_symbol(hp).sym);
  1493. ait_symbol_end :
  1494. begin
  1495. objsym:=ObjData.SymbolRef(Tai_symbol_end(hp).sym);
  1496. objsym.size:=ObjData.CurrObjSec.Size-objsym.offset;
  1497. end;
  1498. ait_label :
  1499. ObjData.SymbolDefine(Tai_label(hp).labsym);
  1500. ait_string :
  1501. ObjData.alloc(Tai_string(hp).len);
  1502. ait_instruction :
  1503. ObjData.alloc(Taicpu(hp).Pass1(ObjData));
  1504. ait_cutobject :
  1505. if SmartAsm then
  1506. break;
  1507. ait_directive :
  1508. begin
  1509. case tai_directive(hp).directive of
  1510. asd_indirect_symbol:
  1511. if tai_directive(hp).name='' then
  1512. Internalerror(2009101103)
  1513. else if not SetIndirectToSymbol(Tai(hp.Previous), tai_directive(hp).name) then
  1514. Internalerror(2009101102);
  1515. asd_lazy_reference:
  1516. { handled in TreePass0 }
  1517. ;
  1518. asd_reference:
  1519. { ignore for now, but should be added}
  1520. ;
  1521. asd_thumb_func:
  1522. { ignore for now, but should be added}
  1523. ;
  1524. else
  1525. internalerror(2010011102);
  1526. end;
  1527. end;
  1528. end;
  1529. hp:=Tai(hp.next);
  1530. end;
  1531. TreePass1:=hp;
  1532. end;
  1533. function TInternalAssembler.TreePass2(hp:Tai):Tai;
  1534. var
  1535. fillbuffer : tfillbuffer;
  1536. leblen : byte;
  1537. lebbuf : array[0..63] of byte;
  1538. objsym,
  1539. ref,
  1540. objsymend : TObjSymbol;
  1541. zerobuf : array[0..63] of byte;
  1542. relative_reloc: boolean;
  1543. pdata : pointer;
  1544. ssingle : single;
  1545. ddouble : double;
  1546. eextended : extended;
  1547. ccomp : comp;
  1548. tmp : word;
  1549. begin
  1550. fillchar(zerobuf,sizeof(zerobuf),0);
  1551. fillchar(objsym,sizeof(objsym),0);
  1552. fillchar(objsymend,sizeof(objsymend),0);
  1553. { main loop }
  1554. while assigned(hp) do
  1555. begin
  1556. case hp.typ of
  1557. ait_align :
  1558. begin
  1559. if tai_align_abstract(hp).aligntype>ObjData.CurrObjSec.secalign then
  1560. InternalError(2012072301);
  1561. if oso_data in ObjData.CurrObjSec.secoptions then
  1562. ObjData.writebytes(Tai_align_abstract(hp).calculatefillbuf(fillbuffer,oso_executable in ObjData.CurrObjSec.secoptions)^,
  1563. Tai_align_abstract(hp).fillsize)
  1564. else
  1565. ObjData.alloc(Tai_align_abstract(hp).fillsize);
  1566. end;
  1567. ait_section :
  1568. begin
  1569. { use cached value }
  1570. ObjData.setsection(Tai_section(hp).sec);
  1571. end;
  1572. ait_symbol :
  1573. begin
  1574. ObjOutput.exportsymbol(ObjData.SymbolRef(Tai_symbol(hp).sym));
  1575. end;
  1576. ait_symbol_end :
  1577. begin
  1578. { recalculate size, as some preceding instructions
  1579. could have been changed to smaller size }
  1580. objsym:=ObjData.SymbolRef(Tai_symbol_end(hp).sym);
  1581. objsym.size:=ObjData.CurrObjSec.Size-objsym.offset;
  1582. end;
  1583. ait_datablock :
  1584. begin
  1585. ObjOutput.exportsymbol(ObjData.SymbolRef(Tai_datablock(hp).sym));
  1586. {$ifdef USE_COMM_IN_BSS}
  1587. if not(writingpackages and
  1588. Tai_datablock(hp).is_global) then
  1589. {$endif USE_COMM_IN_BSS}
  1590. begin
  1591. ObjData.allocalign(used_align(size_2_align(Tai_datablock(hp).size),0,ObjData.CurrObjSec.secalign));
  1592. ObjData.alloc(Tai_datablock(hp).size);
  1593. end;
  1594. end;
  1595. ait_realconst:
  1596. begin
  1597. case tai_realconst(hp).realtyp of
  1598. aitrealconst_s32bit:
  1599. begin
  1600. ssingle:=single(tai_realconst(hp).value.s32val);
  1601. pdata:=@ssingle;
  1602. end;
  1603. aitrealconst_s64bit:
  1604. begin
  1605. ddouble:=double(tai_realconst(hp).value.s64val);
  1606. pdata:=@ddouble;
  1607. end;
  1608. {$if defined(cpuextended) and defined(FPC_HAS_TYPE_EXTENDED)}
  1609. { can't write full 80 bit floating point constants yet on non-x86 }
  1610. aitrealconst_s80bit:
  1611. begin
  1612. eextended:=extended(tai_realconst(hp).value.s80val);
  1613. pdata:=@eextended;
  1614. end;
  1615. {$endif cpuextended}
  1616. aitrealconst_s64comp:
  1617. begin
  1618. ccomp:=comp(tai_realconst(hp).value.s64compval);
  1619. pdata:=@ccomp;
  1620. end;
  1621. else
  1622. internalerror(2015030501);
  1623. end;
  1624. ObjData.writebytes(pdata^,tai_realconst(hp).datasize);
  1625. ObjData.writebytes(zerobuf,tai_realconst(hp).savesize-tai_realconst(hp).datasize);
  1626. end;
  1627. ait_string :
  1628. ObjData.writebytes(Tai_string(hp).str^,Tai_string(hp).len);
  1629. ait_const :
  1630. begin
  1631. { Recalculate relative symbols, addresses of forward references
  1632. can be changed in treepass1 }
  1633. relative_reloc:=false;
  1634. if assigned(tai_const(hp).sym) and
  1635. assigned(tai_const(hp).endsym) then
  1636. begin
  1637. objsym:=Objdata.SymbolRef(tai_const(hp).sym);
  1638. objsymend:=Objdata.SymbolRef(tai_const(hp).endsym);
  1639. relative_reloc:=(objsym.objsection<>objsymend.objsection);
  1640. Tai_const(hp).value:=objsymend.address-objsym.address+Tai_const(hp).symofs;
  1641. end;
  1642. case tai_const(hp).consttype of
  1643. aitconst_64bit,
  1644. aitconst_32bit,
  1645. aitconst_16bit,
  1646. aitconst_64bit_unaligned,
  1647. aitconst_32bit_unaligned,
  1648. aitconst_16bit_unaligned,
  1649. aitconst_8bit :
  1650. begin
  1651. if assigned(tai_const(hp).sym) and
  1652. not assigned(tai_const(hp).endsym) then
  1653. ObjData.writereloc(Tai_const(hp).symofs,tai_const(hp).size,Objdata.SymbolRef(tai_const(hp).sym),RELOC_ABSOLUTE)
  1654. else if relative_reloc then
  1655. ObjData.writereloc(ObjData.CurrObjSec.size+tai_const(hp).size-objsym.address+tai_const(hp).symofs,tai_const(hp).size,objsymend,RELOC_RELATIVE)
  1656. else
  1657. ObjData.writebytes(Tai_const(hp).value,tai_const(hp).size);
  1658. end;
  1659. aitconst_rva_symbol :
  1660. begin
  1661. { PE32+? }
  1662. if target_info.system=system_x86_64_win64 then
  1663. ObjData.writereloc(Tai_const(hp).symofs,sizeof(longint),Objdata.SymbolRef(tai_const(hp).sym),RELOC_RVA)
  1664. else
  1665. ObjData.writereloc(Tai_const(hp).symofs,sizeof(pint),Objdata.SymbolRef(tai_const(hp).sym),RELOC_RVA);
  1666. end;
  1667. aitconst_secrel32_symbol :
  1668. begin
  1669. { Required for DWARF2 support under Windows }
  1670. ObjData.writereloc(Tai_const(hp).symofs,sizeof(longint),Objdata.SymbolRef(tai_const(hp).sym),RELOC_SECREL32);
  1671. end;
  1672. {$ifdef i8086}
  1673. aitconst_farptr :
  1674. if assigned(tai_const(hp).sym) and
  1675. not assigned(tai_const(hp).endsym) then
  1676. ObjData.writereloc(Tai_const(hp).symofs,tai_const(hp).size,Objdata.SymbolRef(tai_const(hp).sym),RELOC_FARPTR)
  1677. else if relative_reloc then
  1678. internalerror(2015040601)
  1679. else
  1680. ObjData.writebytes(Tai_const(hp).value,tai_const(hp).size);
  1681. {$endif i8086}
  1682. {$ifdef arm}
  1683. aitconst_got:
  1684. ObjData.writereloc(Tai_const(hp).symofs,sizeof(longint),Objdata.SymbolRef(tai_const(hp).sym),RELOC_GOT32);
  1685. {$endif arm}
  1686. aitconst_gotoff_symbol:
  1687. ObjData.writereloc(Tai_const(hp).symofs,sizeof(longint),Objdata.SymbolRef(tai_const(hp).sym),RELOC_GOTOFF);
  1688. aitconst_uleb128bit,
  1689. aitconst_sleb128bit :
  1690. begin
  1691. if tai_const(hp).consttype=aitconst_uleb128bit then
  1692. leblen:=EncodeUleb128(qword(Tai_const(hp).value),lebbuf)
  1693. else
  1694. leblen:=EncodeSleb128(Tai_const(hp).value,lebbuf);
  1695. if leblen<>tai_const(hp).size then
  1696. internalerror(200709271);
  1697. ObjData.writebytes(lebbuf,leblen);
  1698. end;
  1699. aitconst_darwin_dwarf_delta32,
  1700. aitconst_darwin_dwarf_delta64:
  1701. ObjData.writebytes(Tai_const(hp).value,tai_const(hp).size);
  1702. aitconst_half16bit,
  1703. aitconst_gs:
  1704. begin
  1705. tmp:=Tai_const(hp).value div 2;
  1706. ObjData.writebytes(tmp,2);
  1707. end;
  1708. else
  1709. internalerror(200603254);
  1710. end;
  1711. end;
  1712. ait_label :
  1713. begin
  1714. { exporting shouldn't be necessary as labels are local,
  1715. but it's better to be on the safe side (PFV) }
  1716. ObjOutput.exportsymbol(ObjData.SymbolRef(Tai_label(hp).labsym));
  1717. end;
  1718. ait_instruction :
  1719. Taicpu(hp).Pass2(ObjData);
  1720. ait_stab :
  1721. WriteStab(Tai_stab(hp).str);
  1722. ait_function_name,
  1723. ait_force_line : ;
  1724. ait_cutobject :
  1725. if SmartAsm then
  1726. break;
  1727. ait_weak:
  1728. begin
  1729. objsym:=ObjData.symbolref(tai_weak(hp).sym^);
  1730. objsym.bind:=AB_WEAK_EXTERNAL;
  1731. end;
  1732. ait_symbolpair:
  1733. begin
  1734. if tai_symbolpair(hp).kind=spk_set then
  1735. begin
  1736. objsym:=ObjData.symbolref(tai_symbolpair(hp).sym^);
  1737. ref:=objdata.symbolref(tai_symbolpair(hp).value^);
  1738. objsym.offset:=ref.offset;
  1739. objsym.objsection:=ref.objsection;
  1740. {$ifdef arm}
  1741. objsym.ThumbFunc:=ref.ThumbFunc;
  1742. {$endif arm}
  1743. end;
  1744. end;
  1745. {$ifndef DISABLE_WIN64_SEH}
  1746. ait_seh_directive :
  1747. tai_seh_directive(hp).generate_code(objdata);
  1748. {$endif DISABLE_WIN64_SEH}
  1749. end;
  1750. hp:=Tai(hp.next);
  1751. end;
  1752. TreePass2:=hp;
  1753. end;
  1754. procedure TInternalAssembler.writetree;
  1755. label
  1756. doexit;
  1757. var
  1758. hp : Tai;
  1759. ObjWriter : TObjectWriter;
  1760. begin
  1761. ObjWriter:=TObjectwriter.create;
  1762. ObjOutput:=CObjOutput.Create(ObjWriter);
  1763. ObjData:=ObjOutput.newObjData(ObjFileName);
  1764. { Pass 0 }
  1765. ObjData.currpass:=0;
  1766. ObjData.createsection(sec_code);
  1767. ObjData.beforealloc;
  1768. { start with list 1 }
  1769. currlistidx:=1;
  1770. currlist:=list[currlistidx];
  1771. hp:=Tai(currList.first);
  1772. while assigned(hp) do
  1773. begin
  1774. hp:=TreePass0(hp);
  1775. MaybeNextList(hp);
  1776. end;
  1777. ObjData.afteralloc;
  1778. { leave if errors have occured }
  1779. if errorcount>0 then
  1780. goto doexit;
  1781. { Pass 1 }
  1782. ObjData.currpass:=1;
  1783. ObjData.resetsections;
  1784. ObjData.beforealloc;
  1785. ObjData.createsection(sec_code);
  1786. { start with list 1 }
  1787. currlistidx:=1;
  1788. currlist:=list[currlistidx];
  1789. hp:=Tai(currList.first);
  1790. while assigned(hp) do
  1791. begin
  1792. hp:=TreePass1(hp);
  1793. MaybeNextList(hp);
  1794. end;
  1795. ObjData.createsection(sec_code);
  1796. ObjData.afteralloc;
  1797. { leave if errors have occured }
  1798. if errorcount>0 then
  1799. goto doexit;
  1800. { Pass 2 }
  1801. ObjData.currpass:=2;
  1802. ObjData.resetsections;
  1803. ObjData.beforewrite;
  1804. ObjData.createsection(sec_code);
  1805. { start with list 1 }
  1806. currlistidx:=1;
  1807. currlist:=list[currlistidx];
  1808. hp:=Tai(currList.first);
  1809. while assigned(hp) do
  1810. begin
  1811. hp:=TreePass2(hp);
  1812. MaybeNextList(hp);
  1813. end;
  1814. ObjData.createsection(sec_code);
  1815. ObjData.afterwrite;
  1816. { don't write the .o file if errors have occured }
  1817. if errorcount=0 then
  1818. begin
  1819. { write objectfile }
  1820. ObjOutput.startobjectfile(ObjFileName);
  1821. ObjOutput.writeobjectfile(ObjData);
  1822. end;
  1823. doexit:
  1824. { Cleanup }
  1825. ObjData.free;
  1826. ObjData:=nil;
  1827. ObjWriter.free;
  1828. end;
  1829. procedure TInternalAssembler.writetreesmart;
  1830. var
  1831. hp : Tai;
  1832. startsectype : TAsmSectiontype;
  1833. place: tcutplace;
  1834. ObjWriter : TObjectWriter;
  1835. startsecname: String;
  1836. startsecorder: TAsmSectionOrder;
  1837. begin
  1838. if not(cs_asm_leave in current_settings.globalswitches) and
  1839. not(af_needar in target_asm.flags) then
  1840. ObjWriter:=CInternalAr.CreateAr(current_module.staticlibfilename)
  1841. else
  1842. ObjWriter:=TObjectwriter.create;
  1843. NextSmartName(cut_normal);
  1844. ObjOutput:=CObjOutput.Create(ObjWriter);
  1845. startsectype:=sec_none;
  1846. startsecname:='';
  1847. startsecorder:=secorder_default;
  1848. { start with list 1 }
  1849. currlistidx:=1;
  1850. currlist:=list[currlistidx];
  1851. hp:=Tai(currList.first);
  1852. while assigned(hp) do
  1853. begin
  1854. ObjData:=ObjOutput.newObjData(ObjFileName);
  1855. { Pass 0 }
  1856. ObjData.currpass:=0;
  1857. ObjData.resetsections;
  1858. ObjData.beforealloc;
  1859. if startsectype<>sec_none then
  1860. ObjData.CreateSection(startsectype,startsecname,startsecorder);
  1861. TreePass0(hp);
  1862. ObjData.afteralloc;
  1863. { leave if errors have occured }
  1864. if errorcount>0 then
  1865. break;
  1866. { Pass 1 }
  1867. ObjData.currpass:=1;
  1868. ObjData.resetsections;
  1869. ObjData.beforealloc;
  1870. if startsectype<>sec_none then
  1871. ObjData.CreateSection(startsectype,startsecname,startsecorder);
  1872. TreePass1(hp);
  1873. ObjData.afteralloc;
  1874. { leave if errors have occured }
  1875. if errorcount>0 then
  1876. break;
  1877. { Pass 2 }
  1878. ObjData.currpass:=2;
  1879. ObjOutput.startobjectfile(ObjFileName);
  1880. ObjData.resetsections;
  1881. ObjData.beforewrite;
  1882. if startsectype<>sec_none then
  1883. ObjData.CreateSection(startsectype,startsecname,startsecorder);
  1884. hp:=TreePass2(hp);
  1885. ObjData.afterwrite;
  1886. { leave if errors have occured }
  1887. if errorcount>0 then
  1888. break;
  1889. { write the current objectfile }
  1890. ObjOutput.writeobjectfile(ObjData);
  1891. ObjData.free;
  1892. ObjData:=nil;
  1893. { end of lists? }
  1894. if not MaybeNextList(hp) then
  1895. break;
  1896. { we will start a new objectfile so reset everything }
  1897. { The place can still change in the next while loop, so don't init }
  1898. { the writer yet (JM) }
  1899. if (hp.typ=ait_cutobject) then
  1900. place := Tai_cutobject(hp).place
  1901. else
  1902. place := cut_normal;
  1903. { avoid empty files }
  1904. startsectype:=sec_none;
  1905. startsecname:='';
  1906. startsecorder:=secorder_default;
  1907. while assigned(hp) and
  1908. (Tai(hp).typ in [ait_marker,ait_comment,ait_section,ait_cutobject]) do
  1909. begin
  1910. if Tai(hp).typ=ait_section then
  1911. begin
  1912. startsectype:=Tai_section(hp).sectype;
  1913. startsecname:=Tai_section(hp).name^;
  1914. startsecorder:=Tai_section(hp).secorder;
  1915. end;
  1916. if (Tai(hp).typ=ait_cutobject) then
  1917. place:=Tai_cutobject(hp).place;
  1918. hp:=Tai(hp.next);
  1919. end;
  1920. if not MaybeNextList(hp) then
  1921. break;
  1922. { start next objectfile }
  1923. NextSmartName(place);
  1924. end;
  1925. ObjData.free;
  1926. ObjData:=nil;
  1927. ObjWriter.free;
  1928. end;
  1929. procedure TInternalAssembler.MakeObject;
  1930. var to_do:set of TasmlistType;
  1931. i:TasmlistType;
  1932. procedure addlist(p:TAsmList);
  1933. begin
  1934. inc(lists);
  1935. list[lists]:=p;
  1936. end;
  1937. begin
  1938. to_do:=[low(Tasmlisttype)..high(Tasmlisttype)];
  1939. if usedeffileforexports then
  1940. exclude(to_do,al_exports);
  1941. if not(tf_section_threadvars in target_info.flags) then
  1942. exclude(to_do,al_threadvars);
  1943. for i:=low(TasmlistType) to high(TasmlistType) do
  1944. if (i in to_do) and (current_asmdata.asmlists[i]<>nil) and
  1945. (not current_asmdata.asmlists[i].empty) then
  1946. addlist(current_asmdata.asmlists[i]);
  1947. if SmartAsm then
  1948. writetreesmart
  1949. else
  1950. writetree;
  1951. end;
  1952. {*****************************************************************************
  1953. Generate Assembler Files Main Procedure
  1954. *****************************************************************************}
  1955. Procedure GenerateAsm(smart:boolean);
  1956. var
  1957. a : TAssembler;
  1958. begin
  1959. if not assigned(CAssembler[target_asm.id]) then
  1960. Message(asmw_f_assembler_output_not_supported);
  1961. a:=CAssembler[target_asm.id].Create(smart);
  1962. a.MakeObject;
  1963. a.Free;
  1964. end;
  1965. Procedure OnlyAsm;
  1966. var
  1967. a : TExternalAssembler;
  1968. begin
  1969. a:=TExternalAssembler.Create(false);
  1970. a.DoAssemble;
  1971. a.Free;
  1972. end;
  1973. {*****************************************************************************
  1974. Init/Done
  1975. *****************************************************************************}
  1976. procedure RegisterAssembler(const r:tasminfo;c:TAssemblerClass);
  1977. var
  1978. t : tasm;
  1979. begin
  1980. t:=r.id;
  1981. if assigned(asminfos[t]) then
  1982. writeln('Warning: Assembler is already registered!')
  1983. else
  1984. Getmem(asminfos[t],sizeof(tasminfo));
  1985. asminfos[t]^:=r;
  1986. CAssembler[t]:=c;
  1987. end;
  1988. end.