ogwasm.pas 255 KB

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