2
0

FoxBinaryObjectFile.Mod 77 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284
  1. MODULE FoxBinaryObjectFile; (** AUTHOR "fof"; PURPOSE "Oberon Compiler Object File Writer"; *)
  2. IMPORT
  3. Scanner := FoxScanner, Basic := FoxBasic, SyntaxTree := FoxSyntaxTree, Global := FoxGlobal, SemanticChecker := FoxSemanticChecker, FingerPrinter := FoxFingerPrinter, Sections := FoxSections,
  4. Streams, D := Debugging, Files, SYSTEM,Strings, BinaryCode := FoxBinaryCode, Log := KernelLog, Diagnostics, SymbolFileFormat := FoxBinarySymbolFile, Options,
  5. Formats := FoxFormats, IntermediateCode := FoxIntermediateCode, Machine
  6. ;
  7. (** Object File Format
  8. ObjectFile = ofFileTag ofNoZeroCompression ofFileVersion
  9. symbolFileSize:RawLInt SymbolFile
  10. Header Entries Commands Pointers Imports VarConstLinks
  11. Links Constants Exports Code Use Types
  12. ExceptionTable PtrsInProcBlock References.
  13. SymbolFile = {Char}:symbolFileSize
  14. Header = refSize:RawLInt numberEntries:RawLInt numberCommands:RawLInt
  15. numberPointers:RawLInt numberTypes:RawLInt numberImports:RawLInt
  16. numberVarConstLinks:RawLInt numberLinks:RawLInt dataSize:RawLInt
  17. constSize:RawLInt codeSize:RawLInt exTableLen:RawLInt numberProcs:RawLInt
  18. maxPtrs:RawLInt typeDescSize:RawLInt crc:RawLInt moduleName:RawString
  19. Entries = 82X:Char { entryOffset:RawNum }:numberEntries
  20. Commands = 83X:Char { firstParTypeOfs:RawNum returnTypeOfs:RawNum
  21. commandName:RawString cmdOffset:RawNum }:numberCommands
  22. Pointers = 84X {pointerOffset:RawNum}:numberPointers
  23. Imports = 85X { moduleName:String }:numberImports
  24. VarConstLinks = 8DX { VarConstLinkEntry }:numberVarConstLinks
  25. VarConstLinkEntry = modNumber:Char entry:RawNum
  26. fixupCount:RawLInt { offset:RawNum }:fixupCount
  27. Links = 86X {LinkEntry}:numberLinks {fixupCount:RawNum}:numberEntries
  28. caseTableSize:RawNum
  29. LinkEntry = moduleNumber:Char entryNumber:Char offset:RawNum
  30. Constants = 87X {character:Char}:constSize
  31. Exports = 88X numberExports:RawLInt {ExportEntry}:numberExpor
  32. ExportEntry = fingerPrint:RawNum offset:RawNum [1X ExportType]
  33. ExportType = reference<0:RawNum
  34. | typeDescriptorOffset:RawNum numberEntries:RawLInt [1X ExportType]
  35. {fingerPrint:RawNum [1X ExportType]}:numberEntries 0X
  36. Code = 89X {character:Char}:codeSize
  37. Use = 08AX {UsedModules} 0X
  38. UsedModules = moduleName:RawString {UsedEntry} 0X
  39. UsedEntry = fingerPrint:RawNum name:RawString number:RawNum [1X UsedType]
  40. UsedType = typeDescOfs:RawNum [fingerPrint:RawNum "@"] 0X
  41. Types = 08BX {TypeEntry}:numberTypes
  42. TypeEntry = recordSize:RawNum entry:RawNum
  43. baseModule:RawNum baseEntry:RawNum
  44. methods:RawNum inheritedMethods:RawNum newMethods:RawNum
  45. pointers:RawNum name:RawString typeDescriptorSize:RawLInt
  46. {method:RawNum entry:RawNum}:newMethods
  47. {offset:RawNum}:pointers
  48. ExceptionTable = 08EX { ExTableEntry }:exTableLength
  49. ExTableEntry = 0FEX pcFrom:RawNum pcTo:RawNum pcHandler:RawNum
  50. PtrsInProcs = 08FX {ProcEntry}:numberProcs
  51. ProcEntry = codeOfs:RawNum beginOfs:RawNum endOfs:RawNum
  52. numberPointers:RawLInt {pointer:RawNum}:numberPointers
  53. References = 08CX RSScope { RSProcedure }
  54. Scope = 0F8X codeOffset:RawNum "$$" {Variable}
  55. Procedure = 0F9X codeOffset:RawNum numberParameters:RawNum ReturnType
  56. level:RawNum 0X name:RawString {Parameter} {Variable}
  57. ReturnType = 0X | BaseType | rfStaticArray | rfDynamicArray | rfOpenArray | rfRecord
  58. Parameter = Variable
  59. Variable = VariableMode Type variableOffset:RawNum variableName:RawString
  60. VariableMode = rfIndirect | rfDirect
  61. Type = BaseType | ArrayType | RecordType
  62. BaseType = rfByte | rfSet | rfAny
  63. | rfBoolean | rfChar8 | rfChar16 | rfChar32
  64. | rfShortint | rfInteger | rfLongint | rfHugeint
  65. | rfReal | rfLongreal |
  66. | rfString | rfPointer | rfAll | rfSame | rfRange
  67. | rfComplex | rfLongcomplex
  68. ArrayType = 80H+BaseType:RawNum dim:RawNum
  69. RecordType = (rfRecord | rfRecordPointer) tdAdr:RawNum
  70. **)
  71. CONST
  72. ofFileTag = 0BBX; (* same constants are defined in Linker and Loader *)
  73. ofNoZeroCompress = 0ADX; (* do. *)
  74. ofFileVersion = SymbolFileFormat.FileVersionCurrent; (* do. *)
  75. ofEUEnd = 0X;
  76. ofEURecord = 1X;
  77. ofEUProcFlag = LONGINT(080000000H);
  78. (** system calls *)
  79. DefaultNofSysCalls = 12;
  80. NewRec = 0; NewArr = 1; NewSys = 2; CaseTable = 3; ProcAddr = 4;
  81. Lock = 5; Unlock = 6; Start = 7; Await = 8; InterfaceLookup = 9;
  82. RegisterInterface = 10; GetProcedure = 11;
  83. Trace = FALSE;
  84. TYPE Name=ARRAY 256 OF CHAR;
  85. ByteArray = POINTER TO ARRAY OF CHAR;
  86. TYPE
  87. ObjectFileFormat*= OBJECT (Formats.ObjectFileFormat)
  88. PROCEDURE & InitObjectFileFormat;
  89. BEGIN
  90. Init; SetExtension(Machine.DefaultObjectFileExtension);
  91. END InitObjectFileFormat;
  92. PROCEDURE Export*(module: Formats.GeneratedModule; symbolFileFormat: Formats.SymbolFileFormat): BOOLEAN;
  93. VAR symbolFile: Files.File; moduleName: SyntaxTree.IdentifierString; fileName: Files.FileName; f: Files.File; w: Files.Writer;
  94. VAR constSize, varSize, codeSize, caseTableSize: LONGINT; VAR const, code: ByteArray;
  95. BEGIN
  96. Global.ModuleFileName(module.module.name,module.module.context,moduleName);
  97. Basic.Concat(fileName,path,moduleName,extension);
  98. IF Trace THEN D.Str("FoxBinaryObjectFile.ObjectFileFormat.Export "); D.Str(moduleName); D.Ln; END;
  99. IF ~(module IS Sections.Module) THEN
  100. Basic.Error(diagnostics, module.module.sourceName,Basic.invalidPosition, "generated module format does not match object file format");
  101. RETURN FALSE;
  102. ELSIF module.findPC # MAX(LONGINT) THEN
  103. MakeSectionOffsets(module(Sections.Module),constSize, varSize, codeSize, caseTableSize,const,code);
  104. RETURN FindPC(module.findPC,module(Sections.Module),diagnostics);
  105. ELSE
  106. WITH module: Sections.Module DO
  107. IF (symbolFileFormat # NIL) & (symbolFileFormat IS SymbolFileFormat.BinarySymbolFile) THEN
  108. symbolFile := symbolFileFormat(SymbolFileFormat.BinarySymbolFile).file;
  109. ELSE
  110. symbolFile := NIL
  111. END;
  112. f := Files.New(fileName);
  113. ASSERT(f # NIL);
  114. (*
  115. IF dump # NIL THEN
  116. dump.String("generated file "); dump.String(fileName); dump.Ln; dump.Update;
  117. END;
  118. *)
  119. NEW(w,f,0);
  120. WriteObjectFile(w,module,symbolFile);
  121. w.Update;
  122. Files.Register(f);
  123. RETURN TRUE
  124. END;
  125. END;
  126. END Export;
  127. PROCEDURE DefineOptions*(options: Options.Options);
  128. BEGIN
  129. options.Add(0X,"objectFileExtension",Options.String);
  130. END DefineOptions;
  131. PROCEDURE GetOptions*(options: Options.Options);
  132. VAR extension: Files.FileName;
  133. BEGIN
  134. IF options.GetString("objectFileExtension",extension) THEN
  135. SetExtension(extension);
  136. END;
  137. END GetOptions;
  138. PROCEDURE DefaultSymbolFileFormat(): Formats.SymbolFileFormat;
  139. BEGIN RETURN SymbolFileFormat.Get();
  140. END DefaultSymbolFileFormat;
  141. PROCEDURE ForceModuleBodies(): BOOLEAN; (* necessary in binary object file format as bodies not recognizable later on *)
  142. BEGIN RETURN TRUE
  143. END ForceModuleBodies;
  144. END ObjectFileFormat;
  145. Fixup = OBJECT
  146. VAR
  147. nextFixup: Fixup;
  148. fixup: BinaryCode.Fixup;
  149. fixupSection: Sections.Section;
  150. END Fixup;
  151. Section=OBJECT (* proprietary format for this object file format *)
  152. VAR
  153. name: Basic.SegmentedName;
  154. symbol: SyntaxTree.Symbol;
  155. entryNumber: LONGINT;
  156. offset: LONGINT;
  157. fixups: Fixup; (* fixups other way round: who references to this section *)
  158. numberFixups: LONGINT;
  159. type: LONGINT;
  160. resolved: BinaryCode.Section;
  161. isCaseTable: BOOLEAN;
  162. referenced: BOOLEAN;
  163. PROCEDURE SetEntryNumber(num: LONGINT);
  164. BEGIN
  165. entryNumber := num
  166. END SetEntryNumber;
  167. PROCEDURE SetSymbol(s: SyntaxTree.Symbol);
  168. BEGIN
  169. symbol := s;
  170. END SetSymbol;
  171. PROCEDURE &Init(CONST name: Basic.SegmentedName);
  172. BEGIN SELF.name := name; fixups := NIL; symbol := NIL; entryNumber := 0; numberFixups := 0;
  173. END Init;
  174. PROCEDURE AddFixup(fixup: BinaryCode.Fixup; fixupSection: Sections.Section);
  175. VAR next: Fixup;
  176. BEGIN
  177. NEW(next);
  178. next.fixup := fixup;
  179. next.fixupSection := fixupSection;
  180. next.nextFixup := fixups;
  181. fixups := next;
  182. INC(numberFixups);
  183. END AddFixup;
  184. PROCEDURE Dump(w: Streams.Writer);
  185. VAR fixup: Fixup; n: Basic.SegmentedName;
  186. BEGIN
  187. Basic.WriteSegmentedName(w,name);
  188. w.String(" : ");
  189. IF symbol = NIL THEN w.String("NIL")
  190. ELSE Global.GetSymbolSegmentedName(symbol, n); Basic.WriteSegmentedName(w,n);
  191. END;
  192. IF referenced THEN w.String("(referenced)") END;
  193. w.Ln;
  194. w.String("no fixups:"); w.Int(numberFixups,1); w.Ln;
  195. fixup := fixups;
  196. WHILE fixup # NIL DO
  197. w.String("fixup in "); Basic.WriteSegmentedName(w,fixups.fixupSection.name); w.String(" "); fixup.fixup.Dump(w); w.Ln;
  198. fixup := fixup.nextFixup;
  199. END;
  200. END Dump;
  201. END Section;
  202. SectionNameLookup = OBJECT(Basic.HashTableSegmentedName); (* SyntaxTree.Symbol _> Symbol *)
  203. PROCEDURE GetSection(CONST name: Basic.SegmentedName):Section;
  204. VAR p: ANY;
  205. BEGIN
  206. p := Get(name);
  207. IF p # NIL THEN RETURN p(Section) ELSE RETURN NIL END;
  208. END GetSection;
  209. PROCEDURE PutSection(CONST name:Basic.SegmentedName; section: Section);
  210. BEGIN
  211. Put(name, section);
  212. END PutSection;
  213. END SectionNameLookup;
  214. SymbolLookup = OBJECT(Basic.HashTable); (* SyntaxTree.Symbol _> Symbol *)
  215. PROCEDURE GetSection(s: SyntaxTree.Symbol):Section;
  216. VAR p: ANY;
  217. BEGIN
  218. p := Get(s);
  219. IF p # NIL THEN RETURN p(Section) ELSE RETURN NIL END;
  220. END GetSection;
  221. PROCEDURE PutSection(symbol: SyntaxTree.Symbol; section: Section);
  222. BEGIN
  223. Put(symbol, section);
  224. END PutSection;
  225. END SymbolLookup;
  226. SectionList= OBJECT (Basic.List)
  227. VAR
  228. lookup: SectionNameLookup;
  229. symbolLookup: SymbolLookup;
  230. PROCEDURE &Init;
  231. BEGIN
  232. InitList(16);
  233. NEW(lookup,16);
  234. NEW(symbolLookup, 16);
  235. END Init;
  236. PROCEDURE AddSection(name: Basic.SegmentedName): Section;
  237. VAR section: Section;
  238. BEGIN
  239. section := lookup.GetSection(name);
  240. IF section = NIL THEN
  241. NEW(section, name);
  242. lookup.Put(name, section);
  243. Add(section);
  244. END;
  245. RETURN section
  246. END AddSection;
  247. PROCEDURE BySymbol(symbol: SyntaxTree.Symbol): Section;
  248. VAR name: Basic.SegmentedName;
  249. BEGIN
  250. RETURN symbolLookup.GetSection(symbol);
  251. END BySymbol;
  252. PROCEDURE GetSection(i: LONGINT): Section;
  253. VAR any: ANY;
  254. BEGIN
  255. any := Get(i);
  256. RETURN any(Section)
  257. END GetSection;
  258. PROCEDURE Dump(w: Streams.Writer);
  259. VAR section: Section; i: LONGINT;
  260. BEGIN
  261. FOR i := 0 TO Length()-1 DO
  262. section := GetSection(i); section.Dump(w);
  263. END;
  264. END Dump;
  265. END SectionList;
  266. VAR SysCallMap : ARRAY DefaultNofSysCalls OF CHAR;
  267. (*
  268. PROCEDURE GetFixups(module: Sections.Module; symbol: Sections.Section; VAR first: Fixup): LONGINT;
  269. VAR temp: Fixup; fixup: BinaryCode.Fixup; nr :LONGINT;
  270. (* only regular sections *)
  271. PROCEDURE DoSections(sectionList: Sections.SectionList);
  272. VAR
  273. i: LONGINT;
  274. section: Sections.Section;
  275. BEGIN
  276. FOR i := 0 TO sectionList.Length() - 1 DO
  277. section := sectionList.GetSection(i);
  278. IF (section.type # Sections.InlineCodeSection) & (section.type # Sections.InitCodeSection) THEN
  279. fixup := section(IntermediateCode.Section).resolved.fixupList.firstFixup;
  280. WHILE (fixup # NIL) DO
  281. IF (fixup.symbol = symbol.name) THEN
  282. INC(nr);
  283. NEW(temp);
  284. temp.fixup := fixup;
  285. temp.fixupSection := section;
  286. temp.nextFixup := first;
  287. first := temp;
  288. END;
  289. fixup := fixup.nextFixup;
  290. END
  291. END
  292. END;
  293. END DoSections;
  294. BEGIN
  295. first := NIL; nr := 0;
  296. DoSections(module.allSections); (* only regular sections *)
  297. (* Sections(module.caseTables.first); *)
  298. RETURN nr
  299. END GetFixups;
  300. *)
  301. PROCEDURE FindPC(pc: LONGINT; module: Sections.Module; diagnostics: Diagnostics.Diagnostics): BOOLEAN;
  302. VAR
  303. section:Sections.Section; binarySection: BinaryCode.Section; label: BinaryCode.LabelList;
  304. i: LONGINT;
  305. BEGIN
  306. FOR i := 0 TO module.allSections.Length() - 1 DO
  307. section := module.allSections.GetSection(i);
  308. binarySection := section(IntermediateCode.Section).resolved;
  309. IF ((section.offset ) <= pc) & (pc < (section.offset +binarySection.pc )) THEN
  310. label := binarySection.labels;
  311. WHILE (label # NIL) & ((label.offset + section.offset ) > pc) DO
  312. label := label.prev;
  313. END;
  314. IF label # NIL THEN
  315. Basic.Information(diagnostics, module.module.sourceName,label.position," pc position");
  316. RETURN TRUE
  317. END;
  318. END
  319. END;
  320. Basic.Error(diagnostics, module.module.sourceName,Basic.invalidPosition, " could not locate pc");
  321. RETURN FALSE
  322. END FindPC;
  323. PROCEDURE MakeSectionOffsets(module: Sections.Module; VAR constSize, varSize, codeSize, caseTableSize: LONGINT; VAR const, code: ByteArray);
  324. VAR symbolName: SyntaxTree.IdentifierString; symbol: SyntaxTree.Symbol; binarySection: BinaryCode.Section;
  325. pc: LONGINT;
  326. addrSize: LONGINT; (* size of ADDRESS in bytes *)
  327. (*
  328. PROCEDURE InModule(s: Sections.Section):BOOLEAN;
  329. VAR
  330. section: Sections.Section;
  331. i: LONGINT;
  332. BEGIN
  333. FOR i := 0 TO module.allSections.Length() - 1 DO
  334. section := module.allSections.GetSection(i);
  335. IF section = s THEN RETURN TRUE END
  336. END;
  337. RETURN FALSE
  338. END InModule;
  339. *)
  340. PROCEDURE FixupSections;
  341. VAR
  342. section: Sections.Section; dest, i: LONGINT; fixup,next: BinaryCode.Fixup; symbol: Sections.Section;
  343. BEGIN
  344. FOR i := 0 TO module.allSections.Length() - 1 DO
  345. section := module.allSections.GetSection(i);
  346. binarySection := section(IntermediateCode.Section).resolved;
  347. fixup := binarySection.fixupList.firstFixup;
  348. binarySection.fixupList.InitFixupList; (* remove all fixups from list *)
  349. WHILE fixup # NIL DO
  350. next := fixup.nextFixup;
  351. symbol := module.allSections.FindByName(fixup.symbol.name);
  352. IF symbol # NIL THEN
  353. symbol.SetReferenced(TRUE);
  354. ELSIF Trace THEN
  355. D.String("fixup symbol not found: "); Basic.WriteSegmentedName(D.Log, fixup.symbol.name); D.Ln;
  356. END;
  357. IF (fixup.mode = BinaryCode.Relative) & (symbol # NIL) THEN (* relative offset within module *)
  358. dest := (symbol.offset + fixup.displacement) - (section.offset + fixup.offset);
  359. ASSERT(fixup.symbolOffset = 0);
  360. binarySection.PutDWordAt(fixup.offset, dest);
  361. (* fixup done, does not need to be put back to list *)
  362. ELSIF (fixup.mode = BinaryCode.Absolute) & (symbol # NIL) THEN (* absolute offset within module *)
  363. dest := symbol.offset + fixup.displacement;
  364. binarySection.PutDWordAt(fixup.offset, dest);
  365. binarySection.fixupList.AddFixup(fixup); (* (re-)insert fixup into fixup list *)
  366. ELSIF (fixup.mode = BinaryCode.Absolute) THEN (* absolute fixup on imported symbol *)
  367. dest := fixup.displacement;
  368. binarySection.PutDWordAt(fixup.offset, dest);
  369. binarySection.fixupList.AddFixup(fixup); (* (re-)insert fixup into fixup list *)
  370. ELSE binarySection.fixupList.AddFixup(fixup); (* keep fixup as is: relative fixup on imported symbol *)
  371. END;
  372. fixup := next;
  373. END
  374. END;
  375. END FixupSections;
  376. PROCEDURE Copy(section: BinaryCode.Section; to: ByteArray; offset: LONGINT);
  377. VAR i,ofs: LONGINT;
  378. BEGIN
  379. ofs := (offset );
  380. FOR i := 0 TO ((section.pc-1) ) DO
  381. to[i+ofs] := CHR(section.os.bits.GetBits(i*8,8));
  382. END;
  383. END Copy;
  384. (* only regular sections *)
  385. PROCEDURE FirstOffsets(sectionList: Sections.SectionList);
  386. VAR
  387. section: Sections.Section;
  388. i: LONGINT;
  389. BEGIN
  390. FOR i := 0 TO sectionList.Length() - 1 DO
  391. section := sectionList.GetSection(i);
  392. binarySection := section(IntermediateCode.Section).resolved;
  393. symbol := section.symbol;
  394. IF symbol # NIL THEN
  395. symbol.GetName(symbolName);
  396. IF section.symbol = module.module.moduleScope.bodyProcedure THEN
  397. section.SetOffset(0); INC(codeSize,binarySection.pc);
  398. ELSIF symbolName = "@moduleSelf" THEN
  399. section.SetOffset(0); INC(constSize,binarySection.pc);
  400. END;
  401. END
  402. END;
  403. END FirstOffsets;
  404. (* note: if 'caseSections' is TRUE, only case table sections are processed, otherwise only regular sections (imported symbol/system call sections are never processed) *)
  405. PROCEDURE SetOffsets(sectionList: Sections.SectionList; caseTables: BOOLEAN);
  406. VAR
  407. section: Sections.Section;
  408. i: LONGINT;
  409. BEGIN
  410. FOR i := 0 TO sectionList.Length() - 1 DO
  411. section := sectionList.GetSection(i);
  412. IF section.isCaseTable = caseTables THEN
  413. binarySection := section(IntermediateCode.Section).resolved;
  414. symbol := section.symbol;
  415. IF symbol # NIL THEN
  416. symbol.GetName(symbolName);
  417. ELSE symbolName := "";
  418. END;
  419. IF section.symbol = module.module.moduleScope.bodyProcedure THEN
  420. ELSIF symbolName = "@moduleSelf" THEN
  421. ELSIF section.type = Sections.ConstSection THEN
  422. IF binarySection.os.alignment # 0 THEN
  423. INC(constSize,(-constSize) MOD binarySection.os.alignment);
  424. END;
  425. section.SetOffset(constSize); INC(constSize,binarySection.pc); (* global constants: positive offset *)
  426. ELSIF (section.type = Sections.CodeSection) OR (section.type = Sections.BodyCodeSection) THEN
  427. section.SetOffset(codeSize); INC(codeSize, binarySection.pc);
  428. ELSIF section.type = Sections.VarSection THEN
  429. INC(varSize, binarySection.pc);
  430. IF binarySection.os.alignment # 0 THEN
  431. INC(varSize,(-varSize) MOD binarySection.os.alignment);
  432. END;
  433. section.SetOffset(-varSize); (* global variables: negative offset *)
  434. END
  435. END;
  436. END;
  437. END SetOffsets;
  438. (* note: if 'caseSections' is TRUE, only case table sections are processed, otherwise only regular sections (imported symbol/system call sections are never processed) *)
  439. PROCEDURE CopySections(sectionList: Sections.SectionList);
  440. VAR
  441. section: Sections.Section;
  442. i: LONGINT;
  443. BEGIN
  444. FOR i := 0 TO sectionList.Length() - 1 DO
  445. section := sectionList.GetSection(i);
  446. binarySection := section(IntermediateCode.Section).resolved;
  447. IF section.type = Sections.ConstSection THEN
  448. Copy(binarySection,const,section.offset);
  449. ELSIF (section.type = Sections.CodeSection) OR (section.type = Sections.BodyCodeSection) THEN
  450. Copy(binarySection,code,section.offset);
  451. END
  452. END;
  453. END CopySections;
  454. BEGIN
  455. addrSize := module.system.addressSize DIV 8;
  456. FirstOffsets(module.allSections); (* regular sections *)
  457. SetOffsets(module.allSections,FALSE); (* regular sections *)
  458. pc := constSize;
  459. SetOffsets(module.allSections, TRUE); (* case table sections *)
  460. caseTableSize := (constSize -pc) DIV addrSize;
  461. FixupSections;
  462. NEW(const,constSize ); NEW(code,codeSize );
  463. CopySections(module.allSections); (* regular sections *)
  464. END MakeSectionOffsets;
  465. PROCEDURE WriteObjectFile*(w:Streams.Writer; module: Sections.Module; symbolFile: Files.File);
  466. VAR moduleName: Name; refSize, numberEntries,numberCommands,numberPointers,numberTypes,numberImports,
  467. numberVarConstLinks,numberLinks: LONGINT;
  468. dataSize,constSize,codeSize,caseTableSize: LONGINT;
  469. exTableLen,numberProcs,maxPtrs,typeDescSize: LONGINT; headerPos,endPos: LONGINT;
  470. moduleScope: SyntaxTree.ModuleScope; fingerprinter: FingerPrinter.FingerPrinter;
  471. const, code: ByteArray; procedureFixupOffset : LONGINT;
  472. crc: LONGINT; crc32: Basic.CRC32Stream;
  473. addrSize: LONGINT; (* size of ADDRESS in bytes *)
  474. symbols, importedSymbols: SectionList; (* list of sections with fixups in the other direction, needed for this particular object file format *)
  475. PROCEDURE RawLIntAt(at: LONGINT; val: LONGINT);
  476. VAR pos: LONGINT;
  477. BEGIN
  478. pos := w.Pos(); w.SetPos(at); w.RawLInt(val); w.SetPos(pos);
  479. END RawLIntAt;
  480. PROCEDURE AppendFile(f: Files.File; to: Streams.Writer);
  481. VAR buffer: ARRAY 1024 OF CHAR; r: Files.Reader; read: LONGINT;
  482. BEGIN
  483. Files.OpenReader(r, f, 0);
  484. REPEAT
  485. r.Bytes(buffer, 0, 1024, read);
  486. to.Bytes(buffer, 0, read)
  487. UNTIL read # 1024
  488. END AppendFile;
  489. PROCEDURE SymbolFile; (* write symbol file *)
  490. BEGIN
  491. IF Trace THEN D.Str("FoxObjectFile.SymbolFile Length at pos "); D.Int(w.Pos(),1); D.Ln END;
  492. IF symbolFile # NIL THEN
  493. w.RawLInt(symbolFile.Length()); (* could also be patched later, if length was not known here *)
  494. IF Trace THEN D.Str("FoxObjectFile.SymbolFile at pos "); D.Int(w.Pos(),1); D.Ln END;
  495. AppendFile(symbolFile,w);
  496. ELSE
  497. IF Trace THEN D.Str("FoxObjectFile.SymbolFile: no symbol file!"); D.Ln END;
  498. w.RawLInt(0);
  499. END;
  500. END SymbolFile;
  501. (* Header =
  502. refSize:4 numberEntries:4 numberCommands:4 numberPointers:4
  503. numberTypes:4 numberImports:4 numberVarConstLinks:4 numberLinks:4
  504. dataSize:4 constSize:4 codeSize:4 exTableLen:4 numberProcs:4 maxPtrs:4
  505. typeDescSize:4 crc:4 moduleName:String
  506. *)
  507. PROCEDURE Header;
  508. BEGIN
  509. headerPos := w.Pos();
  510. w.RawLInt(refSize);
  511. w.RawLInt(numberEntries);
  512. w.RawLInt(numberCommands);
  513. w.RawLInt(numberPointers);
  514. w.RawLInt(numberTypes);
  515. w.RawLInt(numberImports);
  516. w.RawLInt(numberVarConstLinks);
  517. w.RawLInt(numberLinks);
  518. w.RawLInt((dataSize )); ASSERT(dataSize >= 0);
  519. w.RawLInt((constSize ));
  520. w.RawLInt((codeSize ));
  521. w.RawLInt(exTableLen);
  522. w.RawLInt(numberProcs);
  523. w.RawLInt(maxPtrs);
  524. w.RawLInt(typeDescSize);
  525. w.RawLInt(crc);
  526. IF Trace THEN D.Str("moduleName:"); D.Str(moduleName); D.Ln; END;
  527. w.RawString(moduleName);
  528. END Header;
  529. (* Entries = 82X {entryOffset}:numberEntries *)
  530. PROCEDURE Entries;
  531. VAR
  532. p: Section; procedure: SyntaxTree.Procedure; procedureType : SyntaxTree.ProcedureType;
  533. prev,tail: Fixup; firstOffset: LONGINT; name: SyntaxTree.IdentifierString; fixups, i: LONGINT; fixup: Fixup;
  534. CONST
  535. FixupSentinel = LONGINT(0FFFFFFFFH);
  536. PROCEDURE FixupList(l,prev: Fixup; VAR tail: Fixup);
  537. (* Insert fixup list into code *)
  538. VAR offset: LONGINT;
  539. PROCEDURE Put32(offset: LONGINT; number: LONGINT);
  540. BEGIN
  541. code[offset] := CHR(number MOD 256);
  542. INC(offset); number := number DIV 256;
  543. code[offset] := CHR(number MOD 256);
  544. INC(offset); number := number DIV 256;
  545. code[offset] := CHR(number MOD 256);
  546. INC(offset); number := number DIV 256;
  547. code[offset] := CHR(number MOD 256);
  548. END Put32;
  549. BEGIN
  550. tail := NIL;
  551. IF l # NIL THEN
  552. IF prev # NIL THEN
  553. Put32((prev.fixupSection.offset +prev.fixup.offset ),(l.fixupSection.offset + l.fixup.offset ));
  554. END;
  555. offset := (l.fixupSection.offset + l.fixup.offset );
  556. tail := l;
  557. l := l.nextFixup;
  558. WHILE (l# NIL) DO
  559. Put32(offset,(l.fixupSection.offset + l.fixup.offset ));
  560. offset := (l.fixupSection.offset + l.fixup.offset );
  561. tail := l;
  562. l := l.nextFixup;
  563. END;
  564. Put32(offset,FixupSentinel);
  565. END;
  566. END FixupList;
  567. BEGIN
  568. w.Char(82X);
  569. numberEntries := 0; tail := NIL; prev := NIL; firstOffset := -1;
  570. FOR i := 0 TO symbols.Length() - 1 DO
  571. p := symbols.GetSection(i);
  572. IF (p.symbol # NIL) & (p.symbol IS SyntaxTree.Procedure) & ~p.symbol(SyntaxTree.Procedure).isInline THEN
  573. fixup := p.fixups;
  574. p.symbol.GetName(name); (*debugging*)
  575. procedure := p.symbol(SyntaxTree.Procedure);
  576. procedureType := procedure.type(SyntaxTree.ProcedureType);
  577. (* entry for public procedures and all methods *)
  578. IF (procedure.access*SyntaxTree.Public # {}) OR (procedureType.isDelegate) OR (fixup # NIL) THEN
  579. p.SetEntryNumber(numberEntries);
  580. w.RawNum((p.offset )); INC(numberEntries);
  581. FixupList(fixup, prev, tail); (* absolute fixups, relative procedure fixups have already been done during code generation *)
  582. IF tail # NIL THEN
  583. prev := tail
  584. END;
  585. IF (fixup # NIL) & (firstOffset = -1) THEN
  586. firstOffset := (fixup.fixupSection.offset + fixup.fixup.offset );
  587. END
  588. END
  589. END
  590. END;
  591. procedureFixupOffset := firstOffset;
  592. END Entries;
  593. (* Commands =
  594. 83X {firstParTypeOffset:Num returnParTypeOffset:Num cmdName:String cmdOffset:Num}:numberCommands
  595. *)
  596. PROCEDURE Commands;
  597. VAR
  598. procedure : SyntaxTree.Procedure; procedureType: SyntaxTree.ProcedureType;
  599. p: Section; name: Name; numberParameters, i: LONGINT;
  600. (* Returns TRUE if the built-in function GETPROCEDURE can be used with this procedure type *)
  601. PROCEDURE GetProcedureAllowed() : BOOLEAN;
  602. PROCEDURE TypeAllowed(type : SyntaxTree.Type) : BOOLEAN;
  603. BEGIN
  604. RETURN
  605. (type = NIL) OR
  606. (type.resolved IS SyntaxTree.RecordType) OR
  607. (type.resolved IS SyntaxTree.PointerType) & (type.resolved(SyntaxTree.PointerType).pointerBase.resolved IS SyntaxTree.RecordType);
  608. END TypeAllowed;
  609. BEGIN
  610. numberParameters := procedureType.numberParameters;
  611. RETURN
  612. (numberParameters = 0) & TypeAllowed(procedureType.returnType) OR
  613. (numberParameters = 1) & TypeAllowed(procedureType.firstParameter.type) & TypeAllowed(procedureType.returnType) OR
  614. (numberParameters = 1) & (procedureType.firstParameter.type.resolved IS SyntaxTree.AnyType) & (procedureType.returnType # NIL) & (procedureType.returnType.resolved IS SyntaxTree.AnyType);
  615. END GetProcedureAllowed;
  616. PROCEDURE WriteType(type : SyntaxTree.Type);
  617. VAR typeDeclaration: SyntaxTree.TypeDeclaration; section: Section;
  618. name: SyntaxTree.IdentifierString;
  619. BEGIN
  620. IF type = NIL THEN
  621. w.RawNum(0);
  622. IF Trace THEN
  623. D.String(", t="); D.Int(0,1);
  624. END;
  625. ELSIF (type.resolved IS SyntaxTree.AnyType) OR (type.resolved IS SyntaxTree.ObjectType) THEN
  626. w.RawNum(1);
  627. IF Trace THEN
  628. D.String(", t="); D.Int(1,1);
  629. END;
  630. ELSE
  631. type := type.resolved;
  632. IF type IS SyntaxTree.PointerType THEN
  633. type := type(SyntaxTree.PointerType).pointerBase.resolved;
  634. END;
  635. typeDeclaration := type.typeDeclaration; (* must be non-nil *)
  636. typeDeclaration.GetName(name);
  637. section := symbols.BySymbol(type.typeDeclaration);
  638. ASSERT(section # NIL);
  639. w.RawNum((section.offset )); (* type descriptor section offset *)
  640. IF Trace THEN
  641. D.String(", t="); D.Int(section.offset ,1);
  642. END;
  643. END;
  644. END WriteType;
  645. BEGIN
  646. w.Char(83X);
  647. FOR i := 0 TO symbols.Length() - 1 DO
  648. p := symbols.GetSection(i);
  649. IF (p.symbol # NIL) & (p.symbol IS SyntaxTree.Procedure) THEN
  650. procedure := p.symbol(SyntaxTree.Procedure);
  651. procedureType := procedure.type(SyntaxTree.ProcedureType);
  652. IF (SyntaxTree.PublicWrite IN procedure.access) & ~(procedure.isInline) & ~(procedureType.isDelegate) & GetProcedureAllowed() THEN
  653. procedure.GetName(name);
  654. IF Trace THEN
  655. D.Str("Command : "); D.Str(name); D.Str(" @ "); D.Int(p.offset ,1);
  656. END;
  657. numberParameters := procedureType.numberParameters;
  658. (* offset of type of first parameter *)
  659. IF (numberParameters = 0 ) THEN WriteType(NIL)
  660. ELSE WriteType(procedureType.firstParameter.type)
  661. END;
  662. (* offset of type of return parameter *)
  663. WriteType(procedureType.returnType);
  664. (* command name *)
  665. w.RawString(name);
  666. (* command code offset *)
  667. w.RawNum((p.offset ));
  668. INC(numberCommands);
  669. IF Trace THEN
  670. D.Ln
  671. END
  672. END
  673. END
  674. END
  675. END Commands;
  676. (* OutPointers delivers
  677. {pointerOffset}
  678. *)
  679. PROCEDURE OutPointers(offset: LONGINT; type: SyntaxTree.Type; VAR numberPointers: LONGINT);
  680. VAR variable: SyntaxTree.Variable; i,n,size: LONGINT; base: SyntaxTree.Type;
  681. BEGIN
  682. type := type.resolved;
  683. IF type IS SyntaxTree.AnyType THEN
  684. ASSERT(offset MOD 4 = 0);
  685. w.RawNum((offset )); INC(numberPointers);
  686. IF Trace THEN D.Str("ptr at offset="); D.Int(offset,1); D.Ln; END;
  687. ELSIF type IS SyntaxTree.PointerType THEN
  688. ASSERT(offset MOD 4 = 0);
  689. w.RawNum((offset )); INC(numberPointers);
  690. IF Trace THEN D.Str("ptr at offset="); D.Int(offset,1);D.Ln; END;
  691. ELSIF (type IS SyntaxTree.ProcedureType) & (type(SyntaxTree.ProcedureType).isDelegate) THEN
  692. ASSERT(offset MOD 4 = 0);
  693. w.RawNum((offset )+module.system.addressSize DIV 8 ); INC(numberPointers);
  694. IF Trace THEN D.Str("ptr at offset="); D.Int(offset+module.system.addressSize DIV 8,1); END;
  695. ELSIF (type IS SyntaxTree.RecordType) THEN
  696. (* never treat a record like a pointer, even if the pointer field is set! *)
  697. WITH type: SyntaxTree.RecordType DO
  698. base := type.GetBaseRecord();
  699. IF base # NIL THEN
  700. OutPointers(offset,base,numberPointers);
  701. END;
  702. variable := type.recordScope.firstVariable;
  703. WHILE(variable # NIL) DO
  704. IF ~(variable.untraced) THEN
  705. OutPointers(offset+variable.offsetInBits DIV 8,variable.type,numberPointers);
  706. END;
  707. variable := variable.nextVariable;
  708. END;
  709. END;
  710. ELSIF (type IS SyntaxTree.ArrayType) THEN
  711. WITH type: SyntaxTree.ArrayType DO
  712. IF type.form= SyntaxTree.Static THEN
  713. n := type.staticLength;
  714. base := type.arrayBase.resolved;
  715. WHILE(base IS SyntaxTree.ArrayType) DO
  716. type := base(SyntaxTree.ArrayType);
  717. n := n* type.staticLength;
  718. base := type.arrayBase.resolved;
  719. END;
  720. size := module.system.AlignedSizeOf(base) DIV 8;
  721. IF SemanticChecker.ContainsPointer(base) THEN
  722. ASSERT(n<1000000); (* not more than one million pointers on the stack ... *)
  723. FOR i := 0 TO n-1 DO
  724. OutPointers(offset+i*size,base,numberPointers);
  725. END;
  726. END;
  727. ELSE
  728. ASSERT(offset MOD 4 = 0);
  729. w.RawNum((offset )); INC(numberPointers);
  730. IF Trace THEN D.Str("ptr at offset="); D.Int(offset,1); D.Ln; END;
  731. END;
  732. END;
  733. ELSIF (type IS SyntaxTree.MathArrayType) THEN
  734. WITH type: SyntaxTree.MathArrayType DO
  735. IF type.form = SyntaxTree.Static THEN
  736. n := type.staticLength;
  737. base := type.arrayBase.resolved;
  738. WHILE(base IS SyntaxTree.MathArrayType) DO
  739. type := base(SyntaxTree.MathArrayType);
  740. n := n* type.staticLength;
  741. base := type.arrayBase.resolved;
  742. END;
  743. size := module.system.AlignedSizeOf(base) DIV 8;
  744. IF SemanticChecker.ContainsPointer(base) THEN
  745. ASSERT(n<1000000); (* not more than one million pointers on the stack ... *)
  746. FOR i := 0 TO n-1 DO
  747. OutPointers(offset+i*size,base,numberPointers);
  748. END;
  749. END;
  750. ELSE
  751. ASSERT(offset MOD 4 = 0);
  752. w.RawNum((offset )); INC(numberPointers); (* GC relevant pointer is at offset 0 *)
  753. IF Trace THEN D.Str("ptr at offset="); D.Int(offset,1); D.Ln; END;
  754. END
  755. END;
  756. (* ELSE no pointers in type *)
  757. END;
  758. END OutPointers;
  759. (* Pointers =
  760. 84X { pointerOffset:Num}:numberPointers
  761. *)
  762. PROCEDURE Pointers;
  763. VAR
  764. s: Section; variable: SyntaxTree.Variable;
  765. i: LONGINT;
  766. BEGIN
  767. w.Char(84X);
  768. numberPointers := 0;
  769. IF Trace THEN D.Str("Global Pointers: "); D.Ln; END;
  770. FOR i := 0 TO symbols.Length() - 1 DO
  771. s := symbols.GetSection(i);
  772. IF (s.symbol # NIL) & (s.symbol IS SyntaxTree.Variable) THEN
  773. variable := s.symbol(SyntaxTree.Variable);
  774. IF ~(variable.untraced) THEN
  775. OutPointers(s.offset, variable.type, numberPointers);
  776. END
  777. END
  778. END
  779. END Pointers;
  780. PROCEDURE IsFirstOccurence(import: SyntaxTree.Import): BOOLEAN; (*! inefficient *)
  781. VAR i: SyntaxTree.Import;
  782. BEGIN
  783. i := moduleScope.firstImport;
  784. WHILE (i # NIL) & (i.module # import.module) DO
  785. i := i.nextImport;
  786. END;
  787. RETURN i = import
  788. END IsFirstOccurence;
  789. (* Imports =
  790. 85X { moduleName:String }:numberImports
  791. *)
  792. PROCEDURE Imports;
  793. VAR name: Name; import: SyntaxTree.Import;
  794. BEGIN
  795. w.Char(85X);
  796. numberImports := 0;
  797. import := moduleScope.firstImport;
  798. WHILE(import # NIL) DO
  799. IF ~Global.IsSystemModule(import.module) & IsFirstOccurence(import) THEN
  800. Global.ModuleFileName(import.module.name,import.module.context,name);
  801. w.RawString(name); INC(numberImports);
  802. IF Trace THEN
  803. D.Str("Import module : "); D.Str(name); D.Ln;
  804. END;
  805. END;
  806. import := import.nextImport;
  807. END;
  808. END Imports;
  809. (*? should this be coded fix in a separate module list ? *)
  810. (* Module Number returns the position of a module in the written import list *)
  811. PROCEDURE ModuleNumber(m: SyntaxTree.Module): LONGINT;
  812. VAR number: LONGINT; import: SyntaxTree.Import;
  813. BEGIN
  814. number := 1;
  815. import := moduleScope.firstImport;
  816. WHILE(import # NIL) & (import.module # m) DO
  817. IF ~Global.IsSystemModule(import.module) & IsFirstOccurence(import) THEN
  818. INC(number);
  819. END;
  820. import := import.nextImport;
  821. END;
  822. RETURN number;
  823. END ModuleNumber;
  824. (*
  825. VarConstLinks = 8DX {VarConstLinkEntry}: numberVarConstLinks
  826. VarConstLinkEntry = modNumber:1 entry:Number fixupCount:4 {offset:Number}:fixupCount}
  827. *)
  828. PROCEDURE VarConstLinks;
  829. VAR
  830. fixups: LONGINT; fixupsPosition: LONGINT;
  831. s: Section; fixup: Fixup; temp, i: LONGINT;
  832. sym: Section;
  833. PROCEDURE Fixups(f: Fixup);
  834. BEGIN
  835. WHILE f # NIL DO
  836. IF Trace THEN
  837. D.String("fixup "); D.Int(f.fixupSection.offset +f.fixup.offset ,1); D.Ln;
  838. END;
  839. w.RawNum((f.fixupSection.offset + f.fixup.offset )); INC(fixups);
  840. f := f.nextFixup;
  841. END;
  842. END Fixups;
  843. BEGIN
  844. w.Char(8DX);
  845. numberVarConstLinks := 0;
  846. (* global variables and constants of this module *)
  847. w.Char(0X); (* module Number = 0 => this module *)
  848. w.RawNum(-1); (* entry = -1 => this module *)
  849. fixupsPosition := w.Pos(); fixups := 0;
  850. w.RawLInt(fixups); (* number of fixups, to be patche *)
  851. IF Trace THEN D.Str("VarConstLinks:Procedures"); D.Ln; END;
  852. FOR i := 0 TO symbols.Length() - 1 DO
  853. s := symbols.GetSection(i);
  854. IF ~s.isCaseTable THEN
  855. IF (s.symbol=NIL) OR (s.symbol # NIL) & ~(s.symbol IS SyntaxTree.Procedure) THEN
  856. IF Trace THEN D.String("varconstlink, procedure "); Basic.WriteSegmentedName(D.Log, s.name); D.Ln END;
  857. Fixups(s.fixups);
  858. END
  859. END;
  860. END;
  861. (*! can be merged with previous -- for testing consistency *)
  862. FOR i := 0 TO symbols.Length() - 1 DO
  863. s := symbols.GetSection(i);
  864. IF s.isCaseTable THEN
  865. ASSERT(s.symbol # NIL);
  866. IF (s.symbol # NIL) & ~(s.symbol IS SyntaxTree.Procedure) THEN
  867. Fixups(s.fixups);
  868. END
  869. END;
  870. END;
  871. (*
  872. IF Trace THEN D.Str("VarConstLinks:CaseTables"); D.Ln; END;
  873. FOR i := 0 TO module.allSections.Length() - 1 DO
  874. s := module.allSections.GetSection(i);
  875. IF s.kind = Sections.CaseTableKind THEN
  876. IF (s.symbol # NIL) & ~(s.symbol IS SyntaxTree.Procedure) THEN (* includes case symbol! *)
  877. temp := GetFixups(module,s,fixup);
  878. Fixups(fixup);
  879. END
  880. END
  881. END;
  882. *)
  883. RawLIntAt(fixupsPosition,fixups); (* fixups count patched *)
  884. INC(numberVarConstLinks);
  885. IF Trace THEN D.Str("VarConstLinks:ImportedSymbols"); D.Ln; END;
  886. (* imported global variables and constants *)
  887. FOR i := 0 TO importedSymbols.Length()-1 DO
  888. sym := importedSymbols.GetSection(i);
  889. IF (sym.symbol=NIL) OR (sym.symbol # NIL) & ~(sym.symbol IS SyntaxTree.Procedure) THEN
  890. ASSERT(sym.numberFixups > 0);
  891. sym.entryNumber := numberVarConstLinks;
  892. INC(numberVarConstLinks);
  893. w.Char(CHR(ModuleNumber(sym.symbol.scope.ownerModule)));
  894. w.RawNum(0); (* entry = 0 => importing module *)
  895. w.RawLInt(sym.numberFixups); (* number of fixups, to be patched *)
  896. Fixups(sym.fixups);
  897. END;
  898. END;
  899. END VarConstLinks;
  900. (*
  901. Links = 86X {LinkEntry:Number}:numberLinks {FixupCount:Number}:numberEntries caseTableSize:Number
  902. LinkEntry = moduleNumber:1 entryNumber:1 offset:Number
  903. *)
  904. PROCEDURE Links;
  905. VAR
  906. p: Section; procedure: SyntaxTree.Procedure; procedureType: SyntaxTree.ProcedureType; i, counter: LONGINT; temp: LONGINT; fixup: Fixup; fixups: LONGINT;
  907. CONST
  908. FixupSentinel = LONGINT(0FFFFFFFFH);
  909. (* Insert fixup list into code *)
  910. PROCEDURE FixupList(l: Fixup): LONGINT;
  911. VAR
  912. offset,first: LONGINT;
  913. PROCEDURE Put32(offset: LONGINT; number: LONGINT);
  914. BEGIN
  915. code[offset] := CHR(number MOD 256);
  916. INC(offset); number := number DIV 256;
  917. code[offset] := CHR(number MOD 256);
  918. INC(offset); number := number DIV 256;
  919. code[offset] := CHR(number MOD 256);
  920. INC(offset); number := number DIV 256;
  921. code[offset] := CHR(number MOD 256);
  922. END Put32;
  923. BEGIN
  924. offset := (l.fixupSection.offset +l.fixup.offset );first := offset;
  925. l := l.nextFixup;
  926. WHILE l # NIL DO
  927. Put32(offset,(l.fixupSection.offset +l.fixup.offset ));
  928. offset := (l.fixupSection.offset +l.fixup.offset );
  929. l := l.nextFixup;
  930. END;
  931. Put32(offset,FixupSentinel);
  932. RETURN first;
  933. END FixupList;
  934. BEGIN
  935. w.Char(86X);
  936. numberLinks := 0;
  937. (* system call sections removed: replaced by procedure calls *)
  938. IF procedureFixupOffset #-1 THEN
  939. w.Char(0X); w.Char(SysCallMap[ProcAddr]); w.RawNum(procedureFixupOffset);
  940. INC(numberLinks);
  941. END;
  942. IF caseTableSize > 0 THEN
  943. w.Char(0X); w.Char(SysCallMap[CaseTable]);
  944. w.RawNum( constSize - (caseTableSize*addrSize) );
  945. INC(numberLinks);
  946. (* case table is fixuped by the loader using offset of case table in constant section
  947. it is impossible to have disjoint case tables here
  948. *)
  949. END;
  950. counter := 0;
  951. (* cf. Entries *)
  952. FOR i := 0 TO symbols.Length() - 1 DO
  953. p := symbols.GetSection(i);
  954. IF (p.symbol # NIL) & (p.symbol IS SyntaxTree.Procedure) & ~p.symbol(SyntaxTree.Procedure).isInline THEN
  955. fixup := p.fixups;
  956. procedure := p.symbol(SyntaxTree.Procedure);
  957. procedureType := procedure.type(SyntaxTree.ProcedureType);
  958. IF (procedure.access * SyntaxTree.Public # {}) OR (procedureType.isDelegate) OR (fixup # NIL) THEN
  959. w.RawNum(p.numberFixups);
  960. INC(counter);
  961. END
  962. END
  963. END;
  964. ASSERT(counter = numberEntries);
  965. w.RawNum((caseTableSize ));
  966. END Links;
  967. (* Constants = 87X {character:1} *)
  968. PROCEDURE Constants;
  969. VAR i: LONGINT;
  970. BEGIN
  971. w.Char(87X);
  972. FOR i := 0 TO ((constSize-1) ) DO
  973. w.Char(const[i]);
  974. crc32.Char(const[i]);
  975. END;
  976. END Constants;
  977. (* Exports *)
  978. PROCEDURE Exports;
  979. VAR numberExports,numberExportsPosition: LONGINT; constant: SyntaxTree.Constant;
  980. variable: SyntaxTree.Variable; procedure : SyntaxTree.Procedure; typeDeclaration : SyntaxTree.TypeDeclaration;
  981. typeNumber: LONGINT; name: ARRAY 256 OF CHAR;
  982. PROCEDURE ExportType(type: SyntaxTree.Type);
  983. VAR destination: Section; ref: LONGINT; count: LONGINT; countPos: LONGINT;
  984. variable: SyntaxTree.Variable; procedure: SyntaxTree.Procedure; fingerPrint: SyntaxTree.FingerPrint;
  985. initialType: SyntaxTree.Type;
  986. BEGIN
  987. IF type = NIL THEN RETURN END; (* no type *)
  988. type := type.resolved;
  989. (* fof: thjs can cause a repetitive entry of the same type *)
  990. initialType := type;
  991. WHILE (type IS SyntaxTree.PointerType) OR (type IS SyntaxTree.ArrayType) OR (type IS SyntaxTree.MathArrayType) DO
  992. IF type IS SyntaxTree.PointerType THEN
  993. type := type(SyntaxTree.PointerType).pointerBase.resolved;
  994. ELSIF type IS SyntaxTree.ArrayType THEN
  995. type := type(SyntaxTree.ArrayType).arrayBase.resolved;
  996. ELSE
  997. type := type(SyntaxTree.MathArrayType).arrayBase.resolved;
  998. END;
  999. IF type = initialType THEN RETURN END; (* avoid cycles *)
  1000. END;
  1001. IF (type IS SyntaxTree.RecordType) & (type(SyntaxTree.RecordType).recordScope.ownerModule = module.module) THEN
  1002. w.Char(ofEURecord);
  1003. destination := symbols.BySymbol(type.typeDeclaration);
  1004. ASSERT(destination # NIL);
  1005. ref := destination.entryNumber;
  1006. IF ref # 0 THEN
  1007. w.RawNum(-ref);
  1008. IF Trace THEN D.Str("already referenced as "); D.Int(ref,1); D.Ln END;
  1009. ELSE
  1010. count := 0; (* number of exported entries *)
  1011. INC(typeNumber); (* reference number to this type *)
  1012. destination.SetEntryNumber(typeNumber);
  1013. IF Trace THEN D.Str("register as "); D.Int(typeNumber,1); D.Ln END;
  1014. w.RawNum((destination.offset ));
  1015. countPos := w.Pos();
  1016. w.RawLInt(2);
  1017. ExportType(type(SyntaxTree.RecordType).baseType);
  1018. fingerPrint := fingerprinter.TypeFP(type);
  1019. (*
  1020. ASSERT(fingerPrint.privateFP # 0); (* may not be zero by object file format: would be interpreted as end of section *)
  1021. ASSERT(fingerPrint.publicFP # 0); (* ^ ^ *)
  1022. *)
  1023. IF Trace THEN D.Str("export type fp "); D.Int(fingerPrint.private,1); D.Str(","); D.Int(fingerPrint.public,1); D.Ln END;
  1024. w.RawNum(fingerPrint.private); w.RawNum(fingerPrint.public);
  1025. variable := type(SyntaxTree.RecordType).recordScope.firstVariable;
  1026. WHILE variable # NIL DO
  1027. IF variable.access * SyntaxTree.Public # {} THEN
  1028. fingerPrint := fingerprinter.SymbolFP(variable);
  1029. w.RawNum(fingerPrint.shallow);
  1030. ExportType(variable.type);
  1031. INC(count);
  1032. END;
  1033. variable := variable.nextVariable;
  1034. END;
  1035. procedure := type(SyntaxTree.RecordType).recordScope.firstProcedure;
  1036. WHILE procedure # NIL DO
  1037. IF (procedure.access * SyntaxTree.Public # {}) & ~(procedure.isInline) THEN
  1038. fingerPrint := fingerprinter.SymbolFP(procedure);
  1039. w.RawNum(fingerPrint.shallow);
  1040. INC(count);
  1041. END;
  1042. procedure := procedure.nextProcedure;
  1043. END;
  1044. IF count # 0 THEN RawLIntAt(countPos,count+2) END;
  1045. w.Char(ofEUEnd);
  1046. END;
  1047. END;
  1048. END ExportType;
  1049. PROCEDURE SymbolOffset(symbol: SyntaxTree.Symbol): LONGINT;
  1050. VAR s: Section; name: SyntaxTree.IdentifierString;
  1051. BEGIN
  1052. IF (symbol IS SyntaxTree.Procedure) & (symbol(SyntaxTree.Procedure).isInline) THEN
  1053. RETURN 0
  1054. END;
  1055. symbol.GetName(name); (* debugging *)
  1056. s := symbols.BySymbol(symbol); (* TODO *)
  1057. ASSERT(s#NIL);
  1058. RETURN (s.offset);
  1059. END SymbolOffset;
  1060. PROCEDURE ExportSymbol(symbol: SyntaxTree.Symbol; offset: LONGINT;CONST prefix: ARRAY OF CHAR);
  1061. VAR fingerPrint: SyntaxTree.FingerPrint; fp: LONGINT;
  1062. BEGIN
  1063. fingerPrint := fingerprinter.SymbolFP(symbol);
  1064. fp := fingerPrint.shallow;
  1065. (*
  1066. IF prefix # "" THEN (* make unique by object name prefix *)
  1067. FingerPrint.FPString(fp,prefix)
  1068. END;
  1069. *)
  1070. w.RawNum(fp);
  1071. (*! check for duplicate fingerprint *)
  1072. w.RawNum(offset );
  1073. IF Trace THEN
  1074. symbol.GetName(name);
  1075. D.Str("FoxObjectFile.Exports.ExportSymbol ");
  1076. IF prefix # "" THEN D.Str(prefix); D.Str(".") END;
  1077. D.Str(name);
  1078. D.Str(" : ");
  1079. D.Hex(fp,-8); D.Ln;
  1080. END;
  1081. END ExportSymbol;
  1082. PROCEDURE ExportMethods(typeDeclaration: SyntaxTree.TypeDeclaration);
  1083. VAR name: SyntaxTree.IdentifierString; type: SyntaxTree.Type; fingerPrint: SyntaxTree.FingerPrint; initialType: SyntaxTree.Type;
  1084. BEGIN
  1085. type := typeDeclaration.declaredType;
  1086. typeDeclaration.GetName(name);
  1087. type := type.resolved; initialType := type;
  1088. WHILE (type IS SyntaxTree.PointerType) OR (type IS SyntaxTree.ArrayType) OR (type IS SyntaxTree.MathArrayType) DO
  1089. IF type IS SyntaxTree.PointerType THEN
  1090. type := type(SyntaxTree.PointerType).pointerBase.resolved;
  1091. ELSIF type IS SyntaxTree.ArrayType THEN
  1092. type := type(SyntaxTree.ArrayType).arrayBase.resolved;
  1093. ELSE
  1094. type := type(SyntaxTree.MathArrayType).arrayBase.resolved;
  1095. END;
  1096. IF type = initialType THEN RETURN END; (* avoid circles *)
  1097. END;
  1098. IF (type IS SyntaxTree.RecordType) & (type(SyntaxTree.RecordType).recordScope.ownerModule = module.module) THEN
  1099. fingerPrint := fingerprinter.TypeFP(type); (* make sure that fingerprint has traversed all methods ... *)
  1100. procedure := type(SyntaxTree.RecordType).recordScope.firstProcedure;
  1101. WHILE procedure # NIL DO
  1102. IF (procedure.access * SyntaxTree.Public # {}) THEN
  1103. ExportSymbol(procedure,SymbolOffset(procedure),name);
  1104. INC(numberExports);
  1105. END;
  1106. procedure := procedure.nextProcedure;
  1107. END;
  1108. END;
  1109. END ExportMethods;
  1110. BEGIN
  1111. w.Char(88X);
  1112. numberExports := 0; typeNumber := 0;
  1113. numberExportsPosition := w.Pos();
  1114. w.RawLInt(numberExports);
  1115. (*! in the end anything that has an offset should be present in the BackendStructures.Module,
  1116. therefore the list can also be traverse from the respective Backend structure *)
  1117. (* constants *)
  1118. constant := moduleScope.firstConstant;
  1119. WHILE constant # NIL DO
  1120. IF (constant.access * SyntaxTree.Public # {}) THEN
  1121. IF Trace THEN
  1122. constant.GetName(name);
  1123. D.String("Constant:"); D.String(name); D.Ln;
  1124. END;
  1125. IF (~(constant.type IS SyntaxTree.BasicType)) THEN
  1126. ExportSymbol(constant,SymbolOffset(constant),"");
  1127. ELSE
  1128. ExportSymbol(constant,0,"")
  1129. END;
  1130. INC(numberExports);
  1131. END;
  1132. constant := constant.nextConstant;
  1133. END;
  1134. (* global variables *)
  1135. variable := moduleScope.firstVariable;
  1136. WHILE variable # NIL DO
  1137. IF variable.access * SyntaxTree.Public # {} THEN
  1138. IF Trace THEN
  1139. variable.GetName(name);
  1140. D.String("Variable:"); D.String(name); D.Ln;
  1141. END;
  1142. ExportSymbol(variable,SymbolOffset(variable),"");
  1143. ExportType(variable.type);
  1144. INC(numberExports);
  1145. END;
  1146. variable := variable.nextVariable;
  1147. END;
  1148. (* type declarations *)
  1149. typeDeclaration := moduleScope.firstTypeDeclaration;
  1150. WHILE typeDeclaration # NIL DO
  1151. IF TRUE (* typeDeclaration.access * SyntaxTree.Public # {} *) THEN
  1152. IF Trace THEN
  1153. typeDeclaration.GetName(name);
  1154. D.String("TypeDeclaration:"); D.String(name); D.Ln;
  1155. END;
  1156. ExportSymbol(typeDeclaration,0,"");
  1157. ExportType(typeDeclaration.declaredType);
  1158. INC(numberExports);
  1159. END;
  1160. typeDeclaration := typeDeclaration.nextTypeDeclaration
  1161. END;
  1162. (* exported procedures *)
  1163. procedure := moduleScope.firstProcedure;
  1164. WHILE procedure # NIL DO
  1165. IF (procedure.access* SyntaxTree.Public # {}) THEN
  1166. IF Trace THEN
  1167. procedure.GetName(name);
  1168. D.String("Procedure:"); D.String(name); D.Ln;
  1169. END;
  1170. ExportSymbol(procedure,SymbolOffset(procedure),"");
  1171. INC(numberExports);
  1172. END;
  1173. procedure := procedure.nextProcedure;
  1174. END;
  1175. (* exported methods *)
  1176. typeDeclaration := moduleScope.firstTypeDeclaration;
  1177. WHILE typeDeclaration # NIL DO
  1178. IF typeDeclaration.access * SyntaxTree.Public # {} THEN
  1179. ExportMethods(typeDeclaration);
  1180. END;
  1181. typeDeclaration := typeDeclaration.nextTypeDeclaration
  1182. END;
  1183. RawLIntAt(numberExportsPosition,numberExports);
  1184. w.Char(0X);
  1185. END Exports;
  1186. (* Code = 89X {character:1} *)
  1187. PROCEDURE Code;
  1188. VAR i: LONGINT;
  1189. BEGIN
  1190. w.Char(89X);
  1191. FOR i := 0 TO ((codeSize-1) ) DO
  1192. w.Char(code[i]);
  1193. crc32.Char(code[i]);
  1194. END;
  1195. END Code;
  1196. (*
  1197. Use = 08AX {UsedModules} 0X
  1198. UsedModules = moduleName:String {UsedConstant | UsedVariable | UsedProcedure | UsedType } 0X
  1199. UsedConstant = FP:Number constName:String 0X
  1200. UsedVariable = FP:Number varName:String fixlist:Number [1X UsedRecord]
  1201. UsedProcedure = FP:Number procName:String offset:Number
  1202. UsedType = FP:Number typeName:String 0X [1X UsedRecord]
  1203. UsedRecord = tdentry:Number [FP "@"] 0X
  1204. *)
  1205. PROCEDURE Use;
  1206. VAR import: SyntaxTree.Import; name: SyntaxTree.IdentifierString; importedModule: SyntaxTree.Module; s: Section;
  1207. constant: SyntaxTree.Constant; variable: SyntaxTree.Variable; typeDeclaration: SyntaxTree.TypeDeclaration; procedure: SyntaxTree.Procedure;
  1208. type: SyntaxTree.Type;fixup: Fixup; fixups: LONGINT; sym: Section;
  1209. PROCEDURE UseEntry(module: SyntaxTree.Module; symbol: SyntaxTree.Symbol; offsetInBytes: LONGINT; CONST prefix: ARRAY OF CHAR);
  1210. VAR name,suffix: Basic.SectionName; fingerPrint: SyntaxTree.FingerPrint; fp: LONGINT;
  1211. BEGIN
  1212. symbol.GetName(suffix);
  1213. IF prefix # "" THEN
  1214. COPY(prefix,name); Strings.Append(name,"."); Strings.Append(name,suffix);
  1215. ELSE
  1216. name := suffix;
  1217. END;
  1218. fingerPrint := fingerprinter.SymbolFP(symbol);
  1219. fp := fingerPrint.shallow;
  1220. (*
  1221. IF prefix # "" THEN FingerPrint.FPString(fp,prefix) END;
  1222. *)
  1223. w.RawNum(fp);
  1224. IF Trace THEN
  1225. D.Str("FoxObjectFile.Use ");
  1226. D.Str(suffix);
  1227. D.Str(" : "); D.Hex(SYSTEM.VAL(LONGINT,symbol),-8); D.Str(" : ");
  1228. D.Hex(fp,-8);
  1229. D.String(" @ ");
  1230. D.Int(offsetInBytes-ofEUProcFlag,1);
  1231. D.Ln;
  1232. END;
  1233. w.RawString(name);
  1234. w.RawNum(offsetInBytes);
  1235. END UseEntry;
  1236. PROCEDURE UseType(type: SyntaxTree.Type);
  1237. VAR t: Section; fingerPrint: SyntaxTree.FingerPrint; name: SyntaxTree.IdentifierString;
  1238. BEGIN
  1239. type := type.resolved;
  1240. LOOP
  1241. IF type IS SyntaxTree.PointerType THEN type := type(SyntaxTree.PointerType).pointerBase.resolved;
  1242. ELSIF type IS SyntaxTree.ArrayType THEN type := type(SyntaxTree.ArrayType).arrayBase.resolved;
  1243. ELSIF type IS SyntaxTree.MathArrayType THEN type := type(SyntaxTree.MathArrayType).arrayBase.resolved;
  1244. ELSE EXIT
  1245. END;
  1246. END;
  1247. IF type IS SyntaxTree.RecordType THEN
  1248. WITH type: SyntaxTree.RecordType DO
  1249. type.typeDeclaration.GetName(name); (* debugging *)
  1250. IF type.recordScope.ownerModule = importedModule THEN (* type belongs to currently processed module *)
  1251. IF Trace THEN D.Str("UseTypeFP:"); D.Str(name); D.Str("?"); D.Ln END;
  1252. t := symbols.BySymbol(type.typeDeclaration); (* TODO *)
  1253. IF (t # NIL) & (t.referenced) (*(t.fixups # NIL)*) THEN
  1254. t.referenced := FALSE;
  1255. fingerPrint := fingerprinter.TypeFP(type);
  1256. w.Char(ofEURecord);
  1257. w.RawNum(-(t.offset ));
  1258. (* privateFP never set in old compiler *)
  1259. IF Trace THEN D.Str("UseTypeFP:"); D.Str(name); D.Str(":"); D.Int(fingerPrint.public,1); D.Ln END;
  1260. w.RawNum(fingerPrint.public);
  1261. w.RawString("@");
  1262. w.Char(ofEUEnd);
  1263. END;
  1264. ELSE
  1265. (* nothing to be done? => module must be added to import section, this must be done by the semantic checker *)
  1266. END
  1267. END
  1268. END
  1269. END UseType;
  1270. PROCEDURE UseMethods(typeDeclaration: SyntaxTree.TypeDeclaration);
  1271. VAR procedure: SyntaxTree.Procedure; sym: Section; prefix: SyntaxTree.IdentifierString; fingerPrint: SyntaxTree.FingerPrint; type: SyntaxTree.Type;
  1272. fixup: Fixup; fixups: LONGINT;
  1273. BEGIN
  1274. typeDeclaration.GetName(prefix);
  1275. type := typeDeclaration.declaredType.resolved;
  1276. LOOP
  1277. IF type IS SyntaxTree.PointerType THEN type := type(SyntaxTree.PointerType).pointerBase.resolved;
  1278. (*!???? => problems with name prefix. Necessary to treat arrays here?
  1279. ELSIF type IS SyntaxTree.ArrayType THEN type := type(SyntaxTree.ArrayType).arrayBase.resolved;
  1280. ELSIF type IS SyntaxTree.MathArrayType THEN type := type(SyntaxTree.MathArrayType).arrayBase.resolved;
  1281. *)
  1282. ELSE EXIT
  1283. END;
  1284. END;
  1285. IF (type IS SyntaxTree.RecordType) & (type.scope.ownerModule = importedModule) (* do not take alias *) THEN
  1286. fingerPrint := fingerprinter.TypeFP(type); (* make sure that type is fingerprinted including all methods *)
  1287. procedure := type(SyntaxTree.RecordType).recordScope.firstProcedure;
  1288. WHILE procedure # NIL DO
  1289. sym := importedSymbols.BySymbol(procedure);
  1290. IF sym # NIL THEN
  1291. fixup := sym.fixups;
  1292. UseEntry(importedModule,procedure,(fixup.fixupSection.offset + fixup.fixup.offset )+ofEUProcFlag,prefix);
  1293. END;
  1294. procedure := procedure.nextProcedure
  1295. END
  1296. END
  1297. END UseMethods;
  1298. BEGIN
  1299. w.Char(08AX);
  1300. import := moduleScope.firstImport;
  1301. WHILE(import # NIL) DO (*! in a new object file this would not necessarily be ordered by imports (?) *)
  1302. IF (import.module # module.system.systemModule[import.module.case]) & IsFirstOccurence(import) THEN
  1303. importedModule := import.module;
  1304. ASSERT(importedModule # NIL);
  1305. ASSERT(importedModule # module.system.systemModule[0]);
  1306. ASSERT(importedModule # module.system.systemModule[1]);
  1307. Global.ModuleFileName(import.module.name,import.module.context,name);
  1308. w.RawString(name);
  1309. IF Trace THEN
  1310. D.Str("Use module : "); D.Str(name); D.Ln;
  1311. END;
  1312. constant := importedModule.moduleScope.firstConstant;
  1313. WHILE constant # NIL DO
  1314. sym := importedSymbols.BySymbol(constant);
  1315. IF sym # NIL THEN UseEntry(importedModule,constant,0,"") END;
  1316. constant := constant.nextConstant
  1317. END;
  1318. variable := importedModule.moduleScope.firstVariable;
  1319. WHILE variable # NIL DO
  1320. sym := importedSymbols.BySymbol(variable);
  1321. IF sym # NIL THEN
  1322. UseEntry(importedModule,variable,sym.entryNumber,"");
  1323. UseType(variable.type);
  1324. END;
  1325. variable := variable.nextVariable
  1326. END;
  1327. typeDeclaration := importedModule.moduleScope.firstTypeDeclaration;
  1328. WHILE typeDeclaration # NIL DO
  1329. type := typeDeclaration.declaredType;
  1330. IF type IS SyntaxTree.PointerType THEN type := type(SyntaxTree.PointerType).pointerBase END;
  1331. sym := symbols.BySymbol(typeDeclaration); (* only if has been used -- contained in module sections: alias *)
  1332. IF (sym # NIL) & (sym.referenced) THEN
  1333. UseEntry(importedModule,typeDeclaration,0,"");
  1334. UseType(typeDeclaration.declaredType);
  1335. END;
  1336. typeDeclaration := typeDeclaration.nextTypeDeclaration
  1337. END;
  1338. procedure := importedModule.moduleScope.firstProcedure;
  1339. WHILE procedure # NIL DO
  1340. IF ~procedure.isInline THEN
  1341. sym := importedSymbols.BySymbol(procedure);
  1342. IF sym # NIL THEN
  1343. fixup := sym.fixups;
  1344. UseEntry(importedModule,procedure,(fixup.fixupSection.offset + fixup.fixup.offset )+ofEUProcFlag,"");
  1345. END;
  1346. END;
  1347. procedure := procedure.nextProcedure
  1348. END;
  1349. typeDeclaration := importedModule.moduleScope.firstTypeDeclaration;
  1350. WHILE typeDeclaration # NIL DO
  1351. IF ~(typeDeclaration.declaredType IS SyntaxTree.QualifiedType) (* alias *) THEN
  1352. UseMethods(typeDeclaration);
  1353. END;
  1354. typeDeclaration := typeDeclaration.nextTypeDeclaration
  1355. END;
  1356. w.Char(0X);
  1357. END;
  1358. import := import.nextImport;
  1359. END;
  1360. w.Char(0X);
  1361. END Use;
  1362. PROCEDURE WriteType(d:Section; type: SyntaxTree.RecordType; VAR tdSize: LONGINT (* ug *));
  1363. CONST MaxTags = 16; (* ug: temporary solution, Modules.MaxTags *)
  1364. VAR
  1365. tdSizePos, oldmth,newmeth: LONGINT; base: SyntaxTree.RecordType;
  1366. name: SyntaxTree.IdentifierString;
  1367. baseModule: LONGINT; baseEntry: LONGINT;
  1368. upperPartTdSize, lowerPartTdSize: LONGINT;
  1369. size: LONGINT;
  1370. numberPointersPosition: LONGINT;
  1371. numberPointers: LONGINT;
  1372. destination: Section;
  1373. procedure: Section;
  1374. fp: SyntaxTree.FingerPrint;
  1375. m: SyntaxTree.Procedure;
  1376. i: LONGINT;
  1377. typeDeclaration: SyntaxTree.TypeDeclaration;
  1378. BEGIN
  1379. name := "@@";
  1380. ASSERT(type.typeDeclaration # NIL);
  1381. type.typeDeclaration.GetName(name);
  1382. size := module.system.AlignedSizeOf(type) DIV 8;
  1383. w.RawNum(size );
  1384. w.RawNum((d.offset )); (* type descriptor pointer address, patched by loader to type desciptor address *)
  1385. base := type.GetBaseRecord();
  1386. IF (base = NIL) THEN (* no base type *)
  1387. oldmth := 0;
  1388. baseModule := -1;
  1389. baseEntry := -1
  1390. ELSE
  1391. baseModule := 0; (* base type in local module *)
  1392. IF (base.typeDeclaration # NIL) & (base.typeDeclaration.scope # NIL) & (base.typeDeclaration.scope.ownerModule # moduleScope.ownerModule) THEN (* base type in other module *)
  1393. baseModule := ModuleNumber(base.typeDeclaration.scope.ownerModule);
  1394. typeDeclaration := base.typeDeclaration;
  1395. ASSERT(baseModule # 0);
  1396. ELSE
  1397. typeDeclaration := NIL;
  1398. END;
  1399. IF baseModule = 0 THEN
  1400. destination := symbols.BySymbol(base.typeDeclaration); (*TODO*)
  1401. ASSERT(destination # NIL);
  1402. baseEntry := (destination.offset ); (* destination must be non-nil *)
  1403. ELSIF (typeDeclaration # NIL) THEN
  1404. fp := fingerprinter.SymbolFP(typeDeclaration);
  1405. baseEntry := fp.shallow;
  1406. ELSE
  1407. HALT(100);
  1408. (* ELSE
  1409. base := base(SyntaxTree.PointerType).pointerBase;
  1410. fp := fingerprinter.SymbolFP(base.typeDeclaration);
  1411. baseEntry := fp.FP;
  1412. *)
  1413. END;
  1414. oldmth := base.recordScope.numberMethods;
  1415. END;
  1416. w.RawNum(baseModule);
  1417. w.RawNum(baseEntry);
  1418. newmeth := 0;
  1419. m := type.recordScope.firstProcedure;
  1420. WHILE (m# NIL) DO
  1421. INC(newmeth); (*! check that this is not an inline procedure *)
  1422. m := m.nextProcedure;
  1423. END;
  1424. IF type.IsProtected() THEN
  1425. w.RawNum(-type.recordScope.numberMethods); (* number methods total *)
  1426. ELSE
  1427. w.RawNum(type.recordScope.numberMethods); (* number methods total *)
  1428. END;
  1429. w.RawNum(oldmth); (* inherited methods total *)
  1430. w.RawNum(newmeth); (* new methods (overridden or new) *)
  1431. numberPointersPosition:= w.Pos();
  1432. w.RawLInt(0);
  1433. w.RawString(name);
  1434. tdSizePos := w.Pos();
  1435. w.RawLInt(0);
  1436. i := 0;
  1437. m := type.recordScope.firstProcedure;
  1438. WHILE (m#NIL) DO
  1439. IF ~(m.isInline) THEN
  1440. procedure := symbols.BySymbol(m); (*TODO*)
  1441. ASSERT(procedure # NIL);
  1442. m.GetName(name);
  1443. w.RawNum(procedure.symbol(SyntaxTree.Procedure).methodNumber);
  1444. w.RawNum(procedure.entryNumber);
  1445. INC(i);
  1446. END;
  1447. m := m.nextProcedure;
  1448. END;
  1449. (* Ptrs in Record *)
  1450. numberPointers := 0;
  1451. IF Trace THEN D.Str("pointers of type: "); D.Ln; END;
  1452. OutPointers(0, type, numberPointers); (* debug = FALSE *)
  1453. IF numberPointers # 0 THEN RawLIntAt(numberPointersPosition,numberPointers) END;
  1454. (* ug *) upperPartTdSize := module.system.addressSize DIV 8 * (MaxTags + type.recordScope.numberMethods + 1 + 1); (* tags, methods, methods end marker (sentinel), address of TypeInfo *)
  1455. (* ug *) lowerPartTdSize := module.system.addressSize DIV 8 * (2 + (4 + numberPointers) + 1);
  1456. (* ug *) tdSize := upperPartTdSize + lowerPartTdSize;
  1457. (* ug *) RawLIntAt(tdSizePos, tdSize) ;
  1458. END WriteType;
  1459. PROCEDURE Types;
  1460. VAR
  1461. t: Section; tdSize, i: LONGINT;
  1462. typeDeclaration: SyntaxTree.TypeDeclaration; type: SyntaxTree.Type;
  1463. name: ARRAY 256 OF CHAR;
  1464. BEGIN
  1465. w.Char(08BX);
  1466. numberTypes := 0; typeDescSize := 0;
  1467. FOR i := 0 TO symbols.Length() - 1 DO
  1468. t := symbols.GetSection(i);
  1469. IF (t.symbol # NIL) & (t.symbol IS SyntaxTree.TypeDeclaration) THEN
  1470. typeDeclaration := t.symbol(SyntaxTree.TypeDeclaration);
  1471. type := typeDeclaration.declaredType;
  1472. typeDeclaration.GetName(name);
  1473. IF type IS SyntaxTree.PointerType THEN
  1474. IF type(SyntaxTree.PointerType).pointerBase.resolved.typeDeclaration = typeDeclaration THEN (* avoid duplicate declarations *)
  1475. type := type(SyntaxTree.PointerType).pointerBase.resolved;
  1476. END;
  1477. END;
  1478. IF Trace THEN D.Str("FoxObjectFile.Types: "); D.String(name); D.Ln; END;
  1479. IF (type IS SyntaxTree.RecordType) & (type(SyntaxTree.RecordType).recordScope.ownerModule = moduleScope.ownerModule) OR (type(SyntaxTree.RecordType).recordScope.ownerModule = NIL) THEN
  1480. t := symbols.BySymbol(type.typeDeclaration);
  1481. ASSERT(t # NIL);
  1482. WriteType(t,type(SyntaxTree.RecordType),tdSize);
  1483. INC(typeDescSize,tdSize);
  1484. INC(numberTypes);
  1485. END;
  1486. END
  1487. END
  1488. END Types;
  1489. (* Stores the exception handle table in the following format
  1490. ExceptionHandlerTable ::= 8EX {ExceptionTableEntry}
  1491. ExceptionTableEntry ::= 0FFX pcFrom(4 bytes) pcTo(4 bytes) pcHandler(4 bytes)
  1492. Since there is only one FINALLY in every procedure, method, body, ... we don't need
  1493. to obtain an order for nesting.
  1494. *)
  1495. PROCEDURE ExceptionTable;
  1496. VAR
  1497. p: Section; pcFrom, pcTo, pcHandler, i: LONGINT;
  1498. binarySection: BinaryCode.Section;
  1499. BEGIN
  1500. exTableLen := 0;
  1501. w.Char(08EX);
  1502. FOR i := 0 TO symbols.Length() - 1 DO
  1503. p := symbols.GetSection(i);
  1504. IF (p.type = Sections.CodeSection) OR (p.type= Sections.BodyCodeSection) THEN
  1505. binarySection := p.resolved;
  1506. IF binarySection.finally >= 0 THEN
  1507. pcFrom := p.offset;
  1508. pcTo := binarySection.finally+pcFrom;
  1509. pcHandler := binarySection.finally+pcFrom;
  1510. w.Char(0FEX);
  1511. w.RawNum(pcFrom);
  1512. w.RawNum(pcTo);
  1513. w.RawNum(pcHandler);
  1514. INC(exTableLen);
  1515. END;
  1516. END
  1517. END;
  1518. END ExceptionTable;
  1519. PROCEDURE PtrsInProcBlock;
  1520. VAR
  1521. i, counter: LONGINT; destination: Section;
  1522. PROCEDURE PointerOffsets(destination : Section);
  1523. VAR
  1524. numberPointers,numberPointersPos: LONGINT; procedure: SyntaxTree.Procedure; procedureType: SyntaxTree.ProcedureType;
  1525. variable: SyntaxTree.Variable; parameter: SyntaxTree.Parameter;
  1526. BEGIN
  1527. (*!
  1528. ASSERT(destination.offset <= destination.beginOffset);
  1529. ASSERT(destination.beginOffset <= destination.endOffset);
  1530. *)
  1531. w.RawNum((destination.offset ));
  1532. (* the metadata GC is screwed -- validPAF does not work -- removed from compiler *)
  1533. w.RawNum(0);
  1534. w.RawNum(0);
  1535. (*!
  1536. w.RawNum(destination.beginOffset);
  1537. w.RawNum(destination.endOffset);
  1538. *)
  1539. numberPointers := 0;
  1540. numberPointersPos := w.Pos();
  1541. w.RawLInt(0);
  1542. procedure := destination.symbol(SyntaxTree.Procedure);
  1543. procedureType := procedure.type(SyntaxTree.ProcedureType);
  1544. variable := procedure.procedureScope.firstVariable;
  1545. WHILE(variable # NIL) DO
  1546. IF ~(variable.untraced) THEN
  1547. OutPointers(variable.offsetInBits DIV 8,variable.type,numberPointers);
  1548. END;
  1549. variable := variable.nextVariable
  1550. END;
  1551. parameter := procedureType.firstParameter;
  1552. WHILE(parameter # NIL) DO
  1553. IF ~(parameter.untraced) THEN
  1554. OutPointers(parameter.offsetInBits DIV 8,parameter.type,numberPointers);
  1555. END;
  1556. parameter := parameter.nextParameter;
  1557. END;
  1558. (*
  1559. parameter := procedureType.selfParameter;
  1560. IF parameter # NIL THEN
  1561. OutPointers(parameter.offsetInBits DIV 8,parameter.type,numberPointers);
  1562. END;
  1563. *)
  1564. RawLIntAt(numberPointersPos,numberPointers);
  1565. IF numberPointers > maxPtrs THEN
  1566. maxPtrs := numberPointers
  1567. END;
  1568. END PointerOffsets;
  1569. BEGIN
  1570. w.Char(08FX);
  1571. IF Trace THEN D.Str("FoxObjectFile.PtrsInProcBlock"); D.Ln; END;
  1572. maxPtrs := 0;
  1573. counter := 0;
  1574. FOR i := 0 TO symbols.Length() - 1 DO
  1575. destination := symbols.GetSection(i);
  1576. IF (destination.type # Sections.InitCodeSection) & (destination.symbol # NIL) & (destination.symbol IS SyntaxTree.Procedure) & ~destination.symbol(SyntaxTree.Procedure).isInline THEN
  1577. IF Trace THEN D.Str("pointers in "); Basic.WriteSegmentedName(D.Log,destination.name); D.Ln END;
  1578. PointerOffsets(destination);
  1579. INC(counter);
  1580. END
  1581. END;
  1582. numberProcs := counter;
  1583. END PtrsInProcBlock;
  1584. PROCEDURE References;
  1585. CONST
  1586. rfDirect = 1X; rfIndirect = 3X;
  1587. rfStaticArray= 12X; rfDynamicArray=14X; rfOpenArray=15X;
  1588. rfByte = 1X; rfBoolean = 2X; rfChar8=3X; rfShortint=04X; rfInteger = 05X; rfLongint = 06X;
  1589. rfReal = 07X; rfLongreal = 08X; rfSet = 09X; rfDelegate = 0EX; rfString = 0FH; rfPointer = 0DX; rfHugeint = 10X;
  1590. rfChar16=11X; rfChar32=12X; rfAll=13X; rfSame=14X; rfRange=15X; rfRecord=16X; rfComplex = 17X; rfLongcomplex = 18X;
  1591. rfRecordPointer=1DX;
  1592. rfArrayFlag = 80X;
  1593. VAR
  1594. start, i: LONGINT; s: Section;
  1595. PROCEDURE BaseType(type: SyntaxTree.Type): CHAR;
  1596. VAR char: CHAR;
  1597. BEGIN
  1598. IF type = NIL THEN char := rfLongint
  1599. ELSIF type IS SyntaxTree.ByteType THEN char := rfByte
  1600. ELSIF type IS SyntaxTree.BooleanType THEN char := rfBoolean
  1601. ELSIF type IS SyntaxTree.CharacterType THEN
  1602. IF type.sizeInBits = 8 THEN char := rfChar8
  1603. ELSIF type.sizeInBits = 16 THEN char := rfChar16
  1604. ELSIF type.sizeInBits = 32 THEN char := rfChar32
  1605. END;
  1606. ELSIF (type IS SyntaxTree.IntegerType) OR (type IS SyntaxTree.AddressType) OR (type IS SyntaxTree.SizeType) THEN
  1607. IF type.sizeInBits = 8 THEN char := rfShortint
  1608. ELSIF type.sizeInBits = 16 THEN char := rfInteger
  1609. ELSIF type.sizeInBits = 32 THEN char := rfLongint
  1610. ELSIF type.sizeInBits =64 THEN char := rfHugeint
  1611. END;
  1612. ELSIF type IS SyntaxTree.SizeType THEN char := rfLongint
  1613. ELSIF type IS SyntaxTree.FloatType THEN
  1614. IF type.sizeInBits = 32 THEN char := rfReal
  1615. ELSIF type.sizeInBits = 64 THEN char := rfLongreal
  1616. END;
  1617. ELSIF type IS SyntaxTree.ComplexType THEN
  1618. IF type.sizeInBits = 64 THEN char := rfComplex
  1619. ELSIF type.sizeInBits = 128 THEN char := rfLongcomplex
  1620. END;
  1621. ELSIF type IS SyntaxTree.SetType THEN char := rfSet
  1622. ELSIF type IS SyntaxTree.AnyType THEN char := rfPointer
  1623. ELSIF type IS SyntaxTree.ObjectType THEN char := rfPointer
  1624. ELSIF type IS SyntaxTree.PointerType THEN char := rfPointer
  1625. ELSIF type IS SyntaxTree.ProcedureType THEN char := rfDelegate
  1626. ELSIF type IS SyntaxTree.RangeType THEN char := rfRange
  1627. ELSE char := rfShortint; (*RETURN (* ARRAY OF unknown (record): do not write anything *)*)
  1628. END;
  1629. RETURN char
  1630. END BaseType;
  1631. PROCEDURE RecordType(type: SyntaxTree.RecordType);
  1632. VAR destination: Section; name: SyntaxTree.IdentifierString;
  1633. BEGIN
  1634. destination := symbols.BySymbol(type.typeDeclaration);
  1635. IF destination = NIL THEN destination := importedSymbols.BySymbol(type.typeDeclaration) END;
  1636. IF destination = NIL THEN
  1637. (* imported unused record type *)
  1638. w.Char(0X); (* nil type *)
  1639. type.typeDeclaration.GetName(name);
  1640. (*
  1641. this happens when a symbol from a different module is used but the type desciptor is not necessary to be present in the current module
  1642. D.Str("Warning: Unreferenced record type encountered: "); D.String(name); D.String(" unused? "); D.Ln;
  1643. *)
  1644. ELSE
  1645. IF type.pointerType # NIL THEN
  1646. w.Char(rfRecordPointer)
  1647. ELSE
  1648. w.Char(rfRecord);
  1649. END;
  1650. w.RawNum((destination.offset ));
  1651. END;
  1652. END RecordType;
  1653. PROCEDURE StaticArrayLength(type: SyntaxTree.ArrayType; VAR baseType: SyntaxTree.Type): LONGINT;
  1654. BEGIN
  1655. baseType := type.arrayBase.resolved;
  1656. IF type.form = SyntaxTree.Static THEN
  1657. IF baseType IS SyntaxTree.ArrayType THEN
  1658. RETURN type.staticLength * StaticArrayLength(baseType(SyntaxTree.ArrayType),baseType)
  1659. ELSE
  1660. RETURN type.staticLength
  1661. END
  1662. ELSE
  1663. RETURN 0
  1664. END;
  1665. END StaticArrayLength;
  1666. PROCEDURE ArrayType(type: SyntaxTree.ArrayType);
  1667. VAR length: LONGINT; baseType: SyntaxTree.Type; char: CHAR;
  1668. BEGIN
  1669. length := StaticArrayLength(type, baseType);
  1670. char := BaseType(baseType);
  1671. IF type.form # SyntaxTree.Open THEN
  1672. w.Char(CHR(ORD(char)+ORD(rfArrayFlag)));
  1673. w.RawNum(length)
  1674. ELSE
  1675. length :=0;
  1676. (*length := 1+SemanticChecker.Dimension(type,{SyntaxTree.Open});*)
  1677. w.Char(CHR(ORD(char)+ORD(rfArrayFlag)));
  1678. w.RawNum(length)
  1679. END;
  1680. END ArrayType;
  1681. PROCEDURE StaticMathArrayLength(type: SyntaxTree.MathArrayType; VAR baseType: SyntaxTree.Type): LONGINT;
  1682. BEGIN
  1683. baseType := type.arrayBase;
  1684. IF baseType # NIL THEN
  1685. baseType := baseType.resolved;
  1686. END;
  1687. IF type.form = SyntaxTree.Static THEN
  1688. IF (baseType # NIL) & (baseType IS SyntaxTree.MathArrayType) THEN
  1689. RETURN type.staticLength * StaticMathArrayLength(baseType(SyntaxTree.MathArrayType),baseType)
  1690. ELSE
  1691. RETURN type.staticLength
  1692. END
  1693. ELSE
  1694. RETURN 0
  1695. END;
  1696. END StaticMathArrayLength;
  1697. PROCEDURE MathArrayType(type: SyntaxTree.MathArrayType);
  1698. VAR length: LONGINT; baseType: SyntaxTree.Type; char: CHAR;
  1699. BEGIN
  1700. length := StaticMathArrayLength(type, baseType);
  1701. char := BaseType(baseType);
  1702. IF type.form = SyntaxTree.Open THEN
  1703. char := BaseType(module.system.addressType);
  1704. length := 5+2*SemanticChecker.Dimension(type,{SyntaxTree.Open});
  1705. w.Char(CHR(ORD(char)+ORD(rfArrayFlag)));
  1706. w.RawNum(length)
  1707. ELSIF type.form=SyntaxTree.Tensor THEN
  1708. char := BaseType(module.system.addressType);
  1709. w.Char(CHR(ORD(char)));
  1710. ELSE
  1711. w.Char(CHR(ORD(char)+ORD(rfArrayFlag)));
  1712. w.RawNum(length)
  1713. END;
  1714. END MathArrayType;
  1715. PROCEDURE Type(type: SyntaxTree.Type);
  1716. BEGIN
  1717. IF type = NIL THEN w.Char(0X); RETURN ELSE type := type.resolved END;
  1718. IF type IS SyntaxTree.BasicType THEN
  1719. w.Char(BaseType(type))
  1720. ELSIF type IS SyntaxTree.RecordType THEN
  1721. RecordType(type(SyntaxTree.RecordType));
  1722. ELSIF type IS SyntaxTree.ArrayType THEN
  1723. ArrayType(type(SyntaxTree.ArrayType))
  1724. ELSIF type IS SyntaxTree.EnumerationType THEN
  1725. w.Char(BaseType(module.system.longintType))
  1726. ELSIF type IS SyntaxTree.PointerType THEN
  1727. IF type(SyntaxTree.PointerType).pointerBase IS SyntaxTree.RecordType THEN
  1728. RecordType(type(SyntaxTree.PointerType).pointerBase(SyntaxTree.RecordType));
  1729. ELSE
  1730. w.Char(BaseType(type))
  1731. END;
  1732. ELSIF type IS SyntaxTree.ProcedureType THEN
  1733. w.Char(BaseType(type));
  1734. ELSIF type IS SyntaxTree.MathArrayType THEN
  1735. MathArrayType(type(SyntaxTree.MathArrayType));
  1736. ELSE HALT(200)
  1737. END;
  1738. END Type;
  1739. PROCEDURE WriteVariable(variable: SyntaxTree.Variable; indirect: BOOLEAN);
  1740. VAR name: ARRAY 256 OF CHAR; s: Section;
  1741. BEGIN
  1742. IF variable.externalName # NIL THEN RETURN END;
  1743. IF indirect THEN w.Char(rfIndirect) ELSE w.Char(rfDirect) END;
  1744. variable.GetName(name);
  1745. Type(variable.type);
  1746. s := symbols.BySymbol(variable);
  1747. IF s # NIL THEN (* global variable *)
  1748. w.RawNum( s.offset );
  1749. ELSE
  1750. w.RawNum( variable.offsetInBits DIV 8 );
  1751. END;
  1752. w.RawString(name);
  1753. END WriteVariable;
  1754. PROCEDURE WriteParameter(variable: SyntaxTree.Parameter; indirect: BOOLEAN);
  1755. VAR name: ARRAY 256 OF CHAR;
  1756. BEGIN
  1757. IF indirect THEN w.Char(rfIndirect) ELSE w.Char(rfDirect) END;
  1758. variable.GetName(name);
  1759. Type(variable.type);
  1760. w.RawNum((variable.offsetInBits DIV 8));
  1761. variable.GetName(name);
  1762. w.RawString(name);
  1763. END WriteParameter;
  1764. PROCEDURE ReturnType(type: SyntaxTree.Type);
  1765. BEGIN
  1766. IF type = NIL THEN w.Char(0X); RETURN ELSE type := type.resolved END;
  1767. IF type IS SyntaxTree.ArrayType THEN
  1768. WITH type: SyntaxTree.ArrayType DO
  1769. IF type.form = SyntaxTree.Static THEN w.Char(rfStaticArray)
  1770. ELSE w.Char(rfOpenArray)
  1771. END
  1772. END
  1773. ELSIF type IS SyntaxTree.MathArrayType THEN
  1774. WITH type: SyntaxTree.MathArrayType DO
  1775. IF type.form = SyntaxTree.Static THEN w.Char(rfStaticArray)
  1776. ELSE w.Char(rfOpenArray)
  1777. END
  1778. END
  1779. ELSIF type IS SyntaxTree.RecordType THEN
  1780. w.Char(rfRecord);
  1781. ELSE
  1782. w.Char(BaseType(type));
  1783. END;
  1784. END ReturnType;
  1785. PROCEDURE DeclarationName(typeDeclaration: SyntaxTree.TypeDeclaration; VAR name: ARRAY OF CHAR);
  1786. BEGIN
  1787. IF typeDeclaration = NIL THEN COPY("@ANONYMOUS",name)
  1788. ELSE typeDeclaration.GetName(name)
  1789. END;
  1790. END DeclarationName;
  1791. PROCEDURE Procedure(s: Section);
  1792. VAR procedure: SyntaxTree.Procedure; procedureType: SyntaxTree.ProcedureType;
  1793. parameter: SyntaxTree.Parameter; variable: SyntaxTree.Variable;
  1794. name,recordName: ARRAY 256 OF CHAR;
  1795. record: SyntaxTree.RecordType; i: LONGINT;
  1796. BEGIN
  1797. procedure := s.symbol(SyntaxTree.Procedure); (*! check for variable or type symbol for object body *)
  1798. (*procedure.name,name);*)
  1799. Global.GetSymbolNameInScope(procedure,moduleScope,name);
  1800. procedureType := procedure.type(SyntaxTree.ProcedureType);
  1801. w.Char(0F9X);
  1802. w.RawNum((s.offset ));
  1803. w.RawNum(procedureType.numberParameters);
  1804. ReturnType(procedureType.returnType);
  1805. w.RawNum(0); (*! level *)
  1806. w.RawNum(0);
  1807. (*
  1808. IF procedure.scope IS SyntaxTree.RecordScope THEN (* add object name *)
  1809. record := procedure.scope(SyntaxTree.RecordScope).ownerRecord;
  1810. recordName := "";
  1811. IF record.pointerType # NIL THEN
  1812. DeclarationName(record.pointerType.typeDeclaration,recordName);
  1813. ELSE
  1814. DeclarationName(record.typeDeclaration,recordName);
  1815. END;
  1816. i := 0;
  1817. WHILE recordName[i] # 0X DO
  1818. w.Char(recordName[i]); INC(i);
  1819. END;
  1820. w.Char(".");
  1821. END;
  1822. *)
  1823. w.RawString(name);
  1824. parameter := procedureType.firstParameter;
  1825. WHILE(parameter # NIL) DO
  1826. WriteParameter(parameter,parameter.kind # SyntaxTree.ValueParameter); (*!treat exceptions !*)
  1827. parameter := parameter.nextParameter;
  1828. END;
  1829. (*
  1830. parameter := procedureType.selfParameter;
  1831. IF parameter # NIL THEN
  1832. WriteParameter(parameter,parameter.kind # SyntaxTree.ValueParameter); (*!treat exceptions !*)
  1833. END;
  1834. *)
  1835. variable := procedure.procedureScope.firstVariable;
  1836. WHILE(variable # NIL) DO
  1837. WriteVariable(variable,FALSE);
  1838. variable := variable.nextVariable;
  1839. END;
  1840. END Procedure;
  1841. PROCEDURE Scope(s: Section);
  1842. VAR variable: SyntaxTree.Variable;
  1843. BEGIN
  1844. w.Char(0F8X);
  1845. w.RawNum((s.offset ));
  1846. w.RawString("$$");
  1847. variable := moduleScope.firstVariable;
  1848. WHILE(variable # NIL) DO
  1849. WriteVariable(variable,FALSE);
  1850. variable := variable.nextVariable;
  1851. END;
  1852. END Scope;
  1853. BEGIN
  1854. start := w.Pos();
  1855. w.Char(08CX);
  1856. FOR i := 0 TO symbols.Length() - 1 DO
  1857. s := symbols.GetSection(i);
  1858. IF (s.symbol = moduleScope.bodyProcedure) THEN
  1859. Scope(s) (*! must be first procedure in ref section *)
  1860. END
  1861. END;
  1862. FOR i := 0 TO symbols.Length() - 1 DO
  1863. s := symbols.GetSection(i);
  1864. IF (s.symbol = moduleScope.bodyProcedure) THEN (* already done, see above *)
  1865. ELSIF(s.symbol # NIL) & (s.symbol IS SyntaxTree.Procedure) & ~s.symbol(SyntaxTree.Procedure).isInline THEN
  1866. Procedure(s)
  1867. END
  1868. END;
  1869. refSize := w.Pos()-start;
  1870. END References;
  1871. PROCEDURE LinkFixups;
  1872. VAR
  1873. section: Section; symbol: SyntaxTree.Symbol; fixups, i: LONGINT; fixup: Fixup; bfixup: BinaryCode.Fixup;
  1874. PROCEDURE Put32(code: ByteArray; offset: LONGINT; number: LONGINT);
  1875. BEGIN
  1876. code[offset] := CHR(number MOD 256);
  1877. INC(offset); number := number DIV 256;
  1878. code[offset] := CHR(number MOD 256);
  1879. INC(offset); number := number DIV 256;
  1880. code[offset] := CHR(number MOD 256);
  1881. INC(offset); number := number DIV 256;
  1882. code[offset] := CHR(number MOD 256);
  1883. END Put32;
  1884. PROCEDURE Link(first: Fixup);
  1885. VAR this,prev: LONGINT;fixup: Fixup;
  1886. CONST Sentinel = LONGINT(0FFFFFFFFH);
  1887. BEGIN
  1888. fixup := first;
  1889. prev := -1;
  1890. WHILE fixup # NIL DO
  1891. this := (fixup.fixupSection.offset +fixup.fixup.offset );
  1892. IF prev # -1 THEN
  1893. Put32(code,prev,this);
  1894. IF Trace THEN
  1895. D.String("link: "); D.Int(prev,1); D.String(":"); D.Int(this,1); D.Ln;
  1896. END;
  1897. END;
  1898. prev := this;
  1899. fixup := fixup.nextFixup;
  1900. END;
  1901. IF prev # -1 THEN
  1902. Put32(code,prev,Sentinel);
  1903. IF Trace THEN
  1904. D.String("link: "); D.Int(prev,1); D.String(":"); D.Int(Sentinel,1); D.Ln;
  1905. END;
  1906. END;
  1907. END Link;
  1908. BEGIN
  1909. IF Trace THEN D.Str("LinkFixups"); D.Ln; END;
  1910. FOR i := 0 TO importedSymbols.Length()-1 DO
  1911. section := importedSymbols.GetSection(i);
  1912. symbol := section.symbol;
  1913. IF (symbol # NIL) & (symbol IS SyntaxTree.Procedure) THEN
  1914. Link(section.fixups);
  1915. END;
  1916. END;
  1917. END LinkFixups;
  1918. PROCEDURE MakeSections;
  1919. VAR i: LONGINT; fixup: BinaryCode.Fixup; section: Sections.Section; symbol: Section;
  1920. imported: BOOLEAN;
  1921. PROCEDURE Enter(section: Sections.Section; symbols: SectionList; VAR symbol: Section): BOOLEAN;
  1922. BEGIN
  1923. IF section # NIL THEN
  1924. symbol := symbols.AddSection(section.name);
  1925. symbol.isCaseTable := section.isCaseTable;
  1926. symbol.referenced := section.referenced;
  1927. symbol.offset := section.offset;
  1928. symbol.type := section.type;
  1929. symbol.resolved := section(IntermediateCode.Section).resolved;
  1930. IF (section.symbol # NIL) & (symbol.symbol = NIL) THEN
  1931. symbol.symbol := section.symbol;
  1932. symbols.symbolLookup.Put(symbol.symbol, symbol)
  1933. END;
  1934. RETURN TRUE
  1935. ELSE
  1936. RETURN FALSE
  1937. END;
  1938. END Enter;
  1939. BEGIN
  1940. NEW(symbols); NEW(importedSymbols);
  1941. (* enter all sections first to keep ordering *)
  1942. FOR i := 0 TO module.allSections.Length() - 1 DO
  1943. section := module.allSections.GetSection(i);
  1944. IF (section.type # Sections.InlineCodeSection) & (section.type # Sections.InitCodeSection) & ~section.isCaseTable THEN
  1945. IF Enter(section, symbols,symbol) THEN END;
  1946. END;
  1947. END;
  1948. FOR i := 0 TO module.allSections.Length() - 1 DO
  1949. section := module.allSections.GetSection(i);
  1950. IF (section.type # Sections.InlineCodeSection) & (section.type # Sections.InitCodeSection) & ~section.isCaseTable THEN
  1951. (* IF Enter(section, symbols,symbol) THEN END;*)
  1952. fixup := section(IntermediateCode.Section).resolved.fixupList.firstFixup;
  1953. WHILE (fixup # NIL) DO
  1954. IF Enter(module.allSections.FindByName(fixup.symbol.name), symbols,symbol) THEN
  1955. symbol.AddFixup(fixup, section);
  1956. END;
  1957. IF Enter(module.importedSections.FindByName(fixup.symbol.name), importedSymbols,symbol) THEN
  1958. symbol.AddFixup(fixup, section)
  1959. END;
  1960. fixup := fixup.nextFixup;
  1961. END
  1962. END
  1963. END;
  1964. IF Trace THEN
  1965. D.String("imported sections(module) "); D.Ln;
  1966. module.importedSections.Dump(D.Log); D.Ln;
  1967. D.String("sections(module) "); D.Ln;
  1968. module.allSections.Dump(D.Log); D.Ln;
  1969. D.String("imported: "); D.Ln; importedSymbols.Dump(D.Log);
  1970. D.String("not imported: "); D.Ln; symbols.Dump(D.Log);
  1971. D.Ln;
  1972. END;
  1973. END MakeSections;
  1974. (* ObjectFile =
  1975. ofFileTag ofNoZeroCompression ofFileVersion
  1976. SymbolFile
  1977. Header
  1978. Entries
  1979. Commands
  1980. Pointers
  1981. Imports
  1982. VarConstLinks
  1983. Links
  1984. Constants
  1985. Exports
  1986. Code
  1987. Use
  1988. Types
  1989. ExceptionTable
  1990. PtrsInProcBlock
  1991. References
  1992. *)
  1993. BEGIN
  1994. addrSize := module.system.addressSize DIV 8;
  1995. MakeSectionOffsets(module,constSize,dataSize,codeSize,caseTableSize,const,code);
  1996. MakeSections;
  1997. (* from here on we do not need IntermediateCode.Sections any more *)
  1998. LinkFixups;
  1999. IF Trace THEN module.Dump(D.Log);D.Ln; D.Update; END;
  2000. NEW(fingerprinter,module.system);
  2001. (* module.module.name,moduleName);*)
  2002. Global.ModuleFileName(module.module.name,module.module.context,moduleName);
  2003. NEW(crc32);
  2004. IF Trace THEN D.Str("module: "); D.Str(moduleName); D.Ln END;
  2005. moduleScope := module.module.moduleScope;
  2006. w.Char(ofFileTag);
  2007. w.Char(ofNoZeroCompress);
  2008. w.Char(ofFileVersion);
  2009. SymbolFile;
  2010. Header; Entries; Commands; Pointers; Imports; VarConstLinks; Links;
  2011. Constants; Exports; Code; Use; Types; ExceptionTable; PtrsInProcBlock; References;
  2012. endPos := w.Pos();
  2013. w.SetPos(headerPos);
  2014. crc := crc32.GetCRC();
  2015. Header;
  2016. w.SetPos(endPos);
  2017. w.Update;
  2018. END WriteObjectFile;
  2019. PROCEDURE Get*(): Formats.ObjectFileFormat;
  2020. VAR objectFileFormat: ObjectFileFormat;
  2021. BEGIN NEW(objectFileFormat); RETURN objectFileFormat
  2022. END Get;
  2023. BEGIN
  2024. SysCallMap[CaseTable] := 0FFX;
  2025. SysCallMap[ProcAddr] := 0FEX;
  2026. SysCallMap[NewRec] := 0FDX;
  2027. SysCallMap[NewSys] := 0FCX;
  2028. SysCallMap[NewArr] := 0FBX;
  2029. SysCallMap[Start] := CHR(250);
  2030. SysCallMap[Await] := CHR(249);
  2031. SysCallMap[Lock] := CHR(247);
  2032. SysCallMap[Unlock] := CHR(246);
  2033. SysCallMap[InterfaceLookup] := CHR(245);
  2034. SysCallMap[RegisterInterface] := CHR(244);
  2035. SysCallMap[GetProcedure] := CHR(243);
  2036. END FoxBinaryObjectFile.