ogwasm.pas 254 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515
  1. {
  2. Copyright (c) 2021 by Nikolay Nikolov
  3. Contains the WebAssembly binary module format reader and writer
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit ogwasm;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. { common }
  22. cclasses,globtype,
  23. { target }
  24. systems,cpubase,
  25. { assembler }
  26. aasmbase,assemble,aasmcpu,
  27. { WebAssembly module format definitions }
  28. wasmbase,
  29. { output }
  30. ogbase,
  31. owbase;
  32. type
  33. TWasmObjSymbolExtraData = class;
  34. TGlobalInitializer = record
  35. case typ:TWasmBasicType of
  36. wbt_i32: (init_i32: Int32);
  37. wbt_i64: (init_i64: Int64);
  38. wbt_f32: (init_f32: Single);
  39. wbt_f64: (init_f64: Double);
  40. end;
  41. { TWasmObjSymbolLinkingData }
  42. TWasmObjSymbolLinkingData = class
  43. public
  44. ImportModule: ansistring;
  45. ImportName: ansistring;
  46. FuncType: TWasmFuncType;
  47. ExeFunctionIndex: Integer;
  48. ExeIndirectFunctionTableIndex: Integer;
  49. ExeTypeIndex: Integer;
  50. ExeTagIndex: Integer;
  51. GlobalType: TWasmBasicType;
  52. GlobalIsMutable: Boolean;
  53. GlobalInitializer: TGlobalInitializer;
  54. IsExported: Boolean;
  55. ExportName: ansistring;
  56. constructor Create;
  57. destructor Destroy;override;
  58. end;
  59. { TWasmObjSymbol }
  60. TWasmObjSymbol = class(TObjSymbol)
  61. FuncIndex: Integer;
  62. SymbolIndex: Integer;
  63. GlobalIndex: Integer;
  64. TagIndex: Integer;
  65. AliasOf: ansistring;
  66. ExtraData: TWasmObjSymbolExtraData;
  67. LinkingData: TWasmObjSymbolLinkingData;
  68. TlsGlobalSym: TWasmObjSymbol;
  69. TlsDataSym: TWasmObjSymbol;
  70. constructor create(AList:TFPHashObjectList;const AName:string);override;
  71. destructor Destroy;override;
  72. function IsAlias: Boolean;
  73. end;
  74. { TWasmObjRelocation }
  75. TWasmObjRelocation = class(TObjRelocation)
  76. public
  77. TypeIndex: Integer;
  78. Addend: LongInt;
  79. { used during linking }
  80. FuncType: TWasmFuncType;
  81. ExeTypeIndex: Integer;
  82. IsFunctionOffsetI32: Boolean;
  83. constructor CreateTypeIndex(ADataOffset:TObjSectionOfs; ATypeIndex: Integer);
  84. constructor CreateFuncType(ADataOffset:TObjSectionOfs; AFuncType: TWasmFuncType);
  85. destructor Destroy;override;
  86. end;
  87. { TWasmObjSymbolExtraData }
  88. TWasmObjSymbolExtraData = class(TFPHashObject)
  89. TypeIdx: Integer;
  90. ExceptionTagTypeIdx: Integer;
  91. ImportModule: ansistring;
  92. ImportName: ansistring;
  93. ExportName: ansistring;
  94. GlobalType: TWasmBasicType;
  95. GlobalIsImmutable: Boolean;
  96. Locals: array of TWasmBasicType;
  97. EncodedLocals: tdynamicarray;
  98. constructor Create(HashObjectList: TFPHashObjectList; const s: TSymStr);
  99. destructor Destroy; override;
  100. procedure AddLocals(alocals: TWasmLocalsDynArray);
  101. end;
  102. { TWasmObjSection }
  103. TWasmObjSection = class(TObjSection)
  104. public
  105. SegIdx: Integer;
  106. SegSymIdx: Integer;
  107. SegOfs: qword;
  108. FileSectionOfs: qword;
  109. MainFuncSymbol: TWasmObjSymbol;
  110. CustomSectionIdx: Integer;
  111. constructor create(AList:TFPHashObjectList;const Aname:string;Aalign:longint;Aoptions:TObjSectionOptions);override;
  112. function IsCode: Boolean;
  113. function IsData: Boolean;
  114. function IsDebug: Boolean;
  115. end;
  116. { TWasmFuncTypeTable }
  117. TWasmFuncTypeTable = class
  118. private
  119. FFuncTypes: array of TWasmFuncType;
  120. function GetCount: Integer;
  121. function GetItem(Index: Integer): TWasmFuncType;
  122. public
  123. destructor Destroy; override;
  124. function AddOrGetFuncType(wft: TWasmFuncType): integer;
  125. procedure WriteTo(d: tdynamicarray);
  126. property Count: Integer read GetCount;
  127. property Items[Index: Integer]: TWasmFuncType read GetItem; default;
  128. end;
  129. { TWasmObjData }
  130. TWasmObjData = class(TObjData)
  131. private
  132. FFuncTypes: TWasmFuncTypeTable;
  133. FObjSymbolsExtraDataList: TFPHashObjectList;
  134. FLastFuncName: string;
  135. function is_smart_section(atype:TAsmSectiontype):boolean;
  136. function sectionname_gas(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
  137. public
  138. constructor create(const n:string);override;
  139. destructor destroy; override;
  140. function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;override;
  141. procedure writeReloc(Data:TRelocDataInt;len:aword;p:TObjSymbol;Reloctype:TObjRelocationType);override;
  142. function AddOrCreateObjSymbolExtraData(const symname:TSymStr): TWasmObjSymbolExtraData;
  143. function globalref(asmsym:TAsmSymbol):TObjSymbol;
  144. function ExceptionTagRef(asmsym:TAsmSymbol):TObjSymbol;
  145. procedure DeclareGlobalType(gt: tai_globaltype);
  146. procedure DeclareFuncType_Pass0(ft: tai_functype);
  147. procedure DeclareFuncType_Pass1(ft: tai_functype);
  148. procedure DeclareFuncType_Pass2(ft: tai_functype);
  149. procedure DeclareTagType(tt: tai_tagtype);
  150. procedure DeclareExportName(en: tai_export_name);
  151. procedure DeclareImportModule(aim: tai_import_module);
  152. procedure DeclareImportName(ain: tai_import_name);
  153. procedure DeclareLocals_Pass0(al: tai_local);
  154. procedure DeclareLocals_Pass1(al: tai_local);
  155. procedure WriteLocals_Pass2(al: tai_local);
  156. procedure symbolpairdefine(akind: TSymbolPairKind;const asym, avalue: string);override;
  157. property FuncTypes: TWasmFuncTypeTable read FFuncTypes;
  158. end;
  159. { TWasmObjOutput }
  160. TWasmObjOutput = class(tObjOutput)
  161. private
  162. FData: TWasmObjData;
  163. FWasmRelocationCodeTable: tdynamicarray;
  164. FWasmRelocationCodeTableEntriesCount: Integer;
  165. FWasmRelocationDataTable: tdynamicarray;
  166. FWasmRelocationDataTableEntriesCount: Integer;
  167. FWasmRelocationDebugFrameTable: tdynamicarray;
  168. FWasmRelocationDebugFrameTableEntriesCount: Integer;
  169. FWasmRelocationDebugInfoTable: tdynamicarray;
  170. FWasmRelocationDebugInfoTableEntriesCount: Integer;
  171. FWasmRelocationDebugLineTable: tdynamicarray;
  172. FWasmRelocationDebugLineTableEntriesCount: Integer;
  173. FWasmRelocationDebugAbbrevTable: tdynamicarray;
  174. FWasmRelocationDebugAbbrevTableEntriesCount: Integer;
  175. FWasmRelocationDebugArangesTable: tdynamicarray;
  176. FWasmRelocationDebugArangesTableEntriesCount: Integer;
  177. FWasmRelocationDebugRangesTable: tdynamicarray;
  178. FWasmRelocationDebugRangesTableEntriesCount: Integer;
  179. FWasmRelocationDebugStrTable: tdynamicarray;
  180. FWasmRelocationDebugStrTableEntriesCount: Integer;
  181. FWasmSymbolTable: tdynamicarray;
  182. FWasmSymbolTableEntriesCount: Integer;
  183. FWasmSections: array [TWasmSectionID] of tdynamicarray;
  184. FWasmCustomSections: array [TWasmCustomSectionType] of tdynamicarray;
  185. FWasmLinkingSubsections: array [low(TWasmLinkingSubsectionType)..high(TWasmLinkingSubsectionType)] of tdynamicarray;
  186. procedure WriteWasmSection(wsid: TWasmSectionID);
  187. procedure WriteWasmCustomSection(wcst: TWasmCustomSectionType);
  188. function IsExternalFunction(sym: TObjSymbol): Boolean;
  189. function IsExportedFunction(sym: TWasmObjSymbol): Boolean;
  190. procedure WriteFunctionCode(dest: tdynamicarray; objsym: TObjSymbol);
  191. procedure WriteSymbolTable;
  192. procedure WriteRelocationCodeTable(CodeSectionIndex: Integer);
  193. procedure WriteRelocationDataTable(DataSectionIndex: Integer);
  194. procedure MaybeWriteRelocationDebugTable(cst: TWasmCustomSectionType; SectionIndex: Integer; EntriesCount: Integer; Table: tdynamicarray);
  195. procedure WriteLinkingSubsection(wlst: TWasmLinkingSubsectionType);
  196. procedure DoRelocations;
  197. procedure WriteRelocations;
  198. function FindFunctionSymbol(Symbol: TWasmObjSymbol): TWasmObjSymbol;
  199. protected
  200. function writeData(Data:TObjData):boolean;override;
  201. public
  202. constructor create(AWriter:TObjectWriter);override;
  203. destructor destroy;override;
  204. end;
  205. { TWasmObjInput }
  206. TWasmObjInput = class(TObjInput)
  207. private
  208. FFuncTypes: array of TWasmFuncType;
  209. public
  210. constructor create;override;
  211. destructor Destroy;override;
  212. class function CanReadObjData(AReader:TObjectreader):boolean;override;
  213. function ReadObjData(AReader:TObjectreader;out ObjData:TObjData):boolean;override;
  214. end;
  215. { TWasmExeOutput }
  216. TWasmExeOutput = class(TExeOutput)
  217. private
  218. const
  219. DataSections: array [1..3] of string = (
  220. '.rodata',
  221. '.data',
  222. 'fpc.resources');
  223. WasmPageSize = 65536;
  224. type
  225. TCustomSectionNameMapEntry = record
  226. idx: UInt32;
  227. name: string;
  228. end;
  229. TCustomSectionNameMap = array of TCustomSectionNameMapEntry;
  230. private
  231. FImports: TFPHashObjectList;
  232. FFuncTypes: TWasmFuncTypeTable;
  233. FFunctionImports: array of record
  234. ModName: ansistring;
  235. Name: ansistring;
  236. TypeIdx: uint32;
  237. end;
  238. FTagImports: array of record
  239. end;
  240. FIndirectFunctionTable: array of record
  241. FuncIdx: Integer;
  242. end;
  243. FImportedMemories: array of record
  244. ModName: ansistring;
  245. Name: ansistring;
  246. MemType: TWasmMemoryType;
  247. end;
  248. FMemories: array of TWasmMemoryType;
  249. FRelocationPass: Integer;
  250. FWasmSections: array [TWasmSectionID] of tdynamicarray;
  251. FWasmCustomSections: array [TWasmCustomSectionType] of tdynamicarray;
  252. FWasmNameSubsections: array [TWasmNameSubsectionType] of tdynamicarray;
  253. FStackPointerSym: TWasmObjSymbol;
  254. FTlsBaseSym: TWasmObjSymbol;
  255. FTlsSizeSym: TWasmObjSymbol;
  256. FTlsAlignSym: TWasmObjSymbol;
  257. FInitTlsFunctionSym: TWasmObjSymbol;
  258. FInitSharedMemoryFunctionSym: TWasmObjSymbol;
  259. FMinMemoryPages,
  260. FMaxMemoryPages: Integer;
  261. { use for the Name section }
  262. FFunctionNameMap: TCustomSectionNameMap;
  263. FGlobalNameMap: TCustomSectionNameMap;
  264. FDataNameMap: TCustomSectionNameMap;
  265. FTagNameMap: TCustomSectionNameMap;
  266. procedure AddToNameMap(var nm: TCustomSectionNameMap; aidx: UInt32; const aname: string);
  267. procedure AddToFunctionNameMap(aidx: UInt32; const aname: string);
  268. procedure AddToGlobalNameMap(aidx: UInt32; const aname: string);
  269. procedure AddToDataNameMap(aidx: UInt32; const aname: string);
  270. procedure AddToTagNameMap(aidx: UInt32; const aname: string);
  271. procedure WriteWasmSection(wsid: TWasmSectionID);
  272. procedure WriteWasmSectionIfNotEmpty(wsid: TWasmSectionID);
  273. procedure WriteWasmCustomSection(wcst: TWasmCustomSectionType);
  274. procedure PrepareImports;
  275. procedure PrepareFunctions;
  276. procedure PrepareTags;
  277. function AddOrGetIndirectFunctionTableIndex(FuncIdx: Integer): integer;
  278. procedure SetStackPointer;
  279. procedure SetTlsSizeAlignAndBase;
  280. procedure SetThreadVarGlobalsInitValues;
  281. procedure GenerateCode_InitTls;
  282. procedure GenerateCode_InitSharedMemory;
  283. procedure GenerateCode_InvokeHelper;
  284. procedure WriteExeSectionToDynArray(exesec: TExeSection; dynarr: tdynamicarray);
  285. procedure WriteMemoryTo(dest: tdynamicarray;const MemType:TWasmMemoryType);
  286. function Memory2String(const MemType:TWasmMemoryType):string;
  287. procedure WriteMap_TypeSection;
  288. procedure WriteMap_IndirectFunctionTable;
  289. protected
  290. function writeData:boolean;override;
  291. procedure DoRelocationFixup(objsec:TObjSection);override;
  292. public
  293. constructor create;override;
  294. destructor destroy;override;
  295. procedure GenerateLibraryImports(ImportLibraryList:TFPHashObjectList);override;
  296. procedure AfterUnusedSectionRemoval;override;
  297. procedure MemPos_ExeSection(const aname:string);override;
  298. procedure Load_Symbol(const aname: string);override;
  299. end;
  300. { TWasmAssembler }
  301. TWasmAssembler = class(tinternalassembler)
  302. constructor create(info: pasminfo; smart:boolean);override;
  303. end;
  304. implementation
  305. uses
  306. cutils,verbose,version,globals,fmodule,ogmap;
  307. const
  308. StackPointerSymStr='__stack_pointer';
  309. procedure WriteUleb5(d: tdynamicarray; v: uint64);
  310. var
  311. b: byte;
  312. i: Integer;
  313. begin
  314. for i:=1 to 5 do
  315. begin
  316. b:=byte(v) and 127;
  317. v:=v shr 7;
  318. if i<>5 then
  319. b:=b or 128;
  320. d.write(b,1);
  321. end;
  322. end;
  323. procedure WriteUleb5(d: tobjsection; v: uint64);
  324. var
  325. b: byte;
  326. i: Integer;
  327. begin
  328. for i:=1 to 5 do
  329. begin
  330. b:=byte(v) and 127;
  331. v:=v shr 7;
  332. if i<>5 then
  333. b:=b or 128;
  334. d.write(b,1);
  335. end;
  336. end;
  337. procedure WriteSleb5(d: tdynamicarray; v: int64);
  338. var
  339. b: byte;
  340. i: Integer;
  341. begin
  342. for i:=1 to 5 do
  343. begin
  344. b:=byte(v) and 127;
  345. v:=SarInt64(v,7);
  346. if i<>5 then
  347. b:=b or 128;
  348. d.write(b,1);
  349. end;
  350. end;
  351. procedure WriteSleb5(d: tobjsection; v: int64);
  352. var
  353. b: byte;
  354. i: Integer;
  355. begin
  356. for i:=1 to 5 do
  357. begin
  358. b:=byte(v) and 127;
  359. v:=SarInt64(v,7);
  360. if i<>5 then
  361. b:=b or 128;
  362. d.write(b,1);
  363. end;
  364. end;
  365. procedure WriteUleb(d: tdynamicarray; v: uint64);
  366. var
  367. b: byte;
  368. begin
  369. repeat
  370. b:=byte(v) and 127;
  371. v:=v shr 7;
  372. if v<>0 then
  373. b:=b or 128;
  374. d.write(b,1);
  375. until v=0;
  376. end;
  377. procedure WriteUleb(d: tobjsection; v: uint64);
  378. var
  379. b: byte;
  380. begin
  381. repeat
  382. b:=byte(v) and 127;
  383. v:=v shr 7;
  384. if v<>0 then
  385. b:=b or 128;
  386. d.write(b,1);
  387. until v=0;
  388. end;
  389. procedure WriteUleb(w: TObjectWriter; v: uint64);
  390. var
  391. b: byte;
  392. begin
  393. repeat
  394. b:=byte(v) and 127;
  395. v:=v shr 7;
  396. if v<>0 then
  397. b:=b or 128;
  398. w.write(b,1);
  399. until v=0;
  400. end;
  401. procedure WriteSleb(d: tdynamicarray; v: int64);
  402. var
  403. b: byte;
  404. Done: Boolean=false;
  405. begin
  406. repeat
  407. b:=byte(v) and 127;
  408. v:=SarInt64(v,7);
  409. if ((v=0) and ((b and 64)=0)) or ((v=-1) and ((b and 64)<>0)) then
  410. Done:=true
  411. else
  412. b:=b or 128;
  413. d.write(b,1);
  414. until Done;
  415. end;
  416. procedure WriteSleb(d: tobjsection; v: int64);
  417. var
  418. b: byte;
  419. Done: Boolean=false;
  420. begin
  421. repeat
  422. b:=byte(v) and 127;
  423. v:=SarInt64(v,7);
  424. if ((v=0) and ((b and 64)=0)) or ((v=-1) and ((b and 64)<>0)) then
  425. Done:=true
  426. else
  427. b:=b or 128;
  428. d.write(b,1);
  429. until Done;
  430. end;
  431. function UlebEncodingSize(v: uint64): Integer;
  432. var
  433. b: byte;
  434. begin
  435. Result:=0;
  436. repeat
  437. b:=byte(v) and 127;
  438. v:=v shr 7;
  439. if v<>0 then
  440. b:=b or 128;
  441. Inc(Result);
  442. until v=0;
  443. end;
  444. {$ifdef FPC_LITTLE_ENDIAN}
  445. procedure WriteF32LE(d: tdynamicarray; v: Single);
  446. begin
  447. d.write(v,4);
  448. end;
  449. procedure WriteF64LE(d: tdynamicarray; v: Double);
  450. begin
  451. d.write(v,8);
  452. end;
  453. {$else FPC_LITTLE_ENDIAN}
  454. procedure WriteF32LE(d: tdynamicarray; v: Single);
  455. var
  456. tmpI: UInt32;
  457. begin
  458. Move(v,tmpI,4);
  459. tmpI:=SwapEndian(tmpI);
  460. d.write(tmpI,4);
  461. end;
  462. procedure WriteF64LE(d: tdynamicarray; v: Double);
  463. var
  464. tmpI: UInt64;
  465. begin
  466. Move(v,tmpI,8);
  467. tmpI:=SwapEndian(tmpI);
  468. d.write(tmpI,8);
  469. end;
  470. {$endif FPC_LITTLE_ENDIAN}
  471. procedure WriteByte(d: tdynamicarray; b: byte);
  472. begin
  473. d.write(b,1);
  474. end;
  475. procedure WriteName(d: tdynamicarray; const s: string);
  476. begin
  477. WriteUleb(d,Length(s));
  478. d.writestr(s);
  479. end;
  480. procedure WriteWasmBasicType(dest: tdynamicarray; wbt: TWasmBasicType);
  481. begin
  482. WriteByte(dest,encode_wasm_basic_type(wbt));
  483. end;
  484. procedure WriteWasmResultType(dest: tdynamicarray; wrt: TWasmResultType);
  485. var
  486. i: Integer;
  487. begin
  488. WriteUleb(dest,Length(wrt));
  489. for i:=low(wrt) to high(wrt) do
  490. WriteWasmBasicType(dest,wrt[i]);
  491. end;
  492. function ReadUleb(d: tdynamicarray): uint64;
  493. var
  494. b: byte;
  495. shift:integer;
  496. begin
  497. b:=0;
  498. result:=0;
  499. shift:=0;
  500. repeat
  501. d.read(b,1);
  502. result:=result or (uint64(b and 127) shl shift);
  503. inc(shift,7);
  504. until (b and 128)=0;
  505. end;
  506. function ReadSleb(d: tdynamicarray): int64;
  507. var
  508. b: byte;
  509. shift:integer;
  510. begin
  511. b:=0;
  512. result:=0;
  513. shift:=0;
  514. repeat
  515. d.read(b,1);
  516. result:=result or (uint64(b and 127) shl shift);
  517. inc(shift,7);
  518. until (b and 128)=0;
  519. {$ifopt Q+}
  520. {$define overflowon}
  521. {$Q-}
  522. {$endif}
  523. {$ifopt R+}
  524. {$define rangeon}
  525. {$R-}
  526. {$endif}
  527. if (b and 64)<>0 then
  528. result:=result or (high(uint64) shl shift);
  529. end;
  530. {$ifdef overflowon}
  531. {$Q+}
  532. {$undef overflowon}
  533. {$endif}
  534. {$ifdef rangeon}
  535. {$R+}
  536. {$undef rangeon}
  537. {$endif}
  538. procedure AddSleb5(d: tdynamicarray; v: int64);
  539. var
  540. q: Int64;
  541. p: LongWord;
  542. begin
  543. p:=d.Pos;
  544. q:=ReadSleb(d);
  545. q:=q+v;
  546. d.seek(p);
  547. WriteSleb5(d,q);
  548. end;
  549. procedure AddUleb5(d: tdynamicarray; v: int64);
  550. var
  551. q: UInt64;
  552. p: LongWord;
  553. begin
  554. p:=d.Pos;
  555. q:=ReadUleb(d);
  556. q:=q+v;
  557. d.seek(p);
  558. WriteUleb5(d,q);
  559. end;
  560. procedure AddInt32(d: tdynamicarray; v: int32);
  561. var
  562. q: int32;
  563. p: LongWord;
  564. begin
  565. p:=d.Pos;
  566. d.read(q,4);
  567. {$ifdef FPC_BIG_ENDIAN}
  568. q:=SwapEndian(q);
  569. {$endif FPC_BIG_ENDIAN}
  570. q:=q+v;
  571. {$ifdef FPC_BIG_ENDIAN}
  572. q:=SwapEndian(q);
  573. {$endif FPC_BIG_ENDIAN}
  574. d.seek(p);
  575. d.write(q,4);
  576. end;
  577. procedure CopyDynamicArray(src, dest: tdynamicarray; size: QWord);
  578. var
  579. buf: array [0..4095] of byte;
  580. bs: Integer;
  581. begin
  582. while size>0 do
  583. begin
  584. if size<SizeOf(buf) then
  585. bs:=Integer(size)
  586. else
  587. bs:=SizeOf(buf);
  588. src.read(buf,bs);
  589. dest.write(buf,bs);
  590. dec(size,bs);
  591. end;
  592. end;
  593. procedure WriteZeros(dest: tdynamicarray; size: QWord);
  594. var
  595. buf : array[0..1023] of byte;
  596. bs: Integer;
  597. begin
  598. fillchar(buf,sizeof(buf),0);
  599. while size>0 do
  600. begin
  601. if size<SizeOf(buf) then
  602. bs:=Integer(size)
  603. else
  604. bs:=SizeOf(buf);
  605. dest.write(buf,bs);
  606. dec(size,bs);
  607. end;
  608. end;
  609. {****************************************************************************
  610. TWasmObjSymbolLinkingData
  611. ****************************************************************************}
  612. constructor TWasmObjSymbolLinkingData.Create;
  613. begin
  614. ExeFunctionIndex:=-1;
  615. ExeIndirectFunctionTableIndex:=-1;
  616. ExeTypeIndex:=-1;
  617. ExeTagIndex:=-1;
  618. end;
  619. destructor TWasmObjSymbolLinkingData.Destroy;
  620. begin
  621. FuncType.Free;
  622. inherited Destroy;
  623. end;
  624. {****************************************************************************
  625. TWasmObjRelocation
  626. ****************************************************************************}
  627. constructor TWasmObjRelocation.CreateTypeIndex(ADataOffset: TObjSectionOfs; ATypeIndex: Integer);
  628. begin
  629. DataOffset:=ADataOffset;
  630. Symbol:=nil;
  631. OrgSize:=0;
  632. Group:=nil;
  633. ObjSection:=nil;
  634. ftype:=ord(RELOC_TYPE_INDEX_LEB);
  635. TypeIndex:=ATypeIndex;
  636. FuncType:=nil;
  637. ExeTypeIndex:=-1;
  638. end;
  639. constructor TWasmObjRelocation.CreateFuncType(ADataOffset: TObjSectionOfs; AFuncType: TWasmFuncType);
  640. begin
  641. DataOffset:=ADataOffset;
  642. Symbol:=nil;
  643. OrgSize:=0;
  644. Group:=nil;
  645. ObjSection:=nil;
  646. ftype:=ord(RELOC_TYPE_INDEX_LEB);
  647. TypeIndex:=-1;
  648. ExeTypeIndex:=-1;
  649. FuncType:=TWasmFuncType.Create(AFuncType);
  650. end;
  651. destructor TWasmObjRelocation.Destroy;
  652. begin
  653. FuncType.Free;
  654. inherited Destroy;
  655. end;
  656. {****************************************************************************
  657. TWasmObjSymbol
  658. ****************************************************************************}
  659. constructor TWasmObjSymbol.create(AList: TFPHashObjectList; const AName: string);
  660. begin
  661. inherited create(AList,AName);
  662. FuncIndex:=-1;
  663. SymbolIndex:=-1;
  664. GlobalIndex:=-1;
  665. TagIndex:=-1;
  666. AliasOf:='';
  667. ExtraData:=nil;
  668. LinkingData:=TWasmObjSymbolLinkingData.Create;
  669. end;
  670. destructor TWasmObjSymbol.Destroy;
  671. begin
  672. LinkingData.Free;
  673. inherited Destroy;
  674. end;
  675. function TWasmObjSymbol.IsAlias: Boolean;
  676. begin
  677. result:=AliasOf<>'';
  678. end;
  679. {****************************************************************************
  680. TWasmObjSymbolExtraData
  681. ****************************************************************************}
  682. constructor TWasmObjSymbolExtraData.Create(HashObjectList: TFPHashObjectList; const s: TSymStr);
  683. begin
  684. EncodedLocals:=nil;
  685. inherited Create(HashObjectList,s);
  686. TypeIdx:=-1;
  687. ExceptionTagTypeIdx:=-1;
  688. end;
  689. destructor TWasmObjSymbolExtraData.Destroy;
  690. begin
  691. EncodedLocals.Free;
  692. inherited Destroy;
  693. end;
  694. procedure TWasmObjSymbolExtraData.AddLocals(alocals: TWasmLocalsDynArray);
  695. var
  696. i,
  697. rle_entries,
  698. cnt: Integer;
  699. lasttype: TWasmBasicType;
  700. begin
  701. Locals:=alocals;
  702. if Assigned(EncodedLocals) then
  703. internalerror(2024081502);
  704. EncodedLocals:=tdynamicarray.Create(64);
  705. if Length(Locals)=0 then
  706. begin
  707. WriteUleb(EncodedLocals,0);
  708. exit;
  709. end;
  710. rle_entries:=1;
  711. for i:=low(Locals)+1 to high(Locals) do
  712. if Locals[i]<>Locals[i-1] then
  713. inc(rle_entries);
  714. WriteUleb(EncodedLocals,rle_entries);
  715. lasttype:=Locals[Low(Locals)];
  716. cnt:=1;
  717. for i:=low(Locals)+1 to high(Locals) do
  718. if Locals[i]=Locals[i-1] then
  719. inc(cnt)
  720. else
  721. begin
  722. WriteUleb(EncodedLocals,cnt);
  723. WriteWasmBasicType(EncodedLocals,lasttype);
  724. lasttype:=Locals[i];
  725. cnt:=1;
  726. end;
  727. WriteUleb(EncodedLocals,cnt);
  728. WriteWasmBasicType(EncodedLocals,lasttype);
  729. end;
  730. {****************************************************************************
  731. TWasmObjSection
  732. ****************************************************************************}
  733. constructor TWasmObjSection.create(AList: TFPHashObjectList; const Aname: string; Aalign: longint; Aoptions: TObjSectionOptions);
  734. begin
  735. inherited create(AList, Aname, Aalign, Aoptions);
  736. SegIdx:=-1;
  737. SegSymIdx:=-1;
  738. CustomSectionIdx:=-1;
  739. MainFuncSymbol:=nil;
  740. end;
  741. function TWasmObjSection.IsCode: Boolean;
  742. const
  743. CodePrefix = '.text';
  744. begin
  745. result:=(Length(Name)>=Length(CodePrefix)) and
  746. (Copy(Name,1,Length(CodePrefix))=CodePrefix);
  747. end;
  748. function TWasmObjSection.IsData: Boolean;
  749. begin
  750. result:=not (IsCode or IsDebug);
  751. end;
  752. function TWasmObjSection.IsDebug: Boolean;
  753. const
  754. DebugPrefix = '.debug';
  755. begin
  756. result:=(Length(Name)>=Length(DebugPrefix)) and
  757. (Copy(Name,1,Length(DebugPrefix))=DebugPrefix);
  758. end;
  759. {****************************************************************************
  760. TWasmFuncTypeTable
  761. ****************************************************************************}
  762. function TWasmFuncTypeTable.GetCount: Integer;
  763. begin
  764. Result:=Length(FFuncTypes);
  765. end;
  766. function TWasmFuncTypeTable.GetItem(Index: Integer): TWasmFuncType;
  767. begin
  768. if (Index<Low(FFuncTypes)) or (Index>High(FFuncTypes)) then
  769. internalerror(2023123101);
  770. Result:=FFuncTypes[Index];
  771. end;
  772. destructor TWasmFuncTypeTable.Destroy;
  773. var
  774. i: Integer;
  775. begin
  776. for i:=low(FFuncTypes) to high(FFuncTypes) do
  777. begin
  778. FFuncTypes[i].free;
  779. FFuncTypes[i]:=nil;
  780. end;
  781. end;
  782. function TWasmFuncTypeTable.AddOrGetFuncType(wft: TWasmFuncType): integer;
  783. var
  784. i: Integer;
  785. begin
  786. for i:=low(FFuncTypes) to high(FFuncTypes) do
  787. if wft.Equals(FFuncTypes[i]) then
  788. exit(i);
  789. result:=Length(FFuncTypes);
  790. SetLength(FFuncTypes,result+1);
  791. FFuncTypes[result]:=TWasmFuncType.Create(wft);
  792. end;
  793. procedure TWasmFuncTypeTable.WriteTo(d: tdynamicarray);
  794. var
  795. types_count, i: Integer;
  796. begin
  797. types_count:=Count;
  798. WriteUleb(d,types_count);
  799. for i:=0 to types_count-1 do
  800. with Items[i] do
  801. begin
  802. WriteByte(d,$60);
  803. WriteWasmResultType(d,params);
  804. WriteWasmResultType(d,results);
  805. end;
  806. end;
  807. {****************************************************************************
  808. TWasmObjData
  809. ****************************************************************************}
  810. function TWasmObjData.is_smart_section(atype: TAsmSectiontype): boolean;
  811. begin
  812. { For bss we need to set some flags that are target dependent,
  813. it is easier to disable it for smartlinking. It doesn't take up
  814. filespace }
  815. result:=not(target_info.system in systems_darwin) and
  816. create_smartlink_sections and
  817. (atype<>sec_toc) and
  818. (atype<>sec_user) and
  819. { on embedded systems every byte counts, so smartlink bss too }
  820. ((atype<>sec_bss) or (target_info.system in (systems_embedded+systems_freertos)));
  821. end;
  822. function TWasmObjData.sectionname_gas(atype: TAsmSectiontype;
  823. const aname: string; aorder: TAsmSectionOrder): string;
  824. const
  825. secnames : array[TAsmSectiontype] of string[length('__DATA, __datacoal_nt,coalesced')] = ('','',
  826. '.text',
  827. '.data',
  828. { why doesn't .rodata work? (FK) }
  829. { sometimes we have to create a data.rel.ro instead of .rodata, e.g. for }
  830. { vtables (and anything else containing relocations), otherwise those are }
  831. { not relocated properly on e.g. linux/ppc64. g++ generates there for a }
  832. { vtable for a class called Window: }
  833. { .section .data.rel.ro._ZTV6Window,"awG",@progbits,_ZTV6Window,comdat }
  834. { TODO: .data.ro not yet working}
  835. {$if defined(arm) or defined(riscv64) or defined(powerpc)}
  836. '.rodata',
  837. {$else defined(arm) or defined(riscv64) or defined(powerpc)}
  838. '.data',
  839. {$endif defined(arm) or defined(riscv64) or defined(powerpc)}
  840. '.rodata',
  841. '.bss',
  842. '.tbss',
  843. '.pdata',
  844. '', { stubs }
  845. '__DATA,__nl_symbol_ptr',
  846. '__DATA,__la_symbol_ptr',
  847. '__DATA,__mod_init_func',
  848. '__DATA,__mod_term_func',
  849. '.stab',
  850. '.stabstr',
  851. '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
  852. '.eh_frame',
  853. '.debug_frame','.debug_info','.debug_line','.debug_abbrev','.debug_aranges','.debug_ranges','.debug_loc','.debug_loclists',
  854. '.fpc',
  855. '.toc',
  856. '.init',
  857. '.fini',
  858. '.objc_class',
  859. '.objc_meta_class',
  860. '.objc_cat_cls_meth',
  861. '.objc_cat_inst_meth',
  862. '.objc_protocol',
  863. '.objc_string_object',
  864. '.objc_cls_meth',
  865. '.objc_inst_meth',
  866. '.objc_cls_refs',
  867. '.objc_message_refs',
  868. '.objc_symbols',
  869. '.objc_category',
  870. '.objc_class_vars',
  871. '.objc_instance_vars',
  872. '.objc_module_info',
  873. '.objc_class_names',
  874. '.objc_meth_var_types',
  875. '.objc_meth_var_names',
  876. '.objc_selector_strs',
  877. '.objc_protocol_ext',
  878. '.objc_class_ext',
  879. '.objc_property',
  880. '.objc_image_info',
  881. '.objc_cstring_object',
  882. '.objc_sel_fixup',
  883. '__DATA,__objc_data',
  884. '__DATA,__objc_const',
  885. '.objc_superrefs',
  886. '__DATA, __datacoal_nt,coalesced',
  887. '.objc_classlist',
  888. '.objc_nlclasslist',
  889. '.objc_catlist',
  890. '.obcj_nlcatlist',
  891. '.objc_protolist',
  892. '.stack',
  893. '.heap',
  894. '.gcc_except_table',
  895. '.ARM.attributes'
  896. );
  897. var
  898. sep : string[3];
  899. secname : string;
  900. begin
  901. secname:=secnames[atype];
  902. if (atype=sec_fpc) and (Copy(aname,1,3)='res') then
  903. begin
  904. result:=secname+'.'+aname;
  905. exit;
  906. end;
  907. { go32v2 stub only loads .text and .data sections, and allocates space for .bss.
  908. Thus, data which normally goes into .rodata and .rodata_norel sections must
  909. end up in .data section }
  910. if (atype in [sec_rodata,sec_rodata_norel]) and
  911. (target_info.system in [system_i386_go32v2,system_m68k_palmos]) then
  912. secname:='.data';
  913. { Windows correctly handles reallocations in readonly sections }
  914. if (atype=sec_rodata) and
  915. (target_info.system in systems_all_windows+systems_nativent-[system_i8086_win16]) then
  916. secname:='.rodata';
  917. { section type user gives the user full controll on the section name }
  918. if atype=sec_user then
  919. secname:=aname;
  920. if is_smart_section(atype) and (aname<>'') then
  921. begin
  922. case aorder of
  923. secorder_begin :
  924. sep:='.b_';
  925. secorder_end :
  926. sep:='.z_';
  927. else
  928. sep:='.n_';
  929. end;
  930. result:=secname+sep+aname
  931. end
  932. else
  933. result:=secname;
  934. end;
  935. constructor TWasmObjData.create(const n: string);
  936. begin
  937. inherited;
  938. CObjSection:=TWasmObjSection;
  939. CObjSymbol:=TWasmObjSymbol;
  940. FObjSymbolsExtraDataList:=TFPHashObjectList.Create;
  941. FFuncTypes:=TWasmFuncTypeTable.Create;
  942. end;
  943. destructor TWasmObjData.destroy;
  944. var
  945. i: Integer;
  946. begin
  947. FObjSymbolsExtraDataList.Free;
  948. FFuncTypes.Free;
  949. inherited destroy;
  950. end;
  951. function TWasmObjData.sectionname(atype: TAsmSectiontype;
  952. const aname: string; aorder: TAsmSectionOrder): string;
  953. begin
  954. if (atype=sec_fpc) or
  955. ((atype=sec_threadvar) and not (ts_wasm_threads in current_settings.targetswitches)) then
  956. atype:=sec_data;
  957. Result:=sectionname_gas(atype, aname, aorder);
  958. end;
  959. procedure TWasmObjData.writeReloc(Data: TRelocDataInt; len: aword;
  960. p: TObjSymbol; Reloctype: TObjRelocationType);
  961. const
  962. leb_zero: array[0..4] of byte=($80,$80,$80,$80,$00);
  963. var
  964. objreloc: TWasmObjRelocation;
  965. begin
  966. if CurrObjSec=nil then
  967. internalerror(200403072);
  968. { workaround crash, when generating debug info for threadvars, when multithreading is turned off.
  969. todo: ensure the debug info for threadvars is actually correct, once we've got WebAssembly debug info working in general }
  970. if (Reloctype=RELOC_DTPOFF) and not (ts_wasm_threads in current_settings.targetswitches) then
  971. Reloctype:=RELOC_ABSOLUTE;
  972. objreloc:=nil;
  973. case Reloctype of
  974. RELOC_FUNCTION_INDEX_LEB:
  975. begin
  976. if Data<>0 then
  977. internalerror(2021092502);
  978. if len<>5 then
  979. internalerror(2021092503);
  980. if not assigned(p) then
  981. internalerror(2021092504);
  982. objreloc:=TWasmObjRelocation.CreateSymbol(CurrObjSec.Size,p,Reloctype);
  983. CurrObjSec.ObjRelocations.Add(objreloc);
  984. writebytes(leb_zero,5);
  985. end;
  986. RELOC_MEMORY_ADDR_LEB,
  987. RELOC_MEMORY_ADDR_OR_TABLE_INDEX_SLEB:
  988. begin
  989. if (Reloctype=RELOC_MEMORY_ADDR_LEB) and (Data<0) then
  990. internalerror(2021092602);
  991. if len<>5 then
  992. internalerror(2021092503);
  993. if not assigned(p) then
  994. internalerror(2021092504);
  995. objreloc:=TWasmObjRelocation.CreateSymbol(CurrObjSec.Size,p,Reloctype);
  996. objreloc.Addend:=Data;
  997. CurrObjSec.ObjRelocations.Add(objreloc);
  998. if RelocType=RELOC_MEMORY_ADDR_LEB then
  999. WriteUleb5(CurrObjSec,Data)
  1000. else
  1001. WriteSleb5(CurrObjSec,Data);
  1002. end;
  1003. RELOC_ABSOLUTE:
  1004. begin
  1005. if len<>4 then
  1006. internalerror(2021092607);
  1007. if not assigned(p) then
  1008. internalerror(2021092608);
  1009. if (p.objsection<>nil) and TWasmObjSection(p.objsection).IsDebug and
  1010. (p.bind<>AB_COMMON) and (p.bind<>AB_EXTERNAL) then
  1011. begin
  1012. objreloc:=TWasmObjRelocation.CreateSection(CurrObjSec.Size,p.objsection,RELOC_ABSOLUTE);
  1013. objreloc.Addend:=Data+p.Address;
  1014. CurrObjSec.ObjRelocations.Add(objreloc);
  1015. {inc(data,p.address);}
  1016. data:=0;
  1017. Data:=NtoLE(Data);
  1018. writebytes(Data,4);
  1019. end
  1020. else
  1021. begin
  1022. objreloc:=TWasmObjRelocation.CreateSymbol(CurrObjSec.Size,p,Reloctype);
  1023. objreloc.Addend:=Data;
  1024. CurrObjSec.ObjRelocations.Add(objreloc);
  1025. Data:=NtoLE(Data);
  1026. writebytes(Data,4);
  1027. end;
  1028. end;
  1029. RELOC_TYPE_INDEX_LEB:
  1030. begin
  1031. if len<>5 then
  1032. internalerror(2021092612);
  1033. if assigned(p) then
  1034. internalerror(2021092613);
  1035. objreloc:=TWasmObjRelocation.CreateTypeIndex(CurrObjSec.Size,Data);
  1036. CurrObjSec.ObjRelocations.Add(objreloc);
  1037. WriteUleb5(CurrObjSec,Data);
  1038. end;
  1039. RELOC_GLOBAL_INDEX_LEB:
  1040. begin
  1041. if len<>5 then
  1042. internalerror(2021092701);
  1043. if Data<>0 then
  1044. internalerror(2021092702);
  1045. if not assigned(p) then
  1046. internalerror(2021092703);
  1047. objreloc:=TWasmObjRelocation.CreateSymbol(CurrObjSec.Size,p,Reloctype);
  1048. CurrObjSec.ObjRelocations.Add(objreloc);
  1049. WriteUleb5(CurrObjSec,0);
  1050. end;
  1051. RELOC_TAG_INDEX_LEB:
  1052. begin
  1053. if len<>5 then
  1054. internalerror(2021092712);
  1055. if Data<>0 then
  1056. internalerror(2021092713);
  1057. if not assigned(p) then
  1058. internalerror(2021092714);
  1059. objreloc:=TWasmObjRelocation.CreateSymbol(CurrObjSec.Size,p,Reloctype);
  1060. CurrObjSec.ObjRelocations.Add(objreloc);
  1061. WriteSleb5(CurrObjSec,0);
  1062. end;
  1063. else
  1064. internalerror(2021092501);
  1065. end;
  1066. end;
  1067. function TWasmObjData.AddOrCreateObjSymbolExtraData(const symname: TSymStr): TWasmObjSymbolExtraData;
  1068. begin
  1069. result:=TWasmObjSymbolExtraData(FObjSymbolsExtraDataList.Find(symname));
  1070. if not assigned(result) then
  1071. result:=TWasmObjSymbolExtraData.Create(FObjSymbolsExtraDataList,symname);
  1072. end;
  1073. function TWasmObjData.globalref(asmsym: TAsmSymbol): TObjSymbol;
  1074. begin
  1075. if assigned(asmsym) then
  1076. begin
  1077. if (asmsym.typ<>AT_WASM_GLOBAL) and (asmsym.typ<>AT_TLS) then
  1078. internalerror(2021092706);
  1079. result:=symbolref(asmsym);
  1080. result.typ:=asmsym.typ;
  1081. end
  1082. else
  1083. result:=nil;
  1084. end;
  1085. function TWasmObjData.ExceptionTagRef(asmsym: TAsmSymbol): TObjSymbol;
  1086. begin
  1087. if assigned(asmsym) then
  1088. begin
  1089. if asmsym.typ<>AT_WASM_EXCEPTION_TAG then
  1090. internalerror(2021092707);
  1091. result:=symbolref(asmsym);
  1092. result.typ:=AT_WASM_EXCEPTION_TAG;
  1093. end
  1094. else
  1095. result:=nil;
  1096. end;
  1097. procedure TWasmObjData.DeclareGlobalType(gt: tai_globaltype);
  1098. var
  1099. ObjSymExtraData: TWasmObjSymbolExtraData;
  1100. ObjSym: TObjSymbol;
  1101. begin
  1102. if not gt.is_external then
  1103. begin
  1104. ObjSym:=symboldefine(gt.sym);
  1105. ObjSym.typ:=AT_WASM_GLOBAL;
  1106. end;
  1107. ObjSymExtraData:=AddOrCreateObjSymbolExtraData(gt.globalname);
  1108. ObjSymExtraData.GlobalType:=gt.gtype;
  1109. ObjSymExtraData.GlobalIsImmutable:=gt.immutable;
  1110. end;
  1111. procedure TWasmObjData.DeclareFuncType_Pass0(ft: tai_functype);
  1112. var
  1113. i: Integer;
  1114. ObjSymExtraData: TWasmObjSymbolExtraData;
  1115. begin
  1116. FLastFuncName:=ft.funcname;
  1117. i:=FFuncTypes.AddOrGetFuncType(ft.functype);
  1118. ObjSymExtraData:=AddOrCreateObjSymbolExtraData(ft.funcname);
  1119. ObjSymExtraData.TypeIdx:=i;
  1120. end;
  1121. procedure TWasmObjData.DeclareFuncType_Pass1(ft: tai_functype);
  1122. begin
  1123. FLastFuncName:=ft.funcname;
  1124. end;
  1125. procedure TWasmObjData.DeclareFuncType_Pass2(ft: tai_functype);
  1126. begin
  1127. FLastFuncName:=ft.funcname;
  1128. end;
  1129. procedure TWasmObjData.DeclareTagType(tt: tai_tagtype);
  1130. var
  1131. ObjSymExtraData: TWasmObjSymbolExtraData;
  1132. ft: TWasmFuncType;
  1133. i: Integer;
  1134. begin
  1135. ObjSymExtraData:=AddOrCreateObjSymbolExtraData(tt.tagname);
  1136. ft:=TWasmFuncType.Create([],tt.params);
  1137. i:=FFuncTypes.AddOrGetFuncType(ft);
  1138. ft.free;
  1139. ObjSymExtraData.ExceptionTagTypeIdx:=i;
  1140. end;
  1141. procedure TWasmObjData.DeclareExportName(en: tai_export_name);
  1142. var
  1143. ObjSymExtraData: TWasmObjSymbolExtraData;
  1144. begin
  1145. ObjSymExtraData:=AddOrCreateObjSymbolExtraData(en.intname);
  1146. ObjSymExtraData.ExportName:=en.extname;
  1147. end;
  1148. procedure TWasmObjData.DeclareImportModule(aim: tai_import_module);
  1149. var
  1150. ObjSymExtraData: TWasmObjSymbolExtraData;
  1151. begin
  1152. ObjSymExtraData:=AddOrCreateObjSymbolExtraData(aim.symname);
  1153. ObjSymExtraData.ImportModule:=aim.importmodule;
  1154. end;
  1155. procedure TWasmObjData.DeclareImportName(ain: tai_import_name);
  1156. var
  1157. ObjSymExtraData: TWasmObjSymbolExtraData;
  1158. begin
  1159. ObjSymExtraData:=AddOrCreateObjSymbolExtraData(ain.symname);
  1160. ObjSymExtraData.ImportName:=ain.importname;
  1161. end;
  1162. procedure TWasmObjData.DeclareLocals_Pass0(al: tai_local);
  1163. var
  1164. ObjSymExtraData: TWasmObjSymbolExtraData;
  1165. begin
  1166. ObjSymExtraData:=TWasmObjSymbolExtraData(FObjSymbolsExtraDataList.Find(FLastFuncName));
  1167. ObjSymExtraData.AddLocals(al.locals);
  1168. alloc(ObjSymExtraData.EncodedLocals.size);
  1169. end;
  1170. procedure TWasmObjData.DeclareLocals_Pass1(al: tai_local);
  1171. var
  1172. ObjSymExtraData: TWasmObjSymbolExtraData;
  1173. begin
  1174. ObjSymExtraData:=TWasmObjSymbolExtraData(FObjSymbolsExtraDataList.Find(FLastFuncName));
  1175. alloc(ObjSymExtraData.EncodedLocals.size);
  1176. end;
  1177. procedure TWasmObjData.WriteLocals_Pass2(al: tai_local);
  1178. var
  1179. ObjSymExtraData: TWasmObjSymbolExtraData;
  1180. d: tdynamicarray;
  1181. buf: array [0..4095] of byte;
  1182. bs,size: Integer;
  1183. begin
  1184. ObjSymExtraData:=TWasmObjSymbolExtraData(FObjSymbolsExtraDataList.Find(FLastFuncName));
  1185. d:=ObjSymExtraData.EncodedLocals;
  1186. d.seek(0);
  1187. size:=d.size;
  1188. while size>0 do
  1189. begin
  1190. if size<SizeOf(buf) then
  1191. bs:=Integer(size)
  1192. else
  1193. bs:=SizeOf(buf);
  1194. d.read(buf,bs);
  1195. writebytes(buf,bs);
  1196. dec(size,bs);
  1197. end;
  1198. end;
  1199. procedure TWasmObjData.symbolpairdefine(akind: TSymbolPairKind; const asym, avalue: string);
  1200. var
  1201. valsym: TObjSymbol;
  1202. aliassym: TWasmObjSymbol;
  1203. begin
  1204. valsym:=CreateSymbol(avalue);
  1205. aliassym:=TWasmObjSymbol(symboldefine(asym,valsym.bind,valsym.typ));
  1206. aliassym.AliasOf:=valsym.Name;
  1207. end;
  1208. {****************************************************************************
  1209. TWasmObjOutput
  1210. ****************************************************************************}
  1211. procedure TWasmObjOutput.WriteWasmSection(wsid: TWasmSectionID);
  1212. var
  1213. b: byte;
  1214. begin
  1215. b:=ord(wsid);
  1216. Writer.write(b,1);
  1217. WriteUleb(Writer,FWasmSections[wsid].size);
  1218. Writer.writearray(FWasmSections[wsid]);
  1219. end;
  1220. procedure TWasmObjOutput.WriteWasmCustomSection(wcst: TWasmCustomSectionType);
  1221. var
  1222. b: byte;
  1223. begin
  1224. b:=0;
  1225. Writer.write(b,1);
  1226. WriteUleb(Writer,FWasmCustomSections[wcst].size);
  1227. Writer.writearray(FWasmCustomSections[wcst]);
  1228. end;
  1229. function TWasmObjOutput.IsExternalFunction(sym: TObjSymbol): Boolean;
  1230. var
  1231. ExtraData: TWasmObjSymbolExtraData;
  1232. begin
  1233. if sym.bind=AB_EXTERNAL then
  1234. begin
  1235. ExtraData:=TWasmObjSymbolExtraData(TWasmObjData(sym.ObjData).FObjSymbolsExtraDataList.Find(sym.Name));
  1236. result:=(ExtraData<>nil) and (ExtraData.TypeIdx<>-1);
  1237. end
  1238. else
  1239. result:=false;
  1240. end;
  1241. function TWasmObjOutput.IsExportedFunction(sym: TWasmObjSymbol): Boolean;
  1242. var
  1243. ExtraData: TWasmObjSymbolExtraData;
  1244. begin
  1245. if (sym.typ=AT_FUNCTION) and not sym.IsAlias then
  1246. begin
  1247. ExtraData:=TWasmObjSymbolExtraData(TWasmObjData(sym.ObjData).FObjSymbolsExtraDataList.Find(sym.Name));
  1248. result:=(ExtraData<>nil) and (ExtraData.ExportName<>'');
  1249. end
  1250. else
  1251. result:=false;
  1252. end;
  1253. procedure TWasmObjOutput.WriteFunctionCode(dest: tdynamicarray; objsym: TObjSymbol);
  1254. var
  1255. ObjSymExtraData: TWasmObjSymbolExtraData;
  1256. ObjSection: TWasmObjSection;
  1257. codelen: QWord;
  1258. begin
  1259. ObjSymExtraData:=TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name));
  1260. ObjSection:=TWasmObjSection(objsym.objsection);
  1261. ObjSection.Data.seek(objsym.address);
  1262. codelen:=objsym.size;
  1263. WriteUleb(dest,codelen);
  1264. ObjSection.FileSectionOfs:=dest.size-objsym.offset;
  1265. CopyDynamicArray(ObjSection.Data,dest,codelen);
  1266. end;
  1267. procedure TWasmObjOutput.WriteSymbolTable;
  1268. begin
  1269. WriteUleb(FWasmLinkingSubsections[WASM_SYMBOL_TABLE],FWasmSymbolTableEntriesCount);
  1270. FWasmSymbolTable.seek(0);
  1271. CopyDynamicArray(FWasmSymbolTable,FWasmLinkingSubsections[WASM_SYMBOL_TABLE],FWasmSymbolTable.size);
  1272. end;
  1273. procedure TWasmObjOutput.WriteRelocationCodeTable(CodeSectionIndex: Integer);
  1274. begin
  1275. WriteUleb(FWasmCustomSections[wcstRelocCode],CodeSectionIndex);
  1276. WriteUleb(FWasmCustomSections[wcstRelocCode],FWasmRelocationCodeTableEntriesCount);
  1277. FWasmRelocationCodeTable.seek(0);
  1278. CopyDynamicArray(FWasmRelocationCodeTable,FWasmCustomSections[wcstRelocCode],FWasmRelocationCodeTable.size);
  1279. end;
  1280. procedure TWasmObjOutput.WriteRelocationDataTable(DataSectionIndex: Integer);
  1281. begin
  1282. WriteUleb(FWasmCustomSections[wcstRelocData],DataSectionIndex);
  1283. WriteUleb(FWasmCustomSections[wcstRelocData],FWasmRelocationDataTableEntriesCount);
  1284. FWasmRelocationDataTable.seek(0);
  1285. CopyDynamicArray(FWasmRelocationDataTable,FWasmCustomSections[wcstRelocData],FWasmRelocationDataTable.size);
  1286. end;
  1287. procedure TWasmObjOutput.MaybeWriteRelocationDebugTable(cst: TWasmCustomSectionType; SectionIndex: Integer; EntriesCount: Integer; Table: tdynamicarray);
  1288. begin
  1289. if EntriesCount>0 then
  1290. begin
  1291. WriteUleb(FWasmCustomSections[cst],SectionIndex);
  1292. WriteUleb(FWasmCustomSections[cst],EntriesCount);
  1293. Table.seek(0);
  1294. CopyDynamicArray(Table,FWasmCustomSections[cst],Table.size);
  1295. WriteWasmCustomSection(cst);
  1296. end;
  1297. end;
  1298. procedure TWasmObjOutput.WriteLinkingSubsection(wlst: TWasmLinkingSubsectionType);
  1299. begin
  1300. if FWasmLinkingSubsections[wlst].size>0 then
  1301. begin
  1302. WriteByte(FWasmCustomSections[wcstLinking],Ord(wlst));
  1303. WriteUleb(FWasmCustomSections[wcstLinking],FWasmLinkingSubsections[wlst].size);
  1304. FWasmLinkingSubsections[wlst].seek(0);
  1305. CopyDynamicArray(FWasmLinkingSubsections[wlst],FWasmCustomSections[wcstLinking],FWasmLinkingSubsections[wlst].size);
  1306. end;
  1307. end;
  1308. procedure TWasmObjOutput.DoRelocations;
  1309. var
  1310. si, ri: Integer;
  1311. objsec: TWasmObjSection;
  1312. objrel: TWasmObjRelocation;
  1313. begin
  1314. for si:=0 to FData.ObjSectionList.Count-1 do
  1315. begin
  1316. objsec:=TWasmObjSection(FData.ObjSectionList[si]);
  1317. for ri:=0 to objsec.ObjRelocations.Count-1 do
  1318. begin
  1319. objrel:=TWasmObjRelocation(objsec.ObjRelocations[ri]);
  1320. case objrel.typ of
  1321. RELOC_FUNCTION_INDEX_LEB:
  1322. begin
  1323. if not assigned(objrel.symbol) then
  1324. internalerror(2021092509);
  1325. objsec.Data.seek(objrel.DataOffset);
  1326. if TWasmObjSymbol(objrel.symbol).FuncIndex<0 then
  1327. message1(asmw_e_illegal_unset_index,objrel.symbol.name)
  1328. else
  1329. WriteUleb5(objsec.Data,TWasmObjSymbol(objrel.symbol).FuncIndex);
  1330. end;
  1331. RELOC_MEMORY_ADDR_OR_TABLE_INDEX_SLEB:
  1332. begin
  1333. if not assigned(objrel.symbol) then
  1334. internalerror(2021092605);
  1335. if not (IsExternalFunction(objrel.symbol) or (objrel.symbol.typ=AT_FUNCTION) or (objrel.symbol.bind=AB_EXTERNAL)) then
  1336. begin
  1337. objsec.Data.seek(objrel.DataOffset);
  1338. AddSleb5(objsec.Data,objrel.symbol.offset+TWasmObjSection(objrel.symbol.objsection).SegOfs);
  1339. end;
  1340. end;
  1341. RELOC_MEMORY_ADDR_LEB:
  1342. begin
  1343. if not assigned(objrel.symbol) then
  1344. internalerror(2021092606);
  1345. if IsExternalFunction(objrel.symbol) or (objrel.symbol.typ=AT_FUNCTION) then
  1346. internalerror(2021092628);
  1347. if objrel.symbol.bind<>AB_EXTERNAL then
  1348. begin
  1349. objsec.Data.seek(objrel.DataOffset);
  1350. AddUleb5(objsec.Data,objrel.symbol.offset+TWasmObjSection(objrel.symbol.objsection).SegOfs);
  1351. end;
  1352. end;
  1353. RELOC_ABSOLUTE:
  1354. begin
  1355. if assigned(objrel.ObjSection) then
  1356. begin
  1357. { todo: should we do something here? }
  1358. //Writeln('todo: section relocation');
  1359. end
  1360. else if not (IsExternalFunction(objrel.symbol) or (objrel.symbol.typ=AT_FUNCTION) or (objrel.symbol.bind=AB_EXTERNAL)) then
  1361. begin
  1362. objsec.Data.seek(objrel.DataOffset);
  1363. AddInt32(objsec.Data,objrel.symbol.offset+TWasmObjSection(objrel.symbol.objsection).SegOfs);
  1364. end;
  1365. end;
  1366. RELOC_TYPE_INDEX_LEB:
  1367. ;
  1368. RELOC_GLOBAL_INDEX_LEB:
  1369. begin
  1370. if not assigned(objrel.symbol) then
  1371. internalerror(2021092509);
  1372. objsec.Data.seek(objrel.DataOffset);
  1373. if TWasmObjSymbol(objrel.symbol).GlobalIndex<0 then
  1374. message1(asmw_e_illegal_unset_index,objrel.symbol.name)
  1375. else
  1376. WriteUleb5(objsec.Data,TWasmObjSymbol(objrel.symbol).GlobalIndex);
  1377. end;
  1378. RELOC_TAG_INDEX_LEB:
  1379. begin
  1380. if not assigned(objrel.symbol) then
  1381. internalerror(2021092716);
  1382. objsec.Data.seek(objrel.DataOffset);
  1383. if TWasmObjSymbol(objrel.symbol).TagIndex<0 then
  1384. message1(asmw_e_illegal_unset_index,objrel.symbol.name)
  1385. else
  1386. WriteSleb5(objsec.Data,TWasmObjSymbol(objrel.symbol).TagIndex);
  1387. end;
  1388. else
  1389. internalerror(2021092510);
  1390. end;
  1391. end;
  1392. end;
  1393. end;
  1394. procedure TWasmObjOutput.WriteRelocations;
  1395. var
  1396. si, ri: Integer;
  1397. objsec: TWasmObjSection;
  1398. objrel: TWasmObjRelocation;
  1399. relout: tdynamicarray;
  1400. relcount: PInteger;
  1401. FuncSym: TWasmObjSymbol;
  1402. begin
  1403. for si:=0 to FData.ObjSectionList.Count-1 do
  1404. begin
  1405. objsec:=TWasmObjSection(FData.ObjSectionList[si]);
  1406. if objsec.IsCode then
  1407. begin
  1408. relout:=FWasmRelocationCodeTable;
  1409. relcount:=@FWasmRelocationCodeTableEntriesCount;
  1410. end
  1411. else if objsec.IsData then
  1412. begin
  1413. relout:=FWasmRelocationDataTable;
  1414. relcount:=@FWasmRelocationDataTableEntriesCount;
  1415. end
  1416. else if objsec.IsDebug then
  1417. begin
  1418. case objsec.Name of
  1419. '.debug_frame':
  1420. begin
  1421. relout:=FWasmRelocationDebugFrameTable;
  1422. relcount:=@FWasmRelocationDebugFrameTableEntriesCount;
  1423. end;
  1424. '.debug_info':
  1425. begin
  1426. relout:=FWasmRelocationDebugInfoTable;
  1427. relcount:=@FWasmRelocationDebugInfoTableEntriesCount;
  1428. end;
  1429. '.debug_line':
  1430. begin
  1431. relout:=FWasmRelocationDebugLineTable;
  1432. relcount:=@FWasmRelocationDebugLineTableEntriesCount;
  1433. end;
  1434. '.debug_abbrev':
  1435. begin
  1436. relout:=FWasmRelocationDebugAbbrevTable;
  1437. relcount:=@FWasmRelocationDebugAbbrevTableEntriesCount;
  1438. end;
  1439. '.debug_aranges':
  1440. begin
  1441. relout:=FWasmRelocationDebugArangesTable;
  1442. relcount:=@FWasmRelocationDebugArangesTableEntriesCount;
  1443. end;
  1444. '.debug_ranges':
  1445. begin
  1446. relout:=FWasmRelocationDebugRangesTable;
  1447. relcount:=@FWasmRelocationDebugRangesTableEntriesCount;
  1448. end;
  1449. '.debug_str':
  1450. begin
  1451. relout:=FWasmRelocationDebugStrTable;
  1452. relcount:=@FWasmRelocationDebugStrTableEntriesCount;
  1453. end;
  1454. else
  1455. internalerror(2022071601);
  1456. end;
  1457. end
  1458. else
  1459. continue;
  1460. for ri:=0 to objsec.ObjRelocations.Count-1 do
  1461. begin
  1462. objrel:=TWasmObjRelocation(objsec.ObjRelocations[ri]);
  1463. case objrel.typ of
  1464. RELOC_FUNCTION_INDEX_LEB:
  1465. begin
  1466. if not assigned(objrel.symbol) then
  1467. internalerror(2021092508);
  1468. Inc(relcount^);
  1469. WriteByte(relout,Ord(R_WASM_FUNCTION_INDEX_LEB));
  1470. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1471. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  1472. end;
  1473. RELOC_MEMORY_ADDR_LEB:
  1474. begin
  1475. if not assigned(objrel.symbol) then
  1476. internalerror(2021092603);
  1477. Inc(relcount^);
  1478. if IsExternalFunction(objrel.symbol) or (objrel.symbol.typ=AT_FUNCTION) then
  1479. internalerror(2021092628);
  1480. WriteByte(relout,Ord(R_WASM_MEMORY_ADDR_LEB));
  1481. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1482. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  1483. WriteSleb(relout,objrel.Addend); { addend to add to the address }
  1484. end;
  1485. RELOC_MEMORY_ADDR_OR_TABLE_INDEX_SLEB:
  1486. begin
  1487. if not assigned(objrel.symbol) then
  1488. internalerror(2021092604);
  1489. Inc(relcount^);
  1490. if IsExternalFunction(objrel.symbol) or (objrel.symbol.typ=AT_FUNCTION) then
  1491. begin
  1492. WriteByte(relout,Ord(R_WASM_TABLE_INDEX_SLEB));
  1493. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1494. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  1495. end
  1496. else
  1497. begin
  1498. WriteByte(relout,Ord(R_WASM_MEMORY_ADDR_SLEB));
  1499. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1500. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  1501. WriteSleb(relout,objrel.Addend); { addend to add to the address }
  1502. end;
  1503. end;
  1504. RELOC_ABSOLUTE:
  1505. begin
  1506. // todo: figure this out, why do these exist?
  1507. //if assigned(objrel.symbol) and not assigned(objrel.symbol.objsection) then
  1508. // Writeln('!!! ', objrel.symbol.name);
  1509. if assigned(objrel.objsection) then
  1510. begin
  1511. Inc(relcount^);
  1512. WriteByte(relout,Ord(R_WASM_SECTION_OFFSET_I32));
  1513. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1514. if (TWasmObjSection(objrel.objsection).SegSymIdx<0) then
  1515. message1(asmw_e_illegal_unset_index,objrel.objsection.name)
  1516. else
  1517. WriteUleb(relout,TWasmObjSection(objrel.objsection).SegSymIdx);
  1518. WriteSleb(relout,objrel.Addend); { addend to add to the address }
  1519. end
  1520. else if (IsExternalFunction(objrel.symbol) or (objrel.symbol.typ=AT_FUNCTION)) and not objsec.IsDebug then
  1521. begin
  1522. Inc(relcount^);
  1523. WriteByte(relout,Ord(R_WASM_TABLE_INDEX_I32));
  1524. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1525. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  1526. end
  1527. else if assigned(objrel.symbol) and assigned(objrel.symbol.objsection) and TWasmObjSection(objrel.symbol.objsection).IsCode then
  1528. begin
  1529. Inc(relcount^);
  1530. WriteByte(relout,Ord(R_WASM_FUNCTION_OFFSET_I32));
  1531. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1532. FuncSym:=FindFunctionSymbol(TWasmObjSymbol(objrel.Symbol));
  1533. if FuncSym.SymbolIndex<0 then
  1534. message1(asmw_e_illegal_unset_index,FuncSym.Name)
  1535. else
  1536. WriteUleb(relout,FuncSym.SymbolIndex);
  1537. WriteSleb(relout,objrel.Addend+objrel.symbol.address) { addend to add to the address }
  1538. end
  1539. else if assigned(objrel.symbol) and (objrel.symbol.typ=AT_WASM_GLOBAL) then
  1540. begin
  1541. Inc(relcount^);
  1542. WriteByte(relout,Ord(R_WASM_GLOBAL_INDEX_I32));
  1543. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1544. if (TWasmObjSymbol(objrel.symbol).SymbolIndex<0) then
  1545. message1(asmw_e_illegal_unset_index,objrel.symbol.name)
  1546. else
  1547. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  1548. end
  1549. else
  1550. begin
  1551. Inc(relcount^);
  1552. WriteByte(relout,Ord(R_WASM_MEMORY_ADDR_I32));
  1553. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1554. if (TWasmObjSymbol(objrel.symbol).SymbolIndex<0) then
  1555. begin
  1556. Writeln(objrel.symbol.objsection.Name, ' ', objrel.symbol.name, ' ', objsec.Name);
  1557. message1(asmw_e_illegal_unset_index,objrel.symbol.name);
  1558. end
  1559. else
  1560. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  1561. WriteSleb(relout,objrel.Addend); { addend to add to the address }
  1562. end;
  1563. end;
  1564. RELOC_TYPE_INDEX_LEB:
  1565. begin
  1566. Inc(relcount^);
  1567. WriteByte(relout,Ord(R_WASM_TYPE_INDEX_LEB));
  1568. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1569. WriteUleb(relout,objrel.TypeIndex);
  1570. end;
  1571. RELOC_GLOBAL_INDEX_LEB:
  1572. begin
  1573. if not assigned(objrel.symbol) then
  1574. internalerror(2021092704);
  1575. Inc(relcount^);
  1576. WriteByte(relout,Ord(R_WASM_GLOBAL_INDEX_LEB));
  1577. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1578. if (TWasmObjSymbol(objrel.symbol).SymbolIndex<0) then
  1579. message1(asmw_e_illegal_unset_index,objrel.symbol.name)
  1580. else
  1581. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  1582. end;
  1583. RELOC_TAG_INDEX_LEB:
  1584. begin
  1585. if not assigned(objrel.symbol) then
  1586. internalerror(2021092717);
  1587. Inc(relcount^);
  1588. WriteByte(relout,Ord(R_WASM_TAG_INDEX_LEB));
  1589. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1590. if (TWasmObjSymbol(objrel.symbol).SymbolIndex<0) then
  1591. message1(asmw_e_illegal_unset_index,objrel.symbol.name)
  1592. else
  1593. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  1594. end;
  1595. else
  1596. internalerror(2021092507);
  1597. end;
  1598. end;
  1599. end;
  1600. end;
  1601. function TWasmObjOutput.FindFunctionSymbol(Symbol: TWasmObjSymbol): TWasmObjSymbol;
  1602. begin
  1603. Result:=TWasmObjSection(Symbol.objsection).MainFuncSymbol;
  1604. end;
  1605. function TWasmObjOutput.writeData(Data:TObjData):boolean;
  1606. var
  1607. section_nr: Integer;
  1608. procedure MaybeAddDebugSectionToSymbolTable(st: TWasmCustomDebugSectionType; var debug_section_nr: Integer);
  1609. var
  1610. objsec: TWasmObjSection;
  1611. begin
  1612. objsec:=TWasmObjSection(Data.ObjSectionList.Find(WasmCustomSectionName[st]));
  1613. if Assigned(objsec) then
  1614. begin
  1615. debug_section_nr:=section_nr;
  1616. Inc(section_nr);
  1617. objsec.SegSymIdx:=FWasmSymbolTableEntriesCount;
  1618. objsec.CustomSectionIdx:=debug_section_nr;
  1619. Inc(FWasmSymbolTableEntriesCount);
  1620. WriteByte(FWasmSymbolTable,Ord(SYMTAB_SECTION));
  1621. WriteUleb(FWasmSymbolTable,WASM_SYM_BINDING_LOCAL);
  1622. WriteUleb(FWasmSymbolTable,debug_section_nr);
  1623. end;
  1624. end;
  1625. procedure MaybeWriteDebugSection(st: TWasmCustomDebugSectionType);
  1626. var
  1627. objsec: TWasmObjSection;
  1628. begin
  1629. objsec:=TWasmObjSection(Data.ObjSectionList.Find(WasmCustomSectionName[st]));
  1630. if Assigned(objsec) then
  1631. begin
  1632. if oso_Data in objsec.SecOptions then
  1633. begin
  1634. objsec.Data.seek(0);
  1635. CopyDynamicArray(objsec.Data,FWasmCustomSections[st],objsec.Size);
  1636. end
  1637. else
  1638. WriteZeros(FWasmCustomSections[st],objsec.Size);
  1639. WriteWasmCustomSection(st);
  1640. end;
  1641. end;
  1642. var
  1643. i: Integer;
  1644. objsec: TWasmObjSection;
  1645. segment_count: Integer = 0;
  1646. cur_seg_ofs: qword = 0;
  1647. imports_count, NextImportFunctionIndex, NextFunctionIndex,
  1648. code_section_nr, data_section_nr,
  1649. debug_abbrev_section_nr,debug_info_section_nr,debug_str_section_nr,
  1650. debug_line_section_nr,debug_frame_section_nr,debug_aranges_section_nr,
  1651. debug_ranges_section_nr,
  1652. NextGlobalIndex, NextTagIndex: Integer;
  1653. import_globals_count: Integer = 0;
  1654. globals_count: Integer = 0;
  1655. import_functions_count: Integer = 0;
  1656. export_functions_count: Integer = 0;
  1657. functions_count: Integer = 0;
  1658. import_exception_tags_count: Integer = 0;
  1659. exception_tags_count: Integer = 0;
  1660. objsym, ObjSymAlias: TWasmObjSymbol;
  1661. cust_sec: TWasmCustomSectionType;
  1662. SegmentFlags, SymbolFlags: UInt64;
  1663. begin
  1664. FData:=TWasmObjData(Data);
  1665. { each custom sections starts with its name }
  1666. for cust_sec in TWasmCustomSectionType do
  1667. WriteName(FWasmCustomSections[cust_sec],WasmCustomSectionName[cust_sec]);
  1668. WriteUleb(FWasmCustomSections[wcstLinking],2); { linking metadata version }
  1669. for i:=0 to Data.ObjSymbolList.Count-1 do
  1670. begin
  1671. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1672. if objsym.typ=AT_WASM_EXCEPTION_TAG then
  1673. if objsym.bind=AB_EXTERNAL then
  1674. Inc(import_exception_tags_count)
  1675. else
  1676. Inc(exception_tags_count);
  1677. if objsym.typ=AT_WASM_GLOBAL then
  1678. if objsym.bind=AB_EXTERNAL then
  1679. Inc(import_globals_count)
  1680. else
  1681. Inc(globals_count);
  1682. if (objsym.typ=AT_TLS) and (ts_wasm_threads in current_settings.targetswitches) then
  1683. Inc(import_globals_count);
  1684. if IsExternalFunction(objsym) then
  1685. Inc(import_functions_count);
  1686. if (objsym.typ=AT_FUNCTION) and not objsym.IsAlias then
  1687. begin
  1688. TWasmObjSection(objsym.objsection).MainFuncSymbol:=objsym;
  1689. Inc(functions_count);
  1690. end;
  1691. if IsExportedFunction(objsym) then
  1692. Inc(export_functions_count);
  1693. end;
  1694. FData.FFuncTypes.WriteTo(FWasmSections[wsiType]);
  1695. for i:=0 to Data.ObjSectionList.Count-1 do
  1696. begin
  1697. objsec:=TWasmObjSection(Data.ObjSectionList[i]);
  1698. if objsec.IsCode then
  1699. objsec.SegIdx:=-1
  1700. else if objsec.IsData then
  1701. begin
  1702. objsec.SegIdx:=segment_count;
  1703. objsec.SegOfs:=cur_seg_ofs;
  1704. Inc(segment_count);
  1705. Inc(cur_seg_ofs,objsec.Size);
  1706. end;
  1707. end;
  1708. imports_count:=2+import_globals_count+import_functions_count+import_exception_tags_count;
  1709. WriteUleb(FWasmSections[wsiImport],imports_count);
  1710. { import memories }
  1711. WriteName(FWasmSections[wsiImport],'env');
  1712. WriteName(FWasmSections[wsiImport],'__linear_memory');
  1713. WriteByte(FWasmSections[wsiImport],$02); { mem }
  1714. WriteByte(FWasmSections[wsiImport],$00); { min }
  1715. WriteUleb(FWasmSections[wsiImport],1); { 1 page }
  1716. { import globals }
  1717. NextGlobalIndex:=0;
  1718. for i:=0 to Data.ObjSymbolList.Count-1 do
  1719. begin
  1720. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1721. if (objsym.bind=AB_EXTERNAL) and (objsym.typ=AT_WASM_GLOBAL) then
  1722. begin
  1723. objsym.GlobalIndex:=NextGlobalIndex;
  1724. Inc(NextGlobalIndex);
  1725. objsym.ExtraData:=TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name));
  1726. if objsym.ExtraData.ImportModule<>'' then
  1727. WriteName(FWasmSections[wsiImport],objsym.ExtraData.ImportModule)
  1728. else
  1729. WriteName(FWasmSections[wsiImport],'env');
  1730. WriteName(FWasmSections[wsiImport],objsym.Name);
  1731. WriteByte(FWasmSections[wsiImport],$03); { global }
  1732. WriteWasmBasicType(FWasmSections[wsiImport],objsym.ExtraData.GlobalType);
  1733. if objsym.ExtraData.GlobalIsImmutable then
  1734. WriteByte(FWasmSections[wsiImport],$00) { const }
  1735. else
  1736. WriteByte(FWasmSections[wsiImport],$01); { var }
  1737. end
  1738. else if (objsym.typ=AT_TLS) and (ts_wasm_threads in current_settings.targetswitches) then
  1739. begin
  1740. objsym.GlobalIndex:=NextGlobalIndex;
  1741. Inc(NextGlobalIndex);
  1742. objsym.ExtraData:=nil;
  1743. WriteName(FWasmSections[wsiImport],'GOT.mem');
  1744. WriteName(FWasmSections[wsiImport],objsym.Name);
  1745. WriteByte(FWasmSections[wsiImport],$03); { global }
  1746. WriteWasmBasicType(FWasmSections[wsiImport],wbt_i32); { i32 }
  1747. WriteByte(FWasmSections[wsiImport],$01); { var }
  1748. end;
  1749. end;
  1750. { import functions }
  1751. NextImportFunctionIndex:=0;
  1752. for i:=0 to Data.ObjSymbolList.Count-1 do
  1753. begin
  1754. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1755. if IsExternalFunction(objsym) then
  1756. begin
  1757. objsym.FuncIndex:=NextImportFunctionIndex;
  1758. Inc(NextImportFunctionIndex);
  1759. objsym.ExtraData:=TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name));
  1760. if objsym.ExtraData.ImportModule<>'' then
  1761. WriteName(FWasmSections[wsiImport],objsym.ExtraData.ImportModule)
  1762. else
  1763. WriteName(FWasmSections[wsiImport],'env');
  1764. WriteName(FWasmSections[wsiImport],objsym.Name);
  1765. WriteByte(FWasmSections[wsiImport],$00); { func }
  1766. WriteUleb(FWasmSections[wsiImport],TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name)).TypeIdx);
  1767. end;
  1768. end;
  1769. { import tables }
  1770. WriteName(FWasmSections[wsiImport],'env');
  1771. WriteName(FWasmSections[wsiImport],'__indirect_function_table');
  1772. WriteByte(FWasmSections[wsiImport],$01); { table }
  1773. WriteByte(FWasmSections[wsiImport],$70); { funcref }
  1774. WriteByte(FWasmSections[wsiImport],$00); { min }
  1775. WriteUleb(FWasmSections[wsiImport],1); { 1 }
  1776. { import tags }
  1777. NextTagIndex:=0;
  1778. for i:=0 to Data.ObjSymbolList.Count-1 do
  1779. begin
  1780. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1781. if (objsym.typ=AT_WASM_EXCEPTION_TAG) and (objsym.bind=AB_EXTERNAL) then
  1782. begin
  1783. objsym.TagIndex:=NextTagIndex;
  1784. Inc(NextTagIndex);
  1785. objsym.ExtraData:=TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name));
  1786. if objsym.ExtraData.ImportModule<>'' then
  1787. WriteName(FWasmSections[wsiImport],objsym.ExtraData.ImportModule)
  1788. else
  1789. WriteName(FWasmSections[wsiImport],'env');
  1790. WriteName(FWasmSections[wsiImport],objsym.Name);
  1791. WriteByte(FWasmSections[wsiImport],$04); { tag }
  1792. WriteByte(FWasmSections[wsiImport],$00); { exception }
  1793. WriteUleb(FWasmSections[wsiImport],objsym.ExtraData.ExceptionTagTypeIdx);
  1794. end;
  1795. end;
  1796. WriteUleb(FWasmSections[wsiFunction],functions_count);
  1797. NextFunctionIndex:=NextImportFunctionIndex;
  1798. for i:=0 to Data.ObjSymbolList.Count-1 do
  1799. begin
  1800. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1801. if (objsym.typ=AT_FUNCTION) and not objsym.IsAlias then
  1802. begin
  1803. objsym.FuncIndex:=NextFunctionIndex;
  1804. Inc(NextFunctionIndex);
  1805. WriteUleb(FWasmSections[wsiFunction],TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name)).TypeIdx);
  1806. end;
  1807. end;
  1808. if exception_tags_count>0 then
  1809. begin
  1810. WriteUleb(FWasmSections[wsiTag],exception_tags_count);
  1811. for i:=0 to Data.ObjSymbolList.Count-1 do
  1812. begin
  1813. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1814. if (objsym.typ=AT_WASM_EXCEPTION_TAG) and (objsym.bind<>AB_EXTERNAL) then
  1815. begin
  1816. objsym.TagIndex:=NextTagIndex;
  1817. Inc(NextTagIndex);
  1818. objsym.ExtraData:=TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name));
  1819. WriteByte(FWasmSections[wsiTag],$00); { exception }
  1820. WriteUleb(FWasmSections[wsiTag],objsym.ExtraData.ExceptionTagTypeIdx);
  1821. end;
  1822. end;
  1823. end;
  1824. if globals_count>0 then
  1825. begin
  1826. WriteUleb(FWasmSections[wsiGlobal],globals_count);
  1827. for i:=0 to Data.ObjSymbolList.Count-1 do
  1828. begin
  1829. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1830. if (objsym.typ=AT_WASM_GLOBAL) and (objsym.bind<>AB_EXTERNAL) then
  1831. begin
  1832. objsym.GlobalIndex:=NextGlobalIndex;
  1833. Inc(NextGlobalIndex);
  1834. objsym.ExtraData:=TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name));
  1835. WriteWasmBasicType(FWasmSections[wsiGlobal],objsym.ExtraData.GlobalType);
  1836. if objsym.ExtraData.GlobalIsImmutable then
  1837. WriteByte(FWasmSections[wsiGlobal],$00) { const }
  1838. else
  1839. WriteByte(FWasmSections[wsiGlobal],$01); { var }
  1840. { init expr }
  1841. case objsym.ExtraData.GlobalType of
  1842. wbt_i32:
  1843. begin
  1844. WriteByte(FWasmSections[wsiGlobal],$41); { i32.const }
  1845. WriteByte(FWasmSections[wsiGlobal],0); { 0 (in signed LEB128 format) }
  1846. WriteByte(FWasmSections[wsiGlobal],$0B); { end }
  1847. end;
  1848. wbt_i64:
  1849. begin
  1850. WriteByte(FWasmSections[wsiGlobal],$42); { i64.const }
  1851. WriteByte(FWasmSections[wsiGlobal],0); { 0 (in signed LEB128 format) }
  1852. WriteByte(FWasmSections[wsiGlobal],$0B); { end }
  1853. end;
  1854. wbt_f32:
  1855. begin
  1856. WriteByte(FWasmSections[wsiGlobal],$43); { f32.const }
  1857. WriteByte(FWasmSections[wsiGlobal],$00); { 0 (in little endian IEEE single precision floating point format) }
  1858. WriteByte(FWasmSections[wsiGlobal],$00);
  1859. WriteByte(FWasmSections[wsiGlobal],$00);
  1860. WriteByte(FWasmSections[wsiGlobal],$00);
  1861. WriteByte(FWasmSections[wsiGlobal],$0B); { end }
  1862. end;
  1863. wbt_f64:
  1864. begin
  1865. WriteByte(FWasmSections[wsiGlobal],$44); { f64.const }
  1866. WriteByte(FWasmSections[wsiGlobal],$00); { 0 (in little endian IEEE double precision floating point format) }
  1867. WriteByte(FWasmSections[wsiGlobal],$00);
  1868. WriteByte(FWasmSections[wsiGlobal],$00);
  1869. WriteByte(FWasmSections[wsiGlobal],$00);
  1870. WriteByte(FWasmSections[wsiGlobal],$00);
  1871. WriteByte(FWasmSections[wsiGlobal],$00);
  1872. WriteByte(FWasmSections[wsiGlobal],$00);
  1873. WriteByte(FWasmSections[wsiGlobal],$00);
  1874. WriteByte(FWasmSections[wsiGlobal],$0B); { end }
  1875. end;
  1876. wbt_externref:
  1877. begin
  1878. WriteByte(FWasmSections[wsiGlobal],$D0); { ref.null extern }
  1879. WriteByte(FWasmSections[wsiGlobal],$6F);
  1880. WriteByte(FWasmSections[wsiGlobal],$0B); { end }
  1881. end;
  1882. wbt_funcref:
  1883. begin
  1884. WriteByte(FWasmSections[wsiGlobal],$D0); { ref.null func }
  1885. WriteByte(FWasmSections[wsiGlobal],$70);
  1886. WriteByte(FWasmSections[wsiGlobal],$0B); { end }
  1887. end;
  1888. else
  1889. internalerror(2022052801);
  1890. end;
  1891. end;
  1892. end;
  1893. end;
  1894. if export_functions_count>0 then
  1895. begin
  1896. WriteUleb(FWasmSections[wsiExport],export_functions_count);
  1897. for i:=0 to Data.ObjSymbolList.Count-1 do
  1898. begin
  1899. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1900. if IsExportedFunction(objsym) then
  1901. begin
  1902. WriteName(FWasmSections[wsiExport],TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name)).ExportName);
  1903. WriteByte(FWasmSections[wsiExport],0); { func }
  1904. if (objsym.FuncIndex<0) then
  1905. message1(asmw_e_illegal_unset_index,objsym.name)
  1906. else
  1907. WriteUleb(FWasmSections[wsiExport],objsym.FuncIndex);
  1908. end;
  1909. end;
  1910. end;
  1911. Writer.write(WasmModuleMagic,SizeOf(WasmModuleMagic));
  1912. Writer.write(WasmVersion,SizeOf(WasmVersion));
  1913. if ts_wasm_threads in current_settings.targetswitches then
  1914. begin
  1915. WriteUleb(FWasmCustomSections[wcstTargetFeatures],4);
  1916. WriteUleb(FWasmCustomSections[wcstTargetFeatures],$2B);
  1917. WriteName(FWasmCustomSections[wcstTargetFeatures],'atomics');
  1918. WriteUleb(FWasmCustomSections[wcstTargetFeatures],$2B);
  1919. WriteName(FWasmCustomSections[wcstTargetFeatures],'bulk-memory');
  1920. WriteUleb(FWasmCustomSections[wcstTargetFeatures],$2B);
  1921. WriteName(FWasmCustomSections[wcstTargetFeatures],'mutable-globals');
  1922. WriteUleb(FWasmCustomSections[wcstTargetFeatures],$2B);
  1923. WriteName(FWasmCustomSections[wcstTargetFeatures],'sign-ext');
  1924. end
  1925. else
  1926. begin
  1927. WriteUleb(FWasmCustomSections[wcstTargetFeatures],3);
  1928. WriteUleb(FWasmCustomSections[wcstTargetFeatures],$2B);
  1929. WriteName(FWasmCustomSections[wcstTargetFeatures],'bulk-memory');
  1930. WriteUleb(FWasmCustomSections[wcstTargetFeatures],$2B);
  1931. WriteName(FWasmCustomSections[wcstTargetFeatures],'mutable-globals');
  1932. WriteUleb(FWasmCustomSections[wcstTargetFeatures],$2B);
  1933. WriteName(FWasmCustomSections[wcstTargetFeatures],'sign-ext');
  1934. end;
  1935. { Write the producers section:
  1936. https://github.com/WebAssembly/tool-conventions/blob/main/ProducersSection.md }
  1937. WriteUleb(FWasmCustomSections[wcstProducers],2);
  1938. WriteName(FWasmCustomSections[wcstProducers],'language');
  1939. WriteUleb(FWasmCustomSections[wcstProducers],1);
  1940. WriteName(FWasmCustomSections[wcstProducers],'Pascal');
  1941. WriteName(FWasmCustomSections[wcstProducers],'');
  1942. WriteName(FWasmCustomSections[wcstProducers],'processed-by');
  1943. WriteUleb(FWasmCustomSections[wcstProducers],1);
  1944. WriteName(FWasmCustomSections[wcstProducers],'Free Pascal Compiler (FPC)');
  1945. WriteName(FWasmCustomSections[wcstProducers],full_version_string+' ['+date_string+'] for '+target_cpu_string+' - '+target_info.shortname);
  1946. code_section_nr:=-1;
  1947. data_section_nr:=-1;
  1948. debug_abbrev_section_nr:=-1;
  1949. debug_info_section_nr:=-1;
  1950. debug_str_section_nr:=-1;
  1951. debug_line_section_nr:=-1;
  1952. debug_frame_section_nr:=-1;
  1953. debug_aranges_section_nr:=-1;
  1954. debug_ranges_section_nr:=-1;
  1955. section_nr:=0;
  1956. WriteWasmSection(wsiType);
  1957. Inc(section_nr);
  1958. WriteWasmSection(wsiImport);
  1959. Inc(section_nr);
  1960. WriteWasmSection(wsiFunction);
  1961. Inc(section_nr);
  1962. if exception_tags_count>0 then
  1963. begin
  1964. WriteWasmSection(wsiTag);
  1965. Inc(section_nr);
  1966. end;
  1967. if globals_count>0 then
  1968. begin
  1969. WriteWasmSection(wsiGlobal);
  1970. Inc(section_nr);
  1971. end;
  1972. if export_functions_count>0 then
  1973. begin
  1974. WriteWasmSection(wsiExport);
  1975. Inc(section_nr);
  1976. end;
  1977. { determine the section numbers for the datacount, code, data and debug sections ahead of time }
  1978. if segment_count>0 then
  1979. Inc(section_nr); { the DataCount section }
  1980. code_section_nr:=section_nr; { the Code section }
  1981. Inc(section_nr);
  1982. if segment_count>0 then
  1983. begin
  1984. data_section_nr:=section_nr; { the Data section }
  1985. Inc(section_nr);
  1986. end;
  1987. { the debug sections }
  1988. MaybeAddDebugSectionToSymbolTable(wcstDebugAbbrev,debug_abbrev_section_nr);
  1989. MaybeAddDebugSectionToSymbolTable(wcstDebugInfo,debug_info_section_nr);
  1990. MaybeAddDebugSectionToSymbolTable(wcstDebugStr,debug_str_section_nr);
  1991. MaybeAddDebugSectionToSymbolTable(wcstDebugLine,debug_line_section_nr);
  1992. MaybeAddDebugSectionToSymbolTable(wcstDebugFrame,debug_frame_section_nr);
  1993. MaybeAddDebugSectionToSymbolTable(wcstDebugAranges,debug_aranges_section_nr);
  1994. MaybeAddDebugSectionToSymbolTable(wcstDebugRanges,debug_ranges_section_nr);
  1995. for i:=0 to Data.ObjSymbolList.Count-1 do
  1996. begin
  1997. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1998. if objsym.typ=AT_WASM_EXCEPTION_TAG then
  1999. begin
  2000. objsym.SymbolIndex:=FWasmSymbolTableEntriesCount;
  2001. Inc(FWasmSymbolTableEntriesCount);
  2002. WriteByte(FWasmSymbolTable,Ord(SYMTAB_EVENT));
  2003. if objsym.bind=AB_GLOBAL then
  2004. WriteUleb(FWasmSymbolTable,0)
  2005. else if objsym.bind=AB_LOCAL then
  2006. WriteUleb(FWasmSymbolTable,WASM_SYM_BINDING_LOCAL)
  2007. else if objsym.bind=AB_EXTERNAL then
  2008. WriteUleb(FWasmSymbolTable,WASM_SYM_UNDEFINED)
  2009. else if objsym.bind=AB_WEAK then
  2010. WriteUleb(FWasmSymbolTable,WASM_SYM_BINDING_WEAK)
  2011. else
  2012. internalerror(2021092715);
  2013. if (objsym.TagIndex<0) then
  2014. message1(asmw_e_illegal_unset_index,objsym.name)
  2015. else
  2016. WriteUleb(FWasmSymbolTable,objsym.TagIndex);
  2017. if objsym.bind<>AB_EXTERNAL then
  2018. WriteName(FWasmSymbolTable,objsym.Name);
  2019. end
  2020. else if objsym.typ=AT_WASM_GLOBAL then
  2021. begin
  2022. objsym.SymbolIndex:=FWasmSymbolTableEntriesCount;
  2023. Inc(FWasmSymbolTableEntriesCount);
  2024. WriteByte(FWasmSymbolTable,Ord(SYMTAB_GLOBAL));
  2025. if objsym.bind=AB_EXTERNAL then
  2026. begin
  2027. WriteUleb(FWasmSymbolTable,WASM_SYM_UNDEFINED);
  2028. if (objsym.GlobalIndex<0) then
  2029. message1(asmw_e_illegal_unset_index,objsym.name)
  2030. else
  2031. WriteUleb(FWasmSymbolTable,objsym.GlobalIndex);
  2032. end
  2033. else
  2034. begin
  2035. WriteUleb(FWasmSymbolTable,0);
  2036. if (objsym.GlobalIndex<0) then
  2037. message1(asmw_e_illegal_unset_index,objsym.name)
  2038. else
  2039. WriteUleb(FWasmSymbolTable,objsym.GlobalIndex);
  2040. WriteName(FWasmSymbolTable,objsym.Name);
  2041. end;
  2042. end
  2043. else if IsExternalFunction(objsym) then
  2044. begin
  2045. objsym.SymbolIndex:=FWasmSymbolTableEntriesCount;
  2046. Inc(FWasmSymbolTableEntriesCount);
  2047. WriteByte(FWasmSymbolTable,Ord(SYMTAB_FUNCTION));
  2048. if objsym.ExtraData.ImportModule<>'' then
  2049. begin
  2050. WriteUleb(FWasmSymbolTable,WASM_SYM_UNDEFINED or WASM_SYM_EXPLICIT_NAME);
  2051. if (objsym.FuncIndex<0) then
  2052. message1(asmw_e_illegal_unset_index,objsym.name)
  2053. else
  2054. WriteUleb(FWasmSymbolTable,objsym.FuncIndex);
  2055. WriteName(FWasmSymbolTable,objsym.Name);
  2056. end
  2057. else
  2058. begin
  2059. WriteUleb(FWasmSymbolTable,WASM_SYM_UNDEFINED);
  2060. if (objsym.FuncIndex<0) then
  2061. message1(asmw_e_illegal_unset_index,objsym.name)
  2062. else
  2063. WriteUleb(FWasmSymbolTable,objsym.FuncIndex);
  2064. end;
  2065. end
  2066. else if objsym.typ=AT_FUNCTION then
  2067. begin
  2068. objsym.SymbolIndex:=FWasmSymbolTableEntriesCount;
  2069. Inc(FWasmSymbolTableEntriesCount);
  2070. WriteByte(FWasmSymbolTable,Ord(SYMTAB_FUNCTION));
  2071. if objsym.IsAlias then
  2072. begin
  2073. ObjSymAlias:=TWasmObjSymbol(Data.ObjSymbolList.Find(objsym.AliasOf));
  2074. ObjSym.FuncIndex:=ObjSymAlias.FuncIndex;
  2075. WriteUleb(FWasmSymbolTable,WASM_SYM_EXPLICIT_NAME or WASM_SYM_NO_STRIP);
  2076. WriteUleb(FWasmSymbolTable,ObjSymAlias.FuncIndex);
  2077. end
  2078. else
  2079. begin
  2080. if IsExportedFunction(objsym) then
  2081. WriteUleb(FWasmSymbolTable,WASM_SYM_EXPORTED)
  2082. else
  2083. WriteUleb(FWasmSymbolTable,0);
  2084. if (objsym.FuncIndex<0) then
  2085. message1(asmw_e_illegal_unset_index,objsym.name)
  2086. else
  2087. WriteUleb(FWasmSymbolTable,objsym.FuncIndex);
  2088. end;
  2089. WriteName(FWasmSymbolTable,objsym.Name);
  2090. end
  2091. else if (objsym.typ in [AT_DATA,AT_TLS,AT_METADATA]) or ((objsym.typ=AT_NONE) and (objsym.bind=AB_EXTERNAL)) then
  2092. begin
  2093. if (objsym.bind<>AB_EXTERNAL) and TWasmObjSection(objsym.objsection).IsDebug then
  2094. begin
  2095. objsym.SymbolIndex:=FWasmSymbolTableEntriesCount;
  2096. Inc(FWasmSymbolTableEntriesCount);
  2097. WriteByte(FWasmSymbolTable,Ord(SYMTAB_FPC_CUSTOM));
  2098. if objsym.bind=AB_GLOBAL then
  2099. SymbolFlags:=0
  2100. else if objsym.bind=AB_LOCAL then
  2101. SymbolFlags:=WASM_SYM_BINDING_LOCAL
  2102. else if objsym.bind=AB_EXTERNAL then
  2103. SymbolFlags:=WASM_SYM_UNDEFINED
  2104. else
  2105. internalerror(2024090701);
  2106. WriteUleb(FWasmSymbolTable,SymbolFlags);
  2107. WriteName(FWasmSymbolTable,objsym.Name);
  2108. WriteUleb(FWasmSymbolTable,TWasmObjSection(objsym.objsection).CustomSectionIdx);
  2109. WriteUleb(FWasmSymbolTable,objsym.offset);
  2110. WriteUleb(FWasmSymbolTable,objsym.size);
  2111. end
  2112. else
  2113. begin
  2114. objsym.SymbolIndex:=FWasmSymbolTableEntriesCount;
  2115. Inc(FWasmSymbolTableEntriesCount);
  2116. WriteByte(FWasmSymbolTable,Ord(SYMTAB_DATA));
  2117. if objsym.bind=AB_GLOBAL then
  2118. SymbolFlags:=0
  2119. else if objsym.bind=AB_LOCAL then
  2120. SymbolFlags:=WASM_SYM_BINDING_LOCAL
  2121. else if objsym.bind=AB_EXTERNAL then
  2122. SymbolFlags:=WASM_SYM_UNDEFINED
  2123. else
  2124. internalerror(2021092506);
  2125. if (objsym.typ=AT_TLS) and (ts_wasm_threads in current_settings.targetswitches) then
  2126. SymbolFlags:=(SymbolFlags and not WASM_SYM_BINDING_LOCAL) or WASM_SYM_TLS;
  2127. WriteUleb(FWasmSymbolTable,SymbolFlags);
  2128. WriteName(FWasmSymbolTable,objsym.Name);
  2129. if objsym.bind<>AB_EXTERNAL then
  2130. begin
  2131. WriteUleb(FWasmSymbolTable,TWasmObjSection(objsym.objsection).SegIdx);
  2132. WriteUleb(FWasmSymbolTable,objsym.offset);
  2133. WriteUleb(FWasmSymbolTable,objsym.size);
  2134. end;
  2135. end;
  2136. end;
  2137. end;
  2138. DoRelocations;
  2139. if segment_count>0 then
  2140. begin
  2141. WriteUleb(FWasmSections[wsiData],segment_count);
  2142. WriteUleb(FWasmSections[wsiDataCount],segment_count);
  2143. WriteUleb(FWasmLinkingSubsections[WASM_SEGMENT_INFO],segment_count);
  2144. for i:=0 to Data.ObjSectionList.Count-1 do
  2145. begin
  2146. objsec:=TWasmObjSection(Data.ObjSectionList[i]);
  2147. if objsec.IsData then
  2148. begin
  2149. WriteName(FWasmLinkingSubsections[WASM_SEGMENT_INFO],objsec.Name);
  2150. WriteUleb(FWasmLinkingSubsections[WASM_SEGMENT_INFO],BsrQWord(objsec.SecAlign));
  2151. SegmentFlags:=0;
  2152. if (ts_wasm_threads in current_settings.targetswitches) and
  2153. (oso_threadvar in objsec.SecOptions) then
  2154. SegmentFlags:=SegmentFlags or WASM_SEG_FLAG_TLS;
  2155. WriteUleb(FWasmLinkingSubsections[WASM_SEGMENT_INFO],SegmentFlags); { flags }
  2156. WriteByte(FWasmSections[wsiData],0);
  2157. WriteByte(FWasmSections[wsiData],$41);
  2158. WriteSleb(FWasmSections[wsiData],objsec.SegOfs);
  2159. WriteByte(FWasmSections[wsiData],$0b);
  2160. WriteUleb(FWasmSections[wsiData],objsec.Size);
  2161. objsec.FileSectionOfs:=FWasmSections[wsiData].size;
  2162. if oso_Data in objsec.SecOptions then
  2163. begin
  2164. objsec.Data.seek(0);
  2165. CopyDynamicArray(objsec.Data,FWasmSections[wsiData],objsec.Size);
  2166. end
  2167. else
  2168. begin
  2169. WriteZeros(FWasmSections[wsiData],objsec.Size);
  2170. end;
  2171. end;
  2172. end;
  2173. end;
  2174. WriteUleb(FWasmSections[wsiCode],functions_count);
  2175. for i:=0 to Data.ObjSymbolList.Count-1 do
  2176. begin
  2177. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  2178. if (objsym.typ=AT_FUNCTION) and not objsym.IsAlias then
  2179. WriteFunctionCode(FWasmSections[wsiCode],objsym);
  2180. end;
  2181. if segment_count>0 then
  2182. WriteWasmSection(wsiDataCount);
  2183. WriteWasmSection(wsiCode);
  2184. if segment_count>0 then
  2185. WriteWasmSection(wsiData);
  2186. MaybeWriteDebugSection(wcstDebugAbbrev);
  2187. MaybeWriteDebugSection(wcstDebugInfo);
  2188. MaybeWriteDebugSection(wcstDebugStr);
  2189. MaybeWriteDebugSection(wcstDebugLine);
  2190. MaybeWriteDebugSection(wcstDebugFrame);
  2191. MaybeWriteDebugSection(wcstDebugAranges);
  2192. MaybeWriteDebugSection(wcstDebugRanges);
  2193. WriteRelocations;
  2194. WriteSymbolTable;
  2195. WriteLinkingSubsection(WASM_SYMBOL_TABLE);
  2196. if segment_count>0 then
  2197. WriteLinkingSubsection(WASM_SEGMENT_INFO);
  2198. WriteRelocationCodeTable(code_section_nr);
  2199. if segment_count>0 then
  2200. WriteRelocationDataTable(data_section_nr);
  2201. WriteWasmCustomSection(wcstLinking);
  2202. Inc(section_nr);
  2203. WriteWasmCustomSection(wcstRelocCode);
  2204. Inc(section_nr);
  2205. if segment_count>0 then
  2206. begin
  2207. WriteWasmCustomSection(wcstRelocData);
  2208. Inc(section_nr);
  2209. end;
  2210. MaybeWriteRelocationDebugTable(wcstRelocDebugAbbrev,debug_abbrev_section_nr,FWasmRelocationDebugAbbrevTableEntriesCount,FWasmRelocationDebugAbbrevTable);
  2211. MaybeWriteRelocationDebugTable(wcstRelocDebugInfo,debug_info_section_nr,FWasmRelocationDebugInfoTableEntriesCount,FWasmRelocationDebugInfoTable);
  2212. MaybeWriteRelocationDebugTable(wcstRelocDebugStr,debug_str_section_nr,FWasmRelocationDebugStrTableEntriesCount,FWasmRelocationDebugStrTable);
  2213. MaybeWriteRelocationDebugTable(wcstRelocDebugLine,debug_line_section_nr,FWasmRelocationDebugLineTableEntriesCount,FWasmRelocationDebugLineTable);
  2214. MaybeWriteRelocationDebugTable(wcstRelocDebugFrame,debug_frame_section_nr,FWasmRelocationDebugFrameTableEntriesCount,FWasmRelocationDebugFrameTable);
  2215. MaybeWriteRelocationDebugTable(wcstRelocDebugAranges,debug_aranges_section_nr,FWasmRelocationDebugArangesTableEntriesCount,FWasmRelocationDebugArangesTable);
  2216. MaybeWriteRelocationDebugTable(wcstRelocDebugRanges,debug_ranges_section_nr,FWasmRelocationDebugRangesTableEntriesCount,FWasmRelocationDebugRangesTable);
  2217. WriteWasmCustomSection(wcstProducers);
  2218. Inc(section_nr);
  2219. WriteWasmCustomSection(wcstTargetFeatures);
  2220. Inc(section_nr);
  2221. result:=true;
  2222. end;
  2223. constructor TWasmObjOutput.create(AWriter: TObjectWriter);
  2224. var
  2225. i: TWasmSectionID;
  2226. j: TWasmCustomSectionType;
  2227. k: TWasmLinkingSubsectionType;
  2228. begin
  2229. inherited;
  2230. cobjdata:=TWasmObjData;
  2231. for i in TWasmSectionID do
  2232. FWasmSections[i] := tdynamicarray.create(SectionDataMaxGrow);
  2233. for j in TWasmCustomSectionType do
  2234. FWasmCustomSections[j] := tdynamicarray.create(SectionDataMaxGrow);
  2235. for k:=low(TWasmLinkingSubsectionType) to high(TWasmLinkingSubsectionType) do
  2236. FWasmLinkingSubsections[k] := tdynamicarray.create(SectionDataMaxGrow);
  2237. FWasmSymbolTable:=tdynamicarray.create(SectionDataMaxGrow);
  2238. FWasmSymbolTableEntriesCount:=0;
  2239. FWasmRelocationCodeTable:=tdynamicarray.create(SectionDataMaxGrow);
  2240. FWasmRelocationCodeTableEntriesCount:=0;
  2241. FWasmRelocationDataTable:=tdynamicarray.create(SectionDataMaxGrow);
  2242. FWasmRelocationDataTableEntriesCount:=0;
  2243. FWasmRelocationDebugFrameTable:=tdynamicarray.create(SectionDataMaxGrow);
  2244. FWasmRelocationDebugFrameTableEntriesCount:=0;
  2245. FWasmRelocationDebugInfoTable:=tdynamicarray.create(SectionDataMaxGrow);
  2246. FWasmRelocationDebugInfoTableEntriesCount:=0;
  2247. FWasmRelocationDebugLineTable:=tdynamicarray.create(SectionDataMaxGrow);
  2248. FWasmRelocationDebugLineTableEntriesCount:=0;
  2249. FWasmRelocationDebugAbbrevTable:=tdynamicarray.create(SectionDataMaxGrow);
  2250. FWasmRelocationDebugAbbrevTableEntriesCount:=0;
  2251. FWasmRelocationDebugArangesTable:=tdynamicarray.create(SectionDataMaxGrow);
  2252. FWasmRelocationDebugArangesTableEntriesCount:=0;
  2253. FWasmRelocationDebugRangesTable:=tdynamicarray.create(SectionDataMaxGrow);
  2254. FWasmRelocationDebugRangesTableEntriesCount:=0;
  2255. FWasmRelocationDebugStrTable:=tdynamicarray.create(SectionDataMaxGrow);
  2256. FWasmRelocationDebugStrTableEntriesCount:=0;
  2257. end;
  2258. destructor TWasmObjOutput.destroy;
  2259. var
  2260. i: TWasmSectionID;
  2261. j: TWasmCustomSectionType;
  2262. k: TWasmLinkingSubsectionType;
  2263. begin
  2264. for i in TWasmSectionID do
  2265. FWasmSections[i].Free;
  2266. for j in TWasmCustomSectionType do
  2267. FWasmCustomSections[j].Free;
  2268. for k:=low(TWasmLinkingSubsectionType) to high(TWasmLinkingSubsectionType) do
  2269. FWasmLinkingSubsections[k].Free;
  2270. FWasmSymbolTable.Free;
  2271. FWasmRelocationCodeTable.Free;
  2272. FWasmRelocationDataTable.Free;
  2273. FWasmRelocationDebugFrameTable.Free;
  2274. FWasmRelocationDebugInfoTable.Free;
  2275. FWasmRelocationDebugLineTable.Free;
  2276. FWasmRelocationDebugAbbrevTable.Free;
  2277. FWasmRelocationDebugArangesTable.Free;
  2278. FWasmRelocationDebugRangesTable.Free;
  2279. FWasmRelocationDebugStrTable.Free;
  2280. inherited destroy;
  2281. end;
  2282. {****************************************************************************
  2283. TWasmObjInput
  2284. ****************************************************************************}
  2285. constructor TWasmObjInput.create;
  2286. begin
  2287. inherited create;
  2288. cobjdata:=TWasmObjData;
  2289. end;
  2290. destructor TWasmObjInput.Destroy;
  2291. var
  2292. i: Integer;
  2293. begin
  2294. for i:=low(FFuncTypes) to high(FFuncTypes) do
  2295. begin
  2296. FFuncTypes[i].free;
  2297. FFuncTypes[i]:=nil;
  2298. end;
  2299. inherited Destroy;
  2300. end;
  2301. class function TWasmObjInput.CanReadObjData(AReader: TObjectreader): boolean;
  2302. var
  2303. ModuleMagic: array [0..3] of Byte;
  2304. ModuleVersion: array [0..3] of Byte;
  2305. i: Integer;
  2306. begin
  2307. result:=false;
  2308. if not AReader.read(ModuleMagic,4) then
  2309. exit;
  2310. for i:=0 to 3 do
  2311. if ModuleMagic[i]<>WasmModuleMagic[i] then
  2312. exit;
  2313. if not AReader.read(ModuleVersion,4) then
  2314. exit;
  2315. for i:=0 to 3 do
  2316. if ModuleVersion[i]<>WasmVersion[i] then
  2317. exit;
  2318. result:=true;
  2319. end;
  2320. function TWasmObjInput.ReadObjData(AReader: TObjectreader; out ObjData: TObjData): boolean;
  2321. type
  2322. TLimits = record
  2323. Min, Max: uint32;
  2324. HasMax: Boolean;
  2325. end;
  2326. var
  2327. SectionIndex: Integer = -1;
  2328. SectionId: Byte;
  2329. SectionSize: uint32;
  2330. SectionStart: LongInt;
  2331. CheckSectionBounds: Boolean;
  2332. TypeSectionRead: Boolean = false;
  2333. ImportSectionRead: Boolean = false;
  2334. FunctionSectionRead: Boolean = false;
  2335. GlobalSectionRead: Boolean = false;
  2336. ExportSectionRead: Boolean = false;
  2337. ElementSectionRead: Boolean = false;
  2338. TagSectionRead: Boolean = false;
  2339. CodeSectionRead: Boolean = false;
  2340. DataSectionRead: Boolean = false;
  2341. DataCountSectionRead: Boolean = false;
  2342. SegmentInfoSectionRead: Boolean = false;
  2343. SymbolTableSectionRead: Boolean = false;
  2344. CodeSectionIndex: Integer = -1;
  2345. DataSectionIndex: Integer = -1;
  2346. DebugSectionIndex: array [TWasmCustomDebugSectionType] of Integer = (-1,-1,-1,-1,-1,-1,-1);
  2347. FuncTypes: array of record
  2348. IsImport: Boolean;
  2349. ImportName: ansistring;
  2350. ImportModName: ansistring;
  2351. typidx: uint32;
  2352. IsExported: Boolean;
  2353. ExportName: ansistring;
  2354. end;
  2355. FuncTypeImportsCount: uint32;
  2356. TableTypes: array of record
  2357. IsImport: Boolean;
  2358. ImportName: ansistring;
  2359. ImportModName: ansistring;
  2360. reftype: TWasmBAsicType;
  2361. limits: TLimits;
  2362. IsExported: Boolean;
  2363. ExportName: ansistring;
  2364. end;
  2365. TableTypeImportsCount: uint32;
  2366. MemTypes: array of record
  2367. IsImport: Boolean;
  2368. ImportName: ansistring;
  2369. ImportModName: ansistring;
  2370. limits: TLimits;
  2371. IsExported: Boolean;
  2372. ExportName: ansistring;
  2373. end;
  2374. MemTypeImportsCount: uint32;
  2375. GlobalTypes: array of record
  2376. IsImport: Boolean;
  2377. ImportName: ansistring;
  2378. ImportModName: ansistring;
  2379. valtype: TWasmBasicType;
  2380. IsMutable: Boolean;
  2381. IsExported: Boolean;
  2382. ExportName: ansistring;
  2383. GlobalInit: TGlobalInitializer;
  2384. end;
  2385. GlobalTypeImportsCount: uint32;
  2386. TagTypes: array of record
  2387. IsImport: Boolean;
  2388. ImportName: ansistring;
  2389. ImportModName: ansistring;
  2390. TagAttr: Byte;
  2391. TagTypeIdx: uint32;
  2392. IsExported: Boolean;
  2393. ExportName: ansistring;
  2394. end;
  2395. TagTypeImportsCount: uint32;
  2396. CodeSegments: array of record
  2397. CodeSectionOffset: uint32;
  2398. CodeSize: uint32;
  2399. DataPos: LongInt;
  2400. SegName: ansistring;
  2401. SegIsExported: Boolean;
  2402. end;
  2403. DataSegments: array of record
  2404. DataSectionOffset: uint32;
  2405. Active: Boolean;
  2406. MemIdx: uint32;
  2407. Len: uint32;
  2408. Offset: int32;
  2409. DataPos: LongInt;
  2410. SegName: ansistring;
  2411. SegAlignment: uint32;
  2412. SegFlags: uint32;
  2413. end;
  2414. SymbolTable: array of record
  2415. SymFlags: uint32;
  2416. TargetSection: uint32;
  2417. SymIndex: uint32;
  2418. SymOffset: uint32;
  2419. SymSize: uint32;
  2420. SymCustomSectionIndex: uint32;
  2421. SymCustomSectionType: TWasmCustomDebugSectionType;
  2422. SymKind: TWasmSymbolType;
  2423. SymName: ansistring;
  2424. ObjSym: TWasmObjSymbol;
  2425. ObjSec: TWasmObjSection;
  2426. end;
  2427. { meaning of first index: }
  2428. { table 0 is code relocs }
  2429. { table 1 is data relocs }
  2430. { tables 2.. are custom section relocs for debug sections }
  2431. RelocationTable: array of array of record
  2432. RelocType: TWasmRelocationType;
  2433. RelocOffset: uint32;
  2434. RelocIndex: uint32;
  2435. RelocAddend: int32;
  2436. end;
  2437. function FindDebugSectionByIndex(SectionIndex: Integer; out res: TWasmCustomDebugSectionType): Boolean;
  2438. var
  2439. ds: TWasmCustomDebugSectionType;
  2440. begin
  2441. for ds in TWasmCustomDebugSectionType do
  2442. if DebugSectionIndex[ds]=SectionIndex then
  2443. begin
  2444. Res:=ds;
  2445. Result:=True;
  2446. exit;
  2447. end;
  2448. Res:=low(TWasmCustomDebugSectionType);
  2449. Result:=False;
  2450. end;
  2451. function ReadSection: Boolean;
  2452. function read(out b;len:longint):boolean;
  2453. begin
  2454. result:=false;
  2455. if not CheckSectionBounds or ((AReader.Pos+len)<=(SectionStart+SectionSize)) then
  2456. result:=AReader.read(b,len)
  2457. else
  2458. begin
  2459. { trying to read beyond the end of the section }
  2460. AReader.read(b,SectionStart+SectionSize-AReader.Pos);
  2461. result:=false;
  2462. end;
  2463. end;
  2464. function ReadUleb(out v: uint64): boolean;
  2465. var
  2466. b: byte;
  2467. shift:integer;
  2468. begin
  2469. result:=false;
  2470. b:=0;
  2471. v:=0;
  2472. shift:=0;
  2473. repeat
  2474. if not read(b,1) then
  2475. exit;
  2476. v:=v or (uint64(b and 127) shl shift);
  2477. inc(shift,7);
  2478. until (b and 128)=0;
  2479. result:=true;
  2480. end;
  2481. function ReadUleb32(out v: uint32): boolean;
  2482. var
  2483. vv: uint64;
  2484. begin
  2485. result:=false;
  2486. v:=default(uint32);
  2487. if not ReadUleb(vv) then
  2488. exit;
  2489. if vv>high(uint32) then
  2490. exit;
  2491. v:=vv;
  2492. result:=true;
  2493. end;
  2494. function ReadSleb(out v: int64): boolean;
  2495. var
  2496. b: byte;
  2497. shift:integer;
  2498. begin
  2499. result:=false;
  2500. b:=0;
  2501. v:=0;
  2502. shift:=0;
  2503. repeat
  2504. if not read(b,1) then
  2505. exit;
  2506. v:=v or (uint64(b and 127) shl shift);
  2507. inc(shift,7);
  2508. until (b and 128)=0;
  2509. {$ifopt Q+}
  2510. {$define overflowon}
  2511. {$Q-}
  2512. {$endif}
  2513. {$ifopt R+}
  2514. {$define rangeon}
  2515. {$R-}
  2516. {$endif}
  2517. if (b and 64)<>0 then
  2518. v:=v or (high(uint64) shl shift);
  2519. result:=true;
  2520. end;
  2521. {$ifdef overflowon}
  2522. {$Q+}
  2523. {$undef overflowon}
  2524. {$endif}
  2525. {$ifdef rangeon}
  2526. {$R+}
  2527. {$undef rangeon}
  2528. {$endif}
  2529. function ReadSleb32(out v: int32): boolean;
  2530. var
  2531. vv: int64;
  2532. begin
  2533. result:=false;
  2534. v:=default(int32);
  2535. if not ReadSleb(vv) then
  2536. exit;
  2537. if (vv>high(int32)) or (vv<low(int32)) then
  2538. exit;
  2539. v:=vv;
  2540. result:=true;
  2541. end;
  2542. function ReadName(out v: ansistring): boolean;
  2543. var
  2544. len: uint32;
  2545. begin
  2546. result:=false;
  2547. if not ReadUleb32(len) then
  2548. exit;
  2549. SetLength(v,len);
  2550. if len>0 then
  2551. result:=read(v[1],len)
  2552. else
  2553. result:=true;
  2554. end;
  2555. function ReadCustomSection: Boolean;
  2556. function ReadRelocationSection: Boolean;
  2557. var
  2558. TargetSection, RelocCount: uint32;
  2559. i: Integer;
  2560. RelocTableIndex: Integer;
  2561. ds: TWasmCustomDebugSectionType;
  2562. begin
  2563. Result:=False;
  2564. if not ReadUleb32(TargetSection) then
  2565. begin
  2566. InputError('Error reading the index of the target section of a relocation section');
  2567. exit;
  2568. end;
  2569. if TargetSection=CodeSectionIndex then
  2570. RelocTableIndex:=0
  2571. else if TargetSection=DataSectionIndex then
  2572. RelocTableIndex:=1
  2573. else
  2574. begin
  2575. RelocTableIndex:=-1;
  2576. for ds:=Low(DebugSectionIndex) to High(DebugSectionIndex) do
  2577. if DebugSectionIndex[ds]=TargetSection then
  2578. begin
  2579. RelocTableIndex:=2+(Ord(ds)-Ord(Low(TWasmCustomDebugSectionType)));
  2580. break;
  2581. end;
  2582. if RelocTableIndex=-1 then
  2583. begin
  2584. InputError('Relocation found for a custom section, that is not supported');
  2585. exit;
  2586. end;
  2587. end;
  2588. if not ReadUleb32(RelocCount) then
  2589. begin
  2590. InputError('Error reading the relocation entries count from a relocation section');
  2591. exit;
  2592. end;
  2593. SetLength(RelocationTable[RelocTableIndex],RelocCount);
  2594. for i:=0 to RelocCount-1 do
  2595. with RelocationTable[RelocTableIndex,i] do
  2596. begin
  2597. if not Read(RelocType,1) then
  2598. begin
  2599. InputError('Error reading the relocation type of a relocation entry');
  2600. exit;
  2601. end;
  2602. if not (RelocType in [R_WASM_FUNCTION_INDEX_LEB,
  2603. R_WASM_MEMORY_ADDR_LEB,
  2604. R_WASM_TABLE_INDEX_SLEB,
  2605. R_WASM_MEMORY_ADDR_SLEB,
  2606. R_WASM_SECTION_OFFSET_I32,
  2607. R_WASM_TABLE_INDEX_I32,
  2608. R_WASM_FUNCTION_OFFSET_I32,
  2609. R_WASM_MEMORY_ADDR_I32,
  2610. R_WASM_TYPE_INDEX_LEB,
  2611. R_WASM_GLOBAL_INDEX_LEB,
  2612. R_WASM_TAG_INDEX_LEB,
  2613. R_WASM_GLOBAL_INDEX_I32]) then
  2614. begin
  2615. InputError('Unsupported relocation type: ' + tostr(Ord(RelocType)));
  2616. exit;
  2617. end;
  2618. if not ReadUleb32(RelocOffset) then
  2619. begin
  2620. InputError('Error reading the relocation offset of a relocation entry');
  2621. exit;
  2622. end;
  2623. if not ReadUleb32(RelocIndex) then
  2624. begin
  2625. InputError('Error reading the relocation index of a relocation entry');
  2626. exit;
  2627. end;
  2628. if RelocType in [R_WASM_FUNCTION_OFFSET_I32,R_WASM_SECTION_OFFSET_I32,R_WASM_MEMORY_ADDR_LEB,R_WASM_MEMORY_ADDR_SLEB,R_WASM_MEMORY_ADDR_I32] then
  2629. begin
  2630. if not ReadSleb32(RelocAddend) then
  2631. begin
  2632. InputError('Error reading the relocation addend of a relocation entry');
  2633. exit;
  2634. end;
  2635. end;
  2636. if (RelocType in [
  2637. R_WASM_SECTION_OFFSET_I32,
  2638. R_WASM_FUNCTION_INDEX_LEB,
  2639. R_WASM_TABLE_INDEX_SLEB,
  2640. R_WASM_TABLE_INDEX_I32,
  2641. R_WASM_MEMORY_ADDR_LEB,
  2642. R_WASM_MEMORY_ADDR_SLEB,
  2643. R_WASM_MEMORY_ADDR_I32,
  2644. R_WASM_FUNCTION_OFFSET_I32,
  2645. R_WASM_GLOBAL_INDEX_LEB,
  2646. R_WASM_GLOBAL_INDEX_I32]) and (RelocIndex>High(SymbolTable)) then
  2647. begin
  2648. InputError('Relocation index outside the bounds of the symbol table');
  2649. exit;
  2650. end;
  2651. if (RelocType=R_WASM_TYPE_INDEX_LEB) and (RelocIndex>High(FFuncTypes)) then
  2652. begin
  2653. InputError('Relocation index of R_WASM_TYPE_INDEX_LEB outside the bounds of the func types, defined in the func section of the module');
  2654. exit;
  2655. end;
  2656. if (RelocType=R_WASM_SECTION_OFFSET_I32) and (SymbolTable[RelocIndex].SymKind<>SYMTAB_SECTION) then
  2657. begin
  2658. InputError('R_WASM_SECTION_OFFSET_I32 must point to a SYMTAB_SECTION symbol');
  2659. exit;
  2660. end;
  2661. if (RelocType in [R_WASM_GLOBAL_INDEX_LEB,R_WASM_GLOBAL_INDEX_I32]) and
  2662. not ((SymbolTable[RelocIndex].SymKind=SYMTAB_GLOBAL) or
  2663. ((ts_wasm_threads in current_settings.targetswitches) and
  2664. (SymbolTable[RelocIndex].SymKind=SYMTAB_DATA) and
  2665. ((SymbolTable[RelocIndex].SymFlags and WASM_SYM_TLS)<>0))) then
  2666. begin
  2667. if ts_wasm_threads in current_settings.targetswitches then
  2668. InputError('Relocation must point to a SYMTAB_GLOBAL symbol or a SYMTAB_DATA symbol with the WASM_SYM_TLS flag set')
  2669. else
  2670. InputError('Relocation must point to a SYMTAB_GLOBAL symbol');
  2671. exit;
  2672. end;
  2673. if (RelocType=R_WASM_TAG_INDEX_LEB) and (SymbolTable[RelocIndex].SymKind<>SYMTAB_EVENT) then
  2674. begin
  2675. InputError('Relocation must point to a SYMTAB_EVENT symbol');
  2676. exit;
  2677. end;
  2678. if (RelocType in [
  2679. R_WASM_FUNCTION_INDEX_LEB,
  2680. R_WASM_TABLE_INDEX_SLEB,
  2681. R_WASM_TABLE_INDEX_I32,
  2682. R_WASM_FUNCTION_OFFSET_I32]) and (SymbolTable[RelocIndex].SymKind<>SYMTAB_FUNCTION) then
  2683. begin
  2684. InputError('Relocation must point to a SYMTAB_FUNCTION symbol');
  2685. exit;
  2686. end;
  2687. if (RelocType in [
  2688. R_WASM_MEMORY_ADDR_LEB,
  2689. R_WASM_MEMORY_ADDR_SLEB,
  2690. R_WASM_MEMORY_ADDR_I32]) and (SymbolTable[RelocIndex].SymKind<>SYMTAB_DATA) then
  2691. begin
  2692. InputError('Relocation must point to a SYMTAB_DATA symbol');
  2693. exit;
  2694. end;
  2695. end;
  2696. if AReader.Pos<>(SectionStart+SectionSize) then
  2697. begin
  2698. InputError('Unexpected relocation section size');
  2699. exit;
  2700. end;
  2701. Result:=True;
  2702. end;
  2703. function ReadLinkingSection: Boolean;
  2704. function ReadSegmentInfo: Boolean;
  2705. var
  2706. SegmentCount: uint32;
  2707. i: Integer;
  2708. begin
  2709. Result:=False;
  2710. if SegmentInfoSectionRead then
  2711. begin
  2712. InputError('The WASM_SEGMENT_INFO subsection is duplicated');
  2713. exit;
  2714. end;
  2715. SegmentInfoSectionRead:=True;
  2716. if not ReadUleb32(SegmentCount) then
  2717. begin
  2718. InputError('Error reading the segment count from the WASM_SEGMENT_INFO subsection of the ''linking'' section');
  2719. exit;
  2720. end;
  2721. if SegmentCount<>Length(DataSegments) then
  2722. begin
  2723. InputError('Segment count in the WASM_SEGMENT_INFO subsection does not match the data count in the data section');
  2724. exit;
  2725. end;
  2726. for i:=0 to SegmentCount-1 do
  2727. with DataSegments[i] do
  2728. begin
  2729. if not ReadName(SegName) then
  2730. begin
  2731. InputError('Error reading segment name from the WASM_SEGMENT_INFO subsection of the ''linking'' section');
  2732. exit;
  2733. end;
  2734. if not ReadUleb32(SegAlignment) then
  2735. begin
  2736. InputError('Error reading segment alignment from the WASM_SEGMENT_INFO subsection of the ''linking'' section');
  2737. exit;
  2738. end;
  2739. if not ReadUleb32(SegFlags) then
  2740. begin
  2741. InputError('Error reading segment flags from the WASM_SEGMENT_INFO subsection of the ''linking'' section');
  2742. exit;
  2743. end;
  2744. end;
  2745. if AReader.Pos<>(SectionStart+SectionSize) then
  2746. begin
  2747. InputError('Unexpected WASM_SEGMENT_INFO section size');
  2748. exit;
  2749. end;
  2750. Result:=True;
  2751. end;
  2752. function ReadSymbolTable: Boolean;
  2753. var
  2754. SymCount: uint32;
  2755. i: Integer;
  2756. SymKindName: string;
  2757. SymKindB: Byte;
  2758. begin
  2759. Result:=False;
  2760. if SymbolTableSectionRead then
  2761. begin
  2762. InputError('The WASM_SYMBOL_TABLE subsection is duplicated');
  2763. exit;
  2764. end;
  2765. SymbolTableSectionRead:=True;
  2766. if not ReadUleb32(SymCount) then
  2767. begin
  2768. InputError('Error reading the symbol count from the WASM_SYMBOL_TABLE subsection of the ''linking'' section');
  2769. exit;
  2770. end;
  2771. SetLength(SymbolTable,SymCount);
  2772. for i:=0 to SymCount-1 do
  2773. with SymbolTable[i] do
  2774. begin
  2775. if not Read(SymKindB,1) then
  2776. begin
  2777. InputError('Error reading symbol type from the WASM_SYMBOL_TABLE subsection of the ''linking'' section');
  2778. exit;
  2779. end;
  2780. if SymKindB>Ord(High(TWasmSymbolType)) then
  2781. begin
  2782. InputError('Unsupported symbol type from the WASM_SYMBOL_TABLE subsection of the ''linking'' section');
  2783. exit;
  2784. end;
  2785. SymKind:=TWasmSymbolType(SymKindB);
  2786. if not ReadUleb32(SymFlags) then
  2787. begin
  2788. InputError('Error reading symbol flags from the WASM_SYMBOL_TABLE subsection of the ''linking'' section');
  2789. exit;
  2790. end;
  2791. case SymKind of
  2792. SYMTAB_FUNCTION,
  2793. SYMTAB_GLOBAL,
  2794. SYMTAB_EVENT,
  2795. SYMTAB_TABLE:
  2796. begin
  2797. WriteStr(SymKindName, SymKind);
  2798. if not ReadUleb32(SymIndex) then
  2799. begin
  2800. InputError('Error reading the index of a ' + SymKindName + ' symbol');
  2801. exit;
  2802. end;
  2803. if ((SymKind=SYMTAB_FUNCTION) and (SymIndex>high(FuncTypes))) or
  2804. ((SymKind=SYMTAB_EVENT) and (SymIndex>high(TagTypes))) then
  2805. begin
  2806. InputError('Symbol index too high');
  2807. exit;
  2808. end;
  2809. if ((SymFlags and WASM_SYM_EXPLICIT_NAME)<>0) or
  2810. ((SymFlags and WASM_SYM_UNDEFINED)=0) then
  2811. begin
  2812. if not ReadName(SymName) then
  2813. begin
  2814. InputError('Error reading symbol name of a ' + SymKindName + ' symbol');
  2815. exit;
  2816. end;
  2817. end;
  2818. end;
  2819. SYMTAB_DATA:
  2820. begin
  2821. if not ReadName(SymName) then
  2822. begin
  2823. InputError('Error reading symbol name of a SYMTAB_DATA symbol');
  2824. exit;
  2825. end;
  2826. if (SymFlags and WASM_SYM_UNDEFINED)=0 then
  2827. begin
  2828. if not ReadUleb32(SymIndex) then
  2829. begin
  2830. InputError('Error reading the data segment index of a SYMTAB_DATA symbol');
  2831. exit;
  2832. end;
  2833. if SymIndex>high(DataSegments) then
  2834. begin
  2835. InputError('Data segment index of SYMTAB_DATA symbol out of bounds');
  2836. exit;
  2837. end;
  2838. if not ReadUleb32(SymOffset) then
  2839. begin
  2840. InputError('Error reading the offset of a SYMTAB_DATA symbol');
  2841. exit;
  2842. end;
  2843. if not ReadUleb32(SymSize) then
  2844. begin
  2845. InputError('Error reading the size of a SYMTAB_DATA symbol');
  2846. exit;
  2847. end;
  2848. end;
  2849. end;
  2850. SYMTAB_FPC_CUSTOM:
  2851. begin
  2852. if not ReadName(SymName) then
  2853. begin
  2854. InputError('Error reading symbol name of a SYMTAB_FPC_CUSTOM symbol');
  2855. exit;
  2856. end;
  2857. if (SymFlags and WASM_SYM_UNDEFINED)=0 then
  2858. begin
  2859. if not ReadUleb32(SymCustomSectionIndex) then
  2860. begin
  2861. InputError('Error reading the custom section index of a SYMTAB_FPC_CUSTOM symbol');
  2862. exit;
  2863. end;
  2864. if not FindDebugSectionByIndex(SymCustomSectionIndex,SymCustomSectionType) then
  2865. begin
  2866. InputError('Custom section index of SYMTAB_FPC_CUSTOM symbol not pointing to a debug section');
  2867. exit;
  2868. end;
  2869. if not ReadUleb32(SymOffset) then
  2870. begin
  2871. InputError('Error reading the offset of a SYMTAB_FPC_CUSTOM symbol');
  2872. exit;
  2873. end;
  2874. if not ReadUleb32(SymSize) then
  2875. begin
  2876. InputError('Error reading the size of a SYMTAB_FPC_CUSTOM symbol');
  2877. exit;
  2878. end;
  2879. end;
  2880. end;
  2881. SYMTAB_SECTION:
  2882. begin
  2883. if not ReadUleb32(TargetSection) then
  2884. begin
  2885. InputError('Error reading the target section of a SYMTAB_SECTION symbol');
  2886. exit;
  2887. end;
  2888. end;
  2889. end;
  2890. end;
  2891. if AReader.Pos<>(SectionStart+SectionSize) then
  2892. begin
  2893. InputError('Unexpected WASM_SYMBOL_TABLE section size');
  2894. exit;
  2895. end;
  2896. Result:=True;
  2897. end;
  2898. const
  2899. ExpectedVersion = 2;
  2900. var
  2901. Version, SubsectionSize, SaveSectionSize: uint32;
  2902. SubsectionType: Byte;
  2903. SaveSectionStart: LongInt;
  2904. begin
  2905. Result:=False;
  2906. if not ReadUleb32(Version) then
  2907. begin
  2908. InputError('Error reading the version of the ''linking'' section');
  2909. exit;
  2910. end;
  2911. if Version<>ExpectedVersion then
  2912. begin
  2913. InputError('The ''linking'' section has an unsupported version (expected version ' + tostr(ExpectedVersion) + ', got version ' + tostr(Version) + ')');
  2914. exit;
  2915. end;
  2916. while AReader.Pos<(SectionStart+SectionSize) do
  2917. begin
  2918. if not read(SubsectionType, 1) then
  2919. begin
  2920. InputError('Error reading subsection type in the ''linking'' section');
  2921. exit;
  2922. end;
  2923. if not ReadUleb32(SubsectionSize) then
  2924. begin
  2925. InputError('Error reading subsection size in the ''linking'' section');
  2926. exit;
  2927. end;
  2928. if (AReader.Pos+SubsectionSize)>(SectionStart+SectionSize) then
  2929. begin
  2930. InputError('Subsection size exceeds bounds of its parent ''linking'' section');
  2931. exit;
  2932. end;
  2933. SaveSectionStart:=SectionStart;
  2934. SaveSectionSize:=SectionSize;
  2935. SectionStart:=AReader.Pos;
  2936. SectionSize:=SubsectionSize;
  2937. case SubsectionType of
  2938. Byte(WASM_SEGMENT_INFO):
  2939. if not ReadSegmentInfo then
  2940. begin
  2941. InputError('Error reading the WASM_SEGMENT_INFO subsection of the ''linking'' section');
  2942. exit;
  2943. end;
  2944. Byte(WASM_SYMBOL_TABLE):
  2945. if not ReadSymbolTable then
  2946. begin
  2947. InputError('Error reading the WASM_SYMBOL_TABLE subsection of the ''linking'' section');
  2948. exit;
  2949. end;
  2950. else
  2951. begin
  2952. InputError('Unsupported ''linking'' section subsection type ' + tostr(SubsectionType));
  2953. exit;
  2954. end;
  2955. end;
  2956. AReader.Seek(SectionStart+SectionSize);
  2957. SectionStart:=SaveSectionStart;
  2958. SectionSize:=SaveSectionSize;
  2959. end;
  2960. result:=True;
  2961. end;
  2962. function ReadProducersSection: Boolean;
  2963. begin
  2964. Result:=False;
  2965. end;
  2966. function ReadTargetFeaturesSection: Boolean;
  2967. begin
  2968. Result:=False;
  2969. end;
  2970. function ReadDebugSection(const SectionName: string; SectionType: TWasmCustomDebugSectionType): Boolean;
  2971. var
  2972. ObjSec: TObjSection;
  2973. begin
  2974. Result:=False;
  2975. if DebugSectionIndex[SectionType]<>-1 then
  2976. begin
  2977. InputError('Duplicated debug section: ' + SectionName);
  2978. exit;
  2979. end;
  2980. DebugSectionIndex[SectionType]:=SectionIndex;
  2981. ObjSec:=ObjData.createsection(SectionName,1,[oso_Data,oso_debug],false);
  2982. ObjSec.DataPos:=AReader.Pos;
  2983. ObjSec.Size:=SectionStart+SectionSize-AReader.Pos;
  2984. Result:=True;
  2985. end;
  2986. const
  2987. RelocationSectionPrefix = 'reloc.';
  2988. var
  2989. SectionName: ansistring;
  2990. begin
  2991. Result:=False;
  2992. ReadName(SectionName);
  2993. if Copy(SectionName,1,Length(RelocationSectionPrefix)) = RelocationSectionPrefix then
  2994. begin
  2995. if not ReadRelocationSection then
  2996. begin
  2997. InputError('Error reading the relocation section ''' + SectionName + '''');
  2998. exit;
  2999. end;
  3000. end
  3001. else
  3002. case SectionName of
  3003. 'linking':
  3004. if not ReadLinkingSection then
  3005. begin
  3006. InputError('Error reading the ''linking'' section');
  3007. exit;
  3008. end;
  3009. 'producers':
  3010. Result:=ReadProducersSection;
  3011. 'target_features':
  3012. Result:=ReadTargetFeaturesSection;
  3013. '.debug_frame':
  3014. if not ReadDebugSection(SectionName, wcstDebugFrame) then
  3015. begin
  3016. InputError('Error reading section ' + SectionName);
  3017. exit;
  3018. end;
  3019. '.debug_info':
  3020. if not ReadDebugSection(SectionName, wcstDebugInfo) then
  3021. begin
  3022. InputError('Error reading section ' + SectionName);
  3023. exit;
  3024. end;
  3025. '.debug_line':
  3026. if not ReadDebugSection(SectionName, wcstDebugLine) then
  3027. begin
  3028. InputError('Error reading section ' + SectionName);
  3029. exit;
  3030. end;
  3031. '.debug_abbrev':
  3032. if not ReadDebugSection(SectionName, wcstDebugAbbrev) then
  3033. begin
  3034. InputError('Error reading section ' + SectionName);
  3035. exit;
  3036. end;
  3037. '.debug_aranges':
  3038. if not ReadDebugSection(SectionName, wcstDebugAranges) then
  3039. begin
  3040. InputError('Error reading section ' + SectionName);
  3041. exit;
  3042. end;
  3043. '.debug_ranges':
  3044. if not ReadDebugSection(SectionName, wcstDebugRanges) then
  3045. begin
  3046. InputError('Error reading section ' + SectionName);
  3047. exit;
  3048. end;
  3049. '.debug_str':
  3050. if not ReadDebugSection(SectionName, wcstDebugStr) then
  3051. begin
  3052. InputError('Error reading section ' + SectionName);
  3053. exit;
  3054. end;
  3055. else
  3056. InputError('Unsupported custom section: ''' + SectionName + '''');
  3057. end;
  3058. Result:=True;
  3059. end;
  3060. function ReadTypeSection: Boolean;
  3061. var
  3062. FuncTypesCount, ParamsCount, ResultsCount: uint32;
  3063. FuncTypeId, WasmTypeId: Byte;
  3064. i, j: Integer;
  3065. wbt: TWasmBasicType;
  3066. begin
  3067. Result:=False;
  3068. if TypeSectionRead then
  3069. begin
  3070. InputError('Type section is duplicated');
  3071. exit;
  3072. end;
  3073. TypeSectionRead:=True;
  3074. if not ReadUleb32(FuncTypesCount) then
  3075. begin
  3076. InputError('Error reading the func types count');
  3077. exit;
  3078. end;
  3079. SetLength(FFuncTypes,FuncTypesCount);
  3080. for i:=0 to FuncTypesCount - 1 do
  3081. begin
  3082. FFuncTypes[i]:=TWasmFuncType.Create([],[]);
  3083. if not AReader.read(FuncTypeId,1) then
  3084. begin
  3085. InputError('Error reading the function type identifier');
  3086. exit;
  3087. end;
  3088. if FuncTypeId<>$60 then
  3089. begin
  3090. InputError('Incorrect function type identifier (expected $60, got $' + HexStr(FuncTypeId,2) + ')');
  3091. exit;
  3092. end;
  3093. if not ReadUleb32(ParamsCount) then
  3094. begin
  3095. InputError('Error reading the function parameters count');
  3096. exit;
  3097. end;
  3098. for j:=0 to ParamsCount-1 do
  3099. begin
  3100. if not AReader.read(WasmTypeId,1) then
  3101. begin
  3102. InputError('Error reading a function parameter basic type');
  3103. exit;
  3104. end;
  3105. if not decode_wasm_basic_type(WasmTypeId,wbt) then
  3106. begin
  3107. InputError('Unknown function parameter basic type: $' + HexStr(WasmTypeId,2));
  3108. exit;
  3109. end;
  3110. FFuncTypes[i].add_param(wbt);
  3111. end;
  3112. if not ReadUleb32(ResultsCount) then
  3113. begin
  3114. InputError('Error reading the function results count');
  3115. exit;
  3116. end;
  3117. for j:=0 to ResultsCount-1 do
  3118. begin
  3119. if not AReader.read(WasmTypeId,1) then
  3120. begin
  3121. InputError('Error reading a function result basic type');
  3122. exit;
  3123. end;
  3124. if not decode_wasm_basic_type(WasmTypeId,wbt) then
  3125. begin
  3126. InputError('Unknown function result basic type: $' + HexStr(WasmTypeId,2));
  3127. exit;
  3128. end;
  3129. FFuncTypes[i].add_result(wbt);
  3130. end;
  3131. end;
  3132. if AReader.Pos<>(SectionStart+SectionSize) then
  3133. begin
  3134. InputError('Unexpected type section size');
  3135. exit;
  3136. end;
  3137. Result:=true;
  3138. end;
  3139. function ReadImportSection: Boolean;
  3140. var
  3141. ImportsCount: uint32;
  3142. i: Integer;
  3143. ModName, Name: ansistring;
  3144. ImportType, TableElemTyp, TableLimitsKind, MemoryLimitsKind,
  3145. GlobalType, GlobalMutabilityType: Byte;
  3146. begin
  3147. Result:=False;
  3148. if ImportSectionRead then
  3149. begin
  3150. InputError('Import section is duplicated');
  3151. exit;
  3152. end;
  3153. ImportSectionRead:=True;
  3154. if not ReadUleb32(ImportsCount) then
  3155. begin
  3156. InputError('Error reading the imports count');
  3157. exit;
  3158. end;
  3159. for i:=0 to ImportsCount-1 do
  3160. begin
  3161. if not ReadName(ModName) then
  3162. begin
  3163. InputError('Error reading import module name');
  3164. exit;
  3165. end;
  3166. if not ReadName(Name) then
  3167. begin
  3168. InputError('Error import name');
  3169. exit;
  3170. end;
  3171. if not AReader.Read(ImportType,1) then
  3172. begin
  3173. InputError('Error reading import type');
  3174. exit;
  3175. end;
  3176. case ImportType of
  3177. $00: { func }
  3178. begin
  3179. Inc(FuncTypeImportsCount);
  3180. SetLength(FuncTypes,FuncTypeImportsCount);
  3181. with FuncTypes[FuncTypeImportsCount-1] do
  3182. begin
  3183. IsImport:=True;
  3184. ImportName:=Name;
  3185. ImportModName:=ModName;
  3186. if not ReadUleb32(typidx) then
  3187. begin
  3188. InputError('Error reading type index for func import');
  3189. exit;
  3190. end;
  3191. if typidx>high(FFuncTypes) then
  3192. begin
  3193. InputError('Type index in func import exceeds bounds of the types table');
  3194. exit;
  3195. end;
  3196. end;
  3197. end;
  3198. $01: { table }
  3199. begin
  3200. Inc(TableTypeImportsCount);
  3201. SetLength(TableTypes,TableTypeImportsCount);
  3202. with TableTypes[TableTypeImportsCount-1] do
  3203. begin
  3204. IsImport:=True;
  3205. ImportName:=Name;
  3206. ImportModName:=ModName;
  3207. if not AReader.read(TableElemTyp,1) then
  3208. begin
  3209. InputError('Error reading table element type for table import');
  3210. exit;
  3211. end;
  3212. if not decode_wasm_basic_type(TableElemTyp,reftype) then
  3213. begin
  3214. InputError('Invalid table element type for table import: $' + HexStr(TableElemTyp,2));
  3215. exit;
  3216. end;
  3217. if not (reftype in WasmReferenceTypes) then
  3218. begin
  3219. InputError('Table element type for table import must be a reference type');
  3220. exit;
  3221. end;
  3222. if not AReader.read(TableLimitsKind,1) then
  3223. begin
  3224. InputError('Error reading table limits kind for table import');
  3225. exit;
  3226. end;
  3227. case TableLimitsKind of
  3228. $00:
  3229. begin
  3230. limits.HasMax:=False;
  3231. limits.Max:=high(limits.Max);
  3232. if not ReadUleb32(limits.min) then
  3233. begin
  3234. InputError('Error reading table limits min for table import');
  3235. exit;
  3236. end;
  3237. end;
  3238. $01:
  3239. begin
  3240. limits.HasMax:=True;
  3241. if not ReadUleb32(limits.min) then
  3242. begin
  3243. InputError('Error reading table limits min for table import');
  3244. exit;
  3245. end;
  3246. if not ReadUleb32(limits.max) then
  3247. begin
  3248. InputError('Error reading table limits max for table import');
  3249. exit;
  3250. end;
  3251. if limits.min>limits.max then
  3252. begin
  3253. InputError('Table limits min exceed table limits max in table import');
  3254. exit;
  3255. end;
  3256. end;
  3257. else
  3258. begin
  3259. InputError('Unsupported table limits kind for table import: $' + HexStr(TableLimitsKind,2));
  3260. exit;
  3261. end;
  3262. end;
  3263. end;
  3264. end;
  3265. $02: { mem }
  3266. begin
  3267. Inc(MemTypeImportsCount);
  3268. SetLength(MemTypes,MemTypeImportsCount);
  3269. with MemTypes[MemTypeImportsCount-1] do
  3270. begin
  3271. IsImport:=True;
  3272. ImportName:=Name;
  3273. ImportModName:=ModName;
  3274. if not AReader.read(MemoryLimitsKind,1) then
  3275. begin
  3276. InputError('Error reading memory limits kind for memory import');
  3277. exit;
  3278. end;
  3279. case MemoryLimitsKind of
  3280. $00:
  3281. begin
  3282. limits.HasMax:=False;
  3283. limits.Max:=high(limits.Max);
  3284. if not ReadUleb32(limits.min) then
  3285. begin
  3286. InputError('Error reading memory limits min for memory import');
  3287. exit;
  3288. end;
  3289. end;
  3290. $01:
  3291. begin
  3292. limits.HasMax:=True;
  3293. if not ReadUleb32(limits.min) then
  3294. begin
  3295. InputError('Error reading memory limits min for memory import');
  3296. exit;
  3297. end;
  3298. if not ReadUleb32(limits.max) then
  3299. begin
  3300. InputError('Error reading memory limits max for memory import');
  3301. exit;
  3302. end;
  3303. if limits.Min>limits.Max then
  3304. begin
  3305. InputError('Memory limits min exceed memory limits max in memory import');
  3306. exit;
  3307. end;
  3308. end;
  3309. else
  3310. begin
  3311. InputError('Unsupported memory limits kind for memory import: $' + HexStr(MemoryLimitsKind,2));
  3312. exit;
  3313. end;
  3314. end;
  3315. end;
  3316. end;
  3317. $03: { global }
  3318. begin
  3319. Inc(GlobalTypeImportsCount);
  3320. SetLength(GlobalTypes,GlobalTypeImportsCount);
  3321. with GlobalTypes[GlobalTypeImportsCount-1] do
  3322. begin
  3323. IsImport:=True;
  3324. ImportName:=Name;
  3325. ImportModName:=ModName;
  3326. if not AReader.read(GlobalType,1) then
  3327. begin
  3328. InputError('Error reading global type for global import');
  3329. exit;
  3330. end;
  3331. if not decode_wasm_basic_type(GlobalType,valtype) then
  3332. begin
  3333. InputError('Unsupported global type for global import: ' + HexStr(GlobalType,2));
  3334. exit;
  3335. end;
  3336. if not AReader.read(GlobalMutabilityType,1) then
  3337. begin
  3338. InputError('Error reading global mutability flag for global import');
  3339. exit;
  3340. end;
  3341. case GlobalMutabilityType of
  3342. $00:
  3343. IsMutable:=False;
  3344. $01:
  3345. IsMutable:=True;
  3346. else
  3347. begin
  3348. InputError('Unknown global mutability flag for global import: $' + HexStr(GlobalMutabilityType,2));
  3349. exit;
  3350. end;
  3351. end;
  3352. end;
  3353. end;
  3354. $04: { tag }
  3355. begin
  3356. Inc(TagTypeImportsCount);
  3357. SetLength(TagTypes,TagTypeImportsCount);
  3358. with TagTypes[TagTypeImportsCount-1] do
  3359. begin
  3360. IsImport:=True;
  3361. ImportName:=Name;
  3362. ImportModName:=ModName;
  3363. if not Read(TagAttr,1) then
  3364. begin
  3365. InputError('Error reading import tag attribute');
  3366. exit;
  3367. end;
  3368. if not ReadUleb32(TagTypeIdx) then
  3369. begin
  3370. InputError('Error reading import tag type index');
  3371. exit;
  3372. end;
  3373. if TagTypeIdx>high(FFuncTypes) then
  3374. begin
  3375. InputError('Type index in tag import exceeds bounds of the types table');
  3376. exit;
  3377. end;
  3378. end;
  3379. end;
  3380. else
  3381. begin
  3382. InputError('Unknown import type: $' + HexStr(ImportType,2));
  3383. exit;
  3384. end;
  3385. end;
  3386. end;
  3387. if AReader.Pos<>(SectionStart+SectionSize) then
  3388. begin
  3389. InputError('Unexpected import section size');
  3390. exit;
  3391. end;
  3392. Result:=true;
  3393. end;
  3394. function ReadFunctionSection: Boolean;
  3395. var
  3396. FunctionsCount: uint32;
  3397. i: Integer;
  3398. begin
  3399. Result:=False;
  3400. if FunctionSectionRead then
  3401. begin
  3402. InputError('Function section is duplicated');
  3403. exit;
  3404. end;
  3405. FunctionSectionRead:=True;
  3406. if not ReadUleb32(FunctionsCount) then
  3407. begin
  3408. InputError('Error reading the functions count');
  3409. exit;
  3410. end;
  3411. SetLength(FuncTypes, FuncTypeImportsCount + FunctionsCount);
  3412. for i:=0 to FunctionsCount-1 do
  3413. with FuncTypes[i + FuncTypeImportsCount] do
  3414. begin
  3415. IsImport:=False;
  3416. if not ReadUleb32(typidx) then
  3417. begin
  3418. InputError('Error reading type index for function');
  3419. exit;
  3420. end;
  3421. if typidx>high(FFuncTypes) then
  3422. begin
  3423. InputError('Type index in the function section exceeds bounds of the types table');
  3424. exit;
  3425. end;
  3426. end;
  3427. if AReader.Pos<>(SectionStart+SectionSize) then
  3428. begin
  3429. InputError('Unexpected function section size');
  3430. exit;
  3431. end;
  3432. Result:=true;
  3433. end;
  3434. function ReadGlobalSection: Boolean;
  3435. function ParseExpr(out Init: TGlobalInitializer): Boolean;
  3436. var
  3437. B, B2: Byte;
  3438. tmpU32: UInt32;
  3439. tmpU64: UInt64;
  3440. begin
  3441. Result:=False;
  3442. repeat
  3443. if not Read(B, 1) then
  3444. exit;
  3445. case B of
  3446. $0B: { end }
  3447. ;
  3448. $41: { i32.const }
  3449. begin
  3450. Init.typ:=wbt_i32;
  3451. if not ReadSleb32(Init.init_i32) then
  3452. exit;
  3453. end;
  3454. $42: { i64.const }
  3455. begin
  3456. Init.typ:=wbt_i64;
  3457. if not ReadSleb(Init.init_i64) then
  3458. exit;
  3459. end;
  3460. $43: { f32.const }
  3461. begin
  3462. Init.typ:=wbt_f32;
  3463. if not Read(tmpU32, 4) then
  3464. exit;
  3465. {$ifdef FPC_BIG_ENDIAN}
  3466. tmpU32:=SwapEndian(tmpU32);
  3467. {$endif FPC_BIG_ENDIAN}
  3468. Move(tmpU32,Init.init_f32,4);
  3469. end;
  3470. $44: { f64.const }
  3471. begin
  3472. Init.typ:=wbt_f64;
  3473. if not Read(tmpU64, 8) then
  3474. exit;
  3475. {$ifdef FPC_BIG_ENDIAN}
  3476. tmpU64:=SwapEndian(tmpU64);
  3477. {$endif FPC_BIG_ENDIAN}
  3478. Move(tmpU64,Init.init_f64,8);
  3479. end;
  3480. $D0: { ref.null }
  3481. begin
  3482. if not Read(B2, 1) then
  3483. exit;
  3484. if not decode_wasm_basic_type(B2, Init.typ) then
  3485. exit;
  3486. if not (Init.typ in WasmReferenceTypes) then
  3487. exit;
  3488. end;
  3489. else
  3490. begin
  3491. InputError('Unsupported opcode in global initializer');
  3492. exit;
  3493. end;
  3494. end;
  3495. until b = $0B;
  3496. Result:=True;
  3497. end;
  3498. var
  3499. GlobalsCount: uint32;
  3500. i: Integer;
  3501. vt: Byte;
  3502. mut: Byte;
  3503. begin
  3504. Result:=False;
  3505. if GlobalSectionRead then
  3506. begin
  3507. InputError('Global section is duplicated');
  3508. exit;
  3509. end;
  3510. GlobalSectionRead:=True;
  3511. if not ReadUleb32(GlobalsCount) then
  3512. begin
  3513. InputError('Error reading the globals count from the global section');
  3514. exit;
  3515. end;
  3516. SetLength(GlobalTypes,Length(GlobalTypes)+GlobalsCount);
  3517. for i:=0 to GlobalsCount-1 do
  3518. with GlobalTypes[i + GlobalTypeImportsCount] do
  3519. begin
  3520. if not read(vt,1) then
  3521. begin
  3522. InputError('Error reading the type of a global from the global section');
  3523. exit;
  3524. end;
  3525. if not decode_wasm_basic_type(vt,valtype) then
  3526. begin
  3527. InputError('Unsupported type of global in the global section');
  3528. exit;
  3529. end;
  3530. if not read(mut,1) then
  3531. begin
  3532. InputError('Error reading the mutability flag of a global in the global section');
  3533. exit;
  3534. end;
  3535. case mut of
  3536. $00:
  3537. IsMutable:=False;
  3538. $01:
  3539. IsMutable:=True;
  3540. else
  3541. begin
  3542. InputError('Unsupported value (' + tostr(mut) + ') for the mutability flag of a global in the global section');
  3543. exit;
  3544. end;
  3545. end;
  3546. if not ParseExpr(GlobalInit) then
  3547. begin
  3548. InputError('Error parsing the global initializer expression in the global section');
  3549. exit;
  3550. end;
  3551. if GlobalInit.typ<>valtype then
  3552. begin
  3553. InputError('Initializer expression for global produces a type, which does not match the type of the global');
  3554. exit;
  3555. end;
  3556. end;
  3557. if AReader.Pos<>(SectionStart+SectionSize) then
  3558. begin
  3559. InputError('Unexpected global section size');
  3560. exit;
  3561. end;
  3562. Result:=True;
  3563. end;
  3564. function ReadExportSection: Boolean;
  3565. var
  3566. ExportsCount, FuncIdx, TableIdx, MemIdx, GlobalIdx, TagIdx: uint32;
  3567. i: Integer;
  3568. Name: ansistring;
  3569. ExportType: Byte;
  3570. begin
  3571. Result:=False;
  3572. if ExportSectionRead then
  3573. begin
  3574. InputError('Export section is duplicated');
  3575. exit;
  3576. end;
  3577. ExportSectionRead:=True;
  3578. if not ReadUleb32(ExportsCount) then
  3579. begin
  3580. InputError('Error reading the exports count from the export section');
  3581. exit;
  3582. end;
  3583. for i:=0 to ExportsCount-1 do
  3584. begin
  3585. if not ReadName(Name) then
  3586. begin
  3587. InputError('Error reading an export name from the export section');
  3588. exit;
  3589. end;
  3590. if not Read(ExportType,1) then
  3591. begin
  3592. InputError('Error reading an export type from the export section');
  3593. exit;
  3594. end;
  3595. case ExportType of
  3596. $00: { func }
  3597. begin
  3598. if not ReadUleb32(FuncIdx) then
  3599. begin
  3600. InputError('Error reading a func index from the export section');
  3601. exit;
  3602. end;
  3603. if FuncIdx>high(FuncTypes) then
  3604. begin
  3605. InputError('Func index too high in the export section');
  3606. exit;
  3607. end;
  3608. with FuncTypes[FuncIdx] do
  3609. begin
  3610. IsExported:=True;
  3611. ExportName:=Name;
  3612. end;
  3613. end;
  3614. $01: { table }
  3615. begin
  3616. if not ReadUleb32(TableIdx) then
  3617. begin
  3618. InputError('Error reading a table index from the export section');
  3619. exit;
  3620. end;
  3621. if TableIdx>high(TableTypes) then
  3622. begin
  3623. InputError('Table index too high in the export section');
  3624. exit;
  3625. end;
  3626. with TableTypes[TableIdx] do
  3627. begin
  3628. IsExported:=True;
  3629. ExportName:=Name;
  3630. end;
  3631. end;
  3632. $02: { mem }
  3633. begin
  3634. if not ReadUleb32(MemIdx) then
  3635. begin
  3636. InputError('Error reading a mem index from the export section');
  3637. exit;
  3638. end;
  3639. if MemIdx>high(MemTypes) then
  3640. begin
  3641. InputError('Mem index too high in the export section');
  3642. exit;
  3643. end;
  3644. with MemTypes[MemIdx] do
  3645. begin
  3646. IsExported:=True;
  3647. ExportName:=Name;
  3648. end;
  3649. end;
  3650. $03: { global }
  3651. begin
  3652. if not ReadUleb32(GlobalIdx) then
  3653. begin
  3654. InputError('Error reading a global index from the export section');
  3655. exit;
  3656. end;
  3657. if GlobalIdx>high(GlobalTypes) then
  3658. begin
  3659. InputError('Global index too high in the export section');
  3660. exit;
  3661. end;
  3662. with GlobalTypes[GlobalIdx] do
  3663. begin
  3664. IsExported:=True;
  3665. ExportName:=Name;
  3666. end;
  3667. end;
  3668. $04: { tag }
  3669. begin
  3670. if not ReadUleb32(TagIdx) then
  3671. begin
  3672. InputError('Error reading a tag index from the export section');
  3673. exit;
  3674. end;
  3675. if TagIdx>high(TagTypes) then
  3676. begin
  3677. InputError('Tag index too high in the export section');
  3678. exit;
  3679. end;
  3680. with TagTypes[TagIdx] do
  3681. begin
  3682. IsExported:=True;
  3683. ExportName:=Name;
  3684. end;
  3685. end;
  3686. else
  3687. begin
  3688. InputError('Unsupported export type in the export section: ' + tostr(ExportType));
  3689. exit;
  3690. end;
  3691. end;
  3692. end;
  3693. if AReader.Pos<>(SectionStart+SectionSize) then
  3694. begin
  3695. InputError('Unexpected export section size');
  3696. exit;
  3697. end;
  3698. Result:=True;
  3699. end;
  3700. function ReadElementSection: Boolean;
  3701. begin
  3702. Result:=False;
  3703. if ElementSectionRead then
  3704. begin
  3705. InputError('Element section is duplicated');
  3706. exit;
  3707. end;
  3708. ElementSectionRead:=True;
  3709. { We skip the element section for now }
  3710. { TODO: implement reading it (and linking of tables) }
  3711. Result:=True;
  3712. end;
  3713. function ReadTagSection: Boolean;
  3714. var
  3715. TagCount: uint32;
  3716. i: Integer;
  3717. begin
  3718. Result:=False;
  3719. if TagSectionRead then
  3720. begin
  3721. InputError('Tag section is duplicated');
  3722. exit;
  3723. end;
  3724. TagSectionRead:=True;
  3725. if not ReadUleb32(TagCount) then
  3726. begin
  3727. InputError('Error reading the tag count from the tag section');
  3728. exit;
  3729. end;
  3730. SetLength(TagTypes,Length(TagTypes)+TagCount);
  3731. for i:=0 to TagCount-1 do
  3732. with TagTypes[i + TagTypeImportsCount] do
  3733. begin
  3734. if not Read(TagAttr,1) then
  3735. begin
  3736. InputError('Error reading tag attribute');
  3737. exit;
  3738. end;
  3739. if not ReadUleb32(TagTypeIdx) then
  3740. begin
  3741. InputError('Error reading tag type index');
  3742. exit;
  3743. end;
  3744. if TagTypeIdx>high(FFuncTypes) then
  3745. begin
  3746. InputError('Type index in tag import exceeds bounds of the types table');
  3747. exit;
  3748. end;
  3749. end;
  3750. if AReader.Pos<>(SectionStart+SectionSize) then
  3751. begin
  3752. InputError('Unexpected tag section size');
  3753. exit;
  3754. end;
  3755. Result:=True;
  3756. end;
  3757. function ReadCodeSection: Boolean;
  3758. var
  3759. CodeEntriesCount: uint32;
  3760. i: Integer;
  3761. begin
  3762. Result:=False;
  3763. if CodeSectionRead then
  3764. begin
  3765. InputError('Code section is duplicated');
  3766. exit;
  3767. end;
  3768. CodeSectionRead:=True;
  3769. CodeSectionIndex:=SectionIndex;
  3770. if not ReadUleb32(CodeEntriesCount) then
  3771. begin
  3772. InputError('Error reading the code entries cound from the code section');
  3773. exit;
  3774. end;
  3775. if CodeEntriesCount <> (Length(FuncTypes) - FuncTypeImportsCount) then
  3776. begin
  3777. InputError('Code segment count in the code section does not match the function definition count in the function section');
  3778. exit;
  3779. end;
  3780. SetLength(CodeSegments,CodeEntriesCount);
  3781. for i:=0 to CodeEntriesCount-1 do
  3782. with CodeSegments[i] do
  3783. begin
  3784. if not ReadUleb32(CodeSize) then
  3785. begin
  3786. InputError('Error reading the code size of an entry in the code section');
  3787. exit;
  3788. end;
  3789. if (AReader.Pos+CodeSize)>(SectionStart+SectionSize) then
  3790. begin
  3791. InputError('Code segment exceeds the bounds of the code section');
  3792. exit;
  3793. end;
  3794. DataPos:=AReader.Pos;
  3795. CodeSectionOffset:=AReader.Pos-SectionStart;
  3796. AReader.Seek(AReader.Pos+CodeSize);
  3797. end;
  3798. if AReader.Pos<>(SectionStart+SectionSize) then
  3799. begin
  3800. InputError('Unexpected code section size');
  3801. exit;
  3802. end;
  3803. Result:=true;
  3804. end;
  3805. function ReadDataSection: Boolean;
  3806. function ReadExpr(out ExprV: int32): Boolean;
  3807. var
  3808. b: Byte;
  3809. begin
  3810. Result:=False;
  3811. if not Read(b,1) then
  3812. exit;
  3813. if b<>$41 then
  3814. begin
  3815. InputError('Only i32.const expressions supported');
  3816. exit;
  3817. end;
  3818. if not ReadSleb32(ExprV) then
  3819. exit;
  3820. if not Read(b,1) then
  3821. exit;
  3822. if b<>$0B then
  3823. begin
  3824. InputError('Only single const expressions supported');
  3825. exit;
  3826. end;
  3827. Result:=True;
  3828. end;
  3829. var
  3830. DataCount: uint32;
  3831. DataType: Byte;
  3832. i: Integer;
  3833. begin
  3834. Result:=False;
  3835. if DataSectionRead then
  3836. begin
  3837. InputError('Data section is duplicated');
  3838. exit;
  3839. end;
  3840. DataSectionRead:=True;
  3841. DataSectionIndex:=SectionIndex;
  3842. if not ReadUleb32(DataCount) then
  3843. begin
  3844. InputError('Error reading the data entries count from the data section');
  3845. exit;
  3846. end;
  3847. if DataCountSectionRead then
  3848. begin
  3849. if Length(DataSegments)<>DataCount then
  3850. begin
  3851. InputError('Data entries count in the data section do not match the number, specified in the data count section');
  3852. exit;
  3853. end;
  3854. end
  3855. else
  3856. SetLength(DataSegments,DataCount);
  3857. for i:=0 to DataCount-1 do
  3858. with DataSegments[i] do
  3859. begin
  3860. if not read(DataType, 1) then
  3861. begin
  3862. InputError('Error reading data type of segment from the data section');
  3863. exit;
  3864. end;
  3865. case DataType of
  3866. 0:
  3867. begin
  3868. Active:=True;
  3869. MemIdx:=0;
  3870. if not ReadExpr(Offset) then
  3871. begin
  3872. InputError('Error reading memory offset of segment from the data section');
  3873. exit;
  3874. end;
  3875. end;
  3876. 1:
  3877. Active:=False;
  3878. 2:
  3879. begin
  3880. Active:=True;
  3881. if not ReadUleb32(MemIdx) then
  3882. begin
  3883. InputError('Error reading MemIdx of segment from the data section');
  3884. exit;
  3885. end;
  3886. if not ReadExpr(Offset) then
  3887. begin
  3888. InputError('Error reading memory offset of segment from the data section');
  3889. exit;
  3890. end;
  3891. end;
  3892. else
  3893. begin
  3894. InputError('Unsupported data type of segment in the data section: ' + tostr(DataType));
  3895. exit;
  3896. end;
  3897. end;
  3898. if MemIdx<>0 then
  3899. begin
  3900. InputError('Memory index other than 0 not supported (got ' + tostr(MemIdx) + ')');
  3901. exit;
  3902. end;
  3903. if not Active then
  3904. begin
  3905. InputError('Passive memory segments not supported');
  3906. exit;
  3907. end;
  3908. if not ReadUleb32(Len) then
  3909. begin
  3910. InputError('Error reading data segment length');
  3911. exit;
  3912. end;
  3913. if (AReader.Pos+Len)>(SectionStart+SectionSize) then
  3914. begin
  3915. InputError('Data segment exceeds the bounds of the data section');
  3916. exit;
  3917. end;
  3918. DataPos:=AReader.Pos;
  3919. DataSectionOffset:=AReader.Pos-SectionStart;
  3920. AReader.Seek(AReader.Pos+Len);
  3921. end;
  3922. if AReader.Pos<>(SectionStart+SectionSize) then
  3923. begin
  3924. InputError('Unexpected data section size');
  3925. exit;
  3926. end;
  3927. Result:=true;
  3928. end;
  3929. function ReadDataCountSection: Boolean;
  3930. var
  3931. DataCount: uint32;
  3932. begin
  3933. Result:=False;
  3934. if DataCountSectionRead then
  3935. begin
  3936. InputError('Data count section is duplicated');
  3937. exit;
  3938. end;
  3939. DataCountSectionRead:=True;
  3940. if DataSectionRead then
  3941. begin
  3942. InputError('The data count section must occur before the data section');
  3943. exit;
  3944. end;
  3945. if not ReadUleb32(DataCount) then
  3946. begin
  3947. InputError('Error reading the data count from the data count section');
  3948. exit;
  3949. end;
  3950. if AReader.Pos<>(SectionStart+SectionSize) then
  3951. begin
  3952. InputError('Unexpected data count section size');
  3953. exit;
  3954. end;
  3955. SetLength(DataSegments, DataCount);
  3956. Result:=true;
  3957. end;
  3958. begin
  3959. Result:=False;
  3960. Inc(SectionIndex);
  3961. if not AReader.read(SectionId,1) then
  3962. begin
  3963. InputError('Error reading section ID');
  3964. exit;
  3965. end;
  3966. CheckSectionBounds:=false;
  3967. if not ReadUleb32(SectionSize) then
  3968. begin
  3969. InputError('Error reading section size');
  3970. exit;
  3971. end;
  3972. if (AReader.Pos+SectionSize)>AReader.size then
  3973. begin
  3974. InputError('Section exceeds beyond the end of file');
  3975. exit;
  3976. end;
  3977. SectionStart:=AReader.Pos;
  3978. CheckSectionBounds:=true;
  3979. case SectionId of
  3980. Byte(wsiCustom):
  3981. if not ReadCustomSection then
  3982. begin
  3983. InputError('Error encountered, while reading a custom section');
  3984. exit;
  3985. end;
  3986. Byte(wsiType):
  3987. if not ReadTypeSection then
  3988. begin
  3989. InputError('Error reading the type section');
  3990. exit;
  3991. end;
  3992. Byte(wsiImport):
  3993. if not ReadImportSection then
  3994. begin
  3995. InputError('Error reading the import section');
  3996. exit;
  3997. end;
  3998. Byte(wsiFunction):
  3999. if not ReadFunctionSection then
  4000. begin
  4001. InputError('Error reading the function section');
  4002. exit;
  4003. end;
  4004. Byte(wsiGlobal):
  4005. if not ReadGlobalSection then
  4006. begin
  4007. InputError('Error reading the global section');
  4008. exit;
  4009. end;
  4010. Byte(wsiExport):
  4011. if not ReadExportSection then
  4012. begin
  4013. InputError('Error reading the export section');
  4014. exit;
  4015. end;
  4016. Byte(wsiElement):
  4017. if not ReadElementSection then
  4018. begin
  4019. InputError('Error reading the element section');
  4020. exit;
  4021. end;
  4022. Byte(wsiTag):
  4023. if not ReadTagSection then
  4024. begin
  4025. InputError('Error reading the tag section');
  4026. exit;
  4027. end;
  4028. Byte(wsiCode):
  4029. if not ReadCodeSection then
  4030. begin
  4031. InputError('Error reading the code section');
  4032. exit;
  4033. end;
  4034. Byte(wsiData):
  4035. if not ReadDataSection then
  4036. begin
  4037. InputError('Error reading the data section');
  4038. exit;
  4039. end;
  4040. Byte(wsiDataCount):
  4041. begin
  4042. if not ReadDataCountSection then
  4043. begin
  4044. InputError('Error reading the data count section');
  4045. exit;
  4046. end;
  4047. end
  4048. else
  4049. begin
  4050. InputError('Unknown section: ' + ToStr(SectionId));
  4051. exit;
  4052. end;
  4053. end;
  4054. if SectionSize>0 then
  4055. AReader.seek(SectionStart+SectionSize);
  4056. Result:=True;
  4057. end;
  4058. function FindCodeSegment(Ofs: uint32): Integer;
  4059. var
  4060. L, R, M: Integer;
  4061. begin
  4062. L:=Low(CodeSegments);
  4063. R:=High(CodeSegments);
  4064. while L<=R do
  4065. begin
  4066. M:=(L+R) div 2;
  4067. if (CodeSegments[M].CodeSectionOffset+CodeSegments[M].CodeSize-1) < Ofs then
  4068. L:=M+1
  4069. else if CodeSegments[M].CodeSectionOffset > Ofs then
  4070. R:=M-1
  4071. else
  4072. begin
  4073. Result:=M;
  4074. exit;
  4075. end;
  4076. end;
  4077. Result:=-1;
  4078. end;
  4079. function FindDataSegment(Ofs: uint32): Integer;
  4080. var
  4081. L, R, M: Integer;
  4082. begin
  4083. L:=Low(DataSegments);
  4084. R:=High(DataSegments);
  4085. while L<=R do
  4086. begin
  4087. M:=(L+R) div 2;
  4088. if (DataSegments[M].DataSectionOffset+DataSegments[M].Len-1) < Ofs then
  4089. L:=M+1
  4090. else if DataSegments[M].DataSectionOffset > Ofs then
  4091. R:=M-1
  4092. else
  4093. begin
  4094. Result:=M;
  4095. exit;
  4096. end;
  4097. end;
  4098. Result:=-1;
  4099. end;
  4100. var
  4101. ModuleMagic: array [0..3] of Byte;
  4102. ModuleVersion: array [0..3] of Byte;
  4103. i, j, FirstCodeSegmentIdx, FirstDataSegmentIdx, SegI: Integer;
  4104. CurrSec, ObjSec: TObjSection;
  4105. BaseSectionOffset: UInt32;
  4106. ObjReloc: TWasmObjRelocation;
  4107. ds: TWasmCustomDebugSectionType;
  4108. begin
  4109. FReader:=AReader;
  4110. InputFileName:=AReader.FileName;
  4111. objdata:=CObjData.Create(InputFileName);
  4112. result:=false;
  4113. CodeSegments:=nil;
  4114. DataSegments:=nil;
  4115. SymbolTable:=nil;
  4116. RelocationTable:=nil;
  4117. SetLength(RelocationTable,2+(Ord(High(TWasmCustomDebugSectionType))-Ord(Low(TWasmCustomDebugSectionType))+1));
  4118. FuncTypes:=nil;
  4119. FuncTypeImportsCount:=0;
  4120. TableTypes:=nil;
  4121. TableTypeImportsCount:=0;
  4122. MemTypes:=nil;
  4123. MemTypeImportsCount:=0;
  4124. GlobalTypes:=nil;
  4125. GlobalTypeImportsCount:=0;
  4126. TagTypes:=nil;
  4127. TagTypeImportsCount:=0;
  4128. if not AReader.read(ModuleMagic,4) then
  4129. exit;
  4130. for i:=0 to 3 do
  4131. if ModuleMagic[i]<>WasmModuleMagic[i] then
  4132. exit;
  4133. if not AReader.read(ModuleVersion,4) then
  4134. exit;
  4135. for i:=0 to 3 do
  4136. if ModuleVersion[i]<>WasmVersion[i] then
  4137. exit;
  4138. while AReader.Pos<AReader.size do
  4139. if not ReadSection then
  4140. exit;
  4141. { fill the code segment names }
  4142. for i:=low(SymbolTable) to high(SymbolTable) do
  4143. with SymbolTable[i] do
  4144. if (SymKind=SYMTAB_FUNCTION) and ((SymFlags and WASM_SYM_UNDEFINED)=0) then
  4145. begin
  4146. if FuncTypes[SymIndex].IsImport then
  4147. begin
  4148. InputError('WASM_SYM_UNDEFINED not set on a SYMTAB_FUNCTION symbol, that is an import');
  4149. exit;
  4150. end;
  4151. if (SymFlags and WASM_SYM_EXPLICIT_NAME)=0 then
  4152. begin
  4153. with CodeSegments[SymIndex-FuncTypeImportsCount] do
  4154. begin
  4155. SegName:='.text.n_'+SymName;
  4156. SegIsExported:=FuncTypes[SymIndex].IsExported;
  4157. end;
  4158. end;
  4159. end;
  4160. { create segments }
  4161. FirstCodeSegmentIdx:=ObjData.ObjSectionList.Count;
  4162. for i:=low(CodeSegments) to high(CodeSegments) do
  4163. with CodeSegments[i] do
  4164. begin
  4165. if SegName='' then
  4166. begin
  4167. InputError('Code section ' + tostr(i) + ' does not have a main symbol defined in the symbol table');
  4168. exit;
  4169. end;
  4170. if SegIsExported or not (cs_link_smart in current_settings.globalswitches) then
  4171. CurrSec:=ObjData.createsection(SegName,1,[oso_executable,oso_Data,oso_load,oso_keep],false)
  4172. else
  4173. CurrSec:=ObjData.createsection(SegName,1,[oso_executable,oso_Data,oso_load],false);
  4174. CurrSec.DataPos:=DataPos;
  4175. CurrSec.Size:=CodeSize;
  4176. end;
  4177. FirstDataSegmentIdx:=ObjData.ObjSectionList.Count;
  4178. for i:=low(DataSegments) to high(DataSegments) do
  4179. with DataSegments[i] do
  4180. if Active then
  4181. begin
  4182. if not (cs_link_smart in current_settings.globalswitches) then
  4183. CurrSec:=ObjData.createsection(SegName,1 shl SegAlignment,[oso_Data,oso_load,oso_write,oso_keep],false)
  4184. else
  4185. CurrSec:=ObjData.createsection(SegName,1 shl SegAlignment,[oso_Data,oso_load,oso_write],false);
  4186. CurrSec.DataPos:=DataPos;
  4187. CurrSec.MemPos:=Offset;
  4188. CurrSec.Size:=Len;
  4189. end;
  4190. ReadSectionContent(ObjData);
  4191. for i:=low(SymbolTable) to high(SymbolTable) do
  4192. with SymbolTable[i] do
  4193. case SymKind of
  4194. SYMTAB_DATA:
  4195. if (SymFlags and WASM_SYM_UNDEFINED)<>0 then
  4196. begin
  4197. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(SymName));
  4198. objsym.bind:=AB_EXTERNAL;
  4199. if (SymFlags and WASM_SYM_TLS)<>0 then
  4200. begin
  4201. objsym.typ:=AT_TLS;
  4202. objsym.TlsGlobalSym:=TWasmObjSymbol(ObjData.CreateSymbol('GOT.mem.'+SymName));
  4203. objsym.TlsGlobalSym.TlsDataSym:=objsym;
  4204. objsym.TlsGlobalSym.bind:=AB_EXTERNAL;
  4205. objsym.TlsGlobalSym.typ:=AT_WASM_GLOBAL;
  4206. objsym.TlsGlobalSym.objsection:=nil;
  4207. objsym.TlsGlobalSym.offset:=0;
  4208. objsym.TlsGlobalSym.size:=1;
  4209. objsym.TlsGlobalSym.LinkingData.GlobalType:=wbt_i32;
  4210. objsym.TlsGlobalSym.LinkingData.GlobalIsMutable:=true;
  4211. end
  4212. else
  4213. objsym.typ:=AT_DATA;
  4214. objsym.objsection:=nil;
  4215. objsym.offset:=0;
  4216. objsym.size:=0;
  4217. end
  4218. else
  4219. begin
  4220. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(SymName));
  4221. if (SymFlags and WASM_SYM_BINDING_LOCAL)<> 0 then
  4222. objsym.bind:=AB_LOCAL
  4223. else
  4224. objsym.bind:=AB_GLOBAL;
  4225. if (SymFlags and WASM_SYM_TLS)<>0 then
  4226. begin
  4227. objsym.typ:=AT_TLS;
  4228. objsym.TlsGlobalSym:=TWasmObjSymbol(ObjData.CreateSymbol('GOT.mem.'+SymName));
  4229. objsym.TlsGlobalSym.TlsDataSym:=objsym;
  4230. objsym.TlsGlobalSym.bind:=objsym.bind;
  4231. objsym.TlsGlobalSym.typ:=AT_WASM_GLOBAL;
  4232. objsym.TlsGlobalSym.objsection:=ObjData.createsection('.wasm_globals.n_'+objsym.TlsGlobalSym.Name,1,[oso_Data,oso_load],true);
  4233. if objsym.TlsGlobalSym.objsection.Size=0 then
  4234. objsym.TlsGlobalSym.objsection.WriteZeros(1);
  4235. TWasmObjSection(objsym.TlsGlobalSym.objsection).MainFuncSymbol:=objsym.TlsGlobalSym;
  4236. objsym.TlsGlobalSym.offset:=0;
  4237. objsym.TlsGlobalSym.size:=1;
  4238. objsym.TlsGlobalSym.LinkingData.GlobalType:=wbt_i32;
  4239. objsym.TlsGlobalSym.LinkingData.GlobalIsMutable:=true;
  4240. end
  4241. else
  4242. objsym.typ:=AT_DATA;
  4243. objsym.objsection:=TObjSection(ObjData.ObjSectionList[FirstDataSegmentIdx+SymIndex]);
  4244. objsym.offset:=SymOffset;
  4245. objsym.size:=SymSize;
  4246. end;
  4247. SYMTAB_FPC_CUSTOM:
  4248. if (SymFlags and WASM_SYM_UNDEFINED)<>0 then
  4249. begin
  4250. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(SymName));
  4251. objsym.bind:=AB_EXTERNAL;
  4252. if (SymFlags and WASM_SYM_TLS)<>0 then
  4253. internalerror(2024080702);
  4254. objsym.typ:=AT_DATA;
  4255. objsym.objsection:=nil;
  4256. objsym.offset:=0;
  4257. objsym.size:=0;
  4258. end
  4259. else
  4260. begin
  4261. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(SymName));
  4262. if (SymFlags and WASM_SYM_BINDING_LOCAL)<> 0 then
  4263. objsym.bind:=AB_LOCAL
  4264. else
  4265. objsym.bind:=AB_GLOBAL;
  4266. if (SymFlags and WASM_SYM_TLS)<>0 then
  4267. internalerror(2024080703);
  4268. objsym.typ:=AT_DATA;
  4269. objsym.objsection:=TObjSection(ObjData.ObjSectionList.Find(WasmCustomSectionName[SymCustomSectionType]));
  4270. objsym.offset:=SymOffset;
  4271. objsym.size:=SymSize;
  4272. end;
  4273. SYMTAB_FUNCTION:
  4274. begin
  4275. if (SymFlags and WASM_SYM_UNDEFINED)<>0 then
  4276. begin
  4277. if not FuncTypes[SymIndex].IsImport then
  4278. begin
  4279. InputError('WASM_SYM_UNDEFINED set on a SYMTAB_FUNCTION symbol, that is not an import');
  4280. exit;
  4281. end;
  4282. if (SymFlags and WASM_SYM_EXPLICIT_NAME)<>0 then
  4283. begin
  4284. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(SymName));
  4285. objsym.bind:=AB_EXTERNAL;
  4286. objsym.typ:=AT_FUNCTION;
  4287. objsym.objsection:=nil;
  4288. objsym.offset:=0;
  4289. objsym.size:=0;
  4290. objsym.LinkingData.ImportModule:=FuncTypes[SymIndex].ImportModName;
  4291. objsym.LinkingData.ImportName:=FuncTypes[SymIndex].ImportName;
  4292. end
  4293. else
  4294. begin
  4295. if FuncTypes[SymIndex].ImportModName = 'env' then
  4296. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(FuncTypes[SymIndex].ImportName))
  4297. else
  4298. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(FuncTypes[SymIndex].ImportModName + '.' + FuncTypes[SymIndex].ImportName));
  4299. objsym.bind:=AB_EXTERNAL;
  4300. objsym.typ:=AT_FUNCTION;
  4301. objsym.objsection:=nil;
  4302. objsym.offset:=0;
  4303. objsym.size:=0;
  4304. end;
  4305. end
  4306. else
  4307. begin
  4308. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(SymName));
  4309. objsym.bind:=AB_GLOBAL;
  4310. objsym.typ:=AT_FUNCTION;
  4311. objsym.objsection:=TObjSection(ObjData.ObjSectionList[FirstCodeSegmentIdx+SymIndex-FuncTypeImportsCount]);
  4312. if (SymFlags and WASM_SYM_EXPLICIT_NAME)=0 then
  4313. TWasmObjSection(ObjData.ObjSectionList[FirstCodeSegmentIdx+SymIndex-FuncTypeImportsCount]).MainFuncSymbol:=objsym;
  4314. objsym.offset:=0;
  4315. objsym.size:=objsym.objsection.Size;
  4316. end;
  4317. objsym.LinkingData.FuncType:=TWasmFuncType.Create(FFuncTypes[FuncTypes[SymIndex].typidx]);
  4318. objsym.LinkingData.IsExported:=FuncTypes[SymIndex].IsExported;
  4319. objsym.LinkingData.ExportName:=FuncTypes[SymIndex].ExportName;
  4320. end;
  4321. SYMTAB_GLOBAL:
  4322. begin
  4323. if (SymFlags and WASM_SYM_UNDEFINED)<>0 then
  4324. begin
  4325. if not GlobalTypes[SymIndex].IsImport then
  4326. begin
  4327. InputError('WASM_SYM_UNDEFINED set on a SYMTAB_GLOBAL symbol, that is not an import');
  4328. exit;
  4329. end;
  4330. if (SymFlags and WASM_SYM_EXPLICIT_NAME)<>0 then
  4331. begin
  4332. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(SymName));
  4333. objsym.bind:=AB_EXTERNAL;
  4334. objsym.typ:=AT_WASM_GLOBAL;
  4335. objsym.objsection:=nil;
  4336. objsym.offset:=0;
  4337. objsym.size:=1;
  4338. objsym.LinkingData.ImportModule:=GlobalTypes[SymIndex].ImportModName;
  4339. objsym.LinkingData.ImportName:=GlobalTypes[SymIndex].ImportName;
  4340. end
  4341. else
  4342. begin
  4343. if GlobalTypes[SymIndex].ImportModName = 'env' then
  4344. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(GlobalTypes[SymIndex].ImportName))
  4345. else
  4346. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(GlobalTypes[SymIndex].ImportModName + '.' + GlobalTypes[SymIndex].ImportName));
  4347. objsym.bind:=AB_EXTERNAL;
  4348. objsym.typ:=AT_WASM_GLOBAL;
  4349. objsym.objsection:=nil;
  4350. objsym.offset:=0;
  4351. objsym.size:=1;
  4352. end;
  4353. end
  4354. else
  4355. begin
  4356. if GlobalTypes[SymIndex].IsImport then
  4357. begin
  4358. InputError('WASM_SYM_UNDEFINED not set on a SYMTAB_GLOBAL symbol, that is an import');
  4359. exit;
  4360. end;
  4361. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(SymName));
  4362. objsym.bind:=AB_GLOBAL;
  4363. objsym.typ:=AT_WASM_GLOBAL;
  4364. objsym.objsection:=ObjData.createsection('.wasm_globals.n_'+SymName,1,[oso_Data,oso_load],true);
  4365. if objsym.objsection.Size=0 then
  4366. objsym.objsection.WriteZeros(1);
  4367. if (SymFlags and WASM_SYM_EXPLICIT_NAME)=0 then
  4368. TWasmObjSection(objsym.objsection).MainFuncSymbol:=objsym;
  4369. objsym.offset:=0;
  4370. objsym.size:=1;
  4371. objsym.LinkingData.GlobalInitializer:=GlobalTypes[SymIndex].GlobalInit;
  4372. end;
  4373. objsym.LinkingData.GlobalType:=GlobalTypes[SymIndex].valtype;
  4374. objsym.LinkingData.GlobalIsMutable:=GlobalTypes[SymIndex].IsMutable;
  4375. objsym.LinkingData.IsExported:=GlobalTypes[SymIndex].IsExported;
  4376. objsym.LinkingData.ExportName:=GlobalTypes[SymIndex].ExportName;
  4377. end;
  4378. SYMTAB_SECTION:
  4379. begin
  4380. for ds:=Low(DebugSectionIndex) to High(DebugSectionIndex) do
  4381. if DebugSectionIndex[ds]=TargetSection then
  4382. begin
  4383. ObjSec:=TWasmObjSection(ObjData.findsection(WasmCustomSectionName[ds]));
  4384. break;
  4385. end;
  4386. if ObjSec=nil then
  4387. begin
  4388. InputError('SYMTAB_SECTION entry points to an unsupported section');
  4389. exit;
  4390. end;
  4391. end;
  4392. SYMTAB_EVENT:
  4393. begin
  4394. if (SymFlags and WASM_SYM_UNDEFINED)<>0 then
  4395. begin
  4396. if not TagTypes[SymIndex].IsImport then
  4397. begin
  4398. InputError('WASM_SYM_UNDEFINED set on a SYMTAB_EVENT symbol, that is not an import');
  4399. exit;
  4400. end;
  4401. if (SymFlags and WASM_SYM_EXPLICIT_NAME)<>0 then
  4402. begin
  4403. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(SymName));
  4404. objsym.bind:=AB_EXTERNAL;
  4405. objsym.typ:=AT_WASM_EXCEPTION_TAG;
  4406. objsym.objsection:=nil;
  4407. objsym.offset:=0;
  4408. objsym.size:=1;
  4409. objsym.LinkingData.ImportModule:=TagTypes[SymIndex].ImportModName;
  4410. objsym.LinkingData.ImportName:=TagTypes[SymIndex].ImportName;
  4411. end
  4412. else
  4413. begin
  4414. if GlobalTypes[SymIndex].ImportModName = 'env' then
  4415. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(GlobalTypes[SymIndex].ImportName))
  4416. else
  4417. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(GlobalTypes[SymIndex].ImportModName + '.' + GlobalTypes[SymIndex].ImportName));
  4418. objsym.bind:=AB_EXTERNAL;
  4419. objsym.typ:=AT_WASM_EXCEPTION_TAG;
  4420. objsym.objsection:=nil;
  4421. objsym.offset:=0;
  4422. objsym.size:=1;
  4423. end;
  4424. end
  4425. else
  4426. begin
  4427. if TagTypes[SymIndex].IsImport then
  4428. begin
  4429. InputError('WASM_SYM_UNDEFINED not set on a SYMTAB_EVENT symbol, that is an import');
  4430. exit;
  4431. end;
  4432. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(SymName));
  4433. if (symflags and WASM_SYM_BINDING_WEAK) <> 0 then
  4434. objsym.bind:=AB_WEAK_EXTERNAL
  4435. else if (symflags and WASM_SYM_BINDING_LOCAL) <> 0 then
  4436. objsym.bind:=AB_LOCAL
  4437. else
  4438. objsym.bind:=AB_GLOBAL;
  4439. objsym.typ:=AT_WASM_EXCEPTION_TAG;
  4440. objsym.objsection:=ObjData.createsection('.wasm_tags.n_'+SymName,1,[oso_Data,oso_load],true);
  4441. if objsym.objsection.Size=0 then
  4442. objsym.objsection.WriteZeros(1);
  4443. if (SymFlags and WASM_SYM_EXPLICIT_NAME)=0 then
  4444. TWasmObjSection(objsym.objsection).MainFuncSymbol:=objsym;
  4445. objsym.offset:=0;
  4446. objsym.size:=1;
  4447. end;
  4448. objsym.LinkingData.FuncType:=TWasmFuncType.Create(FFuncTypes[TagTypes[SymIndex].TagTypeIdx]);
  4449. objsym.LinkingData.IsExported:=TagTypes[SymIndex].IsExported;
  4450. objsym.LinkingData.ExportName:=TagTypes[SymIndex].ExportName;
  4451. end;
  4452. SYMTAB_TABLE:
  4453. {TODO};
  4454. end;
  4455. for j:=0 to high(RelocationTable) do
  4456. for i:=0 to high(RelocationTable[j]) do
  4457. with RelocationTable[j,i] do
  4458. begin
  4459. case j of
  4460. 0:
  4461. begin
  4462. SegI:=FindCodeSegment(RelocOffset);
  4463. if SegI=-1 then
  4464. begin
  4465. InputError('Relocation offset not found in code segment');
  4466. Exit;
  4467. end;
  4468. BaseSectionOffset:=CodeSegments[SegI].CodeSectionOffset;
  4469. ObjSec:=TObjSection(ObjData.ObjSectionList[FirstCodeSegmentIdx+SegI]);
  4470. end;
  4471. 1:
  4472. begin
  4473. SegI:=FindDataSegment(RelocOffset);
  4474. if SegI=-1 then
  4475. begin
  4476. InputError('Relocation offset not found in data segment');
  4477. Exit;
  4478. end;
  4479. BaseSectionOffset:=DataSegments[SegI].DataSectionOffset;
  4480. ObjSec:=TObjSection(ObjData.ObjSectionList[FirstDataSegmentIdx+SegI]);
  4481. end;
  4482. 2..2+(Ord(High(TWasmCustomDebugSectionType))-Ord(Low(TWasmCustomDebugSectionType))):
  4483. begin
  4484. BaseSectionOffset:=0;
  4485. ObjSec:=ObjData.findsection(WasmCustomSectionName[TWasmCustomSectionType((j-2)+Ord(Low(TWasmCustomDebugSectionType)))]);
  4486. end;
  4487. else
  4488. internalerror(2023122801);
  4489. end;
  4490. case RelocType of
  4491. R_WASM_FUNCTION_INDEX_LEB:
  4492. ObjSec.ObjRelocations.Add(TWasmObjRelocation.CreateSymbol(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSym,RELOC_FUNCTION_INDEX_LEB));
  4493. R_WASM_TABLE_INDEX_SLEB:
  4494. ObjSec.ObjRelocations.Add(TWasmObjRelocation.CreateSymbol(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSym,RELOC_MEMORY_ADDR_OR_TABLE_INDEX_SLEB));
  4495. R_WASM_TABLE_INDEX_I32:
  4496. ObjSec.ObjRelocations.Add(TWasmObjRelocation.CreateSymbol(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSym,RELOC_ABSOLUTE));
  4497. R_WASM_MEMORY_ADDR_LEB:
  4498. begin
  4499. ObjReloc:=TWasmObjRelocation.CreateSymbol(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSym,RELOC_MEMORY_ADDR_LEB);
  4500. ObjReloc.Addend:=RelocAddend;
  4501. ObjSec.ObjRelocations.Add(ObjReloc);
  4502. end;
  4503. R_WASM_MEMORY_ADDR_SLEB:
  4504. begin
  4505. ObjReloc:=TWasmObjRelocation.CreateSymbol(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSym,RELOC_MEMORY_ADDR_OR_TABLE_INDEX_SLEB);
  4506. ObjReloc.Addend:=RelocAddend;
  4507. ObjSec.ObjRelocations.Add(ObjReloc);
  4508. end;
  4509. R_WASM_MEMORY_ADDR_I32:
  4510. begin
  4511. ObjReloc:=TWasmObjRelocation.CreateSymbol(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSym,RELOC_ABSOLUTE);
  4512. ObjReloc.Addend:=RelocAddend;
  4513. ObjSec.ObjRelocations.Add(ObjReloc);
  4514. end;
  4515. R_WASM_TYPE_INDEX_LEB:
  4516. ObjSec.ObjRelocations.Add(TWasmObjRelocation.CreateFuncType(RelocOffset-BaseSectionOffset,FFuncTypes[RelocIndex]));
  4517. R_WASM_FUNCTION_OFFSET_I32:
  4518. begin
  4519. ObjReloc:=TWasmObjRelocation.CreateSymbol(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSym,RELOC_ABSOLUTE);
  4520. ObjReloc.Addend:=RelocAddend;
  4521. ObjReloc.IsFunctionOffsetI32:=True;
  4522. ObjSec.ObjRelocations.Add(ObjReloc);
  4523. end;
  4524. R_WASM_SECTION_OFFSET_I32:
  4525. begin
  4526. ObjReloc:=TWasmObjRelocation.CreateSection(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSec,RELOC_ABSOLUTE);
  4527. ObjReloc.Addend:=RelocAddend;
  4528. ObjSec.ObjRelocations.Add(ObjReloc);
  4529. end;
  4530. R_WASM_GLOBAL_INDEX_LEB:
  4531. begin
  4532. ObjSec.ObjRelocations.Add(TWasmObjRelocation.CreateSymbol(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSym,RELOC_GLOBAL_INDEX_LEB));
  4533. if Assigned(SymbolTable[RelocIndex].ObjSym.TlsGlobalSym) then
  4534. ObjSec.ObjRelocations.Add(TWasmObjRelocation.CreateSymbol(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSym.TlsGlobalSym,RELOC_GLOBAL_INDEX_LEB));
  4535. end;
  4536. R_WASM_GLOBAL_INDEX_I32:
  4537. begin
  4538. ObjSec.ObjRelocations.Add(TWasmObjRelocation.CreateSymbol(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSym,RELOC_ABSOLUTE));
  4539. if Assigned(SymbolTable[RelocIndex].ObjSym.TlsGlobalSym) then
  4540. ObjSec.ObjRelocations.Add(TWasmObjRelocation.CreateSymbol(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSym.TlsGlobalSym,RELOC_ABSOLUTE));
  4541. end;
  4542. R_WASM_TAG_INDEX_LEB:
  4543. ObjSec.ObjRelocations.Add(TWasmObjRelocation.CreateSymbol(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSym,RELOC_TAG_INDEX_LEB));
  4544. else
  4545. internalerror(2023122802);
  4546. end;
  4547. end;
  4548. Result:=True;
  4549. end;
  4550. {****************************************************************************
  4551. TWasmExeOutput
  4552. ****************************************************************************}
  4553. procedure TWasmExeOutput.AddToNameMap(var nm: TCustomSectionNameMap; aidx: UInt32; const aname: string);
  4554. begin
  4555. SetLength(nm,Length(nm)+1);
  4556. with nm[High(nm)] do
  4557. begin
  4558. idx:=aidx;
  4559. name:=aname;
  4560. end;
  4561. end;
  4562. procedure TWasmExeOutput.AddToFunctionNameMap(aidx: UInt32; const aname: string);
  4563. begin
  4564. AddToNameMap(FFunctionNameMap,aidx,aname);
  4565. end;
  4566. procedure TWasmExeOutput.AddToGlobalNameMap(aidx: UInt32; const aname: string);
  4567. begin
  4568. AddToNameMap(FGlobalNameMap,aidx,aname);
  4569. end;
  4570. procedure TWasmExeOutput.AddToDataNameMap(aidx: UInt32; const aname: string);
  4571. begin
  4572. AddToNameMap(FDataNameMap,aidx,aname);
  4573. end;
  4574. procedure TWasmExeOutput.AddToTagNameMap(aidx: UInt32; const aname: string);
  4575. begin
  4576. AddToNameMap(FTagNameMap,aidx,aname);
  4577. end;
  4578. procedure TWasmExeOutput.WriteWasmSection(wsid: TWasmSectionID);
  4579. var
  4580. b: byte;
  4581. begin
  4582. b:=ord(wsid);
  4583. Writer.write(b,1);
  4584. WriteUleb(Writer,FWasmSections[wsid].size);
  4585. Writer.writearray(FWasmSections[wsid]);
  4586. end;
  4587. procedure TWasmExeOutput.WriteWasmSectionIfNotEmpty(wsid: TWasmSectionID);
  4588. begin
  4589. if FWasmSections[wsid].size>0 then
  4590. WriteWasmSection(wsid);
  4591. end;
  4592. procedure TWasmExeOutput.WriteWasmCustomSection(wcst: TWasmCustomSectionType);
  4593. var
  4594. b: byte;
  4595. begin
  4596. b:=0;
  4597. Writer.write(b,1);
  4598. WriteUleb(Writer,FWasmCustomSections[wcst].size);
  4599. Writer.writearray(FWasmCustomSections[wcst]);
  4600. end;
  4601. function TWasmExeOutput.writeData: boolean;
  4602. procedure WriteImportSection;
  4603. var
  4604. imports_count,
  4605. i: Integer;
  4606. begin
  4607. if assigned(exemap) then
  4608. exemap.AddHeader('Import section');
  4609. imports_count:=Length(FImportedMemories)+Length(FFunctionImports);
  4610. WriteUleb(FWasmSections[wsiImport],imports_count);
  4611. for i:=0 to Length(FImportedMemories)-1 do
  4612. with FImportedMemories[i] do
  4613. begin
  4614. WriteName(FWasmSections[wsiImport],ModName);
  4615. WriteName(FWasmSections[wsiImport],Name);
  4616. WriteByte(FWasmSections[wsiImport],$02); { mem }
  4617. WriteMemoryTo(FWasmSections[wsiImport],MemType);
  4618. if assigned(exemap) then
  4619. exemap.Add(' Memory['+tostr(i)+'] '+Memory2String(MemType)+' <- '+ModName+'.'+Name);
  4620. end;
  4621. for i:=0 to Length(FFunctionImports)-1 do
  4622. with FFunctionImports[i] do
  4623. begin
  4624. WriteName(FWasmSections[wsiImport],ModName);
  4625. WriteName(FWasmSections[wsiImport],Name);
  4626. WriteByte(FWasmSections[wsiImport],$00); { func }
  4627. WriteUleb(FWasmSections[wsiImport],TypeIdx);
  4628. if assigned(exemap) then
  4629. exemap.Add(' Function['+tostr(i)+'] sig='+tostr(TypeIdx)+' <- '+ModName+'.'+Name);
  4630. end;
  4631. end;
  4632. procedure WriteCodeSegments;
  4633. var
  4634. i: Integer;
  4635. exesec: TExeSection;
  4636. objsec: TWasmObjSection;
  4637. begin
  4638. exesec:=FindExeSection('.text');
  4639. if not assigned(exesec) then
  4640. internalerror(2023123102);
  4641. if not (oso_Data in exesec.SecOptions) then
  4642. internalerror(2023123103);
  4643. WriteUleb(FWasmSections[wsiFunction],exesec.ObjSectionList.Count);
  4644. WriteUleb(FWasmSections[wsiCode],exesec.ObjSectionList.Count);
  4645. for i:=0 to exesec.ObjSectionList.Count-1 do
  4646. begin
  4647. objsec:=TWasmObjSection(exesec.ObjSectionList[i]);
  4648. if not (oso_data in objsec.secoptions) then
  4649. internalerror(2023123104);
  4650. if not assigned(objsec.data) then
  4651. internalerror(2023123105);
  4652. if objsec.MainFuncSymbol.LinkingData.ExeFunctionIndex<>(i+Length(FFunctionImports)) then
  4653. internalerror(2024010101);
  4654. WriteUleb(FWasmSections[wsiFunction],objsec.MainFuncSymbol.LinkingData.ExeTypeIndex);
  4655. WriteUleb(FWasmSections[wsiCode],objsec.Data.size);
  4656. objsec.Data.seek(0);
  4657. CopyDynamicArray(objsec.Data,FWasmSections[wsiCode],objsec.Data.size);
  4658. end;
  4659. end;
  4660. procedure WriteDataSegments;
  4661. procedure WriteExeSection(exesec: TExeSection);
  4662. var
  4663. i: Integer;
  4664. objsec: TObjSection;
  4665. exesecdatapos: LongWord;
  4666. dpos, pad: QWord;
  4667. begin
  4668. AddToDataNameMap(Length(FDataNameMap),exesec.Name);
  4669. if ts_wasm_threads in current_settings.targetswitches then
  4670. WriteByte(FWasmSections[wsiData],1) { mode passive }
  4671. else
  4672. begin
  4673. WriteByte(FWasmSections[wsiData],0); { mode active, memory 0, offset e }
  4674. WriteByte(FWasmSections[wsiData],$41); { i32.const }
  4675. WriteSleb(FWasmSections[wsiData],longint(exesec.MemPos));
  4676. WriteByte(FWasmSections[wsiData],$0B); { end }
  4677. end;
  4678. WriteUleb(FWasmSections[wsiData],exesec.Size);
  4679. exesecdatapos:=FWasmSections[wsiData].size;
  4680. for i:=0 to exesec.ObjSectionList.Count-1 do
  4681. begin
  4682. objsec:=TObjSection(exesec.ObjSectionList[i]);
  4683. if not (oso_data in objsec.secoptions) then
  4684. internalerror(2024010104);
  4685. if not assigned(objsec.data) then
  4686. internalerror(2024010105);
  4687. dpos:=objsec.MemPos-exesec.MemPos+exesecdatapos;
  4688. pad:=dpos-FWasmSections[wsiData].size;
  4689. { objsection must be within SecAlign bytes from the previous one }
  4690. if (dpos<FWasmSections[wsiData].Size) or
  4691. (pad>=max(objsec.SecAlign,1)) then
  4692. internalerror(2024010106);
  4693. writeZeros(FWasmSections[wsiData],pad);
  4694. objsec.data.seek(0);
  4695. CopyDynamicArray(objsec.data,FWasmSections[wsiData],objsec.data.size);
  4696. end;
  4697. if (FWasmSections[wsiData].size-exesecdatapos)<>exesec.Size then
  4698. internalerror(2024010107);
  4699. end;
  4700. var
  4701. DataCount: Integer;
  4702. DataSecName: string;
  4703. ExeSec: TExeSection;
  4704. begin
  4705. DataCount:=0;
  4706. for DataSecName in DataSections do
  4707. begin
  4708. ExeSec:=FindExeSection(DataSecName);
  4709. if Assigned(ExeSec) and (ExeSec.Size>0) then
  4710. Inc(DataCount);
  4711. end;
  4712. WriteUleb(FWasmSections[wsiDataCount],DataCount);
  4713. WriteUleb(FWasmSections[wsiData],DataCount);
  4714. for DataSecName in DataSections do
  4715. begin
  4716. ExeSec:=FindExeSection(DataSecName);
  4717. if Assigned(ExeSec) and (ExeSec.Size>0) then
  4718. WriteExeSection(ExeSec);
  4719. end;
  4720. end;
  4721. procedure WriteTableAndElemSections;
  4722. const
  4723. TableCount=1;
  4724. var
  4725. i: Integer;
  4726. begin
  4727. { Table section }
  4728. WriteUleb(FWasmSections[wsiTable],TableCount);
  4729. { table 0 }
  4730. { table type }
  4731. WriteByte(FWasmSections[wsiTable],encode_wasm_basic_type(wbt_funcref));
  4732. { table limits }
  4733. WriteByte(FWasmSections[wsiTable],$01); { has min & max }
  4734. WriteUleb(FWasmSections[wsiTable],Length(FIndirectFunctionTable)); { min }
  4735. WriteUleb(FWasmSections[wsiTable],Length(FIndirectFunctionTable)); { max }
  4736. { Elem section }
  4737. WriteUleb(FWasmSections[wsiElement],1); { 1 element segment }
  4738. { element segment 0 }
  4739. WriteByte(FWasmSections[wsiElement],0); { type funcref, init((ref.func y) end)*, mode active <table 0, offset e> }
  4740. { e:expr }
  4741. WriteByte(FWasmSections[wsiElement],$41); { i32.const }
  4742. WriteSleb(FWasmSections[wsiElement],1); { starting from 1 (table entry 0 is ref.null) }
  4743. WriteByte(FWasmSections[wsiElement],$0B); { end }
  4744. { y*:vec(funcidx) }
  4745. WriteUleb(FWasmSections[wsiElement],Length(FIndirectFunctionTable)-1);
  4746. for i:=1 to Length(FIndirectFunctionTable)-1 do
  4747. WriteUleb(FWasmSections[wsiElement],FIndirectFunctionTable[i].FuncIdx);
  4748. end;
  4749. procedure WriteGlobalSection;
  4750. var
  4751. exesec: TExeSection;
  4752. globals_count, i: Integer;
  4753. objsec: TWasmObjSection;
  4754. mapstr: string='';
  4755. begin
  4756. if assigned(exemap) then
  4757. exemap.AddHeader('Global section');
  4758. exesec:=FindExeSection('.wasm_globals');
  4759. if not assigned(exesec) then
  4760. internalerror(2024010112);
  4761. globals_count:=exesec.ObjSectionList.Count;
  4762. if globals_count<>exesec.Size then
  4763. internalerror(2024010113);
  4764. WriteUleb(FWasmSections[wsiGlobal],globals_count);
  4765. for i:=0 to exesec.ObjSectionList.Count-1 do
  4766. begin
  4767. objsec:=TWasmObjSection(exesec.ObjSectionList[i]);
  4768. WriteByte(FWasmSections[wsiGlobal],encode_wasm_basic_type(objsec.MainFuncSymbol.LinkingData.GlobalType));
  4769. if objsec.MainFuncSymbol.LinkingData.GlobalIsMutable then
  4770. WriteByte(FWasmSections[wsiGlobal],1)
  4771. else
  4772. WriteByte(FWasmSections[wsiGlobal],0);
  4773. if assigned(exemap) then
  4774. WriteStr(mapstr,' Global[',i,'] ',wasm_basic_type_str[objsec.MainFuncSymbol.LinkingData.GlobalType],' mutable=',objsec.MainFuncSymbol.LinkingData.GlobalIsMutable,' <',objsec.MainFuncSymbol.Name,'> - init ');
  4775. { initializer expr }
  4776. with objsec.MainFuncSymbol.LinkingData.GlobalInitializer do
  4777. case typ of
  4778. wbt_i32:
  4779. begin
  4780. WriteByte(FWasmSections[wsiGlobal],$41); { i32.const }
  4781. WriteSleb(FWasmSections[wsiGlobal],init_i32);
  4782. if assigned(exemap) then
  4783. mapstr:=mapstr+'i32='+tostr(init_i32);
  4784. end;
  4785. wbt_i64:
  4786. begin
  4787. WriteByte(FWasmSections[wsiGlobal],$42); { i64.const }
  4788. WriteSleb(FWasmSections[wsiGlobal],init_i64);
  4789. if assigned(exemap) then
  4790. mapstr:=mapstr+'i64='+tostr(init_i64);
  4791. end;
  4792. wbt_f32:
  4793. begin
  4794. WriteByte(FWasmSections[wsiGlobal],$43); { f32.const }
  4795. WriteF32LE(FWasmSections[wsiGlobal],init_f32);
  4796. if assigned(exemap) then
  4797. WriteStr(mapstr,mapstr+'f32=',init_f32);
  4798. end;
  4799. wbt_f64:
  4800. begin
  4801. WriteByte(FWasmSections[wsiGlobal],$44); { f64.const }
  4802. WriteF64LE(FWasmSections[wsiGlobal],init_f64);
  4803. if assigned(exemap) then
  4804. WriteStr(mapstr,mapstr+'f64=',init_f64);
  4805. end;
  4806. wbt_funcref,
  4807. wbt_externref:
  4808. begin
  4809. WriteByte(FWasmSections[wsiGlobal],$D0); { ref.null }
  4810. WriteByte(FWasmSections[wsiGlobal],encode_wasm_basic_type(typ));
  4811. if assigned(exemap) then
  4812. mapstr:=mapstr+'ref.null '+wasm_basic_type_str[typ];
  4813. end;
  4814. else
  4815. internalerror(2024010114);
  4816. end;
  4817. WriteByte(FWasmSections[wsiGlobal],$0B); { end }
  4818. { add entry for the name section }
  4819. AddToGlobalNameMap(i,objsec.MainFuncSymbol.Name);
  4820. if assigned(exemap) then
  4821. exemap.Add(mapstr);
  4822. end;
  4823. end;
  4824. procedure WriteTagSection;
  4825. var
  4826. exesec: TExeSection;
  4827. tags_count, i: Integer;
  4828. objsec: TWasmObjSection;
  4829. begin
  4830. exesec:=FindExeSection('.wasm_tags');
  4831. if not assigned(exesec) then
  4832. exit;
  4833. tags_count:=exesec.ObjSectionList.Count;
  4834. if tags_count<>exesec.Size then
  4835. internalerror(2024010702);
  4836. if tags_count=0 then
  4837. exit;
  4838. WriteUleb(FWasmSections[wsiTag],tags_count);
  4839. for i:=0 to exesec.ObjSectionList.Count-1 do
  4840. begin
  4841. objsec:=TWasmObjSection(exesec.ObjSectionList[i]);
  4842. WriteByte(FWasmSections[wsiTag],0);
  4843. WriteUleb(FWasmSections[wsiTag],objsec.MainFuncSymbol.LinkingData.ExeTypeIndex);
  4844. AddToTagNameMap(i,objsec.MainFuncSymbol.Name);
  4845. end;
  4846. end;
  4847. procedure WriteExportSection;
  4848. const
  4849. MemoryExportsCount=1;
  4850. var
  4851. FunctionExportsCount: Integer;
  4852. ExportsCount: Integer;
  4853. textsec: TExeSection;
  4854. i: Integer;
  4855. objsec: TWasmObjSection;
  4856. begin
  4857. if assigned(exemap) then
  4858. exemap.AddHeader('Export section');
  4859. FunctionExportsCount:=0;
  4860. textsec:=FindExeSection('.text');
  4861. if not assigned(textsec) then
  4862. internalerror(2024010115);
  4863. for i:=0 to textsec.ObjSectionList.Count-1 do
  4864. begin
  4865. objsec:=TWasmObjSection(textsec.ObjSectionList[i]);
  4866. if objsec.MainFuncSymbol.LinkingData.IsExported then
  4867. Inc(FunctionExportsCount)
  4868. end;
  4869. ExportsCount:=MemoryExportsCount+FunctionExportsCount;
  4870. WriteUleb(FWasmSections[wsiExport],ExportsCount);
  4871. { export 0 }
  4872. WriteName(FWasmSections[wsiExport],'memory');
  4873. WriteByte(FWasmSections[wsiExport],$02); { mem }
  4874. WriteUleb(FWasmSections[wsiExport],0); { memidx = 0 }
  4875. if assigned(exemap) then
  4876. exemap.Add(' Memory[0] -> "memory"');
  4877. for i:=0 to textsec.ObjSectionList.Count-1 do
  4878. begin
  4879. objsec:=TWasmObjSection(textsec.ObjSectionList[i]);
  4880. if objsec.MainFuncSymbol.LinkingData.IsExported then
  4881. begin
  4882. WriteName(FWasmSections[wsiExport],objsec.MainFuncSymbol.LinkingData.ExportName);
  4883. WriteByte(FWasmSections[wsiExport],$00); { func }
  4884. WriteUleb(FWasmSections[wsiExport],objsec.MainFuncSymbol.LinkingData.ExeFunctionIndex); { funcidx }
  4885. if assigned(exemap) then
  4886. exemap.Add(' Function['+tostr(objsec.MainFuncSymbol.LinkingData.ExeFunctionIndex)+'] -> "'+objsec.MainFuncSymbol.LinkingData.ExportName+'"');
  4887. end;
  4888. end;
  4889. end;
  4890. procedure MaybeWriteDebugSection(st: TWasmCustomDebugSectionType);
  4891. var
  4892. exesec: TExeSection;
  4893. begin
  4894. exesec:=FindExeSection(WasmCustomSectionName[st]);
  4895. if assigned(exesec) then
  4896. begin
  4897. WriteExeSectionToDynArray(exesec,FWasmCustomSections[st]);
  4898. WriteWasmCustomSection(st);
  4899. end;
  4900. end;
  4901. procedure WriteNameMap(const nm: TCustomSectionNameMap; dest: tdynamicarray);
  4902. var
  4903. i: Integer;
  4904. begin
  4905. WriteUleb(dest,Length(nm));
  4906. for i:=low(nm) to high(nm) do
  4907. with nm[i] do
  4908. begin
  4909. WriteUleb(dest,idx);
  4910. WriteName(dest,name);
  4911. end;
  4912. end;
  4913. procedure WriteNameSubsection(wnst: TWasmNameSubsectionType);
  4914. begin
  4915. if FWasmNameSubsections[wnst].size>0 then
  4916. begin
  4917. WriteByte(FWasmCustomSections[wcstName],Ord(wnst));
  4918. WriteUleb(FWasmCustomSections[wcstName],FWasmNameSubsections[wnst].size);
  4919. FWasmNameSubsections[wnst].seek(0);
  4920. CopyDynamicArray(FWasmNameSubsections[wnst],FWasmCustomSections[wcstName],FWasmNameSubsections[wnst].size);
  4921. end;
  4922. end;
  4923. procedure WriteNameSection;
  4924. begin
  4925. WriteName(FWasmNameSubsections[wnstModuleName],current_module.exefilename);
  4926. WriteNameSubsection(wnstModuleName);
  4927. WriteNameMap(FFunctionNameMap,FWasmNameSubsections[wnstFunctionNames]);
  4928. WriteNameSubsection(wnstFunctionNames);
  4929. WriteNameMap(FGlobalNameMap,FWasmNameSubsections[wnstGlobalNames]);
  4930. WriteNameSubsection(wnstGlobalNames);
  4931. WriteNameMap(FDataNameMap,FWasmNameSubsections[wnstDataNames]);
  4932. WriteNameSubsection(wnstDataNames);
  4933. if Length(FTagNameMap)>0 then
  4934. begin
  4935. WriteNameMap(FTagNameMap,FWasmNameSubsections[wnstTagNames]);
  4936. WriteNameSubsection(wnstTagNames);
  4937. end;
  4938. end;
  4939. procedure WriteMemorySection;
  4940. var
  4941. i: Integer;
  4942. begin
  4943. if assigned(exemap) then
  4944. exemap.AddHeader('Memory section');
  4945. WriteUleb(FWasmSections[wsiMemory],Length(FMemories));
  4946. for i:=low(FMemories) to high(FMemories) do
  4947. begin
  4948. WriteMemoryTo(FWasmSections[wsiMemory],FMemories[i]);
  4949. if assigned(exemap) then
  4950. exemap.Add(' Memory['+tostr(i+Length(FImportedMemories))+'] '+Memory2String(FMemories[i]));
  4951. end;
  4952. end;
  4953. var
  4954. cust_sec: TWasmCustomSectionType;
  4955. begin
  4956. result:=false;
  4957. FMaxMemoryPages:=align(maxheapsize,WasmPageSize) div WasmPageSize;
  4958. { each custom sections starts with its name }
  4959. for cust_sec in TWasmCustomSectionType do
  4960. WriteName(FWasmCustomSections[cust_sec],WasmCustomSectionName[cust_sec]);
  4961. SetStackPointer;
  4962. SetTlsSizeAlignAndBase;
  4963. SetThreadVarGlobalsInitValues;
  4964. GenerateCode_InitTls;
  4965. GenerateCode_InitSharedMemory;
  4966. if ts_wasm_threads in current_settings.targetswitches then
  4967. begin
  4968. SetLength(FImportedMemories,1);
  4969. with FImportedMemories[0] do
  4970. begin
  4971. ModName:='env';
  4972. Name:='memory';
  4973. with MemType do
  4974. begin
  4975. Flags:=[wmfShared,wmfHasMaximumBound];
  4976. MinPages:=FMinMemoryPages;
  4977. MaxPages:=Max(FMinMemoryPages,FMaxMemoryPages);
  4978. end;
  4979. end;
  4980. end
  4981. else
  4982. begin
  4983. SetLength(FMemories,1);
  4984. with FMemories[0] do
  4985. begin
  4986. Flags:=[];
  4987. MinPages:=FMinMemoryPages;
  4988. if FMaxMemoryPages>=FMinMemoryPages then
  4989. begin
  4990. Include(Flags,wmfHasMaximumBound);
  4991. MaxPages:=FMaxMemoryPages;
  4992. end;
  4993. end;
  4994. end;
  4995. FFuncTypes.WriteTo(FWasmSections[wsiType]);
  4996. WriteImportSection;
  4997. WriteCodeSegments;
  4998. WriteDataSegments;
  4999. WriteTableAndElemSections;
  5000. WriteGlobalSection;
  5001. WriteTagSection;
  5002. if Length(FMemories)>0 then
  5003. WriteMemorySection;
  5004. WriteExportSection;
  5005. if ts_wasm_threads in current_settings.targetswitches then
  5006. WriteUleb(FWasmSections[wsiStart],FInitSharedMemoryFunctionSym.LinkingData.ExeFunctionIndex);
  5007. WriteNameSection;
  5008. Writer.write(WasmModuleMagic,SizeOf(WasmModuleMagic));
  5009. Writer.write(WasmVersion,SizeOf(WasmVersion));
  5010. WriteWasmSection(wsiType);
  5011. WriteWasmSection(wsiImport);
  5012. WriteWasmSection(wsiFunction);
  5013. WriteWasmSection(wsiTable);
  5014. if not (ts_wasm_threads in current_settings.targetswitches) then
  5015. WriteWasmSection(wsiMemory);
  5016. WriteWasmSectionIfNotEmpty(wsiTag);
  5017. WriteWasmSection(wsiGlobal);
  5018. WriteWasmSection(wsiExport);
  5019. if ts_wasm_threads in current_settings.targetswitches then
  5020. WriteWasmSection(wsiStart);
  5021. WriteWasmSection(wsiElement);
  5022. WriteWasmSection(wsiDataCount);
  5023. WriteWasmSection(wsiCode);
  5024. WriteWasmSection(wsiData);
  5025. MaybeWriteDebugSection(wcstDebugAbbrev);
  5026. MaybeWriteDebugSection(wcstDebugInfo);
  5027. MaybeWriteDebugSection(wcstDebugStr);
  5028. MaybeWriteDebugSection(wcstDebugLine);
  5029. MaybeWriteDebugSection(wcstDebugFrame);
  5030. MaybeWriteDebugSection(wcstDebugAranges);
  5031. MaybeWriteDebugSection(wcstDebugRanges);
  5032. WriteWasmCustomSection(wcstName);
  5033. result := true;
  5034. end;
  5035. procedure TWasmExeOutput.DoRelocationFixup(objsec: TObjSection);
  5036. procedure writeUInt32LE(v: uint32);
  5037. begin
  5038. {$ifdef FPC_BIG_ENDIAN}
  5039. v:=SwapEndian(v);
  5040. {$endif FPC_BIG_ENDIAN}
  5041. objsec.data.write(v,4);
  5042. end;
  5043. var
  5044. i: Integer;
  5045. objreloc: TWasmObjRelocation;
  5046. objsym: TWasmObjSymbol;
  5047. begin
  5048. for i:=0 to objsec.ObjRelocations.Count-1 do
  5049. begin
  5050. objreloc:=TWasmObjRelocation(objsec.ObjRelocations[i]);
  5051. if assigned(objreloc.symbol) then
  5052. begin
  5053. objsym:=TWasmObjSymbol(objreloc.symbol);
  5054. case objreloc.typ of
  5055. RELOC_FUNCTION_INDEX_LEB:
  5056. begin
  5057. if objsym.LinkingData.ExeFunctionIndex=-1 then
  5058. internalerror(2024010103);
  5059. if FRelocationPass=2 then
  5060. begin
  5061. objsec.Data.seek(objreloc.DataOffset);
  5062. WriteUleb5(objsec.Data,objsym.LinkingData.ExeFunctionIndex);
  5063. end;
  5064. end;
  5065. RELOC_ABSOLUTE:
  5066. begin
  5067. case objsym.typ of
  5068. AT_FUNCTION:
  5069. begin
  5070. if objreloc.IsFunctionOffsetI32 then
  5071. begin
  5072. { R_WASM_FUNCTION_OFFSET_I32 }
  5073. if FRelocationPass=2 then
  5074. begin
  5075. objsec.Data.seek(objreloc.DataOffset);
  5076. writeUInt32LE(UInt32(objsym.objsection.MemPos+objreloc.Addend));
  5077. end;
  5078. end
  5079. else
  5080. begin
  5081. { R_WASM_TABLE_INDEX_I32 }
  5082. if objsym.LinkingData.ExeFunctionIndex=-1 then
  5083. internalerror(2024010103);
  5084. case FRelocationPass of
  5085. 1:
  5086. if objsym.LinkingData.ExeIndirectFunctionTableIndex=-1 then
  5087. objsym.LinkingData.ExeIndirectFunctionTableIndex:=AddOrGetIndirectFunctionTableIndex(objsym.LinkingData.ExeFunctionIndex);
  5088. 2:
  5089. begin
  5090. objsec.Data.seek(objreloc.DataOffset);
  5091. writeUInt32LE(UInt32(objsym.LinkingData.ExeIndirectFunctionTableIndex));
  5092. end;
  5093. end;
  5094. end;
  5095. end;
  5096. AT_DATA:
  5097. begin
  5098. if objreloc.IsFunctionOffsetI32 then
  5099. internalerror(2024010602);
  5100. if FRelocationPass=2 then
  5101. begin
  5102. objsec.Data.seek(objreloc.DataOffset);
  5103. writeUInt32LE(UInt32((objsym.offset+objsym.objsection.MemPos)+objreloc.Addend));
  5104. end;
  5105. end;
  5106. AT_TLS:
  5107. begin
  5108. if objreloc.IsFunctionOffsetI32 then
  5109. internalerror(2024010602);
  5110. if FRelocationPass=2 then
  5111. begin
  5112. objsec.Data.seek(objreloc.DataOffset);
  5113. writeUInt32LE(UInt32((objsym.offset+objsym.objsection.MemPos-objsym.objsection.ExeSection.MemPos)+objreloc.Addend));
  5114. end;
  5115. end;
  5116. AT_WASM_GLOBAL:
  5117. begin
  5118. if objreloc.IsFunctionOffsetI32 then
  5119. internalerror(2024010602);
  5120. if FRelocationPass=2 then
  5121. begin
  5122. objsec.Data.seek(objreloc.DataOffset);
  5123. writeUInt32LE(UInt32(objsym.offset+objsym.objsection.MemPos));
  5124. end;
  5125. end;
  5126. else
  5127. internalerror(2024010108);
  5128. end;
  5129. end;
  5130. RELOC_MEMORY_ADDR_LEB:
  5131. begin
  5132. if objsym.typ<>AT_DATA then
  5133. internalerror(2024010109);
  5134. if FRelocationPass=2 then
  5135. begin
  5136. objsec.Data.seek(objreloc.DataOffset);
  5137. WriteUleb5(objsec.Data,UInt32((objsym.offset+objsym.objsection.MemPos)+objreloc.Addend));
  5138. end;
  5139. end;
  5140. RELOC_MEMORY_ADDR_OR_TABLE_INDEX_SLEB:
  5141. begin
  5142. case objsym.typ of
  5143. AT_FUNCTION:
  5144. begin
  5145. if objsym.LinkingData.ExeFunctionIndex=-1 then
  5146. internalerror(2024010103);
  5147. case FRelocationPass of
  5148. 1:
  5149. if objsym.LinkingData.ExeIndirectFunctionTableIndex=-1 then
  5150. objsym.LinkingData.ExeIndirectFunctionTableIndex:=AddOrGetIndirectFunctionTableIndex(objsym.LinkingData.ExeFunctionIndex);
  5151. 2:
  5152. begin
  5153. objsec.Data.seek(objreloc.DataOffset);
  5154. WriteSleb5(objsec.Data,Int32(objsym.LinkingData.ExeIndirectFunctionTableIndex));
  5155. end;
  5156. end;
  5157. end;
  5158. AT_DATA:
  5159. begin
  5160. if FRelocationPass=2 then
  5161. begin
  5162. objsec.Data.seek(objreloc.DataOffset);
  5163. WriteSleb5(objsec.Data,Int32((objsym.offset+objsym.objsection.MemPos)+objreloc.Addend));
  5164. end;
  5165. end;
  5166. else
  5167. internalerror(2024010110);
  5168. end;
  5169. end;
  5170. RELOC_GLOBAL_INDEX_LEB:
  5171. if objsym.typ=AT_WASM_GLOBAL then
  5172. begin
  5173. if FRelocationPass=2 then
  5174. begin
  5175. objsec.Data.seek(objreloc.DataOffset);
  5176. WriteUleb5(objsec.Data,UInt32(objsym.offset+objsym.objsection.MemPos));
  5177. end;
  5178. end
  5179. else if (ts_wasm_threads in current_settings.targetswitches) and
  5180. (objsym.typ=AT_TLS) then
  5181. begin
  5182. { Nothing to do here. A second RELOC_GLOBAL_INDEX_LEB
  5183. relocation, overlaid on top of this one, pointing to
  5184. an AT_WASM_GLOBAL should have already done the job. }
  5185. end
  5186. else
  5187. internalerror(2024010111);
  5188. RELOC_TAG_INDEX_LEB:
  5189. begin
  5190. if objsym.typ<>AT_WASM_EXCEPTION_TAG then
  5191. internalerror(2024010708);
  5192. if FRelocationPass=2 then
  5193. begin
  5194. objsec.Data.seek(objreloc.DataOffset);
  5195. WriteUleb5(objsec.Data,UInt32(objsym.offset+objsym.objsection.MemPos));
  5196. end;
  5197. end;
  5198. else
  5199. internalerror(2024010109);
  5200. end;
  5201. end
  5202. else if assigned(objreloc.objsection) then
  5203. begin
  5204. if objreloc.typ<>RELOC_ABSOLUTE then
  5205. internalerror(2024010601);
  5206. if FRelocationPass=2 then
  5207. begin
  5208. objsec.Data.seek(objreloc.DataOffset);
  5209. writeUInt32LE(UInt32((objreloc.objsection.MemPos)+objreloc.Addend));
  5210. end;
  5211. end
  5212. else if objreloc.typ=RELOC_TYPE_INDEX_LEB then
  5213. begin
  5214. case FRelocationPass of
  5215. 1:
  5216. objreloc.ExeTypeIndex:=FFuncTypes.AddOrGetFuncType(objreloc.FuncType);
  5217. 2:
  5218. begin
  5219. objsec.Data.seek(objreloc.DataOffset);
  5220. WriteUleb5(objsec.Data,objreloc.ExeTypeIndex);
  5221. end;
  5222. end;
  5223. end
  5224. else
  5225. internalerror(2024010110);
  5226. end;
  5227. end;
  5228. constructor TWasmExeOutput.create;
  5229. var
  5230. i: TWasmSectionID;
  5231. j: TWasmCustomSectionType;
  5232. k: TWasmNameSubsectionType;
  5233. begin
  5234. inherited create;
  5235. CObjData:=TWasmObjData;
  5236. SectionMemAlign:=16;
  5237. MaxMemPos:=$FFFFFFFF;
  5238. FFuncTypes:=TWasmFuncTypeTable.Create;
  5239. for i in TWasmSectionID do
  5240. FWasmSections[i] := tdynamicarray.create(SectionDataMaxGrow);
  5241. for j in TWasmCustomSectionType do
  5242. FWasmCustomSections[j] := tdynamicarray.create(SectionDataMaxGrow);
  5243. for k:=low(FWasmNameSubsections) to high(FWasmNameSubsections) do
  5244. FWasmNameSubsections[k] := tdynamicarray.create(SectionDataMaxGrow);
  5245. SetLength(FIndirectFunctionTable,1);
  5246. FIndirectFunctionTable[0].FuncIdx:=-1;
  5247. end;
  5248. destructor TWasmExeOutput.destroy;
  5249. var
  5250. i: TWasmSectionID;
  5251. j: TWasmCustomSectionType;
  5252. k: TWasmNameSubsectionType;
  5253. begin
  5254. for i in TWasmSectionID do
  5255. FWasmSections[i].Free;
  5256. for j in TWasmCustomSectionType do
  5257. FWasmCustomSections[j].Free;
  5258. for k:=low(FWasmNameSubsections) to high(FWasmNameSubsections) do
  5259. FWasmNameSubsections[k].Free;
  5260. FFuncTypes.Free;
  5261. inherited destroy;
  5262. end;
  5263. procedure TWasmExeOutput.GenerateLibraryImports(ImportLibraryList: TFPHashObjectList);
  5264. var
  5265. i, j: Integer;
  5266. ImportLibrary: TImportLibrary;
  5267. ImportSymbol: TImportSymbol;
  5268. exesym: TExeSymbol;
  5269. begin
  5270. { Here map import symbols to exe symbols and create necessary sections.
  5271. Actual import generation is done after unused sections (and symbols) are removed. }
  5272. FImports:=ImportLibraryList;
  5273. for i:=0 to ImportLibraryList.Count-1 do
  5274. begin
  5275. ImportLibrary:=TImportLibrary(ImportLibraryList[i]);
  5276. for j:=0 to ImportLibrary.ImportSymbolList.Count-1 do
  5277. begin
  5278. ImportSymbol:=TImportSymbol(ImportLibrary.ImportSymbolList[j]);
  5279. exesym:=TExeSymbol(ExeSymbolList.Find(ImportSymbol.MangledName));
  5280. if assigned(exesym) and
  5281. (exesym.State<>symstate_defined) then
  5282. begin
  5283. ImportSymbol.CachedExeSymbol:=exesym;
  5284. exesym.State:=symstate_defined;
  5285. end;
  5286. end;
  5287. end;
  5288. PackUnresolvedExeSymbols('after module imports');
  5289. end;
  5290. procedure TWasmExeOutput.AfterUnusedSectionRemoval;
  5291. begin
  5292. PrepareImports;
  5293. PrepareFunctions;
  5294. PrepareTags;
  5295. if Assigned(exemap) then
  5296. WriteMap_TypeSection;
  5297. { we do an extra preliminary relocation pass, in order to prepare the
  5298. indices for the Type section and the Table section. This is required
  5299. by GenerateCode_InvokeHelper. }
  5300. FRelocationPass:=1;
  5301. FixupRelocations;
  5302. { in pass 2, we do the actual relocation fixups. No need to call
  5303. FixupRelocations here, since it'll be called in
  5304. TInternalLinker.RunLinkScript, after this method finishes. We only
  5305. set the FRelocationPass variable here, so DoRelocationFixup knows
  5306. which pass it is. }
  5307. FRelocationPass:=2;
  5308. { This needs to be done before pass 2 of the relocation fixups, because
  5309. it'll generate code, thus it'll move the offsets of the functions that
  5310. follow it in the Code section, and we want our DWARF debug info to
  5311. contain correct code offsets. }
  5312. GenerateCode_InvokeHelper;
  5313. if Assigned(exemap) then
  5314. WriteMap_IndirectFunctionTable;
  5315. end;
  5316. procedure TWasmExeOutput.MemPos_ExeSection(const aname: string);
  5317. const
  5318. DebugPrefix = '.debug_';
  5319. var
  5320. ExeSec: TExeSection;
  5321. i: Integer;
  5322. objsec: TObjSection;
  5323. firstdatasec: string;
  5324. begin
  5325. { WebAssembly is a Harvard architecture.
  5326. Data lives in a separate address space, so start addressing back from 0
  5327. (the LLVM leaves the first 1024 bytes in the data segment empty, so we
  5328. start at 1024). }
  5329. if ts_wasm_threads in current_settings.targetswitches then
  5330. firstdatasec:='.tbss'
  5331. else
  5332. firstdatasec:='.rodata';
  5333. if aname=firstdatasec then
  5334. begin
  5335. CurrMemPos:=1024;
  5336. inherited;
  5337. end
  5338. else if aname='.text' then
  5339. begin
  5340. CurrMemPos:=0;
  5341. ExeSec:=FindExeSection(aname);
  5342. if not assigned(ExeSec) then
  5343. exit;
  5344. exesec.MemPos:=CurrMemPos;
  5345. CurrMemPos:=CurrMemPos+UlebEncodingSize(exesec.ObjSectionList.Count);
  5346. { set position of object ObjSections }
  5347. for i:=0 to exesec.ObjSectionList.Count-1 do
  5348. begin
  5349. objsec:=TObjSection(exesec.ObjSectionList[i]);
  5350. CurrMemPos:=CurrMemPos+UlebEncodingSize(objsec.Size);
  5351. CurrMemPos:=objsec.setmempos(CurrMemPos);
  5352. end;
  5353. { calculate size of the section }
  5354. exesec.Size:=CurrMemPos-exesec.MemPos;
  5355. end
  5356. else if (aname='.wasm_globals') or (aname='.wasm_tags') or
  5357. (Copy(aname,1,Length(DebugPrefix))=DebugPrefix) then
  5358. begin
  5359. CurrMemPos:=0;
  5360. inherited;
  5361. end
  5362. else
  5363. inherited;
  5364. end;
  5365. procedure TWasmExeOutput.Load_Symbol(const aname: string);
  5366. begin
  5367. if aname=StackPointerSymStr then
  5368. begin
  5369. internalObjData.createsection('*'+aname,1,[oso_Data,oso_load]);
  5370. FStackPointerSym:=TWasmObjSymbol(internalObjData.SymbolDefine(aname,AB_GLOBAL,AT_WASM_GLOBAL));
  5371. FStackPointerSym.size:=1;
  5372. FStackPointerSym.ObjSection.WriteZeros(1);
  5373. TWasmObjSection(FStackPointerSym.ObjSection).MainFuncSymbol:=FStackPointerSym;
  5374. FStackPointerSym.LinkingData.GlobalType:=wbt_i32;
  5375. FStackPointerSym.LinkingData.GlobalIsMutable:=True;
  5376. FStackPointerSym.LinkingData.GlobalInitializer.typ:=wbt_i32;
  5377. FStackPointerSym.LinkingData.GlobalInitializer.init_i32:=0;
  5378. end
  5379. else if (ts_wasm_threads in current_settings.targetswitches) and (aname='__tls_base') then
  5380. begin
  5381. internalObjData.createsection('*'+aname,1,[oso_Data,oso_load]);
  5382. FTlsBaseSym:=TWasmObjSymbol(internalObjData.SymbolDefine(aname,AB_GLOBAL,AT_WASM_GLOBAL));
  5383. FTlsBaseSym.size:=1;
  5384. FTlsBaseSym.ObjSection.WriteZeros(1);
  5385. TWasmObjSection(FTlsBaseSym.ObjSection).MainFuncSymbol:=FTlsBaseSym;
  5386. FTlsBaseSym.LinkingData.GlobalType:=wbt_i32;
  5387. FTlsBaseSym.LinkingData.GlobalIsMutable:=True;
  5388. FTlsBaseSym.LinkingData.GlobalInitializer.typ:=wbt_i32;
  5389. FTlsBaseSym.LinkingData.GlobalInitializer.init_i32:=0;
  5390. end
  5391. else if (ts_wasm_threads in current_settings.targetswitches) and (aname='__tls_size') then
  5392. begin
  5393. internalObjData.createsection('*'+aname,1,[oso_Data,oso_load]);
  5394. FTlsSizeSym:=TWasmObjSymbol(internalObjData.SymbolDefine(aname,AB_GLOBAL,AT_WASM_GLOBAL));
  5395. FTlsSizeSym.size:=1;
  5396. FTlsSizeSym.ObjSection.WriteZeros(1);
  5397. TWasmObjSection(FTlsSizeSym.ObjSection).MainFuncSymbol:=FTlsSizeSym;
  5398. FTlsSizeSym.LinkingData.GlobalType:=wbt_i32;
  5399. FTlsSizeSym.LinkingData.GlobalIsMutable:=False;
  5400. FTlsSizeSym.LinkingData.GlobalInitializer.typ:=wbt_i32;
  5401. FTlsSizeSym.LinkingData.GlobalInitializer.init_i32:=0;
  5402. end
  5403. else if (ts_wasm_threads in current_settings.targetswitches) and (aname='__tls_align') then
  5404. begin
  5405. internalObjData.createsection('*'+aname,1,[oso_Data,oso_load]);
  5406. FTlsAlignSym:=TWasmObjSymbol(internalObjData.SymbolDefine(aname,AB_GLOBAL,AT_WASM_GLOBAL));
  5407. FTlsAlignSym.size:=1;
  5408. FTlsAlignSym.ObjSection.WriteZeros(1);
  5409. TWasmObjSection(FTlsAlignSym.ObjSection).MainFuncSymbol:=FTlsAlignSym;
  5410. FTlsAlignSym.LinkingData.GlobalType:=wbt_i32;
  5411. FTlsAlignSym.LinkingData.GlobalIsMutable:=False;
  5412. FTlsAlignSym.LinkingData.GlobalInitializer.typ:=wbt_i32;
  5413. FTlsAlignSym.LinkingData.GlobalInitializer.init_i32:=0;
  5414. end
  5415. else if (ts_wasm_threads in current_settings.targetswitches) and (aname='__wasm_init_tls') then
  5416. begin
  5417. internalObjData.createsection('*'+aname,0,[]);
  5418. FInitTlsFunctionSym:=TWasmObjSymbol(internalObjData.SymbolDefine(aname,AB_GLOBAL,AT_FUNCTION));
  5419. TWasmObjSection(FInitTlsFunctionSym.ObjSection).MainFuncSymbol:=FInitTlsFunctionSym;
  5420. FInitTlsFunctionSym.LinkingData.FuncType:=TWasmFuncType.Create([wbt_i32],[]);
  5421. end
  5422. else if (ts_wasm_threads in current_settings.targetswitches) and (aname='__fpc_wasm_init_shared_memory') then
  5423. begin
  5424. internalObjData.createsection('*'+aname,0,[]);
  5425. FInitSharedMemoryFunctionSym:=TWasmObjSymbol(internalObjData.SymbolDefine(aname,AB_GLOBAL,AT_FUNCTION));
  5426. TWasmObjSection(FInitSharedMemoryFunctionSym.ObjSection).MainFuncSymbol:=FInitSharedMemoryFunctionSym;
  5427. FInitSharedMemoryFunctionSym.ObjSection.SecOptions:=FInitSharedMemoryFunctionSym.ObjSection.SecOptions+[oso_keep];
  5428. FInitSharedMemoryFunctionSym.LinkingData.FuncType:=TWasmFuncType.Create([],[]);
  5429. end
  5430. else
  5431. inherited;
  5432. end;
  5433. procedure TWasmExeOutput.PrepareImports;
  5434. function AddFunctionImport(const libname,symname:TCmdStr; functype: TWasmFuncType): Integer;
  5435. begin
  5436. SetLength(FFunctionImports,Length(FFunctionImports)+1);
  5437. Result:=High(FFunctionImports);
  5438. if assigned(exemap) then
  5439. exemap.Add(' Importing Function[' + tostr(Result) + '] ' + symname + functype.ToString);
  5440. with FFunctionImports[Result] do
  5441. begin
  5442. ModName:=libname;
  5443. Name:=symname;
  5444. TypeIdx:=FFuncTypes.AddOrGetFuncType(functype);
  5445. end;
  5446. end;
  5447. var
  5448. i, j: Integer;
  5449. ImportLibrary: TImportLibrary;
  5450. ImportSymbol: TImportSymbol;
  5451. exesym: TExeSymbol;
  5452. newdll: Boolean;
  5453. fsym: TWasmObjSymbol;
  5454. objdata: TObjData;
  5455. begin
  5456. for i:=0 to FImports.Count-1 do
  5457. begin
  5458. ImportLibrary:=TImportLibrary(FImports[i]);
  5459. newdll:=False;
  5460. for j:=0 to ImportLibrary.ImportSymbolList.Count-1 do
  5461. begin
  5462. ImportSymbol:=TImportSymbol(ImportLibrary.ImportSymbolList[j]);
  5463. exesym:=ImportSymbol.CachedExeSymbol;
  5464. if assigned(exesym) and
  5465. exesym.Used then
  5466. begin
  5467. if (not newdll) and assigned(exemap) then
  5468. begin
  5469. exemap.Add('');
  5470. exemap.Add('Importing from module '+ImportLibrary.Name);
  5471. end;
  5472. newdll:=True;
  5473. TWasmObjSymbol(exesym.ObjSymbol).LinkingData.ExeFunctionIndex:=
  5474. AddFunctionImport(ImportLibrary.Name,ImportSymbol.Name,TWasmObjSymbol(exesym.ObjSymbol).LinkingData.FuncType);
  5475. AddToFunctionNameMap(TWasmObjSymbol(exesym.ObjSymbol).LinkingData.ExeFunctionIndex,ImportSymbol.MangledName);
  5476. end;
  5477. end;
  5478. end;
  5479. { set ExeFunctionIndex to the alias symbols as well }
  5480. for i:=0 to ObjDataList.Count-1 do
  5481. begin
  5482. objdata:=TObjData(ObjDataList[i]);
  5483. for j:=0 to objdata.ObjSymbolList.Count-1 do
  5484. begin
  5485. fsym:=TWasmObjSymbol(objdata.ObjSymbolList[j]);
  5486. if (fsym.LinkingData.ExeFunctionIndex=-1) and assigned(fsym.exesymbol) and (TWasmObjSymbol(fsym.exesymbol.ObjSymbol).LinkingData.ExeFunctionIndex<>-1) then
  5487. fsym.LinkingData.ExeFunctionIndex:=TWasmObjSymbol(fsym.exesymbol.ObjSymbol).LinkingData.ExeFunctionIndex;
  5488. end;
  5489. end;
  5490. end;
  5491. procedure TWasmExeOutput.PrepareFunctions;
  5492. var
  5493. i, j: Integer;
  5494. exesec: TExeSection;
  5495. objsec: TWasmObjSection;
  5496. fsym: TWasmObjSymbol;
  5497. objdata: TObjData;
  5498. begin
  5499. if assigned(exemap) then
  5500. begin
  5501. exemap.Add('');
  5502. exemap.Add('Functions, defined in this module:');
  5503. end;
  5504. exesec:=FindExeSection('.text');
  5505. if not assigned(exesec) then
  5506. internalerror(2023123106);
  5507. for i:=0 to exesec.ObjSectionList.Count-1 do
  5508. begin
  5509. objsec:=TWasmObjSection(exesec.ObjSectionList[i]);
  5510. fsym:=objsec.MainFuncSymbol;
  5511. if not assigned(fsym) then
  5512. internalerror(2023123107);
  5513. if not assigned(fsym.LinkingData.FuncType) then
  5514. internalerror(2023123108);
  5515. if fsym.LinkingData.ExeFunctionIndex<>-1 then
  5516. internalerror(2023123109);
  5517. if fsym.LinkingData.ExeTypeIndex<>-1 then
  5518. internalerror(2023123109);
  5519. fsym.LinkingData.ExeTypeIndex:=FFuncTypes.AddOrGetFuncType(fsym.LinkingData.FuncType);
  5520. fsym.LinkingData.ExeFunctionIndex:=i+Length(FFunctionImports);
  5521. if assigned(exemap) then
  5522. begin
  5523. exemap.Add(' Function[' + tostr(fsym.LinkingData.ExeFunctionIndex) + '] ' + fsym.Name + fsym.LinkingData.FuncType.ToString);
  5524. end;
  5525. AddToFunctionNameMap(fsym.LinkingData.ExeFunctionIndex,fsym.Name);
  5526. end;
  5527. { set ExeFunctionIndex to the alias symbols as well }
  5528. for i:=0 to ObjDataList.Count-1 do
  5529. begin
  5530. objdata:=TObjData(ObjDataList[i]);
  5531. for j:=0 to objdata.ObjSymbolList.Count-1 do
  5532. begin
  5533. fsym:=TWasmObjSymbol(objdata.ObjSymbolList[j]);
  5534. if assigned(fsym.objsection) and fsym.objsection.USed and (fsym.typ=AT_FUNCTION) and (fsym.LinkingData.ExeFunctionIndex=-1) then
  5535. begin
  5536. fsym.LinkingData.ExeFunctionIndex:=TWasmObjSection(fsym.objsection).MainFuncSymbol.LinkingData.ExeFunctionIndex;
  5537. if fsym.LinkingData.ExeFunctionIndex=-1 then
  5538. internalerror(2024010102);
  5539. end;
  5540. end;
  5541. end;
  5542. end;
  5543. procedure TWasmExeOutput.PrepareTags;
  5544. var
  5545. exesec: TExeSection;
  5546. i, j: Integer;
  5547. objsec: TWasmObjSection;
  5548. fsym: TWasmObjSymbol;
  5549. objdata: TObjData;
  5550. begin
  5551. exesec:=FindExeSection('.wasm_tags');
  5552. if not assigned(exesec) then
  5553. exit;
  5554. if assigned(exemap) then
  5555. begin
  5556. exemap.Add('');
  5557. exemap.Add('Tags, defined in this module:');
  5558. end;
  5559. for i:=0 to exesec.ObjSectionList.Count-1 do
  5560. begin
  5561. objsec:=TWasmObjSection(exesec.ObjSectionList[i]);
  5562. fsym:=objsec.MainFuncSymbol;
  5563. if not assigned(fsym) then
  5564. internalerror(2024010703);
  5565. if not assigned(fsym.LinkingData.FuncType) then
  5566. internalerror(2024010704);
  5567. if fsym.LinkingData.ExeTagIndex<>-1 then
  5568. internalerror(2024010705);
  5569. if fsym.LinkingData.ExeTypeIndex<>-1 then
  5570. internalerror(2024010706);
  5571. fsym.LinkingData.ExeTypeIndex:=FFuncTypes.AddOrGetFuncType(fsym.LinkingData.FuncType);
  5572. fsym.LinkingData.ExeTagIndex:=i+Length(FTagImports);
  5573. if assigned(exemap) then
  5574. begin
  5575. exemap.Add(' Tag[' + tostr(fsym.LinkingData.ExeTagIndex) + '] ' + fsym.Name + fsym.LinkingData.FuncType.ToString);
  5576. end;
  5577. end;
  5578. { set ExeTagIndex to the alias symbols as well }
  5579. for i:=0 to ObjDataList.Count-1 do
  5580. begin
  5581. objdata:=TObjData(ObjDataList[i]);
  5582. for j:=0 to objdata.ObjSymbolList.Count-1 do
  5583. begin
  5584. fsym:=TWasmObjSymbol(objdata.ObjSymbolList[j]);
  5585. if assigned(fsym.objsection) and fsym.objsection.USed and (fsym.typ=AT_WASM_EXCEPTION_TAG) and (fsym.LinkingData.ExeTagIndex=-1) then
  5586. begin
  5587. fsym.LinkingData.ExeTagIndex:=TWasmObjSection(fsym.objsection).MainFuncSymbol.LinkingData.ExeTagIndex;
  5588. if fsym.LinkingData.ExeTagIndex=-1 then
  5589. internalerror(2024010707);
  5590. end;
  5591. end;
  5592. end;
  5593. end;
  5594. function TWasmExeOutput.AddOrGetIndirectFunctionTableIndex(FuncIdx: Integer): integer;
  5595. var
  5596. i: Integer;
  5597. begin
  5598. for i:=1 to length(FIndirectFunctionTable)-1 do
  5599. if FIndirectFunctionTable[i].FuncIdx=FuncIdx then
  5600. begin
  5601. Result:=i;
  5602. exit;
  5603. end;
  5604. SetLength(FIndirectFunctionTable,Length(FIndirectFunctionTable)+1);
  5605. Result:=High(FIndirectFunctionTable);
  5606. FIndirectFunctionTable[Result].FuncIdx:=FuncIdx;
  5607. end;
  5608. procedure TWasmExeOutput.SetStackPointer;
  5609. var
  5610. BssSec: TExeSection;
  5611. StackStart, InitialStackPtrAddr: QWord;
  5612. begin
  5613. BssSec:=FindExeSection('.bss');
  5614. InitialStackPtrAddr := (BssSec.MemPos+BssSec.Size+stacksize+15) and (not 15);
  5615. FMinMemoryPages := Max(
  5616. QWord(Align(QWord(InitialStackPtrAddr),QWord(WasmPageSize)) div WasmPageSize),
  5617. QWord(Align(QWord(heapsize),QWord(WasmPageSize)) div WasmPageSize));
  5618. FStackPointerSym.LinkingData.GlobalInitializer.init_i32:=Int32(InitialStackPtrAddr);
  5619. end;
  5620. procedure TWasmExeOutput.SetTlsSizeAlignAndBase;
  5621. var
  5622. TBssSec: TExeSection;
  5623. begin
  5624. if not (ts_wasm_threads in current_settings.targetswitches) then
  5625. exit;
  5626. TBssSec:=FindExeSection('.tbss');
  5627. FTlsSizeSym.LinkingData.GlobalInitializer.init_i32:=Int32(TBssSec.Size);
  5628. FTlsAlignSym.LinkingData.GlobalInitializer.init_i32:=Int32(TBssSec.SecAlign);
  5629. FTlsBaseSym.LinkingData.GlobalInitializer.init_i32:=Int32(TBssSec.MemPos);
  5630. end;
  5631. procedure TWasmExeOutput.SetThreadVarGlobalsInitValues;
  5632. var
  5633. exesec: TExeSection;
  5634. i: Integer;
  5635. objsec: TWasmObjSection;
  5636. objsym: TWasmObjSymbol;
  5637. begin
  5638. if not (ts_wasm_threads in current_settings.targetswitches) then
  5639. exit;
  5640. exesec:=FindExeSection('.wasm_globals');
  5641. if not assigned(exesec) then
  5642. internalerror(2024010112);
  5643. for i:=0 to exesec.ObjSectionList.Count-1 do
  5644. begin
  5645. objsec:=TWasmObjSection(exesec.ObjSectionList[i]);
  5646. objsym:=objsec.MainFuncSymbol;
  5647. if Assigned(objsym.TlsDataSym) then
  5648. begin
  5649. objsym.LinkingData.GlobalInitializer.typ:=wbt_i32;
  5650. objsym.LinkingData.GlobalInitializer.init_i32:=objsym.TlsDataSym.offset+objsym.TlsDataSym.objsection.MemPos;
  5651. end;
  5652. end;
  5653. end;
  5654. procedure TWasmExeOutput.GenerateCode_InitTls;
  5655. var
  5656. Sec: TObjSection;
  5657. globalexesec: TExeSection;
  5658. i: Integer;
  5659. globalobjsec: TWasmObjSection;
  5660. globalobjsym: TWasmObjSymbol;
  5661. OffsetInTls: QWord;
  5662. begin
  5663. if not (ts_wasm_threads in current_settings.targetswitches) then
  5664. exit;
  5665. globalexesec:=FindExeSection('.wasm_globals');
  5666. if not assigned(globalexesec) then
  5667. internalerror(2024010112);
  5668. Sec:=FInitTlsFunctionSym.objsection;
  5669. Sec.SecOptions:=Sec.SecOptions+[oso_Data];
  5670. { locals }
  5671. Sec.writeUInt8($00);
  5672. { local.get 0 }
  5673. Sec.writeUInt16BE($2000);
  5674. { global.set $__tls_base }
  5675. Sec.writeUInt8($24);
  5676. WriteUleb(sec,FTlsBaseSym.offset+FTlsBaseSym.objsection.MemPos);
  5677. for i:=0 to globalexesec.ObjSectionList.Count-1 do
  5678. begin
  5679. globalobjsec:=TWasmObjSection(globalexesec.ObjSectionList[i]);
  5680. globalobjsym:=globalobjsec.MainFuncSymbol;
  5681. if Assigned(globalobjsym.TlsDataSym) then
  5682. begin
  5683. OffsetInTls:=globalobjsym.TlsDataSym.offset+globalobjsym.TlsDataSym.objsection.MemPos-globalobjsym.TlsDataSym.objsection.ExeSection.MemPos;
  5684. { local.get 0 }
  5685. Sec.writeUInt16BE($2000);
  5686. if OffsetInTls<>0 then
  5687. begin
  5688. { i32.const $OffsetInTls }
  5689. Sec.writeUInt8($41);
  5690. WriteSleb(Sec,Int32(OffsetInTls));
  5691. { i32.add }
  5692. Sec.writeUInt8($6A);
  5693. end;
  5694. { global.set y }
  5695. Sec.writeUInt8($24);
  5696. WriteUleb(sec,globalobjsym.offset+globalobjsym.objsection.MemPos);
  5697. end;
  5698. end;
  5699. Sec.writeUInt8($0B); { end }
  5700. end;
  5701. procedure TWasmExeOutput.GenerateCode_InitSharedMemory;
  5702. const
  5703. InitFlagOfs=256;
  5704. var
  5705. Sec: TObjSection;
  5706. DataSecName: string;
  5707. DataSecIdx: Integer;
  5708. ExeSec: TExeSection;
  5709. begin
  5710. if not (ts_wasm_threads in current_settings.targetswitches) then
  5711. exit;
  5712. Sec:=FInitSharedMemoryFunctionSym.objsection;
  5713. Sec.SecOptions:=Sec.SecOptions+[oso_Data];
  5714. { locals }
  5715. Sec.writeUInt8($00);
  5716. { block }
  5717. Sec.writeUInt16BE($0240);
  5718. { block }
  5719. Sec.writeUInt16BE($0240);
  5720. { block }
  5721. Sec.writeUInt16BE($0240);
  5722. { i32.const $InitFlag }
  5723. Sec.writeUInt8($41);
  5724. WriteSleb(sec,InitFlagOfs);
  5725. { i32.const 0 }
  5726. Sec.writeUInt16BE($4100);
  5727. { i32.const 1 }
  5728. Sec.writeUInt16BE($4101);
  5729. { i32.atomic.rmw.cmpxchg 2 0 }
  5730. Sec.writeUInt32BE($fe480200);
  5731. { br_table 0 1 2 }
  5732. Sec.writebytes(#$0e#$02#$00#$01#$02);
  5733. { end }
  5734. Sec.writeUInt8($0B);
  5735. DataSecIdx:=-1;
  5736. for DataSecName in DataSections do
  5737. begin
  5738. ExeSec:=FindExeSection(DataSecName);
  5739. if Assigned(ExeSec) and (ExeSec.Size>0) then
  5740. begin
  5741. Inc(DataSecIdx);
  5742. { i32.const $memPos }
  5743. Sec.writeUInt8($41);
  5744. WriteSleb(sec,Int32(ExeSec.MemPos));
  5745. { i32.const 0 }
  5746. Sec.writeUInt16BE($4100);
  5747. { i32.const size }
  5748. Sec.writeUInt8($41);
  5749. WriteSleb(sec,Int32(ExeSec.Size));
  5750. { memory.init $DataSecIdx 0 }
  5751. Sec.writeUInt16BE($fc08);
  5752. WriteUleb(sec,DataSecIdx);
  5753. Sec.writeUInt8(0);
  5754. end;
  5755. end;
  5756. { i32.const $InitFlag }
  5757. Sec.writeUInt8($41);
  5758. WriteSleb(sec,InitFlagOfs);
  5759. { i32.const 2 }
  5760. Sec.writeUInt16BE($4102);
  5761. { i32.atomic.store 2 0 }
  5762. Sec.writeUInt32BE($fe170200);
  5763. { i32.const $InitFlag }
  5764. Sec.writeUInt8($41);
  5765. WriteSleb(sec,InitFlagOfs);
  5766. { i32.const 4294967295 }
  5767. Sec.writeUInt16BE($417f);
  5768. { memory.atomic.notify 2 0 }
  5769. Sec.writeUInt32BE($fe000200);
  5770. { drop }
  5771. Sec.writeUInt8($1A);
  5772. { br 1 }
  5773. Sec.writeUInt16BE($0C01);
  5774. { end }
  5775. Sec.writeUInt8($0B);
  5776. { i32.const $InitFlag }
  5777. Sec.writeUInt8($41);
  5778. WriteSleb(sec,InitFlagOfs);
  5779. { i32.const 1 }
  5780. Sec.writeUInt16BE($4101);
  5781. { i64.const -1 }
  5782. Sec.writeUInt16BE($427f);
  5783. { memory.atomic.wait32 2 0 }
  5784. Sec.writeUInt32BE($fe010200);
  5785. { drop }
  5786. Sec.writeUInt8($1A);
  5787. { end }
  5788. Sec.writeUInt8($0B);
  5789. DataSecIdx:=-1;
  5790. for DataSecName in DataSections do
  5791. begin
  5792. ExeSec:=FindExeSection(DataSecName);
  5793. if Assigned(ExeSec) and (ExeSec.Size>0) then
  5794. begin
  5795. Inc(DataSecIdx);
  5796. { data.drop $DataSecIdx }
  5797. Sec.writeUInt16BE($fc09);
  5798. WriteUleb(sec,DataSecIdx);
  5799. end;
  5800. end;
  5801. { end }
  5802. Sec.writeUInt8($0B);
  5803. end;
  5804. procedure TWasmExeOutput.GenerateCode_InvokeHelper;
  5805. var
  5806. Sec: TObjSection;
  5807. IndirectFunctionTableMap: array of Integer;
  5808. procedure InvokeFuncType(typidx: Integer; islast: Boolean);
  5809. var
  5810. ft: TWasmFuncType;
  5811. i, nextofs: Integer;
  5812. begin
  5813. ft:=FFuncTypes[typidx];
  5814. for i:=0 to Length(ft.results)-1 do
  5815. { local.get 2 }
  5816. Sec.writeUInt16BE($2002);
  5817. nextofs:=0;
  5818. for i:=0 to Length(ft.params)-1 do
  5819. begin
  5820. { local.get 1 }
  5821. Sec.writeUInt16BE($2001);
  5822. case ft.params[i] of
  5823. wbt_i32:
  5824. begin
  5825. { i32.load nextofs }
  5826. Sec.writeUInt16BE($2802);
  5827. WriteUleb(Sec, nextofs);
  5828. Inc(nextofs,4);
  5829. end;
  5830. wbt_i64:
  5831. begin
  5832. { i64.load nextofs }
  5833. Sec.writeUInt16BE($2902);
  5834. WriteUleb(Sec, nextofs);
  5835. Inc(nextofs,8);
  5836. end;
  5837. wbt_f32:
  5838. begin
  5839. { f32.load nextofs }
  5840. Sec.writeUInt16BE($2A02);
  5841. WriteUleb(Sec, nextofs);
  5842. Inc(nextofs,4);
  5843. end;
  5844. wbt_f64:
  5845. begin
  5846. { f64.load nextofs }
  5847. Sec.writeUInt16BE($2B02);
  5848. WriteUleb(Sec, nextofs);
  5849. Inc(nextofs,8);
  5850. end;
  5851. wbt_v128:
  5852. begin
  5853. { v128.load nextofs }
  5854. Sec.writeUInt16BE($FD00);
  5855. Sec.writeUInt8($02); { align: 4 bytes }
  5856. WriteUleb(Sec, nextofs);
  5857. Inc(nextofs,16);
  5858. end;
  5859. wbt_externref,
  5860. wbt_funcref:
  5861. begin
  5862. { unreachable }
  5863. Sec.writeUInt8($00);
  5864. end;
  5865. else
  5866. internalerror(2025012501);
  5867. end;
  5868. end;
  5869. { local.get 0 }
  5870. Sec.writeUInt16BE($2000);
  5871. { call_indirect }
  5872. Sec.writeUInt8($11);
  5873. WriteUleb(Sec,typidx);
  5874. Sec.writeUInt8($0); { table index 0 }
  5875. nextofs:=0;
  5876. for i:=0 to Length(ft.results)-1 do
  5877. begin
  5878. case ft.results[i] of
  5879. wbt_i32:
  5880. begin
  5881. { i32.store nextofs }
  5882. Sec.writeUInt16BE($3602);
  5883. WriteUleb(Sec, nextofs);
  5884. Inc(nextofs,4);
  5885. end;
  5886. wbt_i64:
  5887. begin
  5888. { i64.store nextofs }
  5889. Sec.writeUInt16BE($3702);
  5890. WriteUleb(Sec, nextofs);
  5891. Inc(nextofs,8);
  5892. end;
  5893. wbt_f32:
  5894. begin
  5895. { f32.store nextofs }
  5896. Sec.writeUInt16BE($3802);
  5897. WriteUleb(Sec, nextofs);
  5898. Inc(nextofs,4);
  5899. end;
  5900. wbt_f64:
  5901. begin
  5902. { f64.store nextofs }
  5903. Sec.writeUInt16BE($3902);
  5904. WriteUleb(Sec, nextofs);
  5905. Inc(nextofs,8);
  5906. end;
  5907. wbt_v128:
  5908. begin
  5909. { v128.store nextofs }
  5910. Sec.writeUInt16BE($FD0B);
  5911. Sec.writeUInt8($02); { align: 4 bytes }
  5912. WriteUleb(Sec, nextofs);
  5913. Inc(nextofs,16);
  5914. end;
  5915. wbt_externref,
  5916. wbt_funcref:
  5917. begin
  5918. { unreachable }
  5919. Sec.writeUInt8($00);
  5920. end;
  5921. else
  5922. internalerror(2025012501);
  5923. end;
  5924. end;
  5925. if not islast then
  5926. { return }
  5927. Sec.writeUInt8($0F);
  5928. end;
  5929. function FuncIdx2TypeIdx(fi: Integer): Integer;
  5930. var
  5931. exesec: TExeSection;
  5932. objsec: TWasmObjSection;
  5933. fsym: TWasmObjSymbol;
  5934. begin
  5935. if fi<Length(FFunctionImports) then
  5936. Result:=FFunctionImports[fi].TypeIdx
  5937. else
  5938. begin
  5939. exesec:=FindExeSection('.text');
  5940. if not assigned(exesec) then
  5941. internalerror(2023123106);
  5942. objsec:=TWasmObjSection(exesec.ObjSectionList[fi-Length(FFunctionImports)]);
  5943. fsym:=objsec.MainFuncSymbol;
  5944. Result:=fsym.LinkingData.ExeTypeIndex;
  5945. end;
  5946. end;
  5947. procedure WriteBrTable(l,h: Integer; addend: Integer=0);
  5948. const
  5949. { max len of br_table instruction }
  5950. MaxLen=1000;
  5951. var
  5952. i, len, m: Integer;
  5953. begin
  5954. { local.get 0 }
  5955. Sec.writeUInt16BE($2000);
  5956. len:=h-l+1;
  5957. if len<=MaxLen then
  5958. begin
  5959. if l>0 then
  5960. begin
  5961. { i32.const l }
  5962. Sec.writeUInt8($41);
  5963. WriteSleb(sec,l);
  5964. { i32.sub }
  5965. Sec.writeUInt8($6B);
  5966. end;
  5967. { br_table }
  5968. Sec.writeUInt8($0E);
  5969. if h=high(IndirectFunctionTableMap) then
  5970. begin
  5971. WriteUleb(Sec,len);
  5972. for i:=l to h do
  5973. WriteUleb(Sec,IndirectFunctionTableMap[i]+addend);
  5974. WriteUleb(Sec,addend);
  5975. end
  5976. else
  5977. begin
  5978. WriteUleb(Sec,len-1);
  5979. for i:=l to h do
  5980. WriteUleb(Sec,IndirectFunctionTableMap[i]+addend);
  5981. end;
  5982. end
  5983. else
  5984. begin
  5985. m:=(l+h) div 2;
  5986. { i32.const m }
  5987. Sec.writeUInt8($41);
  5988. WriteSleb(sec,m);
  5989. { i32.lt_u }
  5990. Sec.writeUInt8($49);
  5991. { if }
  5992. Sec.writeUInt16BE($0440);
  5993. WriteBrTable(l,m-1,addend+1);
  5994. { else }
  5995. Sec.writeUInt8($05);
  5996. WriteBrTable(m,h,addend+1);
  5997. { end }
  5998. Sec.writeUInt8($0B);
  5999. end;
  6000. end;
  6001. var
  6002. exesym: TExeSymbol;
  6003. objsym: TObjSymbol;
  6004. i, j, TypIdx: Integer;
  6005. InvokableTypeIndices: array of Integer;
  6006. begin
  6007. exesym:=TExeSymbol(ExeSymbolList.Find('fpc_wasm_invoke_helper'));
  6008. if not Assigned(exesym) then
  6009. exit;
  6010. SetLength(IndirectFunctionTableMap, Length(FIndirectFunctionTable));
  6011. SetLength(InvokableTypeIndices, 1);
  6012. InvokableTypeIndices[0] := -1;
  6013. for i:=1 to Length(FIndirectFunctionTable)-1 do
  6014. begin
  6015. IndirectFunctionTableMap[i]:=0;
  6016. TypIdx := FuncIdx2TypeIdx(FIndirectFunctionTable[i].FuncIdx);
  6017. for j := 1 to Length(InvokableTypeIndices)-1 do
  6018. if InvokableTypeIndices[j]=TypIdx then
  6019. begin
  6020. IndirectFunctionTableMap[i]:=j;
  6021. break;
  6022. end;
  6023. if IndirectFunctionTableMap[i]=0 then
  6024. begin
  6025. SetLength(InvokableTypeIndices,Length(InvokableTypeIndices)+1);
  6026. InvokableTypeIndices[High(InvokableTypeIndices)]:=TypIdx;
  6027. IndirectFunctionTableMap[i]:=High(InvokableTypeIndices);
  6028. end;
  6029. end;
  6030. objsym:=exesym.ObjSymbol;
  6031. Sec:=objsym.objsection;
  6032. Sec.Size:=0;
  6033. Sec.Data.reset;
  6034. { locals }
  6035. Sec.writeUInt8($00);
  6036. for i:=1 to Length(InvokableTypeIndices)-1 do
  6037. { block }
  6038. Sec.writeUInt16BE($0240);
  6039. { block }
  6040. Sec.writeUInt16BE($0240);
  6041. { local.get 0 + br_table }
  6042. WriteBrTable(low(IndirectFunctionTableMap),high(IndirectFunctionTableMap));
  6043. { end }
  6044. Sec.writeUInt8($0B);
  6045. { unreachable }
  6046. Sec.writeUInt8($00);
  6047. for i:=1 to Length(InvokableTypeIndices)-1 do
  6048. begin
  6049. { end }
  6050. Sec.writeUInt8($0B);
  6051. InvokeFuncType(InvokableTypeIndices[i],i=(Length(InvokableTypeIndices)-1));
  6052. end;
  6053. { end }
  6054. Sec.writeUInt8($0B);
  6055. end;
  6056. procedure TWasmExeOutput.WriteExeSectionToDynArray(exesec: TExeSection; dynarr: tdynamicarray);
  6057. var
  6058. exesecdatapos: LongWord;
  6059. i: Integer;
  6060. objsec: TObjSection;
  6061. dpos, pad: QWord;
  6062. begin
  6063. exesecdatapos:=dynarr.size;
  6064. for i:=0 to exesec.ObjSectionList.Count-1 do
  6065. begin
  6066. objsec:=TObjSection(exesec.ObjSectionList[i]);
  6067. if not (oso_data in objsec.secoptions) then
  6068. internalerror(2024010104);
  6069. if not assigned(objsec.data) then
  6070. internalerror(2024010105);
  6071. dpos:=objsec.MemPos-exesec.MemPos+exesecdatapos;
  6072. pad:=dpos-dynarr.size;
  6073. { objsection must be within SecAlign bytes from the previous one }
  6074. if (dpos<dynarr.Size) or
  6075. (pad>=max(objsec.SecAlign,1)) then
  6076. internalerror(2024010106);
  6077. writeZeros(dynarr,pad);
  6078. objsec.data.seek(0);
  6079. CopyDynamicArray(objsec.data,dynarr,objsec.data.size);
  6080. end;
  6081. if (dynarr.size-exesecdatapos)<>exesec.Size then
  6082. internalerror(2024010107);
  6083. end;
  6084. procedure TWasmExeOutput.WriteMemoryTo(dest: tdynamicarray; const MemType: TWasmMemoryType);
  6085. begin
  6086. WriteByte(dest,Byte(MemType.Flags));
  6087. WriteUleb(dest,MemType.MinPages);
  6088. if wmfHasMaximumBound in MemType.Flags then
  6089. WriteUleb(dest,MemType.MaxPages);
  6090. { todo: wmfCustomPageSize }
  6091. end;
  6092. function TWasmExeOutput.Memory2String(const MemType: TWasmMemoryType): string;
  6093. begin
  6094. Result:='index type: ';
  6095. if wmfMemory64 in MemType.Flags then
  6096. Result:=Result+'i64'
  6097. else
  6098. Result:=Result+'i32';
  6099. Result:=Result+', pages: initial='+tostr(MemType.MinPages);
  6100. if wmfHasMaximumBound in MemType.Flags then
  6101. Result:=Result+' max='+tostr(MemType.MaxPages);
  6102. if wmfShared in MemType.Flags then
  6103. Result:=Result+', shared'
  6104. else
  6105. Result:=Result+', unshared';
  6106. { todo: wmfCustomPageSize }
  6107. end;
  6108. procedure TWasmExeOutput.WriteMap_TypeSection;
  6109. var
  6110. i: Integer;
  6111. begin
  6112. exemap.AddHeader('Type section');
  6113. for i:=0 to FFuncTypes.Count-1 do
  6114. exemap.Add(' Type[' + tostr(i) + '] ' + FFuncTypes.Items[i].ToString);
  6115. end;
  6116. procedure TWasmExeOutput.WriteMap_IndirectFunctionTable;
  6117. var
  6118. i: Integer;
  6119. begin
  6120. exemap.AddHeader('Indirect function table');
  6121. for i:=1 to High(FIndirectFunctionTable) do
  6122. exemap.Add(' Elem[' + tostr(i) + '] = Function[' + tostr(FIndirectFunctionTable[i].FuncIdx) + ']');
  6123. end;
  6124. {****************************************************************************
  6125. TWasmAssembler
  6126. ****************************************************************************}
  6127. constructor TWasmAssembler.Create(info: pasminfo; smart:boolean);
  6128. begin
  6129. inherited;
  6130. CObjOutput:=TWasmObjOutput;
  6131. end;
  6132. {*****************************************************************************
  6133. Initialize
  6134. *****************************************************************************}
  6135. {$ifdef wasm32}
  6136. const
  6137. as_wasm32_wasm_info : tasminfo =
  6138. (
  6139. id : as_wasm32_wasm;
  6140. idtxt : 'WASM';
  6141. asmbin : '';
  6142. asmcmd : '';
  6143. supported_targets : [system_wasm32_embedded,system_wasm32_wasip1,system_wasm32_wasip1threads,
  6144. system_wasm32_wasip2];
  6145. flags : [af_outputbinary,af_smartlink_sections];
  6146. labelprefix : '..@';
  6147. labelmaxlen : -1;
  6148. comment : '; ';
  6149. dollarsign: '$';
  6150. );
  6151. {$endif wasm32}
  6152. initialization
  6153. {$ifdef wasm32}
  6154. RegisterAssembler(as_wasm32_wasm_info,TWasmAssembler);
  6155. {$endif wasm32}
  6156. finalization
  6157. end.