FoxBinaryObjectFile.Mod 78 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293
  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, 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. diagnostics.Error(module.module.sourceName,Diagnostics.Invalid,Diagnostics.Invalid,"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. diagnostics.Information(module.module.sourceName,label.position,Diagnostics.Invalid," pc position");
  316. RETURN TRUE
  317. END;
  318. END
  319. END;
  320. diagnostics.Error(module.module.sourceName,Diagnostics.Invalid,Diagnostics.Invalid," 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. (*
  327. PROCEDURE InModule(s: Sections.Section):BOOLEAN;
  328. VAR
  329. section: Sections.Section;
  330. i: LONGINT;
  331. BEGIN
  332. FOR i := 0 TO module.allSections.Length() - 1 DO
  333. section := module.allSections.GetSection(i);
  334. IF section = s THEN RETURN TRUE END
  335. END;
  336. RETURN FALSE
  337. END InModule;
  338. *)
  339. PROCEDURE FixupSections;
  340. VAR
  341. section: Sections.Section; dest, i: LONGINT; fixup,next: BinaryCode.Fixup; symbol: Sections.Section;
  342. BEGIN
  343. FOR i := 0 TO module.allSections.Length() - 1 DO
  344. section := module.allSections.GetSection(i);
  345. binarySection := section(IntermediateCode.Section).resolved;
  346. fixup := binarySection.fixupList.firstFixup;
  347. binarySection.fixupList.InitFixupList; (* remove all fixups from list *)
  348. WHILE fixup # NIL DO
  349. next := fixup.nextFixup;
  350. symbol := module.allSections.FindByName(fixup.symbol.name);
  351. IF symbol = NIL THEN
  352. symbol := module.importedSections.FindByName(fixup.symbol.name)
  353. END;
  354. IF symbol # NIL THEN
  355. symbol.SetReferenced(TRUE);
  356. ELSIF Trace THEN
  357. D.String("fixup symbol not found: "); Basic.WriteSegmentedName(D.Log, fixup.symbol.name); D.Ln;
  358. END;
  359. IF (fixup.mode = BinaryCode.Relative) & (symbol # NIL) THEN (* relative offset within module *)
  360. dest := (symbol.offset + fixup.displacement) - (section.offset + fixup.offset);
  361. ASSERT(fixup.symbolOffset = 0);
  362. binarySection.PutDWordAt(fixup.offset, dest);
  363. (* fixup done, does not need to be put back to list *)
  364. ELSIF (fixup.mode = BinaryCode.Absolute) & (symbol # NIL) THEN (* absolute offset within module *)
  365. dest := symbol.offset + fixup.displacement;
  366. binarySection.PutDWordAt(fixup.offset, dest);
  367. binarySection.fixupList.AddFixup(fixup); (* (re-)insert fixup into fixup list *)
  368. ELSIF (fixup.mode = BinaryCode.Absolute) THEN (* absolute fixup on imported symbol *)
  369. dest := fixup.displacement;
  370. binarySection.PutDWordAt(fixup.offset, dest);
  371. binarySection.fixupList.AddFixup(fixup); (* (re-)insert fixup into fixup list *)
  372. ELSE binarySection.fixupList.AddFixup(fixup); (* keep fixup as is: relative fixup on imported symbol *)
  373. END;
  374. fixup := next;
  375. END
  376. END;
  377. END FixupSections;
  378. PROCEDURE Copy(section: BinaryCode.Section; to: ByteArray; offset: LONGINT);
  379. VAR i,ofs: LONGINT;
  380. BEGIN
  381. ofs := (offset );
  382. FOR i := 0 TO ((section.pc-1) ) DO
  383. to[i+ofs] := CHR(section.os.bits.GetBits(i*8,8));
  384. END;
  385. END Copy;
  386. (* only regular sections *)
  387. PROCEDURE FirstOffsets(sectionList: Sections.SectionList);
  388. VAR
  389. section: Sections.Section;
  390. i: LONGINT;
  391. BEGIN
  392. FOR i := 0 TO sectionList.Length() - 1 DO
  393. section := sectionList.GetSection(i);
  394. binarySection := section(IntermediateCode.Section).resolved;
  395. symbol := section.symbol;
  396. IF symbol # NIL THEN
  397. symbol.GetName(symbolName);
  398. IF section.symbol = module.module.moduleScope.bodyProcedure THEN
  399. section.SetOffset(0); INC(codeSize,binarySection.pc);
  400. ELSIF symbolName = "@moduleSelf" THEN
  401. section.SetOffset(0); INC(constSize,binarySection.pc);
  402. END;
  403. END
  404. END;
  405. END FirstOffsets;
  406. (* note: if 'caseSections' is TRUE, only case table sections are processed, otherwise only regular sections (imported symbol/system call sections are never processed) *)
  407. PROCEDURE SetOffsets(sectionList: Sections.SectionList; caseTables: BOOLEAN);
  408. VAR
  409. section: Sections.Section;
  410. i: LONGINT;
  411. BEGIN
  412. FOR i := 0 TO sectionList.Length() - 1 DO
  413. section := sectionList.GetSection(i);
  414. IF section.isCaseTable = caseTables THEN
  415. binarySection := section(IntermediateCode.Section).resolved;
  416. symbol := section.symbol;
  417. IF symbol # NIL THEN
  418. symbol.GetName(symbolName);
  419. ELSE symbolName := "";
  420. END;
  421. IF section.symbol = module.module.moduleScope.bodyProcedure THEN
  422. ELSIF symbolName = "@moduleSelf" THEN
  423. ELSIF section.type = Sections.ConstSection THEN
  424. IF binarySection.os.alignment # 0 THEN
  425. INC(constSize,(-constSize) MOD binarySection.os.alignment);
  426. END;
  427. section.SetOffset(constSize); INC(constSize,binarySection.pc); (* global constants: positive offset *)
  428. ELSIF (section.type = Sections.CodeSection) OR (section.type = Sections.BodyCodeSection) THEN
  429. section.SetOffset(codeSize); INC(codeSize, binarySection.pc);
  430. ELSIF section.type = Sections.VarSection THEN
  431. INC(varSize, binarySection.pc);
  432. IF binarySection.os.alignment # 0 THEN
  433. INC(varSize,(-varSize) MOD binarySection.os.alignment);
  434. END;
  435. section.SetOffset(-varSize); (* global variables: negative offset *)
  436. END
  437. END;
  438. END;
  439. END SetOffsets;
  440. (* note: if 'caseSections' is TRUE, only case table sections are processed, otherwise only regular sections (imported symbol/system call sections are never processed) *)
  441. PROCEDURE CopySections(sectionList: Sections.SectionList);
  442. VAR
  443. section: Sections.Section;
  444. i: LONGINT;
  445. BEGIN
  446. FOR i := 0 TO sectionList.Length() - 1 DO
  447. section := sectionList.GetSection(i);
  448. binarySection := section(IntermediateCode.Section).resolved;
  449. IF section.type = Sections.ConstSection THEN
  450. Copy(binarySection,const,section.offset);
  451. ELSIF (section.type = Sections.CodeSection) OR (section.type = Sections.BodyCodeSection) THEN
  452. Copy(binarySection,code,section.offset);
  453. END
  454. END;
  455. END CopySections;
  456. BEGIN
  457. FirstOffsets(module.allSections); (* regular sections *)
  458. SetOffsets(module.allSections,FALSE); (* regular sections *)
  459. pc := constSize;
  460. SetOffsets(module.allSections, TRUE); (* case table sections *)
  461. caseTableSize := (constSize -pc) DIV 4 ;
  462. FixupSections;
  463. NEW(const,constSize ); NEW(code,codeSize );
  464. CopySections(module.allSections); (* regular sections *)
  465. END MakeSectionOffsets;
  466. PROCEDURE WriteObjectFile*(w:Streams.Writer; module: Sections.Module; symbolFile: Files.File);
  467. VAR moduleName: Name; refSize, numberEntries,numberCommands,numberPointers,numberTypes,numberImports,
  468. numberVarConstLinks,numberLinks: LONGINT;
  469. dataSize,constSize,codeSize,caseTableSize: LONGINT;
  470. exTableLen,numberProcs,maxPtrs,typeDescSize: LONGINT; headerPos,endPos: LONGINT;
  471. moduleScope: SyntaxTree.ModuleScope; fingerprinter: FingerPrinter.FingerPrinter;
  472. const, code: ByteArray; procedureFixupOffset : LONGINT;
  473. crc: LONGINT; crc32: Basic.CRC32Stream;
  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. IF section = NIL THEN
  639. section := importedSymbols.BySymbol(type.typeDeclaration);
  640. END;
  641. ASSERT(section # NIL);
  642. w.RawNum((section.offset )); (* type descriptor section offset *)
  643. IF Trace THEN
  644. D.String(", t="); D.Int(section.offset ,1);
  645. END;
  646. END;
  647. END WriteType;
  648. BEGIN
  649. w.Char(83X);
  650. FOR i := 0 TO symbols.Length() - 1 DO
  651. p := symbols.GetSection(i);
  652. IF (p.symbol # NIL) & (p.symbol IS SyntaxTree.Procedure) THEN
  653. procedure := p.symbol(SyntaxTree.Procedure);
  654. procedureType := procedure.type(SyntaxTree.ProcedureType);
  655. IF (SyntaxTree.PublicWrite IN procedure.access) & ~(procedure.isInline) & ~(procedureType.isDelegate) & GetProcedureAllowed() THEN
  656. procedure.GetName(name);
  657. IF Trace THEN
  658. D.Str("Command : "); D.Str(name); D.Str(" @ "); D.Int(p.offset ,1);
  659. END;
  660. numberParameters := procedureType.numberParameters;
  661. (* offset of type of first parameter *)
  662. IF (numberParameters = 0 ) THEN WriteType(NIL)
  663. ELSE WriteType(procedureType.firstParameter.type)
  664. END;
  665. (* offset of type of return parameter *)
  666. WriteType(procedureType.returnType);
  667. (* command name *)
  668. w.RawString(name);
  669. (* command code offset *)
  670. w.RawNum((p.offset ));
  671. INC(numberCommands);
  672. IF Trace THEN
  673. D.Ln
  674. END
  675. END
  676. END
  677. END
  678. END Commands;
  679. (* OutPointers delivers
  680. {pointerOffset}
  681. *)
  682. PROCEDURE OutPointers(offset: LONGINT; type: SyntaxTree.Type; VAR numberPointers: LONGINT);
  683. VAR variable: SyntaxTree.Variable; i,n,size: LONGINT; base: SyntaxTree.Type;
  684. BEGIN
  685. type := type.resolved;
  686. IF type IS SyntaxTree.AnyType THEN
  687. ASSERT(offset MOD 4 = 0);
  688. w.RawNum((offset )); INC(numberPointers);
  689. IF Trace THEN D.Str("ptr at offset="); D.Int(offset,1); D.Ln; END;
  690. ELSIF type IS SyntaxTree.PointerType THEN
  691. ASSERT(offset MOD 4 = 0);
  692. w.RawNum((offset )); INC(numberPointers);
  693. IF Trace THEN D.Str("ptr at offset="); D.Int(offset,1);D.Ln; END;
  694. ELSIF (type IS SyntaxTree.ProcedureType) & (type(SyntaxTree.ProcedureType).isDelegate) THEN
  695. ASSERT(offset MOD 4 = 0);
  696. w.RawNum((offset )+module.system.addressSize DIV 8 ); INC(numberPointers);
  697. IF Trace THEN D.Str("ptr at offset="); D.Int(offset+module.system.addressSize DIV 8,1); END;
  698. ELSIF (type IS SyntaxTree.RecordType) THEN
  699. (* never treat a record like a pointer, even if the pointer field is set! *)
  700. WITH type: SyntaxTree.RecordType DO
  701. base := type.GetBaseRecord();
  702. IF base # NIL THEN
  703. OutPointers(offset,base,numberPointers);
  704. END;
  705. variable := type.recordScope.firstVariable;
  706. WHILE(variable # NIL) DO
  707. IF ~(variable.untraced) THEN
  708. OutPointers(offset+variable.offsetInBits DIV 8,variable.type,numberPointers);
  709. END;
  710. variable := variable.nextVariable;
  711. END;
  712. END;
  713. ELSIF (type IS SyntaxTree.ArrayType) THEN
  714. WITH type: SyntaxTree.ArrayType DO
  715. IF type.form= SyntaxTree.Static THEN
  716. n := type.staticLength;
  717. base := type.arrayBase.resolved;
  718. WHILE(base IS SyntaxTree.ArrayType) DO
  719. type := base(SyntaxTree.ArrayType);
  720. n := n* type.staticLength;
  721. base := type.arrayBase.resolved;
  722. END;
  723. size := module.system.AlignedSizeOf(base) DIV 8;
  724. IF SemanticChecker.ContainsPointer(base) THEN
  725. ASSERT(n<1000000); (* not more than one million pointers on the stack ... *)
  726. FOR i := 0 TO n-1 DO
  727. OutPointers(offset+i*size,base,numberPointers);
  728. END;
  729. END;
  730. ELSE
  731. ASSERT(offset MOD 4 = 0);
  732. w.RawNum((offset )); INC(numberPointers);
  733. IF Trace THEN D.Str("ptr at offset="); D.Int(offset,1); D.Ln; END;
  734. END;
  735. END;
  736. ELSIF (type IS SyntaxTree.MathArrayType) THEN
  737. WITH type: SyntaxTree.MathArrayType DO
  738. IF type.form = SyntaxTree.Static THEN
  739. n := type.staticLength;
  740. base := type.arrayBase.resolved;
  741. WHILE(base IS SyntaxTree.MathArrayType) DO
  742. type := base(SyntaxTree.MathArrayType);
  743. n := n* type.staticLength;
  744. base := type.arrayBase.resolved;
  745. END;
  746. size := module.system.AlignedSizeOf(base) DIV 8;
  747. IF SemanticChecker.ContainsPointer(base) THEN
  748. ASSERT(n<1000000); (* not more than one million pointers on the stack ... *)
  749. FOR i := 0 TO n-1 DO
  750. OutPointers(offset+i*size,base,numberPointers);
  751. END;
  752. END;
  753. ELSE
  754. ASSERT(offset MOD 4 = 0);
  755. w.RawNum((offset )); INC(numberPointers); (* GC relevant pointer is at offset 0 *)
  756. IF Trace THEN D.Str("ptr at offset="); D.Int(offset,1); D.Ln; END;
  757. END
  758. END;
  759. (* ELSE no pointers in type *)
  760. END;
  761. END OutPointers;
  762. (* Pointers =
  763. 84X { pointerOffset:Num}:numberPointers
  764. *)
  765. PROCEDURE Pointers;
  766. VAR
  767. s: Section; variable: SyntaxTree.Variable;
  768. i: LONGINT;
  769. BEGIN
  770. w.Char(84X);
  771. numberPointers := 0;
  772. IF Trace THEN D.Str("Global Pointers: "); D.Ln; END;
  773. FOR i := 0 TO symbols.Length() - 1 DO
  774. s := symbols.GetSection(i);
  775. IF (s.symbol # NIL) & (s.symbol IS SyntaxTree.Variable) THEN
  776. variable := s.symbol(SyntaxTree.Variable);
  777. IF ~(variable.untraced) THEN
  778. OutPointers(s.offset, variable.type, numberPointers);
  779. END
  780. END
  781. END
  782. END Pointers;
  783. PROCEDURE IsFirstOccurence(import: SyntaxTree.Import): BOOLEAN; (*! inefficient *)
  784. VAR i: SyntaxTree.Import;
  785. BEGIN
  786. i := moduleScope.firstImport;
  787. WHILE (i # NIL) & (i.module # import.module) DO
  788. i := i.nextImport;
  789. END;
  790. RETURN i = import
  791. END IsFirstOccurence;
  792. (* Imports =
  793. 85X { moduleName:String }:numberImports
  794. *)
  795. PROCEDURE Imports;
  796. VAR name: Name; import: SyntaxTree.Import;
  797. BEGIN
  798. w.Char(85X);
  799. numberImports := 0;
  800. import := moduleScope.firstImport;
  801. WHILE(import # NIL) DO
  802. IF ~Global.IsSystemModule(import.module) & IsFirstOccurence(import) THEN
  803. Global.ModuleFileName(import.module.name,import.module.context,name);
  804. w.RawString(name); INC(numberImports);
  805. IF Trace THEN
  806. D.Str("Import module : "); D.Str(name); D.Ln;
  807. END;
  808. END;
  809. import := import.nextImport;
  810. END;
  811. END Imports;
  812. (*? should this be coded fix in a separate module list ? *)
  813. (* Module Number returns the position of a module in the written import list *)
  814. PROCEDURE ModuleNumber(m: SyntaxTree.Module): LONGINT;
  815. VAR number: LONGINT; import: SyntaxTree.Import;
  816. BEGIN
  817. number := 1;
  818. import := moduleScope.firstImport;
  819. WHILE(import # NIL) & (import.module # m) DO
  820. IF ~Global.IsSystemModule(import.module) & IsFirstOccurence(import) THEN
  821. INC(number);
  822. END;
  823. import := import.nextImport;
  824. END;
  825. RETURN number;
  826. END ModuleNumber;
  827. (*
  828. VarConstLinks = 8DX {VarConstLinkEntry}: numberVarConstLinks
  829. VarConstLinkEntry = modNumber:1 entry:Number fixupCount:4 {offset:Number}:fixupCount}
  830. *)
  831. PROCEDURE VarConstLinks;
  832. VAR
  833. fixups: LONGINT; fixupsPosition: LONGINT;
  834. s: Section; fixup: Fixup; temp, i: LONGINT;
  835. sym: Section;
  836. PROCEDURE Fixups(f: Fixup);
  837. BEGIN
  838. WHILE f # NIL DO
  839. IF Trace THEN
  840. D.String("fixup "); D.Int(f.fixupSection.offset +f.fixup.offset ,1); D.Ln;
  841. END;
  842. w.RawNum((f.fixupSection.offset + f.fixup.offset )); INC(fixups);
  843. f := f.nextFixup;
  844. END;
  845. END Fixups;
  846. BEGIN
  847. w.Char(8DX);
  848. numberVarConstLinks := 0;
  849. (* global variables and constants of this module *)
  850. w.Char(0X); (* module Number = 0 => this module *)
  851. w.RawNum(-1); (* entry = -1 => this module *)
  852. fixupsPosition := w.Pos(); fixups := 0;
  853. w.RawLInt(fixups); (* number of fixups, to be patche *)
  854. IF Trace THEN D.Str("VarConstLinks:Procedures"); D.Ln; END;
  855. FOR i := 0 TO symbols.Length() - 1 DO
  856. s := symbols.GetSection(i);
  857. IF ~s.isCaseTable THEN
  858. IF (s.symbol=NIL) OR (s.symbol # NIL) & ~(s.symbol IS SyntaxTree.Procedure) THEN
  859. IF Trace THEN D.String("varconstlink, procedure "); Basic.WriteSegmentedName(D.Log, s.name); D.Ln END;
  860. Fixups(s.fixups);
  861. END
  862. END;
  863. END;
  864. (*! can be merged with previous -- for testing consistency *)
  865. FOR i := 0 TO symbols.Length() - 1 DO
  866. s := symbols.GetSection(i);
  867. IF s.isCaseTable THEN
  868. ASSERT(s.symbol # NIL);
  869. IF (s.symbol # NIL) & ~(s.symbol IS SyntaxTree.Procedure) THEN
  870. Fixups(s.fixups);
  871. END
  872. END;
  873. END;
  874. (*
  875. IF Trace THEN D.Str("VarConstLinks:CaseTables"); D.Ln; END;
  876. FOR i := 0 TO module.allSections.Length() - 1 DO
  877. s := module.allSections.GetSection(i);
  878. IF s.kind = Sections.CaseTableKind THEN
  879. IF (s.symbol # NIL) & ~(s.symbol IS SyntaxTree.Procedure) THEN (* includes case symbol! *)
  880. temp := GetFixups(module,s,fixup);
  881. Fixups(fixup);
  882. END
  883. END
  884. END;
  885. *)
  886. RawLIntAt(fixupsPosition,fixups); (* fixups count patched *)
  887. INC(numberVarConstLinks);
  888. IF Trace THEN D.Str("VarConstLinks:ImportedSymbols"); D.Ln; END;
  889. (* imported global variables and constants *)
  890. FOR i := 0 TO importedSymbols.Length()-1 DO
  891. sym := importedSymbols.GetSection(i);
  892. IF (sym.symbol=NIL) OR (sym.symbol # NIL) & ~(sym.symbol IS SyntaxTree.Procedure) THEN
  893. ASSERT(sym.numberFixups > 0);
  894. sym.entryNumber := numberVarConstLinks;
  895. INC(numberVarConstLinks);
  896. w.Char(CHR(ModuleNumber(sym.symbol.scope.ownerModule)));
  897. w.RawNum(0); (* entry = 0 => importing module *)
  898. w.RawLInt(sym.numberFixups); (* number of fixups, to be patched *)
  899. Fixups(sym.fixups);
  900. END;
  901. END;
  902. END VarConstLinks;
  903. (*
  904. Links = 86X {LinkEntry:Number}:numberLinks {FixupCount:Number}:numberEntries caseTableSize:Number
  905. LinkEntry = moduleNumber:1 entryNumber:1 offset:Number
  906. *)
  907. PROCEDURE Links;
  908. VAR
  909. p: Section; procedure: SyntaxTree.Procedure; procedureType: SyntaxTree.ProcedureType; i, counter: LONGINT; temp: LONGINT; fixup: Fixup; fixups: LONGINT;
  910. CONST
  911. FixupSentinel = LONGINT(0FFFFFFFFH);
  912. (* Insert fixup list into code *)
  913. PROCEDURE FixupList(l: Fixup): LONGINT;
  914. VAR
  915. offset,first: LONGINT;
  916. PROCEDURE Put32(offset: LONGINT; number: LONGINT);
  917. BEGIN
  918. code[offset] := CHR(number MOD 256);
  919. INC(offset); number := number DIV 256;
  920. code[offset] := CHR(number MOD 256);
  921. INC(offset); number := number DIV 256;
  922. code[offset] := CHR(number MOD 256);
  923. INC(offset); number := number DIV 256;
  924. code[offset] := CHR(number MOD 256);
  925. END Put32;
  926. BEGIN
  927. offset := (l.fixupSection.offset +l.fixup.offset );first := offset;
  928. l := l.nextFixup;
  929. WHILE l # NIL DO
  930. Put32(offset,(l.fixupSection.offset +l.fixup.offset ));
  931. offset := (l.fixupSection.offset +l.fixup.offset );
  932. l := l.nextFixup;
  933. END;
  934. Put32(offset,FixupSentinel);
  935. RETURN first;
  936. END FixupList;
  937. BEGIN
  938. w.Char(86X);
  939. numberLinks := 0;
  940. (* system call sections removed: replaced by procedure calls *)
  941. IF procedureFixupOffset #-1 THEN
  942. w.Char(0X); w.Char(SysCallMap[ProcAddr]); w.RawNum(procedureFixupOffset);
  943. INC(numberLinks);
  944. END;
  945. IF caseTableSize > 0 THEN
  946. w.Char(0X); w.Char(SysCallMap[CaseTable]); w.RawNum((constSize -caseTableSize *4));
  947. INC(numberLinks);
  948. (* case table is fixuped by the loader using offset of case table in constant section
  949. it is impossible to have disjoint case tables here
  950. *)
  951. END;
  952. counter := 0;
  953. (* cf. Entries *)
  954. FOR i := 0 TO symbols.Length() - 1 DO
  955. p := symbols.GetSection(i);
  956. IF (p.symbol # NIL) & (p.symbol IS SyntaxTree.Procedure) & ~p.symbol(SyntaxTree.Procedure).isInline THEN
  957. fixup := p.fixups;
  958. procedure := p.symbol(SyntaxTree.Procedure);
  959. procedureType := procedure.type(SyntaxTree.ProcedureType);
  960. IF (procedure.access * SyntaxTree.Public # {}) OR (procedureType.isDelegate) OR (fixup # NIL) THEN
  961. w.RawNum(p.numberFixups);
  962. INC(counter);
  963. END
  964. END
  965. END;
  966. ASSERT(counter = numberEntries);
  967. w.RawNum((caseTableSize ));
  968. END Links;
  969. (* Constants = 87X {character:1} *)
  970. PROCEDURE Constants;
  971. VAR i: LONGINT;
  972. BEGIN
  973. w.Char(87X);
  974. FOR i := 0 TO ((constSize-1) ) DO
  975. w.Char(const[i]);
  976. crc32.Char(const[i]);
  977. END;
  978. END Constants;
  979. (* Exports *)
  980. PROCEDURE Exports;
  981. VAR numberExports,numberExportsPosition: LONGINT; constant: SyntaxTree.Constant;
  982. variable: SyntaxTree.Variable; procedure : SyntaxTree.Procedure; typeDeclaration : SyntaxTree.TypeDeclaration;
  983. typeNumber: LONGINT; name: ARRAY 256 OF CHAR;
  984. PROCEDURE ExportType(type: SyntaxTree.Type);
  985. VAR destination: Section; ref: LONGINT; count: LONGINT; countPos: LONGINT;
  986. variable: SyntaxTree.Variable; procedure: SyntaxTree.Procedure; fingerPrint: SyntaxTree.FingerPrint;
  987. initialType: SyntaxTree.Type;
  988. BEGIN
  989. IF type = NIL THEN RETURN END; (* no type *)
  990. type := type.resolved;
  991. (* fof: thjs can cause a repetitive entry of the same type *)
  992. initialType := type;
  993. WHILE (type IS SyntaxTree.PointerType) OR (type IS SyntaxTree.ArrayType) OR (type IS SyntaxTree.MathArrayType) DO
  994. IF type IS SyntaxTree.PointerType THEN
  995. type := type(SyntaxTree.PointerType).pointerBase.resolved;
  996. ELSIF type IS SyntaxTree.ArrayType THEN
  997. type := type(SyntaxTree.ArrayType).arrayBase.resolved;
  998. ELSE
  999. type := type(SyntaxTree.MathArrayType).arrayBase.resolved;
  1000. END;
  1001. IF type = initialType THEN RETURN END; (* avoid cycles *)
  1002. END;
  1003. IF (type IS SyntaxTree.RecordType) & (type(SyntaxTree.RecordType).recordScope.ownerModule = module.module) THEN
  1004. w.Char(ofEURecord);
  1005. destination := symbols.BySymbol(type.typeDeclaration);
  1006. ASSERT(destination # NIL);
  1007. ref := destination.entryNumber;
  1008. IF ref # 0 THEN
  1009. w.RawNum(-ref);
  1010. IF Trace THEN D.Str("already referenced as "); D.Int(ref,1); D.Ln END;
  1011. ELSE
  1012. count := 0; (* number of exported entries *)
  1013. INC(typeNumber); (* reference number to this type *)
  1014. destination.SetEntryNumber(typeNumber);
  1015. IF Trace THEN D.Str("register as "); D.Int(typeNumber,1); D.Ln END;
  1016. w.RawNum((destination.offset ));
  1017. countPos := w.Pos();
  1018. w.RawLInt(2);
  1019. ExportType(type(SyntaxTree.RecordType).baseType);
  1020. fingerPrint := fingerprinter.TypeFP(type);
  1021. (*
  1022. ASSERT(fingerPrint.privateFP # 0); (* may not be zero by object file format: would be interpreted as end of section *)
  1023. ASSERT(fingerPrint.publicFP # 0); (* ^ ^ *)
  1024. *)
  1025. IF Trace THEN D.Str("export type fp "); D.Int(fingerPrint.private,1); D.Str(","); D.Int(fingerPrint.public,1); D.Ln END;
  1026. w.RawNum(fingerPrint.private); w.RawNum(fingerPrint.public);
  1027. variable := type(SyntaxTree.RecordType).recordScope.firstVariable;
  1028. WHILE variable # NIL DO
  1029. IF variable.access * SyntaxTree.Public # {} THEN
  1030. fingerPrint := fingerprinter.SymbolFP(variable);
  1031. w.RawNum(fingerPrint.shallow);
  1032. ExportType(variable.type);
  1033. INC(count);
  1034. END;
  1035. variable := variable.nextVariable;
  1036. END;
  1037. procedure := type(SyntaxTree.RecordType).recordScope.firstProcedure;
  1038. WHILE procedure # NIL DO
  1039. IF (procedure.access * SyntaxTree.Public # {}) & ~(procedure.isInline) THEN
  1040. fingerPrint := fingerprinter.SymbolFP(procedure);
  1041. w.RawNum(fingerPrint.shallow);
  1042. INC(count);
  1043. END;
  1044. procedure := procedure.nextProcedure;
  1045. END;
  1046. IF count # 0 THEN RawLIntAt(countPos,count+2) END;
  1047. w.Char(ofEUEnd);
  1048. END;
  1049. END;
  1050. END ExportType;
  1051. PROCEDURE SymbolOffset(symbol: SyntaxTree.Symbol): LONGINT;
  1052. VAR s: Section; name: SyntaxTree.IdentifierString;
  1053. BEGIN
  1054. IF (symbol IS SyntaxTree.Procedure) & (symbol(SyntaxTree.Procedure).isInline) THEN
  1055. RETURN 0
  1056. END;
  1057. symbol.GetName(name); (* debugging *)
  1058. s := symbols.BySymbol(symbol); (* TODO *)
  1059. ASSERT(s#NIL);
  1060. RETURN (s.offset);
  1061. END SymbolOffset;
  1062. PROCEDURE ExportSymbol(symbol: SyntaxTree.Symbol; offset: LONGINT;CONST prefix: ARRAY OF CHAR);
  1063. VAR fingerPrint: SyntaxTree.FingerPrint; fp: LONGINT;
  1064. BEGIN
  1065. fingerPrint := fingerprinter.SymbolFP(symbol);
  1066. fp := fingerPrint.shallow;
  1067. (*
  1068. IF prefix # "" THEN (* make unique by object name prefix *)
  1069. FingerPrint.FPString(fp,prefix)
  1070. END;
  1071. *)
  1072. w.RawNum(fp);
  1073. (*! check for duplicate fingerprint *)
  1074. w.RawNum(offset );
  1075. IF Trace THEN
  1076. symbol.GetName(name);
  1077. D.Str("FoxObjectFile.Exports.ExportSymbol ");
  1078. IF prefix # "" THEN D.Str(prefix); D.Str(".") END;
  1079. D.Str(name);
  1080. D.Str(" : ");
  1081. D.Hex(fp,-8); D.Ln;
  1082. END;
  1083. END ExportSymbol;
  1084. PROCEDURE ExportMethods(typeDeclaration: SyntaxTree.TypeDeclaration);
  1085. VAR name: SyntaxTree.IdentifierString; type: SyntaxTree.Type; fingerPrint: SyntaxTree.FingerPrint; initialType: SyntaxTree.Type;
  1086. BEGIN
  1087. type := typeDeclaration.declaredType;
  1088. typeDeclaration.GetName(name);
  1089. type := type.resolved; initialType := type;
  1090. WHILE (type IS SyntaxTree.PointerType) OR (type IS SyntaxTree.ArrayType) OR (type IS SyntaxTree.MathArrayType) DO
  1091. IF type IS SyntaxTree.PointerType THEN
  1092. type := type(SyntaxTree.PointerType).pointerBase.resolved;
  1093. ELSIF type IS SyntaxTree.ArrayType THEN
  1094. type := type(SyntaxTree.ArrayType).arrayBase.resolved;
  1095. ELSE
  1096. type := type(SyntaxTree.MathArrayType).arrayBase.resolved;
  1097. END;
  1098. IF type = initialType THEN RETURN END; (* avoid circles *)
  1099. END;
  1100. IF (type IS SyntaxTree.RecordType) & (type(SyntaxTree.RecordType).recordScope.ownerModule = module.module) THEN
  1101. fingerPrint := fingerprinter.TypeFP(type); (* make sure that fingerprint has traversed all methods ... *)
  1102. procedure := type(SyntaxTree.RecordType).recordScope.firstProcedure;
  1103. WHILE procedure # NIL DO
  1104. IF (procedure.access * SyntaxTree.Public # {}) THEN
  1105. ExportSymbol(procedure,SymbolOffset(procedure),name);
  1106. INC(numberExports);
  1107. END;
  1108. procedure := procedure.nextProcedure;
  1109. END;
  1110. END;
  1111. END ExportMethods;
  1112. BEGIN
  1113. w.Char(88X);
  1114. numberExports := 0; typeNumber := 0;
  1115. numberExportsPosition := w.Pos();
  1116. w.RawLInt(numberExports);
  1117. (*! in the end anything that has an offset should be present in the BackendStructures.Module,
  1118. therefore the list can also be traverse from the respective Backend structure *)
  1119. (* constants *)
  1120. constant := moduleScope.firstConstant;
  1121. WHILE constant # NIL DO
  1122. IF (constant.access * SyntaxTree.Public # {}) THEN
  1123. IF Trace THEN
  1124. constant.GetName(name);
  1125. D.String("Constant:"); D.String(name); D.Ln;
  1126. END;
  1127. IF (~(constant.type IS SyntaxTree.BasicType)) THEN
  1128. ExportSymbol(constant,SymbolOffset(constant),"");
  1129. ELSE
  1130. ExportSymbol(constant,0,"")
  1131. END;
  1132. INC(numberExports);
  1133. END;
  1134. constant := constant.nextConstant;
  1135. END;
  1136. (* global variables *)
  1137. variable := moduleScope.firstVariable;
  1138. WHILE variable # NIL DO
  1139. IF variable.access * SyntaxTree.Public # {} THEN
  1140. IF Trace THEN
  1141. variable.GetName(name);
  1142. D.String("Variable:"); D.String(name); D.Ln;
  1143. END;
  1144. ExportSymbol(variable,SymbolOffset(variable),"");
  1145. ExportType(variable.type);
  1146. INC(numberExports);
  1147. END;
  1148. variable := variable.nextVariable;
  1149. END;
  1150. (* type declarations *)
  1151. typeDeclaration := moduleScope.firstTypeDeclaration;
  1152. WHILE typeDeclaration # NIL DO
  1153. IF TRUE (* typeDeclaration.access * SyntaxTree.Public # {} *) THEN
  1154. IF Trace THEN
  1155. typeDeclaration.GetName(name);
  1156. D.String("TypeDeclaration:"); D.String(name); D.Ln;
  1157. END;
  1158. ExportSymbol(typeDeclaration,0,"");
  1159. ExportType(typeDeclaration.declaredType);
  1160. INC(numberExports);
  1161. END;
  1162. typeDeclaration := typeDeclaration.nextTypeDeclaration
  1163. END;
  1164. (* exported procedures *)
  1165. procedure := moduleScope.firstProcedure;
  1166. WHILE procedure # NIL DO
  1167. IF (procedure.access* SyntaxTree.Public # {}) THEN
  1168. IF Trace THEN
  1169. procedure.GetName(name);
  1170. D.String("Procedure:"); D.String(name); D.Ln;
  1171. END;
  1172. ExportSymbol(procedure,SymbolOffset(procedure),"");
  1173. INC(numberExports);
  1174. END;
  1175. procedure := procedure.nextProcedure;
  1176. END;
  1177. (* exported methods *)
  1178. typeDeclaration := moduleScope.firstTypeDeclaration;
  1179. WHILE typeDeclaration # NIL DO
  1180. IF typeDeclaration.access * SyntaxTree.Public # {} THEN
  1181. ExportMethods(typeDeclaration);
  1182. END;
  1183. typeDeclaration := typeDeclaration.nextTypeDeclaration
  1184. END;
  1185. RawLIntAt(numberExportsPosition,numberExports);
  1186. w.Char(0X);
  1187. END Exports;
  1188. (* Code = 89X {character:1} *)
  1189. PROCEDURE Code;
  1190. VAR i: LONGINT;
  1191. BEGIN
  1192. w.Char(89X);
  1193. FOR i := 0 TO ((codeSize-1) ) DO
  1194. w.Char(code[i]);
  1195. crc32.Char(code[i]);
  1196. END;
  1197. END Code;
  1198. (*
  1199. Use = 08AX {UsedModules} 0X
  1200. UsedModules = moduleName:String {UsedConstant | UsedVariable | UsedProcedure | UsedType } 0X
  1201. UsedConstant = FP:Number constName:String 0X
  1202. UsedVariable = FP:Number varName:String fixlist:Number [1X UsedRecord]
  1203. UsedProcedure = FP:Number procName:String offset:Number
  1204. UsedType = FP:Number typeName:String 0X [1X UsedRecord]
  1205. UsedRecord = tdentry:Number [FP "@"] 0X
  1206. *)
  1207. PROCEDURE Use;
  1208. VAR import: SyntaxTree.Import; name: SyntaxTree.IdentifierString; importedModule: SyntaxTree.Module; s: Section;
  1209. constant: SyntaxTree.Constant; variable: SyntaxTree.Variable; typeDeclaration: SyntaxTree.TypeDeclaration; procedure: SyntaxTree.Procedure;
  1210. type: SyntaxTree.Type;fixup: Fixup; fixups: LONGINT; sym: Section;
  1211. PROCEDURE UseEntry(module: SyntaxTree.Module; symbol: SyntaxTree.Symbol; offsetInBytes: LONGINT; CONST prefix: ARRAY OF CHAR);
  1212. VAR name,suffix: Basic.SectionName; fingerPrint: SyntaxTree.FingerPrint; fp: LONGINT;
  1213. BEGIN
  1214. symbol.GetName(suffix);
  1215. IF prefix # "" THEN
  1216. COPY(prefix,name); Strings.Append(name,"."); Strings.Append(name,suffix);
  1217. ELSE
  1218. name := suffix;
  1219. END;
  1220. fingerPrint := fingerprinter.SymbolFP(symbol);
  1221. fp := fingerPrint.shallow;
  1222. (*
  1223. IF prefix # "" THEN FingerPrint.FPString(fp,prefix) END;
  1224. *)
  1225. w.RawNum(fp);
  1226. IF Trace THEN
  1227. D.Str("FoxObjectFile.Use ");
  1228. D.Str(suffix);
  1229. D.Str(" : "); D.Hex(SYSTEM.VAL(LONGINT,symbol),-8); D.Str(" : ");
  1230. D.Hex(fp,-8);
  1231. D.String(" @ ");
  1232. D.Int(offsetInBytes-ofEUProcFlag,1);
  1233. D.Ln;
  1234. END;
  1235. w.RawString(name);
  1236. w.RawNum(offsetInBytes);
  1237. END UseEntry;
  1238. PROCEDURE UseType(type: SyntaxTree.Type);
  1239. VAR t: Section; fingerPrint: SyntaxTree.FingerPrint; name: SyntaxTree.IdentifierString;
  1240. BEGIN
  1241. type := type.resolved;
  1242. LOOP
  1243. IF type IS SyntaxTree.PointerType THEN type := type(SyntaxTree.PointerType).pointerBase.resolved;
  1244. ELSIF type IS SyntaxTree.ArrayType THEN type := type(SyntaxTree.ArrayType).arrayBase.resolved;
  1245. ELSIF type IS SyntaxTree.MathArrayType THEN type := type(SyntaxTree.MathArrayType).arrayBase.resolved;
  1246. ELSE EXIT
  1247. END;
  1248. END;
  1249. IF type IS SyntaxTree.RecordType THEN
  1250. WITH type: SyntaxTree.RecordType DO
  1251. type.typeDeclaration.GetName(name); (* debugging *)
  1252. IF type.recordScope.ownerModule = importedModule THEN (* type belongs to currently processed module *)
  1253. IF Trace THEN D.Str("UseTypeFP:"); D.Str(name); D.Str("?"); D.Ln END;
  1254. t := symbols.BySymbol(type.typeDeclaration); (* TODO *)
  1255. IF t = NIL THEN
  1256. t := importedSymbols.BySymbol(type.typeDeclaration);
  1257. END;
  1258. IF (t # NIL) & (t.referenced) (*(t.fixups # NIL)*) THEN
  1259. t.referenced := FALSE;
  1260. fingerPrint := fingerprinter.TypeFP(type);
  1261. w.Char(ofEURecord);
  1262. w.RawNum(-(t.offset ));
  1263. (* privateFP never set in old compiler *)
  1264. IF Trace THEN D.Str("UseTypeFP:"); D.Str(name); D.Str(":"); D.Int(fingerPrint.public,1); D.Ln END;
  1265. w.RawNum(fingerPrint.public);
  1266. w.RawString("@");
  1267. w.Char(ofEUEnd);
  1268. END;
  1269. ELSE
  1270. (* nothing to be done? => module must be added to import section, this must be done by the semantic checker *)
  1271. END
  1272. END
  1273. END
  1274. END UseType;
  1275. PROCEDURE UseMethods(typeDeclaration: SyntaxTree.TypeDeclaration);
  1276. VAR procedure: SyntaxTree.Procedure; sym: Section; prefix: SyntaxTree.IdentifierString; fingerPrint: SyntaxTree.FingerPrint; type: SyntaxTree.Type;
  1277. fixup: Fixup; fixups: LONGINT;
  1278. BEGIN
  1279. typeDeclaration.GetName(prefix);
  1280. type := typeDeclaration.declaredType.resolved;
  1281. LOOP
  1282. IF type IS SyntaxTree.PointerType THEN type := type(SyntaxTree.PointerType).pointerBase.resolved;
  1283. (*!???? => problems with name prefix. Necessary to treat arrays here?
  1284. ELSIF type IS SyntaxTree.ArrayType THEN type := type(SyntaxTree.ArrayType).arrayBase.resolved;
  1285. ELSIF type IS SyntaxTree.MathArrayType THEN type := type(SyntaxTree.MathArrayType).arrayBase.resolved;
  1286. *)
  1287. ELSE EXIT
  1288. END;
  1289. END;
  1290. IF (type IS SyntaxTree.RecordType) & (type.scope.ownerModule = importedModule) (* do not take alias *) THEN
  1291. fingerPrint := fingerprinter.TypeFP(type); (* make sure that type is fingerprinted including all methods *)
  1292. procedure := type(SyntaxTree.RecordType).recordScope.firstProcedure;
  1293. WHILE procedure # NIL DO
  1294. sym := importedSymbols.BySymbol(procedure);
  1295. IF sym # NIL THEN
  1296. fixup := sym.fixups;
  1297. UseEntry(importedModule,procedure,(fixup.fixupSection.offset + fixup.fixup.offset )+ofEUProcFlag,prefix);
  1298. END;
  1299. procedure := procedure.nextProcedure
  1300. END
  1301. END
  1302. END UseMethods;
  1303. BEGIN
  1304. w.Char(08AX);
  1305. import := moduleScope.firstImport;
  1306. WHILE(import # NIL) DO (*! in a new object file this would not necessarily be ordered by imports (?) *)
  1307. IF (import.module # module.system.systemModule[import.module.case]) & IsFirstOccurence(import) THEN
  1308. importedModule := import.module;
  1309. ASSERT(importedModule # NIL);
  1310. ASSERT(importedModule # module.system.systemModule[0]);
  1311. ASSERT(importedModule # module.system.systemModule[1]);
  1312. Global.ModuleFileName(import.module.name,import.module.context,name);
  1313. w.RawString(name);
  1314. IF Trace THEN
  1315. D.Str("Use module : "); D.Str(name); D.Ln;
  1316. END;
  1317. constant := importedModule.moduleScope.firstConstant;
  1318. WHILE constant # NIL DO
  1319. sym := importedSymbols.BySymbol(constant);
  1320. IF sym # NIL THEN UseEntry(importedModule,constant,0,"") END;
  1321. constant := constant.nextConstant
  1322. END;
  1323. variable := importedModule.moduleScope.firstVariable;
  1324. WHILE variable # NIL DO
  1325. sym := importedSymbols.BySymbol(variable);
  1326. IF sym # NIL THEN
  1327. UseEntry(importedModule,variable,sym.entryNumber,"");
  1328. UseType(variable.type);
  1329. END;
  1330. variable := variable.nextVariable
  1331. END;
  1332. typeDeclaration := importedModule.moduleScope.firstTypeDeclaration;
  1333. WHILE typeDeclaration # NIL DO
  1334. type := typeDeclaration.declaredType;
  1335. IF type IS SyntaxTree.PointerType THEN type := type(SyntaxTree.PointerType).pointerBase END;
  1336. sym := symbols.BySymbol(typeDeclaration); (* only if has been used -- contained in module sections: alias *)
  1337. IF sym = NIL THEN sym := importedSymbols.BySymbol(typeDeclaration) END;
  1338. IF (sym # NIL) & (sym.referenced) THEN
  1339. UseEntry(importedModule,typeDeclaration,0,"");
  1340. UseType(typeDeclaration.declaredType);
  1341. END;
  1342. typeDeclaration := typeDeclaration.nextTypeDeclaration
  1343. END;
  1344. procedure := importedModule.moduleScope.firstProcedure;
  1345. WHILE procedure # NIL DO
  1346. IF ~procedure.isInline THEN
  1347. sym := importedSymbols.BySymbol(procedure);
  1348. IF sym # NIL THEN
  1349. fixup := sym.fixups;
  1350. UseEntry(importedModule,procedure,(fixup.fixupSection.offset + fixup.fixup.offset )+ofEUProcFlag,"");
  1351. END;
  1352. END;
  1353. procedure := procedure.nextProcedure
  1354. END;
  1355. typeDeclaration := importedModule.moduleScope.firstTypeDeclaration;
  1356. WHILE typeDeclaration # NIL DO
  1357. IF ~(typeDeclaration.declaredType IS SyntaxTree.QualifiedType) (* alias *) THEN
  1358. UseMethods(typeDeclaration);
  1359. END;
  1360. typeDeclaration := typeDeclaration.nextTypeDeclaration
  1361. END;
  1362. w.Char(0X);
  1363. END;
  1364. import := import.nextImport;
  1365. END;
  1366. w.Char(0X);
  1367. END Use;
  1368. PROCEDURE WriteType(d:Section; type: SyntaxTree.RecordType; VAR tdSize: LONGINT (* ug *));
  1369. CONST MaxTags = 16; (* ug: temporary solution, Modules.MaxTags *)
  1370. VAR
  1371. tdSizePos, oldmth,newmeth: LONGINT; base: SyntaxTree.RecordType;
  1372. name: SyntaxTree.IdentifierString;
  1373. baseModule: LONGINT; baseEntry: LONGINT;
  1374. upperPartTdSize, lowerPartTdSize: LONGINT;
  1375. size: LONGINT;
  1376. numberPointersPosition: LONGINT;
  1377. numberPointers: LONGINT;
  1378. destination: Section;
  1379. procedure: Section;
  1380. fp: SyntaxTree.FingerPrint;
  1381. m: SyntaxTree.Procedure;
  1382. i: LONGINT;
  1383. typeDeclaration: SyntaxTree.TypeDeclaration;
  1384. BEGIN
  1385. name := "@@";
  1386. ASSERT(type.typeDeclaration # NIL);
  1387. type.typeDeclaration.GetName(name);
  1388. size := module.system.AlignedSizeOf(type) DIV 8;
  1389. w.RawNum(size );
  1390. w.RawNum((d.offset )); (* type descriptor pointer address, patched by loader to type desciptor address *)
  1391. base := type.GetBaseRecord();
  1392. IF (base = NIL) THEN (* no base type *)
  1393. oldmth := 0;
  1394. baseModule := -1;
  1395. baseEntry := -1
  1396. ELSE
  1397. baseModule := 0; (* base type in local module *)
  1398. IF (base.typeDeclaration # NIL) & (base.typeDeclaration.scope # NIL) & (base.typeDeclaration.scope.ownerModule # moduleScope.ownerModule) THEN (* base type in other module *)
  1399. baseModule := ModuleNumber(base.typeDeclaration.scope.ownerModule);
  1400. typeDeclaration := base.typeDeclaration;
  1401. ASSERT(baseModule # 0);
  1402. ELSE
  1403. typeDeclaration := NIL;
  1404. END;
  1405. IF baseModule = 0 THEN
  1406. destination := symbols.BySymbol(base.typeDeclaration); (*TODO*)
  1407. ASSERT(destination # NIL);
  1408. baseEntry := (destination.offset ); (* destination must be non-nil *)
  1409. ELSIF (typeDeclaration # NIL) THEN
  1410. fp := fingerprinter.SymbolFP(typeDeclaration);
  1411. baseEntry := fp.shallow;
  1412. ELSE
  1413. HALT(100);
  1414. (* ELSE
  1415. base := base(SyntaxTree.PointerType).pointerBase;
  1416. fp := fingerprinter.SymbolFP(base.typeDeclaration);
  1417. baseEntry := fp.FP;
  1418. *)
  1419. END;
  1420. oldmth := base.recordScope.numberMethods;
  1421. END;
  1422. w.RawNum(baseModule);
  1423. w.RawNum(baseEntry);
  1424. newmeth := 0;
  1425. m := type.recordScope.firstProcedure;
  1426. WHILE (m# NIL) DO
  1427. INC(newmeth); (*! check that this is not an inline procedure *)
  1428. m := m.nextProcedure;
  1429. END;
  1430. IF type.IsProtected() THEN
  1431. w.RawNum(-type.recordScope.numberMethods); (* number methods total *)
  1432. ELSE
  1433. w.RawNum(type.recordScope.numberMethods); (* number methods total *)
  1434. END;
  1435. w.RawNum(oldmth); (* inherited methods total *)
  1436. w.RawNum(newmeth); (* new methods (overridden or new) *)
  1437. numberPointersPosition:= w.Pos();
  1438. w.RawLInt(0);
  1439. w.RawString(name);
  1440. tdSizePos := w.Pos();
  1441. w.RawLInt(0);
  1442. i := 0;
  1443. m := type.recordScope.firstProcedure;
  1444. WHILE (m#NIL) DO
  1445. IF ~(m.isInline) THEN
  1446. procedure := symbols.BySymbol(m); (*TODO*)
  1447. ASSERT(procedure # NIL);
  1448. m.GetName(name);
  1449. w.RawNum(procedure.symbol(SyntaxTree.Procedure).methodNumber);
  1450. w.RawNum(procedure.entryNumber);
  1451. INC(i);
  1452. END;
  1453. m := m.nextProcedure;
  1454. END;
  1455. (* Ptrs in Record *)
  1456. numberPointers := 0;
  1457. IF Trace THEN D.Str("pointers of type: "); D.Ln; END;
  1458. OutPointers(0, type, numberPointers); (* debug = FALSE *)
  1459. IF numberPointers # 0 THEN RawLIntAt(numberPointersPosition,numberPointers) END;
  1460. (* ug *) upperPartTdSize := module.system.addressSize DIV 8 * (MaxTags + type.recordScope.numberMethods + 1 + 1); (* tags, methods, methods end marker (sentinel), address of TypeInfo *)
  1461. (* ug *) lowerPartTdSize := module.system.addressSize DIV 8 * (2 + (4 + numberPointers) + 1);
  1462. (* ug *) tdSize := upperPartTdSize + lowerPartTdSize;
  1463. (* ug *) RawLIntAt(tdSizePos, tdSize) ;
  1464. END WriteType;
  1465. PROCEDURE Types;
  1466. VAR
  1467. t: Section; tdSize, i: LONGINT;
  1468. typeDeclaration: SyntaxTree.TypeDeclaration; type: SyntaxTree.Type;
  1469. name: ARRAY 256 OF CHAR;
  1470. BEGIN
  1471. w.Char(08BX);
  1472. numberTypes := 0; typeDescSize := 0;
  1473. FOR i := 0 TO symbols.Length() - 1 DO
  1474. t := symbols.GetSection(i);
  1475. IF (t.symbol # NIL) & (t.symbol IS SyntaxTree.TypeDeclaration) THEN
  1476. typeDeclaration := t.symbol(SyntaxTree.TypeDeclaration);
  1477. type := typeDeclaration.declaredType;
  1478. typeDeclaration.GetName(name);
  1479. IF type IS SyntaxTree.PointerType THEN
  1480. IF type(SyntaxTree.PointerType).pointerBase.resolved.typeDeclaration = typeDeclaration THEN (* avoid duplicate declarations *)
  1481. type := type(SyntaxTree.PointerType).pointerBase.resolved;
  1482. END;
  1483. END;
  1484. IF Trace THEN D.Str("FoxObjectFile.Types: "); D.String(name); D.Ln; END;
  1485. IF (type IS SyntaxTree.RecordType) & (type(SyntaxTree.RecordType).recordScope.ownerModule = moduleScope.ownerModule) OR (type(SyntaxTree.RecordType).recordScope.ownerModule = NIL) THEN
  1486. t := symbols.BySymbol(type.typeDeclaration);
  1487. ASSERT(t # NIL);
  1488. WriteType(t,type(SyntaxTree.RecordType),tdSize);
  1489. INC(typeDescSize,tdSize);
  1490. INC(numberTypes);
  1491. END;
  1492. END
  1493. END
  1494. END Types;
  1495. (* Stores the exception handle table in the following format
  1496. ExceptionHandlerTable ::= 8EX {ExceptionTableEntry}
  1497. ExceptionTableEntry ::= 0FFX pcFrom(4 bytes) pcTo(4 bytes) pcHandler(4 bytes)
  1498. Since there is only one FINALLY in every procedure, method, body, ... we don't need
  1499. to obtain an order for nesting.
  1500. *)
  1501. PROCEDURE ExceptionTable;
  1502. VAR
  1503. p: Section; pcFrom, pcTo, pcHandler, i: LONGINT;
  1504. binarySection: BinaryCode.Section;
  1505. BEGIN
  1506. exTableLen := 0;
  1507. w.Char(08EX);
  1508. FOR i := 0 TO symbols.Length() - 1 DO
  1509. p := symbols.GetSection(i);
  1510. IF (p.type = Sections.CodeSection) OR (p.type= Sections.BodyCodeSection) THEN
  1511. binarySection := p.resolved;
  1512. IF binarySection.finally >= 0 THEN
  1513. pcFrom := p.offset;
  1514. pcTo := binarySection.finally+pcFrom;
  1515. pcHandler := binarySection.finally+pcFrom;
  1516. w.Char(0FEX);
  1517. w.RawNum(pcFrom);
  1518. w.RawNum(pcTo);
  1519. w.RawNum(pcHandler);
  1520. INC(exTableLen);
  1521. END;
  1522. END
  1523. END;
  1524. END ExceptionTable;
  1525. PROCEDURE PtrsInProcBlock;
  1526. VAR
  1527. i, counter: LONGINT; destination: Section;
  1528. PROCEDURE PointerOffsets(destination : Section);
  1529. VAR
  1530. numberPointers,numberPointersPos: LONGINT; procedure: SyntaxTree.Procedure; procedureType: SyntaxTree.ProcedureType;
  1531. variable: SyntaxTree.Variable; parameter: SyntaxTree.Parameter;
  1532. BEGIN
  1533. (*!
  1534. ASSERT(destination.offset <= destination.beginOffset);
  1535. ASSERT(destination.beginOffset <= destination.endOffset);
  1536. *)
  1537. w.RawNum((destination.offset ));
  1538. w.RawNum(destination.offset+destination.resolved.validPAFEnter);
  1539. w.RawNum(destination.offset+destination.resolved.validPAFExit);
  1540. (*!
  1541. w.RawNum(destination.beginOffset);
  1542. w.RawNum(destination.endOffset);
  1543. *)
  1544. numberPointers := 0;
  1545. numberPointersPos := w.Pos();
  1546. w.RawLInt(0);
  1547. procedure := destination.symbol(SyntaxTree.Procedure);
  1548. procedureType := procedure.type(SyntaxTree.ProcedureType);
  1549. variable := procedure.procedureScope.firstVariable;
  1550. WHILE(variable # NIL) DO
  1551. IF ~(variable.untraced) THEN
  1552. OutPointers(variable.offsetInBits DIV 8,variable.type,numberPointers);
  1553. END;
  1554. variable := variable.nextVariable
  1555. END;
  1556. parameter := procedureType.firstParameter;
  1557. WHILE(parameter # NIL) DO
  1558. IF ~(parameter.untraced) THEN
  1559. OutPointers(parameter.offsetInBits DIV 8,parameter.type,numberPointers);
  1560. END;
  1561. parameter := parameter.nextParameter;
  1562. END;
  1563. (*
  1564. parameter := procedureType.selfParameter;
  1565. IF parameter # NIL THEN
  1566. OutPointers(parameter.offsetInBits DIV 8,parameter.type,numberPointers);
  1567. END;
  1568. *)
  1569. RawLIntAt(numberPointersPos,numberPointers);
  1570. IF numberPointers > maxPtrs THEN
  1571. maxPtrs := numberPointers
  1572. END;
  1573. END PointerOffsets;
  1574. BEGIN
  1575. w.Char(08FX);
  1576. IF Trace THEN D.Str("FoxObjectFile.PtrsInProcBlock"); D.Ln; END;
  1577. maxPtrs := 0;
  1578. counter := 0;
  1579. FOR i := 0 TO symbols.Length() - 1 DO
  1580. destination := symbols.GetSection(i);
  1581. IF (destination.type # Sections.InitCodeSection) & (destination.symbol # NIL) & (destination.symbol IS SyntaxTree.Procedure) & ~destination.symbol(SyntaxTree.Procedure).isInline THEN
  1582. IF Trace THEN D.Str("pointers in "); Basic.WriteSegmentedName(D.Log,destination.name); D.Ln END;
  1583. PointerOffsets(destination);
  1584. INC(counter);
  1585. END
  1586. END;
  1587. numberProcs := counter;
  1588. END PtrsInProcBlock;
  1589. PROCEDURE References;
  1590. CONST
  1591. rfDirect = 1X; rfIndirect = 3X;
  1592. rfStaticArray= 12X; rfDynamicArray=14X; rfOpenArray=15X;
  1593. rfByte = 1X; rfBoolean = 2X; rfChar8=3X; rfShortint=04X; rfInteger = 05X; rfLongint = 06X;
  1594. rfReal = 07X; rfLongreal = 08X; rfSet = 09X; rfDelegate = 0EX; rfString = 0FH; rfPointer = 0DX; rfHugeint = 10X;
  1595. rfChar16=11X; rfChar32=12X; rfAll=13X; rfSame=14X; rfRange=15X; rfRecord=16X; rfComplex = 17X; rfLongcomplex = 18X;
  1596. rfRecordPointer=1DX;
  1597. rfArrayFlag = 80X;
  1598. VAR
  1599. start, i: LONGINT; s: Section;
  1600. PROCEDURE BaseType(type: SyntaxTree.Type): CHAR;
  1601. VAR char: CHAR;
  1602. BEGIN
  1603. IF type = NIL THEN char := rfLongint
  1604. ELSIF type IS SyntaxTree.ByteType THEN char := rfByte
  1605. ELSIF type IS SyntaxTree.BooleanType THEN char := rfBoolean
  1606. ELSIF type IS SyntaxTree.CharacterType THEN
  1607. IF type.sizeInBits = 8 THEN char := rfChar8
  1608. ELSIF type.sizeInBits = 16 THEN char := rfChar16
  1609. ELSIF type.sizeInBits = 32 THEN char := rfChar32
  1610. END;
  1611. ELSIF (type IS SyntaxTree.IntegerType) OR (type IS SyntaxTree.AddressType) OR (type IS SyntaxTree.SizeType) THEN
  1612. IF type.sizeInBits = 8 THEN char := rfShortint
  1613. ELSIF type.sizeInBits = 16 THEN char := rfInteger
  1614. ELSIF type.sizeInBits = 32 THEN char := rfLongint
  1615. ELSIF type.sizeInBits =64 THEN char := rfHugeint
  1616. END;
  1617. ELSIF type IS SyntaxTree.SizeType THEN char := rfLongint
  1618. ELSIF type IS SyntaxTree.FloatType THEN
  1619. IF type.sizeInBits = 32 THEN char := rfReal
  1620. ELSIF type.sizeInBits = 64 THEN char := rfLongreal
  1621. END;
  1622. ELSIF type IS SyntaxTree.ComplexType THEN
  1623. IF type.sizeInBits = 64 THEN char := rfComplex
  1624. ELSIF type.sizeInBits = 128 THEN char := rfLongcomplex
  1625. END;
  1626. ELSIF type IS SyntaxTree.SetType THEN char := rfSet
  1627. ELSIF type IS SyntaxTree.AnyType THEN char := rfPointer
  1628. ELSIF type IS SyntaxTree.ObjectType THEN char := rfPointer
  1629. ELSIF type IS SyntaxTree.PointerType THEN char := rfPointer
  1630. ELSIF type IS SyntaxTree.ProcedureType THEN char := rfDelegate
  1631. ELSIF type IS SyntaxTree.RangeType THEN char := rfRange
  1632. ELSE char := rfShortint; (*RETURN (* ARRAY OF unknown (record): do not write anything *)*)
  1633. END;
  1634. RETURN char
  1635. END BaseType;
  1636. PROCEDURE RecordType(type: SyntaxTree.RecordType);
  1637. VAR destination: Section; name: SyntaxTree.IdentifierString;
  1638. BEGIN
  1639. destination := symbols.BySymbol(type.typeDeclaration);
  1640. IF destination = NIL THEN destination := importedSymbols.BySymbol(type.typeDeclaration) END;
  1641. IF destination = NIL THEN
  1642. (* imported unused record type *)
  1643. w.Char(0X); (* nil type *)
  1644. type.typeDeclaration.GetName(name);
  1645. (*
  1646. 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
  1647. D.Str("Warning: Unreferenced record type encountered: "); D.String(name); D.String(" unused? "); D.Ln;
  1648. *)
  1649. ELSE
  1650. IF type.pointerType # NIL THEN
  1651. w.Char(rfRecordPointer)
  1652. ELSE
  1653. w.Char(rfRecord);
  1654. END;
  1655. w.RawNum((destination.offset ));
  1656. END;
  1657. END RecordType;
  1658. PROCEDURE StaticArrayLength(type: SyntaxTree.ArrayType; VAR baseType: SyntaxTree.Type): LONGINT;
  1659. BEGIN
  1660. baseType := type.arrayBase.resolved;
  1661. IF type.form = SyntaxTree.Static THEN
  1662. IF baseType IS SyntaxTree.ArrayType THEN
  1663. RETURN type.staticLength * StaticArrayLength(baseType(SyntaxTree.ArrayType),baseType)
  1664. ELSE
  1665. RETURN type.staticLength
  1666. END
  1667. ELSE
  1668. RETURN 0
  1669. END;
  1670. END StaticArrayLength;
  1671. PROCEDURE ArrayType(type: SyntaxTree.ArrayType);
  1672. VAR length: LONGINT; baseType: SyntaxTree.Type; char: CHAR;
  1673. BEGIN
  1674. length := StaticArrayLength(type, baseType);
  1675. char := BaseType(baseType);
  1676. IF type.form # SyntaxTree.Open THEN
  1677. w.Char(CHR(ORD(char)+ORD(rfArrayFlag)));
  1678. w.RawNum(length)
  1679. ELSE
  1680. length :=0;
  1681. (*length := 1+SemanticChecker.Dimension(type,{SyntaxTree.Open});*)
  1682. w.Char(CHR(ORD(char)+ORD(rfArrayFlag)));
  1683. w.RawNum(length)
  1684. END;
  1685. END ArrayType;
  1686. PROCEDURE StaticMathArrayLength(type: SyntaxTree.MathArrayType; VAR baseType: SyntaxTree.Type): LONGINT;
  1687. BEGIN
  1688. baseType := type.arrayBase;
  1689. IF baseType # NIL THEN
  1690. baseType := baseType.resolved;
  1691. END;
  1692. IF type.form = SyntaxTree.Static THEN
  1693. IF (baseType # NIL) & (baseType IS SyntaxTree.MathArrayType) THEN
  1694. RETURN type.staticLength * StaticMathArrayLength(baseType(SyntaxTree.MathArrayType),baseType)
  1695. ELSE
  1696. RETURN type.staticLength
  1697. END
  1698. ELSE
  1699. RETURN 0
  1700. END;
  1701. END StaticMathArrayLength;
  1702. PROCEDURE MathArrayType(type: SyntaxTree.MathArrayType);
  1703. VAR length: LONGINT; baseType: SyntaxTree.Type; char: CHAR;
  1704. BEGIN
  1705. length := StaticMathArrayLength(type, baseType);
  1706. char := BaseType(baseType);
  1707. IF type.form = SyntaxTree.Open THEN
  1708. char := BaseType(module.system.addressType);
  1709. length := 5+2*SemanticChecker.Dimension(type,{SyntaxTree.Open});
  1710. w.Char(CHR(ORD(char)+ORD(rfArrayFlag)));
  1711. w.RawNum(length)
  1712. ELSIF type.form=SyntaxTree.Tensor THEN
  1713. char := BaseType(module.system.addressType);
  1714. w.Char(CHR(ORD(char)));
  1715. ELSE
  1716. w.Char(CHR(ORD(char)+ORD(rfArrayFlag)));
  1717. w.RawNum(length)
  1718. END;
  1719. END MathArrayType;
  1720. PROCEDURE Type(type: SyntaxTree.Type);
  1721. BEGIN
  1722. IF type = NIL THEN w.Char(0X); RETURN ELSE type := type.resolved END;
  1723. IF type IS SyntaxTree.BasicType THEN
  1724. w.Char(BaseType(type))
  1725. ELSIF type IS SyntaxTree.RecordType THEN
  1726. RecordType(type(SyntaxTree.RecordType));
  1727. ELSIF type IS SyntaxTree.ArrayType THEN
  1728. ArrayType(type(SyntaxTree.ArrayType))
  1729. ELSIF type IS SyntaxTree.EnumerationType THEN
  1730. w.Char(BaseType(module.system.longintType))
  1731. ELSIF type IS SyntaxTree.PointerType THEN
  1732. IF type(SyntaxTree.PointerType).pointerBase IS SyntaxTree.RecordType THEN
  1733. RecordType(type(SyntaxTree.PointerType).pointerBase(SyntaxTree.RecordType));
  1734. ELSE
  1735. w.Char(BaseType(type))
  1736. END;
  1737. ELSIF type IS SyntaxTree.ProcedureType THEN
  1738. w.Char(BaseType(type));
  1739. ELSIF type IS SyntaxTree.MathArrayType THEN
  1740. MathArrayType(type(SyntaxTree.MathArrayType));
  1741. ELSE HALT(200)
  1742. END;
  1743. END Type;
  1744. PROCEDURE WriteVariable(variable: SyntaxTree.Variable; indirect: BOOLEAN);
  1745. VAR name: ARRAY 256 OF CHAR;
  1746. BEGIN
  1747. IF variable.externalName # NIL THEN RETURN END;
  1748. IF indirect THEN w.Char(rfIndirect) ELSE w.Char(rfDirect) END;
  1749. variable.GetName(name);
  1750. Type(variable.type);
  1751. w.RawNum((variable.offsetInBits DIV 8));
  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. (* enter unused types to local sections -- required, otherwise traps *)
  1965. FOR i := 0 TO module.importedSections.Length() - 1 DO
  1966. section := module.importedSections.GetSection(i);
  1967. IF (section.type = Sections.ConstSection) & (section.symbol # NIL) & (section.symbol IS SyntaxTree.TypeDeclaration) THEN
  1968. IF symbols.BySymbol(section.symbol) = NIL THEN
  1969. ASSERT(Enter(section, symbols, symbol))
  1970. END;
  1971. END;
  1972. END;
  1973. IF Trace THEN
  1974. D.String("imported sections(module) "); D.Ln;
  1975. module.importedSections.Dump(D.Log); D.Ln;
  1976. D.String("sections(module) "); D.Ln;
  1977. module.allSections.Dump(D.Log); D.Ln;
  1978. D.String("imported: "); D.Ln; importedSymbols.Dump(D.Log);
  1979. D.String("not imported: "); D.Ln; symbols.Dump(D.Log);
  1980. D.Ln;
  1981. END;
  1982. END MakeSections;
  1983. (* ObjectFile =
  1984. ofFileTag ofNoZeroCompression ofFileVersion
  1985. SymbolFile
  1986. Header
  1987. Entries
  1988. Commands
  1989. Pointers
  1990. Imports
  1991. VarConstLinks
  1992. Links
  1993. Constants
  1994. Exports
  1995. Code
  1996. Use
  1997. Types
  1998. ExceptionTable
  1999. PtrsInProcBlock
  2000. References
  2001. *)
  2002. BEGIN
  2003. MakeSectionOffsets(module,constSize,dataSize,codeSize,caseTableSize,const,code);
  2004. MakeSections;
  2005. (* from here on we do not need IntermediateCode.Sections any more *)
  2006. LinkFixups;
  2007. IF Trace THEN module.Dump(D.Log);D.Ln; D.Update; END;
  2008. NEW(fingerprinter,module.system);
  2009. (* module.module.name,moduleName);*)
  2010. Global.ModuleFileName(module.module.name,module.module.context,moduleName);
  2011. NEW(crc32);
  2012. IF Trace THEN D.Str("module: "); D.Str(moduleName); D.Ln END;
  2013. moduleScope := module.module.moduleScope;
  2014. w.Char(ofFileTag);
  2015. w.Char(ofNoZeroCompress);
  2016. w.Char(ofFileVersion);
  2017. SymbolFile;
  2018. Header; Entries; Commands; Pointers; Imports; VarConstLinks; Links;
  2019. Constants; Exports; Code; Use; Types; ExceptionTable; PtrsInProcBlock; References;
  2020. endPos := w.Pos();
  2021. w.SetPos(headerPos);
  2022. crc := crc32.GetCRC();
  2023. Header;
  2024. w.SetPos(endPos);
  2025. w.Update;
  2026. END WriteObjectFile;
  2027. PROCEDURE Get*(): Formats.ObjectFileFormat;
  2028. VAR objectFileFormat: ObjectFileFormat;
  2029. BEGIN NEW(objectFileFormat); RETURN objectFileFormat
  2030. END Get;
  2031. BEGIN
  2032. SysCallMap[CaseTable] := 0FFX;
  2033. SysCallMap[ProcAddr] := 0FEX;
  2034. SysCallMap[NewRec] := 0FDX;
  2035. SysCallMap[NewSys] := 0FCX;
  2036. SysCallMap[NewArr] := 0FBX;
  2037. SysCallMap[Start] := CHR(250);
  2038. SysCallMap[Await] := CHR(249);
  2039. SysCallMap[Lock] := CHR(247);
  2040. SysCallMap[Unlock] := CHR(246);
  2041. SysCallMap[InterfaceLookup] := CHR(245);
  2042. SysCallMap[RegisterInterface] := CHR(244);
  2043. SysCallMap[GetProcedure] := CHR(243);
  2044. END FoxBinaryObjectFile.