AsmJSModule.cpp 132 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #include "RuntimeLanguagePch.h"
  6. #ifndef TEMP_DISABLE_ASMJS
  7. #include "ByteCode\Symbol.h"
  8. #include "ByteCode\FuncInfo.h"
  9. #include "ByteCode\ByteCodeAPI.h"
  10. #include "ByteCode\ByteCodeWriter.h"
  11. #include "ByteCode\ByteCodeGenerator.h"
  12. #include "ByteCode\AsmJsByteCodeWriter.h"
  13. #include "Language\AsmJsByteCodeGenerator.h"
  14. namespace Js
  15. {
  16. bool AsmJsModuleCompiler::CompileAllFunctions()
  17. {
  18. const int size = mFunctionArray.Count();
  19. for (int i = 0; i < size; i++)
  20. {
  21. AsmJsFunc* func = mFunctionArray.Item(i);
  22. if (!CompileFunction(func, i))
  23. {
  24. // an error occurred in the function, revert state on all asm.js functions
  25. for (int j = 0; j <= i; j++)
  26. {
  27. RevertFunction(j);
  28. }
  29. return false;
  30. }
  31. func->Finish();
  32. }
  33. return true;
  34. }
  35. void AsmJsModuleCompiler::RevertFunction(int funcIndex)
  36. {
  37. AsmJsFunc* func = mFunctionArray.Item(funcIndex);
  38. FunctionBody * funcBody = func->GetFuncBody();
  39. funcBody->ResetByteCodeGenState();
  40. funcBody->AddDeferParseAttribute();
  41. funcBody->SetFunctionParsed(false);
  42. funcBody->ResetEntryPoint();
  43. funcBody->SetEntryPoint(funcBody->GetDefaultEntryPointInfo(), GetScriptContext()->DeferredParsingThunk);
  44. funcBody->SetIsAsmjsMode(false);
  45. funcBody->SetIsAsmJsFunction(false);
  46. func->GetFncNode()->sxFnc.funcInfo->byteCodeFunction = func->GetFuncBody();
  47. }
  48. void AsmJsModuleCompiler::RevertAllFunctions()
  49. {
  50. for (int i = 0; i < mFunctionArray.Count(); i++)
  51. {
  52. RevertFunction(i);
  53. }
  54. }
  55. bool AsmJsModuleCompiler::CommitFunctions()
  56. {
  57. const int size = mFunctionArray.Count();
  58. // if changeHeap is defined, it must be first function, so we should skip it
  59. for (int i = 0; i < size; i++)
  60. {
  61. AsmJsFunc* func = mFunctionArray.Item(i);
  62. FunctionBody* functionBody = func->GetFuncBody();
  63. AsmJsFunctionInfo* asmInfo = functionBody->AllocateAsmJsFunctionInfo();
  64. if (i == 0 && mUsesChangeHeap)
  65. {
  66. continue;
  67. }
  68. const auto& intRegisterSpace = func->GetRegisterSpace<int>();
  69. const auto& doubleRegisterSpace = func->GetRegisterSpace<double>();
  70. const auto& floatRegisterSpace = func->GetRegisterSpace<float>();
  71. if (!asmInfo->Init(func))
  72. {
  73. return false;
  74. }
  75. asmInfo->SetIsHeapBufferConst(!mUsesChangeHeap);
  76. asmInfo->SetUsesHeapBuffer(mUsesHeapBuffer);
  77. int varCount = 0;
  78. varCount += (int)((intRegisterSpace.GetTotalVarCount() * INT_SLOTS_SPACE) + 0.5);
  79. varCount += (int)(floatRegisterSpace.GetTotalVarCount() * FLOAT_SLOTS_SPACE + 0.5);
  80. varCount += doubleRegisterSpace.GetTotalVarCount() * DOUBLE_SLOTS_SPACE;
  81. if (IsSimdjsEnabled())
  82. {
  83. const auto& simdRegisterSpace = func->GetRegisterSpace<AsmJsSIMDValue>();
  84. varCount += (int)(simdRegisterSpace.GetTotalVarCount() * SIMD_SLOTS_SPACE);
  85. }
  86. functionBody->SetOutParamDepth(func->GetMaxArgOutDepth());
  87. functionBody->SetVarCount(varCount);
  88. // should be set in EmitOneFunction
  89. Assert(functionBody->GetIsAsmjsMode());
  90. Assert(functionBody->GetIsAsmJsFunction());
  91. ((EntryPointInfo*)functionBody->GetDefaultEntryPointInfo())->SetIsAsmJSFunction(true);
  92. #if _M_IX86
  93. if (PHASE_ON1(AsmJsJITTemplatePhase) && !Configuration::Global.flags.NoNative)
  94. {
  95. AsmJsCodeGenerator* generator = GetScriptContext()->GetAsmJsCodeGenerator();
  96. AccumulateCompileTime();
  97. if (!generator)
  98. {
  99. generator = GetScriptContext()->InitAsmJsCodeGenerator();
  100. }
  101. Assert( generator );
  102. generator->CodeGen(functionBody);
  103. AccumulateCompileTime(AsmJsCompilation::TemplateJIT);
  104. }
  105. #endif
  106. }
  107. return true;
  108. }
  109. bool AsmJsModuleCompiler::CommitModule()
  110. {
  111. FuncInfo* funcInfo = GetModuleFunctionNode()->sxFnc.funcInfo;
  112. FunctionBody* functionBody = funcInfo->GetParsedFunctionBody();
  113. AsmJsModuleInfo* asmInfo = functionBody->AllocateAsmJsModuleInfo();
  114. int argCount = 0;
  115. if (mBufferArgName)
  116. {
  117. argCount = 3;
  118. }
  119. else if (mForeignArgName)
  120. {
  121. argCount = 2;
  122. }
  123. else if (mStdLibArgName)
  124. {
  125. argCount = 1;
  126. }
  127. const int functionCount = mFunctionArray.Count();
  128. const int functionTableCount = mFunctionTableArray.Count();
  129. const int importFunctionCount = mImportFunctions.GetTotalVarCount();
  130. asmInfo->SetFunctionCount(functionCount);
  131. asmInfo->SetFunctionTableCount(functionTableCount);
  132. asmInfo->SetFunctionImportCount(importFunctionCount);
  133. asmInfo->SetVarCount(mVarCount);
  134. asmInfo->SetVarImportCount(mVarImportCount);
  135. asmInfo->SetArgInCount(argCount);
  136. asmInfo->SetModuleMemory(mModuleMemory);
  137. asmInfo->SetAsmMathBuiltinUsed(mAsmMathBuiltinUsedBV);
  138. asmInfo->SetAsmArrayBuiltinUsed(mAsmArrayBuiltinUsedBV);
  139. asmInfo->SetUsesChangeHeap(mUsesChangeHeap);
  140. asmInfo->SetMaxHeapAccess(mMaxHeapAccess);
  141. if (IsSimdjsEnabled())
  142. {
  143. asmInfo->SetAsmSimdBuiltinUsed(mAsmSimdBuiltinUsedBV);
  144. asmInfo->SetSimdRegCount(mSimdVarSpace.GetTotalVarCount());
  145. }
  146. int varCount = 3; // 3 possible arguments
  147. functionBody->SetInParamsCount(4); // Always set 4 inParams so the memory space is the same (globalEnv,stdlib,foreign,buffer)
  148. functionBody->SetReportedInParamsCount(4);
  149. functionBody->SetConstantCount(2); // Return register + Root
  150. functionBody->CreateConstantTable();
  151. functionBody->SetVarCount(varCount);
  152. functionBody->SetIsAsmjsMode(true);
  153. functionBody->NewObjectLiteral(); // allocate one object literal for the export object
  154. AsmJSByteCodeGenerator::EmitEmptyByteCode(funcInfo, GetByteCodeGenerator(), GetModuleFunctionNode());
  155. // Create export module proxy
  156. asmInfo->SetExportFunctionIndex(mExportFuncIndex);
  157. asmInfo->SetExportsCount(mExports.Count());
  158. for (int i = 0; i < mExports.Count(); i++)
  159. {
  160. AsmJsModuleExport& exMod = mExports.Item(i);
  161. auto ex = asmInfo->GetExport(i);
  162. *ex.id = exMod.id;
  163. *ex.location = exMod.location;
  164. }
  165. int iVar = 0, iVarImp = 0, iFunc = 0, iFuncImp = 0;
  166. const int size = mModuleEnvironment.Count();
  167. asmInfo->InitializeSlotMap(size);
  168. auto slotMap = asmInfo->GetAsmJsSlotMap();
  169. for (int i = 0; i < size; i++)
  170. {
  171. AsmJsSymbol* sym = mModuleEnvironment.GetValueAt(i);
  172. if (sym)
  173. {
  174. AsmJsSlot * slot = RecyclerNewLeaf(GetScriptContext()->GetRecycler(), AsmJsSlot);
  175. slot->symType = sym->GetSymbolType();
  176. slotMap->AddNew(sym->GetName()->GetPropertyId(), slot);
  177. switch (sym->GetSymbolType())
  178. {
  179. case AsmJsSymbol::Variable:{
  180. AsmJsVar* var = sym->Cast<AsmJsVar>();
  181. auto& modVar = asmInfo->GetVar(iVar++);
  182. modVar.location = var->GetLocation();
  183. modVar.type = var->GetVarType().which();
  184. if (var->GetVarType().isInt())
  185. {
  186. modVar.initialiser.intInit = var->GetIntInitialiser();
  187. }
  188. else if (var->GetVarType().isFloat())
  189. {
  190. modVar.initialiser.floatInit = var->GetFloatInitialiser();
  191. }
  192. else if (var->GetVarType().isDouble())
  193. {
  194. modVar.initialiser.doubleInit = var->GetDoubleInitialiser();
  195. }
  196. else if (IsSimdjsEnabled() && var->GetVarType().isSIMD())
  197. {
  198. modVar.initialiser.simdInit = var->GetSimdConstInitialiser();
  199. }
  200. else
  201. {
  202. Assert(UNREACHED);
  203. }
  204. modVar.isMutable = var->isMutable();
  205. slot->location = modVar.location;
  206. slot->varType = var->GetVarType().which();
  207. slot->isConstVar = !modVar.isMutable;
  208. break;
  209. }
  210. case AsmJsSymbol::ConstantImport:{
  211. AsmJsConstantImport* var = sym->Cast<AsmJsConstantImport>();
  212. auto& modVar = asmInfo->GetVarImport(iVarImp++);
  213. modVar.location = var->GetLocation();
  214. modVar.field = var->GetField()->GetPropertyId();
  215. modVar.type = var->GetVarType().which();
  216. slot->location = modVar.location;
  217. slot->varType = modVar.type;
  218. break;
  219. }
  220. case AsmJsSymbol::ImportFunction:{
  221. AsmJsImportFunction* func = sym->Cast<AsmJsImportFunction>();
  222. auto& modVar = asmInfo->GetFunctionImport(iFuncImp++);
  223. modVar.location = func->GetFunctionIndex();
  224. modVar.field = func->GetField()->GetPropertyId();
  225. slot->location = modVar.location;
  226. break;
  227. }
  228. case AsmJsSymbol::FuncPtrTable:{
  229. AsmJsFunctionTable* funcTable = sym->Cast<AsmJsFunctionTable>();
  230. const uint size = funcTable->GetSize();
  231. const RegSlot index = funcTable->GetFunctionIndex();
  232. asmInfo->SetFunctionTableSize(index, size);
  233. auto& modTable = asmInfo->GetFunctionTable(index);
  234. for (uint j = 0; j < size; j++)
  235. {
  236. modTable.moduleFunctionIndex[j] = funcTable->GetModuleFunctionIndex(j);
  237. }
  238. slot->funcTableSize = size;
  239. slot->location = index;
  240. break;
  241. }
  242. case AsmJsSymbol::ModuleFunction:{
  243. AsmJsFunc* func = sym->Cast<AsmJsFunc>();
  244. auto& modVar = asmInfo->GetFunction(iFunc++);
  245. modVar.location = func->GetFunctionIndex();
  246. slot->location = modVar.location;
  247. break;
  248. }
  249. case AsmJsSymbol::ArrayView:
  250. {
  251. AsmJsArrayView * var = sym->Cast<AsmJsArrayView>();
  252. slot->viewType = var->GetViewType();
  253. break;
  254. }
  255. case AsmJsSymbol::ModuleArgument:
  256. {
  257. AsmJsModuleArg * arg = sym->Cast<AsmJsModuleArg>();
  258. slot->argType = arg->GetArgType();
  259. break;
  260. }
  261. // used only for module validation
  262. case AsmJsSymbol::MathConstant:
  263. {
  264. AsmJsMathConst * constVar = sym->Cast<AsmJsMathConst>();
  265. slot->mathConstVal = *constVar->GetVal();
  266. break;
  267. }
  268. case AsmJsSymbol::MathBuiltinFunction:
  269. {
  270. AsmJsMathFunction * mathFunc = sym->Cast<AsmJsMathFunction>();
  271. slot->builtinMathFunc = mathFunc->GetMathBuiltInFunction();
  272. break;
  273. }
  274. case AsmJsSymbol::TypedArrayBuiltinFunction:
  275. {
  276. AsmJsTypedArrayFunction * mathFunc = sym->Cast<AsmJsTypedArrayFunction>();
  277. slot->builtinArrayFunc = mathFunc->GetArrayBuiltInFunction();
  278. break;
  279. }
  280. case AsmJsSymbol::SIMDBuiltinFunction:
  281. {
  282. AsmJsSIMDFunction * mathFunc = sym->Cast<AsmJsSIMDFunction>();
  283. slot->builtinSIMDFunc = mathFunc->GetSimdBuiltInFunction();
  284. break;
  285. }
  286. default:
  287. Assume(UNREACHED);
  288. }
  289. }
  290. }
  291. return true;
  292. }
  293. void AsmJsModuleCompiler::ASTPrepass(ParseNodePtr pnode, AsmJsFunc * func)
  294. {
  295. ThreadContext::ProbeCurrentStackNoDispose(Js::Constants::MinStackByteCodeVisitor, GetByteCodeGenerator()->GetScriptContext());
  296. if (pnode == NULL)
  297. {
  298. return;
  299. }
  300. switch (pnode->nop) {
  301. // these first cases do the interesting work
  302. case knopBreak:
  303. case knopContinue:
  304. GetByteCodeGenerator()->AddTargetStmt(pnode->sxJump.pnodeTarget);
  305. break;
  306. case knopInt:
  307. func->AddConst<int>(pnode->sxInt.lw);
  308. break;
  309. case knopFlt:
  310. {
  311. const double d = pnode->sxFlt.dbl;
  312. if (ParserWrapper::IsMinInt(pnode))
  313. {
  314. func->AddConst<int>((int)d);
  315. }
  316. else if (ParserWrapper::IsUnsigned(pnode))
  317. {
  318. func->AddConst<int>((int)(uint32)d);
  319. }
  320. else
  321. {
  322. func->AddConst<double>(d);
  323. }
  324. break;
  325. }
  326. case knopName:
  327. {
  328. GetByteCodeGenerator()->AssignPropertyId(pnode->name());
  329. AsmJsSymbol * declSym = LookupIdentifier(pnode->name());
  330. if (declSym)
  331. {
  332. if (declSym->GetSymbolType() == AsmJsSymbol::MathConstant)
  333. {
  334. AsmJsMathConst * definition = declSym->Cast<AsmJsMathConst>();
  335. Assert(definition->GetType().isDouble());
  336. func->AddConst<double>(*definition->GetVal());
  337. }
  338. else if (declSym->GetSymbolType() == AsmJsSymbol::Variable && !declSym->isMutable())
  339. {
  340. AsmJsVar * definition = declSym->Cast<AsmJsVar>();
  341. switch (definition->GetVarType().which())
  342. {
  343. case AsmJsVarType::Double:
  344. func->AddConst<double>(definition->GetDoubleInitialiser());
  345. break;
  346. case AsmJsVarType::Float:
  347. func->AddConst<float>(definition->GetFloatInitialiser());
  348. break;
  349. case AsmJsVarType::Int:
  350. func->AddConst<int>(definition->GetIntInitialiser());
  351. break;
  352. default:
  353. Assume(UNREACHED);
  354. }
  355. }
  356. }
  357. break;
  358. }
  359. case knopCall:
  360. {
  361. ASTPrepass(pnode->sxCall.pnodeTarget, func);
  362. bool evalArgs = true;
  363. if (pnode->sxCall.pnodeTarget->nop == knopName)
  364. {
  365. AsmJsFunctionDeclaration* funcDecl = this->LookupFunction(pnode->sxCall.pnodeTarget->name());
  366. if (funcDecl && funcDecl->GetSymbolType() == AsmJsSymbol::MathBuiltinFunction)
  367. {
  368. AsmJsMathFunction* mathFunc = funcDecl->Cast<AsmJsMathFunction>();
  369. if (mathFunc->GetMathBuiltInFunction() == AsmJSMathBuiltin_fround)
  370. {
  371. switch (pnode->sxCall.pnodeArgs->nop)
  372. {
  373. case knopFlt:
  374. func->AddConst<float>((float)pnode->sxCall.pnodeArgs->sxFlt.dbl);
  375. evalArgs = false;
  376. break;
  377. case knopInt:
  378. func->AddConst<float>((float)pnode->sxCall.pnodeArgs->sxInt.lw);
  379. evalArgs = false;
  380. break;
  381. case knopNeg:
  382. if (pnode->sxCall.pnodeArgs->sxUni.pnode1->nop == knopInt && pnode->sxCall.pnodeArgs->sxUni.pnode1->sxInt.lw == 0)
  383. {
  384. func->AddConst<float>(-0.0f);
  385. evalArgs = false;
  386. break;
  387. }
  388. }
  389. }
  390. }
  391. else if (IsSimdjsEnabled())
  392. {
  393. /*
  394. Float32x4 operations work on Float reg space.
  395. If any of the args is a literal (DoubleLit), we need to have a copy of it in the Float reg space.
  396. Note that we may end up with redundant copies in the Double reg space, since we ASTPrepass the args (Fix later ?)
  397. */
  398. if (funcDecl && funcDecl->GetSymbolType() == AsmJsSymbol::SIMDBuiltinFunction)
  399. {
  400. AsmJsSIMDFunction* simdFunc = funcDecl->Cast<AsmJsSIMDFunction>();
  401. if (simdFunc->IsFloat32x4Func())
  402. {
  403. ParseNode *argNode, *arg;
  404. argNode = arg = pnode->sxCall.pnodeArgs;
  405. do
  406. {
  407. if (argNode->nop == knopList)
  408. {
  409. arg = ParserWrapper::GetBinaryLeft(argNode);
  410. argNode = ParserWrapper::GetBinaryRight(argNode);
  411. }
  412. if (arg->nop == knopFlt)
  413. {
  414. func->AddConst<float>((float)arg->sxFlt.dbl);
  415. }
  416. if (argNode != arg && argNode->nop == knopFlt)
  417. { // last arg
  418. func->AddConst<float>((float)argNode->sxFlt.dbl);
  419. }
  420. } while (argNode->nop == knopList);
  421. }
  422. }
  423. }
  424. }
  425. if (evalArgs)
  426. {
  427. ASTPrepass(pnode->sxCall.pnodeArgs, func);
  428. }
  429. break;
  430. }
  431. case knopVarDecl:
  432. GetByteCodeGenerator()->AssignPropertyId(pnode->name());
  433. ASTPrepass(pnode->sxVar.pnodeInit, func);
  434. break;
  435. // all the rest of the cases simply walk the AST
  436. case knopQmark:
  437. ASTPrepass(pnode->sxTri.pnode1, func);
  438. ASTPrepass(pnode->sxTri.pnode2, func);
  439. ASTPrepass(pnode->sxTri.pnode3, func);
  440. break;
  441. case knopList:
  442. do
  443. {
  444. ParseNode * pnode1 = pnode->sxBin.pnode1;
  445. ASTPrepass(pnode1, func);
  446. pnode = pnode->sxBin.pnode2;
  447. } while (pnode->nop == knopList);
  448. ASTPrepass(pnode, func);
  449. break;
  450. case knopFor:
  451. ASTPrepass(pnode->sxFor.pnodeInit, func);
  452. ASTPrepass(pnode->sxFor.pnodeCond, func);
  453. ASTPrepass(pnode->sxFor.pnodeIncr, func);
  454. ASTPrepass(pnode->sxFor.pnodeBody, func);
  455. break;
  456. case knopIf:
  457. ASTPrepass(pnode->sxIf.pnodeCond, func);
  458. ASTPrepass(pnode->sxIf.pnodeTrue, func);
  459. ASTPrepass(pnode->sxIf.pnodeFalse, func);
  460. break;
  461. case knopDoWhile:
  462. case knopWhile:
  463. ASTPrepass(pnode->sxWhile.pnodeCond, func);
  464. ASTPrepass(pnode->sxWhile.pnodeBody, func);
  465. break;
  466. case knopReturn:
  467. ASTPrepass(pnode->sxReturn.pnodeExpr, func);
  468. break;
  469. case knopBlock:
  470. ASTPrepass(pnode->sxBlock.pnodeStmt, func);
  471. break;
  472. case knopSwitch:
  473. ASTPrepass(pnode->sxSwitch.pnodeVal, func);
  474. for (ParseNode *pnodeT = pnode->sxSwitch.pnodeCases; NULL != pnodeT; pnodeT = pnodeT->sxCase.pnodeNext)
  475. {
  476. ASTPrepass(pnodeT, func);
  477. }
  478. ASTPrepass(pnode->sxSwitch.pnodeBlock, func);
  479. break;
  480. case knopCase:
  481. ASTPrepass(pnode->sxCase.pnodeExpr, func);
  482. ASTPrepass(pnode->sxCase.pnodeBody, func);
  483. break;
  484. case knopComma:
  485. {
  486. ParseNode *pnode1 = pnode->sxBin.pnode1;
  487. if (pnode1->nop == knopComma)
  488. {
  489. // avoid recursion on very large comma expressions.
  490. ArenaAllocator *alloc = GetByteCodeGenerator()->GetAllocator();
  491. SList<ParseNode*> *rhsStack = Anew(alloc, SList<ParseNode*>, alloc);
  492. do {
  493. rhsStack->Push(pnode1->sxBin.pnode2);
  494. pnode1 = pnode1->sxBin.pnode1;
  495. } while (pnode1->nop == knopComma);
  496. ASTPrepass(pnode1, func);
  497. while (!rhsStack->Empty())
  498. {
  499. ParseNode *pnodeRhs = rhsStack->Pop();
  500. ASTPrepass(pnodeRhs, func);
  501. }
  502. Adelete(alloc, rhsStack);
  503. }
  504. else
  505. {
  506. ASTPrepass(pnode1, func);
  507. }
  508. ASTPrepass(pnode->sxBin.pnode2, func);
  509. break;
  510. }
  511. default:
  512. {
  513. uint flags = ParseNode::Grfnop(pnode->nop);
  514. if (flags&fnopUni)
  515. {
  516. ASTPrepass(pnode->sxUni.pnode1, func);
  517. }
  518. else if (flags&fnopBin)
  519. {
  520. ASTPrepass(pnode->sxBin.pnode1, func);
  521. ASTPrepass(pnode->sxBin.pnode2, func);
  522. }
  523. break;
  524. }
  525. }
  526. }
  527. void AsmJsModuleCompiler::BindArguments(ParseNode* argList)
  528. {
  529. for (ParseNode* pnode = argList; pnode; pnode = pnode->sxVar.pnodeNext)
  530. {
  531. GetByteCodeGenerator()->AssignPropertyId(pnode->name());
  532. }
  533. }
  534. bool AsmJsModuleCompiler::CompileFunction(AsmJsFunc * func, int funcIndex)
  535. {
  536. ParseNodePtr fncNode = func->GetFncNode();
  537. ParseNodePtr pnodeBody = nullptr;
  538. Assert(fncNode->nop == knopFncDecl && fncNode->sxFnc.funcInfo && fncNode->sxFnc.funcInfo->IsDeferred() && fncNode->sxFnc.pnodeBody == NULL);
  539. Js::ParseableFunctionInfo* deferParseFunction = fncNode->sxFnc.funcInfo->byteCodeFunction;
  540. Utf8SourceInfo * utf8SourceInfo = deferParseFunction->GetUtf8SourceInfo();
  541. ULONG grfscr = utf8SourceInfo->GetParseFlags();
  542. grfscr = grfscr & (~fscrGlobalCode);
  543. func->SetOrigParseFlags(grfscr);
  544. deferParseFunction->SetGrfscr(grfscr | (grfscr & ~fscrDeferredFncExpression));
  545. deferParseFunction->SetSourceInfo(GetByteCodeGenerator()->GetCurrentSourceIndex(),
  546. fncNode,
  547. !!(grfscr & fscrEvalCode),
  548. ((grfscr & fscrDynamicCode) && !(grfscr & fscrEvalCode)));
  549. deferParseFunction->SetInParamsCount(fncNode->sxFnc.funcInfo->inArgsCount);
  550. deferParseFunction->SetReportedInParamsCount(fncNode->sxFnc.funcInfo->inArgsCount);
  551. if (fncNode->sxFnc.pnodeBody == NULL)
  552. {
  553. if (GetScriptContext()->GetConfig()->BindDeferredPidRefs() &&
  554. !PHASE_OFF1(Js::SkipNestedDeferredPhase))
  555. {
  556. deferParseFunction->BuildDeferredStubs(fncNode);
  557. }
  558. }
  559. deferParseFunction->SetIsAsmjsMode(true);
  560. PageAllocator tempPageAlloc(NULL, Js::Configuration::Global.flags);
  561. Parser ps(GetScriptContext(), FALSE, &tempPageAlloc);
  562. FunctionBody * funcBody;
  563. ParseNodePtr parseTree;
  564. Assert(!deferParseFunction->GetIsStrictMode());
  565. CompileScriptException se;
  566. funcBody = deferParseFunction->ParseAsmJs(&ps, &se, &parseTree);
  567. TRACE_BYTECODE(L"\nDeferred parse %s\n", funcBody->GetDisplayName());
  568. if (parseTree && parseTree->nop == knopProg)
  569. {
  570. auto body = parseTree->sxProg.pnodeBody;
  571. if (body && body->nop == knopList)
  572. {
  573. auto fncDecl = body->sxBin.pnode1;
  574. if (fncDecl && fncDecl->nop == knopFncDecl)
  575. {
  576. pnodeBody = fncDecl->sxFnc.pnodeBody;
  577. func->SetFuncBody(funcBody);
  578. }
  579. }
  580. }
  581. GetByteCodeGenerator()->PushFuncInfo(L"Start asm.js AST prepass", fncNode->sxFnc.funcInfo);
  582. fncNode->sxFnc.funcInfo->byteCodeFunction->SetBoundPropertyRecords(GetByteCodeGenerator()->EnsurePropertyRecordList());
  583. BindArguments(fncNode->sxFnc.pnodeArgs);
  584. ASTPrepass(pnodeBody, func);
  585. GetByteCodeGenerator()->PopFuncInfo(L"End asm.js AST prepass");
  586. fncNode->sxFnc.pnodeBody = pnodeBody;
  587. if (!pnodeBody)
  588. {
  589. // body should never be null if parsing succeeded
  590. Assert(UNREACHED);
  591. return Fail(fncNode, L"Function should always have parse nodes");
  592. }
  593. // Check if this function requires a bigger Ast
  594. UpdateMaxAstSize(fncNode->sxFnc.astSize);
  595. if (funcIndex == 0 && CheckChangeHeap(func))
  596. {
  597. fncNode->sxFnc.pnodeBody = NULL;
  598. return true;
  599. }
  600. if (!SetupFunctionArguments(func, pnodeBody))
  601. {
  602. // failure message will be printed by SetupFunctionArguments
  603. fncNode->sxFnc.pnodeBody = NULL;
  604. return false;
  605. }
  606. if (!SetupLocalVariables(func))
  607. {
  608. // failure message will be printed by SetupLocalVariables
  609. fncNode->sxFnc.pnodeBody = NULL;
  610. return false;
  611. }
  612. // now that we have setup the function, we can generate bytecode for it
  613. AsmJSByteCodeGenerator gen(func, this);
  614. bool wasEmit = gen.EmitOneFunction();
  615. fncNode->sxFnc.pnodeBody = NULL;
  616. return wasEmit;
  617. }
  618. bool AsmJsModuleCompiler::SetupFunctionArguments(AsmJsFunc * func, ParseNodePtr pnode)
  619. {
  620. // Check arguments
  621. ArgSlot numArguments = 0;
  622. ParseNode * fncNode = func->GetFncNode();
  623. ParseNode* argNode = ParserWrapper::FunctionArgsList(fncNode, numArguments);
  624. if (!func->EnsureArgCount(numArguments))
  625. {
  626. return Fail(argNode, L"Cannot have variable number of arguments");
  627. }
  628. ArgSlot index = 0;
  629. while (argNode)
  630. {
  631. if (pnode->nop != knopList)
  632. {
  633. return Fail(pnode, L"Missing assignment statement for argument");
  634. }
  635. if (!ParserWrapper::IsDefinition(argNode))
  636. {
  637. return Fail(argNode, L"duplicate argument name not allowed");
  638. }
  639. PropertyName argName = argNode->name();
  640. if (!AsmJSCompiler::CheckIdentifier(*this, argNode, argName))
  641. {
  642. return false;
  643. }
  644. // creates the variable
  645. AsmJsVarBase* var = func->DefineVar(argName, true);
  646. if (!var)
  647. {
  648. return Fail(argNode, L"Failed to define var");
  649. }
  650. ParseNode* argDefinition = ParserWrapper::GetBinaryLeft(pnode);
  651. if (argDefinition->nop != knopAsg)
  652. {
  653. return Fail(argDefinition, L"Expecting an assignment");
  654. }
  655. ParseNode* lhs = ParserWrapper::GetBinaryLeft(argDefinition);
  656. ParseNode* rhs = ParserWrapper::GetBinaryRight(argDefinition);
  657. #define NodeDefineThisArgument(n,var) (n->nop == knopName && ParserWrapper::VariableName(n)->GetPropertyId() == var->GetName()->GetPropertyId())
  658. if (!NodeDefineThisArgument(lhs, var))
  659. {
  660. return Fail(lhs, L"Defining wrong argument");
  661. }
  662. if (rhs->nop == knopPos)
  663. {
  664. // unary + => double
  665. var->SetVarType(AsmJsVarType::Double);
  666. var->SetLocation(func->AcquireRegister<double>());
  667. // validate stmt
  668. ParseNode* argSym = ParserWrapper::GetUnaryNode(rhs);
  669. if (!NodeDefineThisArgument(argSym, var))
  670. {
  671. return Fail(lhs, L"Defining wrong argument");
  672. }
  673. }
  674. else if (rhs->nop == knopOr)
  675. {
  676. var->SetVarType(AsmJsVarType::Int);
  677. var->SetLocation(func->AcquireRegister<int>());
  678. ParseNode* argSym = ParserWrapper::GetBinaryLeft(rhs);
  679. ParseNode* intSym = ParserWrapper::GetBinaryRight(rhs);
  680. // validate stmt
  681. if (!NodeDefineThisArgument(argSym, var))
  682. {
  683. return Fail(lhs, L"Defining wrong argument");
  684. }
  685. if (intSym->nop != knopInt || intSym->sxInt.lw != 0)
  686. {
  687. return Fail(lhs, L"Or value must be 0 when defining arguments");
  688. }
  689. }
  690. else if (rhs->nop == knopCall)
  691. {
  692. if (rhs->sxCall.pnodeTarget->nop != knopName)
  693. {
  694. return Fail(rhs, L"call should be for fround");
  695. }
  696. AsmJsFunctionDeclaration* funcDecl = this->LookupFunction(rhs->sxCall.pnodeTarget->name());
  697. if (!funcDecl)
  698. return Fail(rhs, L"Cannot resolve function for argument definition, or wrong function");
  699. if (funcDecl->GetSymbolType() == AsmJsSymbol::MathBuiltinFunction)
  700. {
  701. AsmJsMathFunction* mathFunc = funcDecl->Cast<AsmJsMathFunction>();
  702. if (!(mathFunc && mathFunc->GetMathBuiltInFunction() == AsmJSMathBuiltin_fround))
  703. {
  704. return Fail(rhs, L"call should be for fround");
  705. }
  706. var->SetVarType(AsmJsVarType::Float);
  707. var->SetLocation(func->AcquireRegister<float>());
  708. }
  709. else if (IsSimdjsEnabled() && funcDecl->GetSymbolType() == AsmJsSymbol::SIMDBuiltinFunction)
  710. {
  711. AsmJsSIMDFunction* simdFunc = funcDecl->Cast<AsmJsSIMDFunction>();
  712. // x = f4check(x)
  713. if (!simdFunc->IsTypeCheck())
  714. {
  715. return Fail(rhs, L"Invalid SIMD argument type check. E.g. expected x = f4check(x)");
  716. }
  717. var->SetVarType(simdFunc->GetTypeCheckVarType());
  718. // We don't set SIMD args reg location here. We defer that after all function locals are processed.
  719. // This allows us to capture all SIMD constants from locals initializations, add them to the register space before we assign registers to args and locals.
  720. func->GetSimdVarsList().Add(var);
  721. }
  722. else
  723. {
  724. return Fail(rhs, L"Wrong function used for argument definition");
  725. }
  726. if (!NodeDefineThisArgument(rhs->sxCall.pnodeArgs, var))
  727. {
  728. return Fail(lhs, L"Defining wrong argument");
  729. }
  730. }
  731. else
  732. {
  733. return Fail(rhs, L"arguments are not casted as valid Asm.js type");
  734. }
  735. if (PHASE_TRACE1(ByteCodePhase))
  736. {
  737. Output::Print(L" Argument [%s] Valid", argName->Psz());
  738. }
  739. if (!func->EnsureArgType(var, index++))
  740. {
  741. return Fail(rhs, L"Unexpected argument type");
  742. }
  743. argNode = ParserWrapper::NextVar(argNode);
  744. pnode = ParserWrapper::GetBinaryRight(pnode);
  745. }
  746. func->SetBodyNode(pnode);
  747. return true;
  748. }
  749. bool AsmJsModuleCompiler::SetupLocalVariables(AsmJsFunc * func)
  750. {
  751. ParseNodePtr pnode = func->GetBodyNode();
  752. MathBuiltin mathBuiltin;
  753. AsmJsMathFunction* mathFunc = nullptr;
  754. AsmJsSIMDFunction* simdFunc = nullptr;
  755. AsmJsSIMDValue simdValue;
  756. simdValue.Zero();
  757. // define all variables
  758. while (pnode->nop == knopList)
  759. {
  760. ParseNode * varNode = ParserWrapper::GetBinaryLeft(pnode);
  761. while (varNode && varNode->nop != knopEndCode)
  762. {
  763. ParseNode * decl;
  764. if (varNode->nop == knopList)
  765. {
  766. decl = ParserWrapper::GetBinaryLeft(varNode);
  767. varNode = ParserWrapper::GetBinaryRight(varNode);
  768. }
  769. else
  770. {
  771. decl = varNode;
  772. varNode = nullptr;
  773. }
  774. // if we have hit a non-declaration, we are done processing the function header
  775. if (decl->nop != knopVarDecl)
  776. {
  777. goto varDeclEnd;
  778. }
  779. ParseNode* pnodeInit = decl->sxVar.pnodeInit;
  780. AsmJsSymbol * declSym = nullptr;
  781. mathFunc = nullptr;
  782. simdFunc = nullptr;
  783. if (pnodeInit->nop == knopName)
  784. {
  785. declSym = LookupIdentifier(pnodeInit->name(), func);
  786. if (!declSym || declSym->isMutable() || (declSym->GetSymbolType() != AsmJsSymbol::Variable && declSym->GetSymbolType() != AsmJsSymbol::MathConstant))
  787. {
  788. return Fail(decl, L"Var declaration with non-constant");
  789. }
  790. }
  791. else if (pnodeInit->nop == knopCall)
  792. {
  793. if (pnodeInit->sxCall.pnodeTarget->nop != knopName)
  794. {
  795. return Fail(decl, L"Var declaration with something else than a literal value|fround call");
  796. }
  797. AsmJsFunctionDeclaration* funcDecl = this->LookupFunction(pnodeInit->sxCall.pnodeTarget->name());
  798. if (!funcDecl)
  799. return Fail(pnodeInit, L"Cannot resolve function name");
  800. if (funcDecl->GetSymbolType() == AsmJsSymbol::MathBuiltinFunction)
  801. {
  802. mathFunc = funcDecl->Cast<AsmJsMathFunction>();
  803. if (!(mathFunc && mathFunc->GetMathBuiltInFunction() == AsmJSMathBuiltin_fround))
  804. {
  805. return Fail(decl, L"Var declaration with something else than a literal value|fround call");
  806. }
  807. if (!ParserWrapper::IsFroundNumericLiteral(pnodeInit->sxCall.pnodeArgs))
  808. {
  809. return Fail(decl, L"Var declaration with something else than a literal value|fround call");
  810. }
  811. }
  812. else if (IsSimdjsEnabled() && funcDecl->GetSymbolType() == AsmJsSymbol::SIMDBuiltinFunction)
  813. {
  814. // var x = f4(1.0, 2.0, 3.0, 4.0);
  815. simdFunc = funcDecl->Cast<AsmJsSIMDFunction>();
  816. if (!ValidateSimdConstructor(pnodeInit, simdFunc, simdValue))
  817. {
  818. return Fail(varNode, L"Invalid SIMD local declaration");
  819. }
  820. }
  821. }
  822. else if (pnodeInit->nop != knopInt && pnodeInit->nop != knopFlt)
  823. {
  824. return Fail(decl, L"Var declaration with something else than a literal value|fround call");
  825. }
  826. if (!AsmJSCompiler::CheckIdentifier(*this, decl, decl->name()))
  827. {
  828. // CheckIdentifier will print failure message
  829. return false;
  830. }
  831. AsmJsVar* var = (AsmJsVar*)func->DefineVar(decl->name(), false);
  832. if (!var)
  833. {
  834. return Fail(decl, L"Failed to define var");
  835. }
  836. RegSlot loc = Constants::NoRegister;
  837. if (pnodeInit->nop == knopInt)
  838. {
  839. var->SetVarType(AsmJsVarType::Int);
  840. var->SetLocation(func->AcquireRegister<int>());
  841. var->SetConstInitialiser(pnodeInit->sxInt.lw);
  842. loc = func->GetConstRegister<int>(pnodeInit->sxInt.lw);
  843. }
  844. else if (ParserWrapper::IsMinInt(pnodeInit))
  845. {
  846. var->SetVarType(AsmJsVarType::Int);
  847. var->SetLocation(func->AcquireRegister<int>());
  848. var->SetConstInitialiser(MININT);
  849. loc = func->GetConstRegister<int>(MININT);
  850. }
  851. else if (ParserWrapper::IsUnsigned(pnodeInit))
  852. {
  853. var->SetVarType(AsmJsVarType::Int);
  854. var->SetLocation(func->AcquireRegister<int>());
  855. var->SetConstInitialiser((int)((uint32)pnodeInit->sxFlt.dbl));
  856. loc = func->GetConstRegister<int>((uint32)pnodeInit->sxFlt.dbl);
  857. }
  858. else if (pnodeInit->nop == knopFlt)
  859. {
  860. if (pnodeInit->sxFlt.maybeInt)
  861. {
  862. return Fail(decl, L"Var declaration with integer literal outside range [-2^31, 2^32)");
  863. }
  864. var->SetVarType(AsmJsVarType::Double);
  865. var->SetLocation(func->AcquireRegister<double>());
  866. loc = func->GetConstRegister<double>(pnodeInit->sxFlt.dbl);
  867. var->SetConstInitialiser(pnodeInit->sxFlt.dbl);
  868. }
  869. else if (pnodeInit->nop == knopName)
  870. {
  871. if (declSym->GetSymbolType() == AsmJsSymbol::Variable)
  872. {
  873. AsmJsVar * definition = declSym->Cast<AsmJsVar>();
  874. switch (definition->GetVarType().which())
  875. {
  876. case AsmJsVarType::Double:
  877. var->SetVarType(AsmJsVarType::Double);
  878. var->SetLocation(func->AcquireRegister<double>());
  879. var->SetConstInitialiser(definition->GetDoubleInitialiser());
  880. break;
  881. case AsmJsVarType::Float:
  882. var->SetVarType(AsmJsVarType::Float);
  883. var->SetLocation(func->AcquireRegister<float>());
  884. var->SetConstInitialiser(definition->GetFloatInitialiser());
  885. break;
  886. case AsmJsVarType::Int:
  887. var->SetVarType(AsmJsVarType::Int);
  888. var->SetLocation(func->AcquireRegister<int>());
  889. var->SetConstInitialiser(definition->GetIntInitialiser());
  890. break;
  891. default:
  892. Assume(UNREACHED);
  893. }
  894. }
  895. else
  896. {
  897. Assert(declSym->GetSymbolType() == AsmJsSymbol::MathConstant);
  898. Assert(declSym->GetType() == AsmJsType::Double);
  899. AsmJsMathConst * definition = declSym->Cast<AsmJsMathConst>();
  900. var->SetVarType(AsmJsVarType::Double);
  901. var->SetLocation(func->AcquireRegister<double>());
  902. var->SetConstInitialiser(*definition->GetVal());
  903. }
  904. }
  905. else if (pnodeInit->nop == knopCall)
  906. {
  907. if (mathFunc)
  908. {
  909. var->SetVarType(AsmJsVarType::Float);
  910. var->SetLocation(func->AcquireRegister<float>());
  911. if (pnodeInit->sxCall.pnodeArgs->nop == knopInt)
  912. {
  913. int iVal = pnodeInit->sxCall.pnodeArgs->sxInt.lw;
  914. var->SetConstInitialiser((float)iVal);
  915. loc = func->GetConstRegister<float>((float)iVal);
  916. }
  917. else if (ParserWrapper::IsNegativeZero(pnodeInit->sxCall.pnodeArgs))
  918. {
  919. var->SetConstInitialiser(-0.0f);
  920. loc = func->GetConstRegister<float>(-0.0f);
  921. }
  922. else
  923. {
  924. // note: fround((-)NumericLiteral) is explicitly allowed for any range, so we do not need to check for maybeInt
  925. Assert(pnodeInit->sxCall.pnodeArgs->nop == knopFlt);
  926. float fVal = (float)pnodeInit->sxCall.pnodeArgs->sxFlt.dbl;
  927. var->SetConstInitialiser((float)fVal);
  928. loc = func->GetConstRegister<float>(fVal);
  929. }
  930. }
  931. else if (IsSimdjsEnabled() && simdFunc)
  932. {
  933. // simd constructor call
  934. // en-register the simdvalue constant first
  935. func->AddConst<AsmJsSIMDValue>(simdValue);
  936. loc = func->GetConstRegister<AsmJsSIMDValue>(simdValue);
  937. var->SetConstInitialiser(simdValue);
  938. var->SetVarType(simdFunc->GetConstructorVarType());
  939. // add to list. assign register after all constants.
  940. func->GetSimdVarsList().Add(var);
  941. }
  942. else
  943. {
  944. Assert(UNREACHED);
  945. }
  946. }
  947. if (loc == Constants::NoRegister && pnodeInit->nop != knopName)
  948. {
  949. return Fail(decl, L"Cannot find Register constant for var");
  950. }
  951. }
  952. if (ParserWrapper::GetBinaryRight(pnode)->nop == knopEndCode)
  953. {
  954. break;
  955. }
  956. pnode = ParserWrapper::GetBinaryRight(pnode);
  957. }
  958. varDeclEnd:
  959. // this code has to be on all exit-path from the function
  960. if (IsSimdjsEnabled())
  961. {
  962. // Now, assign registers to all SIMD vars after all constants are en-registered.
  963. for (int i = 0; i < func->GetSimdVarsList().Count(); i++)
  964. {
  965. AsmJsVarBase *var = func->GetSimdVarsList().Item(i);
  966. var->SetLocation(func->AcquireRegister<AsmJsSIMDValue>());
  967. }
  968. func->GetSimdVarsList().Reset(); // list not needed anymore
  969. }
  970. return true;
  971. }
  972. AsmJsFunc* AsmJsModuleCompiler::CreateNewFunctionEntry( ParseNode* pnodeFnc )
  973. {
  974. PropertyName name = ParserWrapper::FunctionName( pnodeFnc );
  975. GetByteCodeGenerator()->AssignPropertyId(name);
  976. AsmJsFunc* func = Anew( &mAllocator, AsmJsFunc, name, pnodeFnc, &mAllocator );
  977. if( func )
  978. {
  979. if( DefineIdentifier( name, func ) )
  980. {
  981. func->SetFunctionIndex( pnodeFnc->sxFnc.nestedIndex );
  982. // Add extra check to make sure all the slots between 0 - Count are filled with func;
  983. mFunctionArray.SetItem( func->GetFunctionIndex(), func );
  984. return func;
  985. }
  986. // Error adding function
  987. mAllocator.Free( func, sizeof( AsmJsFunc ) );
  988. }
  989. // Error allocating a new function
  990. return nullptr;
  991. }
  992. bool AsmJsModuleCompiler::CheckChangeHeap(AsmJsFunc * func)
  993. {
  994. ParseNode * fncNode = func->GetFncNode();
  995. ParseNode * pnodeBody = fncNode->sxFnc.pnodeBody;
  996. ParseNode * pnodeArgs = fncNode->sxFnc.pnodeArgs;
  997. // match AST for changeHeap function.
  998. // it must be defined in the following format (names/whitespace can differ):
  999. //function changeHeap(newBuffer)
  1000. //{
  1001. // if (byteLength(newBuffer) & 0xffffff ||
  1002. // byteLength(newBuffer) <= 0xffffff ||
  1003. // byteLength(newBuffer) > 0x80000000)
  1004. // return false;
  1005. // heap32 = new Int32Array(newBuffer);
  1006. // ...
  1007. // buffer = newBuffer;
  1008. // return true;
  1009. //}
  1010. // ensure function
  1011. if (pnodeBody->nop != knopList || !pnodeArgs || pnodeArgs->nop != knopVarDecl)
  1012. {
  1013. return false;
  1014. }
  1015. // ensure if expression
  1016. ParseNode * ifNode = pnodeBody->sxBin.pnode1;
  1017. if (ifNode->nop != knopIf || ifNode->sxIf.pnodeFalse)
  1018. {
  1019. return false;
  1020. }
  1021. // validate "byteLength(newBuffer) > 0x80000000"
  1022. ParseNode * orNode = ifNode->sxIf.pnodeCond;
  1023. if (orNode->nop != knopLogOr || orNode->sxBin.pnode1->nop != knopLogOr)
  1024. {
  1025. return false;
  1026. }
  1027. ParseNode * cond = orNode->sxBin.pnode2;
  1028. if (cond->nop != knopGt || !CheckByteLengthCall(cond->sxBin.pnode1, pnodeArgs) || cond->sxBin.pnode2->nop != knopFlt || cond->sxBin.pnode2->sxFlt.dbl != 2147483648.0 || !cond->sxBin.pnode2->sxFlt.maybeInt)
  1029. {
  1030. return false;
  1031. }
  1032. // validate "byteLength(newBuffer) <= 0xffffff"
  1033. orNode = orNode->sxBin.pnode1;
  1034. cond = orNode->sxBin.pnode2;
  1035. if (cond->nop != knopLe || !CheckByteLengthCall(cond->sxBin.pnode1, pnodeArgs) || cond->sxBin.pnode2->nop != knopInt || cond->sxBin.pnode2->sxInt.lw != 0x00ffffff)
  1036. {
  1037. return false;
  1038. }
  1039. // validate "byteLength(newBuffer) & 0xffffff"
  1040. cond = orNode->sxBin.pnode1;
  1041. if (cond->nop != knopAnd || !CheckByteLengthCall(cond->sxBin.pnode1, pnodeArgs) || cond->sxBin.pnode2->nop != knopInt || cond->sxBin.pnode2->sxInt.lw != 0x00ffffff)
  1042. {
  1043. return false;
  1044. }
  1045. // validate "return false;"
  1046. cond = ifNode->sxIf.pnodeTrue;
  1047. if (!cond || cond->nop != knopReturn || cond->sxReturn.pnodeExpr->nop != knopFalse)
  1048. {
  1049. return false;
  1050. }
  1051. // validate heap32 = new Int32Array(newBuffer); etc.
  1052. while (!mArrayViews.Empty())
  1053. {
  1054. // all views that were instantiated must be replaced in the order which they were instantiated
  1055. AsmJsArrayView * requiredArrayView = mArrayViews.Dequeue();
  1056. pnodeBody = pnodeBody->sxBin.pnode2;
  1057. if (pnodeBody->nop != knopList)
  1058. {
  1059. return false;
  1060. }
  1061. ParseNode * assignNode = pnodeBody->sxBin.pnode1;
  1062. if (assignNode->nop != knopAsg || assignNode->sxBin.pnode1->nop != knopName)
  1063. {
  1064. return false;
  1065. }
  1066. // validate left hand side
  1067. AsmJsSymbol * actualArraySym = LookupIdentifier(assignNode->sxBin.pnode1->name());
  1068. if (requiredArrayView != actualArraySym)
  1069. {
  1070. return false;
  1071. }
  1072. ParseNode * callNode = assignNode->sxBin.pnode2;
  1073. // validate correct argument is passed
  1074. if (callNode->nop != knopNew || !callNode->sxCall.pnodeArgs || callNode->sxCall.pnodeArgs->nop != knopName || callNode->sxCall.pnodeArgs->name()->GetPropertyId() != pnodeArgs->name()->GetPropertyId() || callNode->sxCall.pnodeTarget->nop != knopName)
  1075. {
  1076. return false;
  1077. }
  1078. // validate correct function is being called
  1079. AsmJsSymbol * callTargetSym = LookupIdentifier(callNode->sxCall.pnodeTarget->name());
  1080. if (!callTargetSym || callTargetSym->GetSymbolType() != AsmJsSymbol::TypedArrayBuiltinFunction)
  1081. {
  1082. return false;
  1083. }
  1084. if (requiredArrayView->GetViewType() != callTargetSym->Cast<AsmJsTypedArrayFunction>()->GetViewType())
  1085. {
  1086. return false;
  1087. }
  1088. }
  1089. pnodeBody = pnodeBody->sxBin.pnode2;
  1090. if (pnodeBody->nop != knopList)
  1091. {
  1092. return false;
  1093. }
  1094. // validate buffer = newBuffer;
  1095. ParseNode * assign = pnodeBody->sxBin.pnode1;
  1096. if (assign->nop != knopAsg || assign->sxBin.pnode1->nop != knopName || !mBufferArgName || mBufferArgName->GetPropertyId() != assign->sxBin.pnode1->name()->GetPropertyId() ||
  1097. assign->sxBin.pnode2->nop != knopName || pnodeArgs->name()->GetPropertyId() != assign->sxBin.pnode2->name()->GetPropertyId())
  1098. {
  1099. return false;
  1100. }
  1101. // validate return true;
  1102. pnodeBody = pnodeBody->sxBin.pnode2;
  1103. if (pnodeBody->nop != knopList || pnodeBody->sxBin.pnode2->nop != knopEndCode ||
  1104. pnodeBody->sxBin.pnode1->nop != knopReturn || !pnodeBody->sxBin.pnode1->sxReturn.pnodeExpr || pnodeBody->sxBin.pnode1->sxReturn.pnodeExpr->nop != knopTrue)
  1105. {
  1106. return false;
  1107. }
  1108. // now we should flag this module as containing changeHeap method
  1109. mUsesChangeHeap = true;
  1110. AsmJSByteCodeGenerator::EmitEmptyByteCode(func->GetFuncInfo(), GetByteCodeGenerator(), fncNode);
  1111. return true;
  1112. }
  1113. bool AsmJsModuleCompiler::CheckByteLengthCall(ParseNode * callNode, ParseNode * bufferDecl)
  1114. {
  1115. if (callNode->nop != knopCall || callNode->sxCall.pnodeTarget->nop != knopName)
  1116. {
  1117. return false;
  1118. }
  1119. AsmJsSymbol* funcDecl = LookupIdentifier(callNode->sxCall.pnodeTarget->name());
  1120. if (!funcDecl || funcDecl->GetSymbolType() != AsmJsSymbol::TypedArrayBuiltinFunction)
  1121. {
  1122. return false;
  1123. }
  1124. AsmJsTypedArrayFunction* arrayFunc = funcDecl->Cast<AsmJsTypedArrayFunction>();
  1125. return callNode->sxCall.argCount == 1 &&
  1126. !callNode->sxCall.isApplyCall &&
  1127. !callNode->sxCall.isEvalCall &&
  1128. callNode->sxCall.spreadArgCount == 0 &&
  1129. arrayFunc->GetArrayBuiltInFunction() == AsmJSTypedArrayBuiltin_byteLength &&
  1130. callNode->sxCall.pnodeArgs->nop == knopName &&
  1131. callNode->sxCall.pnodeArgs->name()->GetPropertyId() == bufferDecl->name()->GetPropertyId();
  1132. }
  1133. bool AsmJsModuleCompiler::Fail( ParseNode* usepn, const wchar *error )
  1134. {
  1135. AsmJSCompiler::OutputError(GetScriptContext(), error);
  1136. return false;
  1137. }
  1138. bool AsmJsModuleCompiler::FailName( ParseNode *usepn, const wchar *fmt, PropertyName name )
  1139. {
  1140. AsmJSCompiler::OutputError(GetScriptContext(), fmt, name->Psz());
  1141. return false;
  1142. }
  1143. bool AsmJsModuleCompiler::LookupStandardLibraryMathName( PropertyName name, MathBuiltin *mathBuiltin ) const
  1144. {
  1145. return mStandardLibraryMathNames.TryGetValue( name->GetPropertyId(), mathBuiltin );
  1146. }
  1147. bool AsmJsModuleCompiler::LookupStandardLibraryArrayName(PropertyName name, TypedArrayBuiltin *builtin) const
  1148. {
  1149. return mStandardLibraryArrayNames.TryGetValue(name->GetPropertyId(), builtin);
  1150. }
  1151. void AsmJsModuleCompiler::InitBufferArgName( PropertyName n )
  1152. {
  1153. #if DBG
  1154. Assert( !mBufferArgNameInit );
  1155. mBufferArgNameInit = true;
  1156. #endif
  1157. mBufferArgName = n;
  1158. }
  1159. void AsmJsModuleCompiler::InitForeignArgName( PropertyName n )
  1160. {
  1161. #if DBG
  1162. Assert( !mForeignArgNameInit );
  1163. mForeignArgNameInit = true;
  1164. #endif
  1165. mForeignArgName = n;
  1166. }
  1167. void AsmJsModuleCompiler::InitStdLibArgName( PropertyName n )
  1168. {
  1169. #if DBG
  1170. Assert( !mStdLibArgNameInit );
  1171. mStdLibArgNameInit = true;
  1172. #endif
  1173. mStdLibArgName = n;
  1174. }
  1175. Js::PropertyName AsmJsModuleCompiler::GetStdLibArgName() const
  1176. {
  1177. #if DBG
  1178. Assert( mBufferArgNameInit );
  1179. #endif
  1180. return mStdLibArgName;
  1181. }
  1182. Js::PropertyName AsmJsModuleCompiler::GetForeignArgName() const
  1183. {
  1184. #if DBG
  1185. Assert( mForeignArgNameInit );
  1186. #endif
  1187. return mForeignArgName;
  1188. }
  1189. Js::PropertyName AsmJsModuleCompiler::GetBufferArgName() const
  1190. {
  1191. #if DBG
  1192. Assert( mStdLibArgNameInit );
  1193. #endif
  1194. return mBufferArgName;
  1195. }
  1196. bool AsmJsModuleCompiler::Init()
  1197. {
  1198. if( mInitialised )
  1199. {
  1200. return false;
  1201. }
  1202. mInitialised = true;
  1203. struct MathFunc
  1204. {
  1205. MathFunc( PropertyId id_ = 0, AsmJsMathFunction* val_ = nullptr ) :
  1206. id( id_ ), val( val_ )
  1207. {
  1208. }
  1209. PropertyId id;
  1210. AsmJsMathFunction* val;
  1211. };
  1212. MathFunc mathFunctions[AsmJSMathBuiltinFunction_COUNT];
  1213. // we could move the mathBuiltinFuncname to MathFunc struct
  1214. mathFunctions[AsmJSMathBuiltin_sin ] = MathFunc(PropertyIds::sin , Anew( &mAllocator, AsmJsMathFunction, nullptr, &mAllocator, 1, AsmJSMathBuiltin_sin , OpCodeAsmJs::Sin_Db , AsmJsRetType::Double, AsmJsType::MaybeDouble ));
  1215. mathFunctions[AsmJSMathBuiltin_cos ] = MathFunc(PropertyIds::cos , Anew( &mAllocator, AsmJsMathFunction, nullptr, &mAllocator, 1, AsmJSMathBuiltin_cos , OpCodeAsmJs::Cos_Db , AsmJsRetType::Double, AsmJsType::MaybeDouble ));
  1216. mathFunctions[AsmJSMathBuiltin_tan ] = MathFunc(PropertyIds::tan , Anew( &mAllocator, AsmJsMathFunction, nullptr, &mAllocator, 1, AsmJSMathBuiltin_tan , OpCodeAsmJs::Tan_Db , AsmJsRetType::Double, AsmJsType::MaybeDouble ));
  1217. mathFunctions[AsmJSMathBuiltin_asin ] = MathFunc(PropertyIds::asin , Anew( &mAllocator, AsmJsMathFunction, nullptr, &mAllocator, 1, AsmJSMathBuiltin_asin , OpCodeAsmJs::Asin_Db , AsmJsRetType::Double, AsmJsType::MaybeDouble ));
  1218. mathFunctions[AsmJSMathBuiltin_acos ] = MathFunc(PropertyIds::acos , Anew( &mAllocator, AsmJsMathFunction, nullptr, &mAllocator, 1, AsmJSMathBuiltin_acos , OpCodeAsmJs::Acos_Db , AsmJsRetType::Double, AsmJsType::MaybeDouble ));
  1219. mathFunctions[AsmJSMathBuiltin_atan ] = MathFunc(PropertyIds::atan , Anew( &mAllocator, AsmJsMathFunction, nullptr, &mAllocator, 1, AsmJSMathBuiltin_atan , OpCodeAsmJs::Atan_Db , AsmJsRetType::Double, AsmJsType::MaybeDouble ));
  1220. mathFunctions[AsmJSMathBuiltin_ceil ] = MathFunc(PropertyIds::ceil , Anew( &mAllocator, AsmJsMathFunction, nullptr, &mAllocator, 1, AsmJSMathBuiltin_ceil , OpCodeAsmJs::Ceil_Db , AsmJsRetType::Double, AsmJsType::MaybeDouble ));
  1221. mathFunctions[AsmJSMathBuiltin_floor ] = MathFunc(PropertyIds::floor , Anew( &mAllocator, AsmJsMathFunction, nullptr, &mAllocator, 1, AsmJSMathBuiltin_floor , OpCodeAsmJs::Floor_Db , AsmJsRetType::Double, AsmJsType::MaybeDouble ));
  1222. mathFunctions[AsmJSMathBuiltin_exp ] = MathFunc(PropertyIds::exp , Anew( &mAllocator, AsmJsMathFunction, nullptr, &mAllocator, 1, AsmJSMathBuiltin_exp , OpCodeAsmJs::Exp_Db , AsmJsRetType::Double, AsmJsType::MaybeDouble ));
  1223. mathFunctions[AsmJSMathBuiltin_log ] = MathFunc(PropertyIds::log , Anew( &mAllocator, AsmJsMathFunction, nullptr, &mAllocator, 1, AsmJSMathBuiltin_log , OpCodeAsmJs::Log_Db , AsmJsRetType::Double, AsmJsType::MaybeDouble ));
  1224. mathFunctions[AsmJSMathBuiltin_pow ] = MathFunc(PropertyIds::pow , Anew( &mAllocator, AsmJsMathFunction, nullptr, &mAllocator, 2, AsmJSMathBuiltin_pow , OpCodeAsmJs::Pow_Db , AsmJsRetType::Double, AsmJsType::MaybeDouble, AsmJsType::MaybeDouble ));
  1225. mathFunctions[AsmJSMathBuiltin_sqrt ] = MathFunc(PropertyIds::sqrt , Anew( &mAllocator, AsmJsMathFunction, nullptr, &mAllocator, 1, AsmJSMathBuiltin_sqrt , OpCodeAsmJs::Sqrt_Db , AsmJsRetType::Double, AsmJsType::MaybeDouble ));
  1226. mathFunctions[AsmJSMathBuiltin_abs ] = MathFunc(PropertyIds::abs , Anew( &mAllocator, AsmJsMathFunction, nullptr, &mAllocator, 1, AsmJSMathBuiltin_abs , OpCodeAsmJs::Abs_Db , AsmJsRetType::Double, AsmJsType::MaybeDouble ));
  1227. mathFunctions[AsmJSMathBuiltin_atan2 ] = MathFunc(PropertyIds::atan2 , Anew( &mAllocator, AsmJsMathFunction, nullptr, &mAllocator, 2, AsmJSMathBuiltin_atan2 , OpCodeAsmJs::Atan2_Db , AsmJsRetType::Double, AsmJsType::MaybeDouble, AsmJsType::MaybeDouble ));
  1228. mathFunctions[AsmJSMathBuiltin_imul ] = MathFunc(PropertyIds::imul , Anew( &mAllocator, AsmJsMathFunction, nullptr, &mAllocator, 2, AsmJSMathBuiltin_imul , OpCodeAsmJs::Imul_Int , AsmJsRetType::Signed, AsmJsType::Intish , AsmJsType::Intish ));
  1229. mathFunctions[AsmJSMathBuiltin_fround] = MathFunc(PropertyIds::fround, Anew( &mAllocator, AsmJsMathFunction, nullptr, &mAllocator, 1, AsmJSMathBuiltin_fround, OpCodeAsmJs::Fround_Flt,AsmJsRetType::Float , AsmJsType::Floatish ));
  1230. mathFunctions[AsmJSMathBuiltin_min ] = MathFunc(PropertyIds::min , Anew( &mAllocator, AsmJsMathFunction, nullptr, &mAllocator, 2, AsmJSMathBuiltin_min , OpCodeAsmJs::Min_Db , AsmJsRetType::Double, AsmJsType::MaybeDouble, AsmJsType::MaybeDouble));
  1231. mathFunctions[AsmJSMathBuiltin_max ] = MathFunc(PropertyIds::max , Anew( &mAllocator, AsmJsMathFunction, nullptr, &mAllocator, 2, AsmJSMathBuiltin_max , OpCodeAsmJs::Max_Db , AsmJsRetType::Double, AsmJsType::MaybeDouble, AsmJsType::MaybeDouble));
  1232. mathFunctions[AsmJSMathBuiltin_clz32 ] = MathFunc(PropertyIds::clz32 , Anew( &mAllocator, AsmJsMathFunction, nullptr, &mAllocator, 1, AsmJSMathBuiltin_clz32 , OpCodeAsmJs::Clz32_Int, AsmJsRetType::Fixnum, AsmJsType::Intish));
  1233. mathFunctions[AsmJSMathBuiltin_abs].val->SetOverload(Anew( &mAllocator, AsmJsMathFunction, nullptr, &mAllocator, 1, AsmJSMathBuiltin_abs, OpCodeAsmJs::Abs_Int, AsmJsRetType::Unsigned, AsmJsType::Signed));
  1234. mathFunctions[AsmJSMathBuiltin_min].val->SetOverload(Anew( &mAllocator, AsmJsMathFunction, nullptr, &mAllocator, 2, AsmJSMathBuiltin_min, OpCodeAsmJs::Min_Int, AsmJsRetType::Signed, AsmJsType::Signed, AsmJsType::Signed));
  1235. mathFunctions[AsmJSMathBuiltin_max].val->SetOverload(Anew( &mAllocator, AsmJsMathFunction, nullptr, &mAllocator, 2, AsmJSMathBuiltin_max, OpCodeAsmJs::Max_Int, AsmJsRetType::Signed, AsmJsType::Signed, AsmJsType::Signed));
  1236. //Float Overloads
  1237. mathFunctions[AsmJSMathBuiltin_fround].val->SetOverload(Anew(&mAllocator, AsmJsMathFunction, nullptr, &mAllocator, 1, AsmJSMathBuiltin_fround, OpCodeAsmJs::Fround_Db, AsmJsRetType::Float, AsmJsType::MaybeDouble));
  1238. mathFunctions[AsmJSMathBuiltin_fround].val->SetOverload(Anew(&mAllocator, AsmJsMathFunction, nullptr, &mAllocator, 1, AsmJSMathBuiltin_fround, OpCodeAsmJs::Fround_Int, AsmJsRetType::Float, AsmJsType::Int));// should we split this into signed and unsigned?
  1239. mathFunctions[AsmJSMathBuiltin_abs].val->SetOverload( Anew(&mAllocator, AsmJsMathFunction, nullptr, &mAllocator, 1, AsmJSMathBuiltin_abs, OpCodeAsmJs::Abs_Flt, AsmJsRetType::Floatish, AsmJsType::MaybeFloat));
  1240. mathFunctions[AsmJSMathBuiltin_ceil].val->SetOverload( Anew(&mAllocator, AsmJsMathFunction, nullptr, &mAllocator, 1, AsmJSMathBuiltin_ceil, OpCodeAsmJs::Ceil_Flt, AsmJsRetType::Floatish, AsmJsType::MaybeFloat));
  1241. mathFunctions[AsmJSMathBuiltin_floor].val->SetOverload( Anew(&mAllocator, AsmJsMathFunction, nullptr, &mAllocator, 1, AsmJSMathBuiltin_floor, OpCodeAsmJs::Floor_Flt, AsmJsRetType::Floatish, AsmJsType::MaybeFloat));
  1242. mathFunctions[AsmJSMathBuiltin_sqrt].val->SetOverload( Anew(&mAllocator, AsmJsMathFunction, nullptr, &mAllocator, 1, AsmJSMathBuiltin_sqrt, OpCodeAsmJs::Sqrt_Flt, AsmJsRetType::Floatish, AsmJsType::MaybeFloat));
  1243. for (int i = 0; i < AsmJSMathBuiltinFunction_COUNT ; i++)
  1244. {
  1245. if( !AddStandardLibraryMathName( (PropertyId)mathFunctions[i].id, mathFunctions[i].val, mathFunctions[i].val->GetMathBuiltInFunction() ) )
  1246. {
  1247. return false;
  1248. }
  1249. }
  1250. struct ConstMath
  1251. {
  1252. ConstMath( PropertyId id_, const double* val_, AsmJSMathBuiltinFunction mathLibConstName_):
  1253. id(id_), val(val_), mathLibConstName(mathLibConstName_) { }
  1254. PropertyId id;
  1255. AsmJSMathBuiltinFunction mathLibConstName;
  1256. const double* val;
  1257. };
  1258. ConstMath constMath[] = {
  1259. ConstMath( PropertyIds::E , &Math::E , AsmJSMathBuiltinFunction::AsmJSMathBuiltin_e ),
  1260. ConstMath(PropertyIds::LN10 , &Math::LN10 , AsmJSMathBuiltinFunction::AsmJSMathBuiltin_ln10),
  1261. ConstMath(PropertyIds::LN2 , &Math::LN2 , AsmJSMathBuiltinFunction::AsmJSMathBuiltin_ln2),
  1262. ConstMath(PropertyIds::LOG2E , &Math::LOG2E , AsmJSMathBuiltinFunction::AsmJSMathBuiltin_log2e),
  1263. ConstMath(PropertyIds::LOG10E , &Math::LOG10E , AsmJSMathBuiltinFunction::AsmJSMathBuiltin_log10e),
  1264. ConstMath(PropertyIds::PI , &Math::PI , AsmJSMathBuiltinFunction::AsmJSMathBuiltin_pi),
  1265. ConstMath(PropertyIds::SQRT1_2 , &Math::SQRT1_2 , AsmJSMathBuiltinFunction::AsmJSMathBuiltin_sqrt1_2),
  1266. ConstMath(PropertyIds::SQRT2 , &Math::SQRT2 , AsmJSMathBuiltinFunction::AsmJSMathBuiltin_sqrt2),
  1267. ConstMath(PropertyIds::Infinity , &NumberConstants::POSITIVE_INFINITY, AsmJSMathBuiltinFunction::AsmJSMathBuiltin_infinity),
  1268. ConstMath(PropertyIds::NaN , &NumberConstants::NaN , AsmJSMathBuiltinFunction::AsmJSMathBuiltin_nan),
  1269. };
  1270. const int size = sizeof( constMath ) / sizeof( ConstMath );
  1271. for (int i = 0; i < size ; i++)
  1272. {
  1273. if( !AddStandardLibraryMathName( constMath[i].id, constMath[i].val, constMath[i].mathLibConstName ) )
  1274. {
  1275. return false;
  1276. }
  1277. }
  1278. struct ArrayFunc
  1279. {
  1280. ArrayFunc(PropertyId id_ = 0, AsmJsTypedArrayFunction* val_ = nullptr) :
  1281. id(id_), val(val_)
  1282. {
  1283. }
  1284. PropertyId id;
  1285. AsmJsTypedArrayFunction* val;
  1286. };
  1287. ArrayFunc arrayFunctions[AsmJSMathBuiltinFunction_COUNT];
  1288. arrayFunctions[AsmJSTypedArrayBuiltin_Int8Array ] = ArrayFunc(PropertyIds::Int8Array, Anew(&mAllocator, AsmJsTypedArrayFunction, nullptr, &mAllocator, AsmJSTypedArrayBuiltin_Int8Array, ArrayBufferView::TYPE_INT8));
  1289. arrayFunctions[AsmJSTypedArrayBuiltin_Uint8Array ] = ArrayFunc(PropertyIds::Uint8Array, Anew(&mAllocator, AsmJsTypedArrayFunction, nullptr, &mAllocator, AsmJSTypedArrayBuiltin_Uint8Array, ArrayBufferView::TYPE_UINT8));
  1290. arrayFunctions[AsmJSTypedArrayBuiltin_Int16Array ] = ArrayFunc(PropertyIds::Int16Array, Anew(&mAllocator, AsmJsTypedArrayFunction, nullptr, &mAllocator, AsmJSTypedArrayBuiltin_Int16Array, ArrayBufferView::TYPE_INT16));
  1291. arrayFunctions[AsmJSTypedArrayBuiltin_Uint16Array ] = ArrayFunc(PropertyIds::Uint16Array, Anew(&mAllocator, AsmJsTypedArrayFunction, nullptr, &mAllocator, AsmJSTypedArrayBuiltin_Uint16Array, ArrayBufferView::TYPE_UINT16));
  1292. arrayFunctions[AsmJSTypedArrayBuiltin_Int32Array ] = ArrayFunc(PropertyIds::Int32Array, Anew(&mAllocator, AsmJsTypedArrayFunction, nullptr, &mAllocator, AsmJSTypedArrayBuiltin_Int32Array, ArrayBufferView::TYPE_INT32));
  1293. arrayFunctions[AsmJSTypedArrayBuiltin_Uint32Array ] = ArrayFunc(PropertyIds::Uint32Array, Anew(&mAllocator, AsmJsTypedArrayFunction, nullptr, &mAllocator, AsmJSTypedArrayBuiltin_Uint32Array, ArrayBufferView::TYPE_UINT32));
  1294. arrayFunctions[AsmJSTypedArrayBuiltin_Float32Array] = ArrayFunc(PropertyIds::Float32Array, Anew(&mAllocator, AsmJsTypedArrayFunction, nullptr, &mAllocator, AsmJSTypedArrayBuiltin_Float32Array, ArrayBufferView::TYPE_FLOAT32));
  1295. arrayFunctions[AsmJSTypedArrayBuiltin_Float64Array] = ArrayFunc(PropertyIds::Float64Array, Anew(&mAllocator, AsmJsTypedArrayFunction, nullptr, &mAllocator, AsmJSTypedArrayBuiltin_Float64Array, ArrayBufferView::TYPE_FLOAT64));
  1296. arrayFunctions[AsmJSTypedArrayBuiltin_byteLength ] = ArrayFunc(PropertyIds::byteLength, Anew(&mAllocator, AsmJsTypedArrayFunction, nullptr, &mAllocator, AsmJSTypedArrayBuiltin_byteLength, ArrayBufferView::TYPE_INVALID));
  1297. for (int i = 0; i < AsmJSTypedArrayBuiltin_COUNT; i++)
  1298. {
  1299. if (!AddStandardLibraryArrayName((PropertyId)arrayFunctions[i].id, arrayFunctions[i].val, arrayFunctions[i].val->GetArrayBuiltInFunction()))
  1300. {
  1301. return false;
  1302. }
  1303. }
  1304. // similar to math functions maps initialization.
  1305. if (IsSimdjsEnabled())
  1306. {
  1307. if (!InitSIMDBuiltins())
  1308. {
  1309. return false;
  1310. }
  1311. }
  1312. return true;
  1313. }
  1314. bool AsmJsModuleCompiler::InitSIMDBuiltins()
  1315. {
  1316. struct SIMDFunc
  1317. {
  1318. SIMDFunc(PropertyId id_ = 0, AsmJsSIMDFunction* val_ = nullptr) :
  1319. id(id_), val(val_)
  1320. {
  1321. }
  1322. PropertyId id;
  1323. AsmJsSIMDFunction* val;
  1324. };
  1325. SIMDFunc simdFunctions[AsmJsSIMDBuiltin_COUNT];
  1326. // !! NOTE: Keep these grouped by SIMD type
  1327. /* Int32x4 builtins*/
  1328. //-------------------
  1329. simdFunctions[AsmJsSIMDBuiltin_Int32x4] = SIMDFunc(PropertyIds::Int32x4, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 4, AsmJsSIMDBuiltin_Int32x4, OpCodeAsmJs::Simd128_IntsToI4, AsmJsRetType::Int32x4, AsmJsType::Intish, AsmJsType::Intish, AsmJsType::Intish, AsmJsType::Intish));
  1330. simdFunctions[AsmJsSIMDBuiltin_int32x4_check] = SIMDFunc(PropertyIds::check, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 1, AsmJsSIMDBuiltin_int32x4_check, OpCodeAsmJs::Simd128_Ld_I4 /*no dynamic checks*/, AsmJsRetType::Int32x4, AsmJsType::Int32x4));
  1331. simdFunctions[AsmJsSIMDBuiltin_int32x4_splat] = SIMDFunc(PropertyIds::splat, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 1, AsmJsSIMDBuiltin_int32x4_splat, OpCodeAsmJs::Simd128_Splat_I4, AsmJsRetType::Int32x4, AsmJsType::Int));
  1332. // Q: Is this operation supported in ASMJS ? We don't have bool type.
  1333. //simdFunctions[AsmJsSIMDBuiltin_int32x4_bool] = SIMDFunc(PropertyIds::bool_, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 4, AsmJsSIMDBuiltin_int32x4_bool, OpCodeAsmJs::Simd128_Bool_I4, AsmJsRetType::Int32x4, AsmJsType::Int, AsmJsType::Int, AsmJsType::Int, AsmJsType::Int));
  1334. simdFunctions[AsmJsSIMDBuiltin_int32x4_fromFloat64x2] = SIMDFunc(PropertyIds::fromFloat64x2, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 1, AsmJsSIMDBuiltin_int32x4_fromFloat64x2, OpCodeAsmJs::Simd128_FromFloat64x2_I4, AsmJsRetType::Int32x4, AsmJsType::Float64x2));
  1335. simdFunctions[AsmJsSIMDBuiltin_int32x4_fromFloat64x2Bits] = SIMDFunc(PropertyIds::fromFloat64x2Bits, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 1, AsmJsSIMDBuiltin_int32x4_fromFloat64x2Bits, OpCodeAsmJs::Simd128_FromFloat64x2Bits_I4, AsmJsRetType::Int32x4, AsmJsType::Float64x2));
  1336. simdFunctions[AsmJsSIMDBuiltin_int32x4_fromFloat32x4] = SIMDFunc(PropertyIds::fromFloat32x4, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 1, AsmJsSIMDBuiltin_int32x4_fromFloat32x4, OpCodeAsmJs::Simd128_FromFloat32x4_I4, AsmJsRetType::Int32x4, AsmJsType::Float32x4));
  1337. simdFunctions[AsmJsSIMDBuiltin_int32x4_fromFloat32x4Bits] = SIMDFunc(PropertyIds::fromFloat32x4Bits, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 1, AsmJsSIMDBuiltin_int32x4_fromFloat32x4Bits, OpCodeAsmJs::Simd128_FromFloat32x4Bits_I4, AsmJsRetType::Int32x4, AsmJsType::Float32x4));
  1338. simdFunctions[AsmJsSIMDBuiltin_int32x4_neg] = SIMDFunc(PropertyIds::neg, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 1, AsmJsSIMDBuiltin_int32x4_neg, OpCodeAsmJs::Simd128_Neg_I4, AsmJsRetType::Int32x4, AsmJsType::Int32x4));
  1339. simdFunctions[AsmJsSIMDBuiltin_int32x4_add] = SIMDFunc(PropertyIds::add, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_int32x4_add, OpCodeAsmJs::Simd128_Add_I4, AsmJsRetType::Int32x4, AsmJsType::Int32x4, AsmJsType::Int32x4));
  1340. simdFunctions[AsmJsSIMDBuiltin_int32x4_sub] = SIMDFunc(PropertyIds::sub, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_int32x4_sub, OpCodeAsmJs::Simd128_Sub_I4, AsmJsRetType::Int32x4, AsmJsType::Int32x4, AsmJsType::Int32x4));
  1341. simdFunctions[AsmJsSIMDBuiltin_int32x4_mul] = SIMDFunc(PropertyIds::mul, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_int32x4_mul, OpCodeAsmJs::Simd128_Mul_I4, AsmJsRetType::Int32x4, AsmJsType::Int32x4, AsmJsType::Int32x4));
  1342. // TODO: Enable after fix in lib
  1343. simdFunctions[AsmJsSIMDBuiltin_int32x4_swizzle] = SIMDFunc(PropertyIds::swizzle, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 5, AsmJsSIMDBuiltin_int32x4_swizzle, OpCodeAsmJs::Simd128_Swizzle_I4, AsmJsRetType::Int32x4, AsmJsType::Int32x4, AsmJsType::Int, AsmJsType::Int, AsmJsType::Int, AsmJsType::Int));
  1344. simdFunctions[AsmJsSIMDBuiltin_int32x4_shuffle] = SIMDFunc(PropertyIds::shuffle, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 6, AsmJsSIMDBuiltin_int32x4_shuffle, OpCodeAsmJs::Simd128_Shuffle_I4, AsmJsRetType::Int32x4, AsmJsType::Int32x4, AsmJsType::Int32x4, AsmJsType::Int, AsmJsType::Int, AsmJsType::Int, AsmJsType::Int));
  1345. simdFunctions[AsmJsSIMDBuiltin_int32x4_extractLane] = SIMDFunc(PropertyIds::extractLane, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_int32x4_extractLane, OpCodeAsmJs::Simd128_ExtractLane_I4, AsmJsRetType::Signed, AsmJsType::Int32x4, AsmJsType::Int));
  1346. simdFunctions[AsmJsSIMDBuiltin_int32x4_replaceLane] = SIMDFunc(PropertyIds::replaceLane, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 3, AsmJsSIMDBuiltin_int32x4_replaceLane, OpCodeAsmJs::Simd128_ReplaceLane_I4, AsmJsRetType::Int32x4, AsmJsType::Int32x4, AsmJsType::Int, AsmJsType::Int));
  1347. simdFunctions[AsmJsSIMDBuiltin_int32x4_lessThan] = SIMDFunc(PropertyIds::lessThan, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_int32x4_lessThan, OpCodeAsmJs::Simd128_Lt_I4, AsmJsRetType::Int32x4, AsmJsType::Int32x4, AsmJsType::Int32x4));
  1348. simdFunctions[AsmJsSIMDBuiltin_int32x4_equal] = SIMDFunc(PropertyIds::equal, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_int32x4_equal, OpCodeAsmJs::Simd128_Eq_I4, AsmJsRetType::Int32x4, AsmJsType::Int32x4, AsmJsType::Int32x4));
  1349. simdFunctions[AsmJsSIMDBuiltin_int32x4_greaterThan] = SIMDFunc(PropertyIds::greaterThan, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_int32x4_greaterThan, OpCodeAsmJs::Simd128_Gt_I4, AsmJsRetType::Int32x4, AsmJsType::Int32x4, AsmJsType::Int32x4));
  1350. simdFunctions[AsmJsSIMDBuiltin_int32x4_select] = SIMDFunc(PropertyIds::select, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 3, AsmJsSIMDBuiltin_int32x4_select, OpCodeAsmJs::Simd128_Select_I4, AsmJsRetType::Int32x4, AsmJsType::Int32x4, AsmJsType::Int32x4, AsmJsType::Int32x4));
  1351. simdFunctions[AsmJsSIMDBuiltin_int32x4_and] = SIMDFunc(PropertyIds::and, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_int32x4_and, OpCodeAsmJs::Simd128_And_I4, AsmJsRetType::Int32x4, AsmJsType::Int32x4, AsmJsType::Int32x4));
  1352. simdFunctions[AsmJsSIMDBuiltin_int32x4_or] = SIMDFunc(PropertyIds::or, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_int32x4_or, OpCodeAsmJs::Simd128_Or_I4, AsmJsRetType::Int32x4, AsmJsType::Int32x4, AsmJsType::Int32x4));
  1353. simdFunctions[AsmJsSIMDBuiltin_int32x4_xor] = SIMDFunc(PropertyIds::xor, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_int32x4_xor, OpCodeAsmJs::Simd128_Xor_I4, AsmJsRetType::Int32x4, AsmJsType::Int32x4, AsmJsType::Int32x4));
  1354. simdFunctions[AsmJsSIMDBuiltin_int32x4_not] = SIMDFunc(PropertyIds::not, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 1, AsmJsSIMDBuiltin_int32x4_not, OpCodeAsmJs::Simd128_Not_I4, AsmJsRetType::Int32x4, AsmJsType::Int32x4));
  1355. // Loads and Stores
  1356. // We fill Void for the tarray type. This is ok since we special handle these ops.
  1357. simdFunctions[AsmJsSIMDBuiltin_int32x4_load] = SIMDFunc(PropertyIds::load, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_int32x4_load, OpCodeAsmJs::Simd128_LdArr_I4, AsmJsRetType::Int32x4, AsmJsType::Void, AsmJsType::Int));
  1358. simdFunctions[AsmJsSIMDBuiltin_int32x4_load1] = SIMDFunc(PropertyIds::load1, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_int32x4_load1, OpCodeAsmJs::Simd128_LdArr_I4, AsmJsRetType::Int32x4, AsmJsType::Void, AsmJsType::Int));
  1359. simdFunctions[AsmJsSIMDBuiltin_int32x4_load2] = SIMDFunc(PropertyIds::load2, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_int32x4_load2, OpCodeAsmJs::Simd128_LdArr_I4, AsmJsRetType::Int32x4, AsmJsType::Void, AsmJsType::Int));
  1360. simdFunctions[AsmJsSIMDBuiltin_int32x4_load3] = SIMDFunc(PropertyIds::load3, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_int32x4_load3, OpCodeAsmJs::Simd128_LdArr_I4, AsmJsRetType::Int32x4, AsmJsType::Void, AsmJsType::Int));
  1361. simdFunctions[AsmJsSIMDBuiltin_int32x4_store] = SIMDFunc(PropertyIds::store, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 3, AsmJsSIMDBuiltin_int32x4_store, OpCodeAsmJs::Simd128_StArr_I4, AsmJsRetType::Int32x4, AsmJsType::Void, AsmJsType::Int, AsmJsType::Int32x4));
  1362. simdFunctions[AsmJsSIMDBuiltin_int32x4_store1] = SIMDFunc(PropertyIds::store1, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 3, AsmJsSIMDBuiltin_int32x4_store1, OpCodeAsmJs::Simd128_StArr_I4, AsmJsRetType::Int32x4, AsmJsType::Void, AsmJsType::Int, AsmJsType::Int32x4));
  1363. simdFunctions[AsmJsSIMDBuiltin_int32x4_store2] = SIMDFunc(PropertyIds::store2, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 3, AsmJsSIMDBuiltin_int32x4_store2, OpCodeAsmJs::Simd128_StArr_I4, AsmJsRetType::Int32x4, AsmJsType::Void, AsmJsType::Int, AsmJsType::Int32x4));
  1364. simdFunctions[AsmJsSIMDBuiltin_int32x4_store3] = SIMDFunc(PropertyIds::store3, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 3, AsmJsSIMDBuiltin_int32x4_store3, OpCodeAsmJs::Simd128_StArr_I4, AsmJsRetType::Int32x4, AsmJsType::Void, AsmJsType::Int, AsmJsType::Int32x4));
  1365. /* Float32x4 builtins*/
  1366. //-------------------
  1367. simdFunctions[AsmJsSIMDBuiltin_Float32x4] = SIMDFunc(PropertyIds::Float32x4, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 4, AsmJsSIMDBuiltin_Float32x4, OpCodeAsmJs::Simd128_FloatsToF4, AsmJsRetType::Float32x4, AsmJsType::FloatishDoubleLit, AsmJsType::FloatishDoubleLit, AsmJsType::FloatishDoubleLit, AsmJsType::FloatishDoubleLit));
  1368. simdFunctions[AsmJsSIMDBuiltin_float32x4_check] = SIMDFunc(PropertyIds::check, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 1, AsmJsSIMDBuiltin_float32x4_check, OpCodeAsmJs::Simd128_Ld_F4 /*no dynamic checks*/, AsmJsRetType::Float32x4, AsmJsType::Float32x4));
  1369. simdFunctions[AsmJsSIMDBuiltin_float32x4_splat] = SIMDFunc(PropertyIds::splat, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 1, AsmJsSIMDBuiltin_float32x4_splat, OpCodeAsmJs::Simd128_Splat_F4, AsmJsRetType::Float32x4, AsmJsType::FloatishDoubleLit));
  1370. simdFunctions[AsmJsSIMDBuiltin_float32x4_fromFloat64x2] = SIMDFunc(PropertyIds::fromFloat64x2, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 1, AsmJsSIMDBuiltin_float32x4_fromFloat64x2, OpCodeAsmJs::Simd128_FromFloat64x2_F4, AsmJsRetType::Float32x4, AsmJsType::Float64x2));
  1371. simdFunctions[AsmJsSIMDBuiltin_float32x4_fromFloat64x2Bits] = SIMDFunc(PropertyIds::fromFloat64x2Bits, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 1, AsmJsSIMDBuiltin_float32x4_fromFloat64x2Bits, OpCodeAsmJs::Simd128_FromFloat64x2Bits_F4, AsmJsRetType::Float32x4, AsmJsType::Float64x2));
  1372. simdFunctions[AsmJsSIMDBuiltin_float32x4_fromInt32x4] = SIMDFunc(PropertyIds::fromInt32x4, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 1, AsmJsSIMDBuiltin_float32x4_fromInt32x4, OpCodeAsmJs::Simd128_FromInt32x4_F4, AsmJsRetType::Float32x4, AsmJsType::Int32x4));
  1373. simdFunctions[AsmJsSIMDBuiltin_float32x4_fromInt32x4Bits] = SIMDFunc(PropertyIds::fromInt32x4Bits, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 1, AsmJsSIMDBuiltin_float32x4_fromInt32x4Bits, OpCodeAsmJs::Simd128_FromInt32x4Bits_F4, AsmJsRetType::Float32x4, AsmJsType::Int32x4));
  1374. simdFunctions[AsmJsSIMDBuiltin_float32x4_abs] = SIMDFunc(PropertyIds::abs, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 1, AsmJsSIMDBuiltin_float32x4_abs, OpCodeAsmJs::Simd128_Abs_F4, AsmJsRetType::Float32x4, AsmJsType::Float32x4));
  1375. simdFunctions[AsmJsSIMDBuiltin_float32x4_neg] = SIMDFunc(PropertyIds::neg, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 1, AsmJsSIMDBuiltin_float32x4_neg, OpCodeAsmJs::Simd128_Neg_F4, AsmJsRetType::Float32x4, AsmJsType::Float32x4));
  1376. simdFunctions[AsmJsSIMDBuiltin_float32x4_add] = SIMDFunc(PropertyIds::add, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float32x4_add, OpCodeAsmJs::Simd128_Add_F4, AsmJsRetType::Float32x4, AsmJsType::Float32x4, AsmJsType::Float32x4));
  1377. simdFunctions[AsmJsSIMDBuiltin_float32x4_sub] = SIMDFunc(PropertyIds::sub, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float32x4_sub, OpCodeAsmJs::Simd128_Sub_F4, AsmJsRetType::Float32x4, AsmJsType::Float32x4, AsmJsType::Float32x4));
  1378. simdFunctions[AsmJsSIMDBuiltin_float32x4_mul] = SIMDFunc(PropertyIds::mul, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float32x4_mul, OpCodeAsmJs::Simd128_Mul_F4, AsmJsRetType::Float32x4, AsmJsType::Float32x4, AsmJsType::Float32x4));
  1379. simdFunctions[AsmJsSIMDBuiltin_float32x4_div] = SIMDFunc(PropertyIds::div, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float32x4_div, OpCodeAsmJs::Simd128_Div_F4, AsmJsRetType::Float32x4, AsmJsType::Float32x4, AsmJsType::Float32x4));
  1380. simdFunctions[AsmJsSIMDBuiltin_float32x4_clamp] = SIMDFunc(PropertyIds::clamp, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 3, AsmJsSIMDBuiltin_float32x4_clamp, OpCodeAsmJs::Simd128_Clamp_F4, AsmJsRetType::Float32x4, AsmJsType::Float32x4, AsmJsType::Float32x4, AsmJsType::Float32x4));
  1381. simdFunctions[AsmJsSIMDBuiltin_float32x4_min] = SIMDFunc(PropertyIds::min, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float32x4_min, OpCodeAsmJs::Simd128_Min_F4, AsmJsRetType::Float32x4, AsmJsType::Float32x4, AsmJsType::Float32x4));
  1382. simdFunctions[AsmJsSIMDBuiltin_float32x4_max] = SIMDFunc(PropertyIds::max, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float32x4_max, OpCodeAsmJs::Simd128_Max_F4, AsmJsRetType::Float32x4, AsmJsType::Float32x4, AsmJsType::Float32x4));
  1383. simdFunctions[AsmJsSIMDBuiltin_float32x4_reciprocal] = SIMDFunc(PropertyIds::reciprocal, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 1, AsmJsSIMDBuiltin_float32x4_reciprocal, OpCodeAsmJs::Simd128_Rcp_F4, AsmJsRetType::Float32x4, AsmJsType::Float32x4));
  1384. simdFunctions[AsmJsSIMDBuiltin_float32x4_reciprocalSqrt] = SIMDFunc(PropertyIds::reciprocalSqrt, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 1, AsmJsSIMDBuiltin_float32x4_reciprocalSqrt, OpCodeAsmJs::Simd128_RcpSqrt_F4, AsmJsRetType::Float32x4, AsmJsType::Float32x4));
  1385. simdFunctions[AsmJsSIMDBuiltin_float32x4_sqrt] = SIMDFunc(PropertyIds::sqrt, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 1, AsmJsSIMDBuiltin_float32x4_sqrt, OpCodeAsmJs::Simd128_Sqrt_F4, AsmJsRetType::Float32x4, AsmJsType::Float32x4));
  1386. simdFunctions[AsmJsSIMDBuiltin_float32x4_swizzle] = SIMDFunc(PropertyIds::swizzle, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 5, AsmJsSIMDBuiltin_float32x4_swizzle, OpCodeAsmJs::Simd128_Swizzle_F4, AsmJsRetType::Float32x4, AsmJsType::Float32x4, AsmJsType::Int, AsmJsType::Int, AsmJsType::Int, AsmJsType::Int));
  1387. simdFunctions[AsmJsSIMDBuiltin_float32x4_shuffle] = SIMDFunc(PropertyIds::shuffle, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 6, AsmJsSIMDBuiltin_float32x4_shuffle, OpCodeAsmJs::Simd128_Shuffle_F4, AsmJsRetType::Float32x4, AsmJsType::Float32x4, AsmJsType::Float32x4, AsmJsType::Int, AsmJsType::Int, AsmJsType::Int, AsmJsType::Int));
  1388. simdFunctions[AsmJsSIMDBuiltin_float32x4_extractLane] = SIMDFunc(PropertyIds::extractLane, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float32x4_extractLane, OpCodeAsmJs::Simd128_ExtractLane_F4, AsmJsRetType::Float, AsmJsType::Float32x4, AsmJsType::Int));
  1389. simdFunctions[AsmJsSIMDBuiltin_float32x4_replaceLane] = SIMDFunc(PropertyIds::replaceLane, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 3, AsmJsSIMDBuiltin_float32x4_replaceLane, OpCodeAsmJs::Simd128_ReplaceLane_F4, AsmJsRetType::Float32x4, AsmJsType::Float32x4, AsmJsType::Int, AsmJsType::FloatishDoubleLit));
  1390. simdFunctions[AsmJsSIMDBuiltin_float32x4_lessThan] = SIMDFunc(PropertyIds::lessThan, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float32x4_lessThan, OpCodeAsmJs::Simd128_Lt_F4, AsmJsRetType::Int32x4, AsmJsType::Float32x4, AsmJsType::Float32x4));
  1391. simdFunctions[AsmJsSIMDBuiltin_float32x4_lessThanOrEqual] = SIMDFunc(PropertyIds::lessThanOrEqual, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float32x4_lessThanOrEqual, OpCodeAsmJs::Simd128_LtEq_F4, AsmJsRetType::Int32x4, AsmJsType::Float32x4, AsmJsType::Float32x4));
  1392. simdFunctions[AsmJsSIMDBuiltin_float32x4_equal] = SIMDFunc(PropertyIds::equal, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float32x4_equal, OpCodeAsmJs::Simd128_Eq_F4, AsmJsRetType::Int32x4, AsmJsType::Float32x4, AsmJsType::Float32x4));
  1393. simdFunctions[AsmJsSIMDBuiltin_float32x4_notEqual] = SIMDFunc(PropertyIds::notEqual, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float32x4_notEqual, OpCodeAsmJs::Simd128_Neq_F4, AsmJsRetType::Int32x4, AsmJsType::Float32x4, AsmJsType::Float32x4));
  1394. simdFunctions[AsmJsSIMDBuiltin_float32x4_greaterThan] = SIMDFunc(PropertyIds::greaterThan, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float32x4_greaterThan, OpCodeAsmJs::Simd128_Gt_F4, AsmJsRetType::Int32x4, AsmJsType::Float32x4, AsmJsType::Float32x4));
  1395. simdFunctions[AsmJsSIMDBuiltin_float32x4_greaterThanOrEqual]= SIMDFunc(PropertyIds::greaterThanOrEqual, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float32x4_greaterThanOrEqual, OpCodeAsmJs::Simd128_GtEq_F4, AsmJsRetType::Int32x4, AsmJsType::Float32x4, AsmJsType::Float32x4));
  1396. simdFunctions[AsmJsSIMDBuiltin_float32x4_select] = SIMDFunc(PropertyIds::select, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 3, AsmJsSIMDBuiltin_float32x4_select, OpCodeAsmJs::Simd128_Select_F4, AsmJsRetType::Float32x4, AsmJsType::Int32x4, AsmJsType::Float32x4, AsmJsType::Float32x4));
  1397. simdFunctions[AsmJsSIMDBuiltin_float32x4_and] = SIMDFunc(PropertyIds::and, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float32x4_and, OpCodeAsmJs::Simd128_And_F4, AsmJsRetType::Float32x4, AsmJsType::Float32x4, AsmJsType::Float32x4));
  1398. simdFunctions[AsmJsSIMDBuiltin_float32x4_or] = SIMDFunc(PropertyIds::or, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float32x4_or, OpCodeAsmJs::Simd128_Or_F4, AsmJsRetType::Float32x4, AsmJsType::Float32x4, AsmJsType::Float32x4));
  1399. simdFunctions[AsmJsSIMDBuiltin_float32x4_xor] = SIMDFunc(PropertyIds::xor, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float32x4_xor, OpCodeAsmJs::Simd128_Xor_F4, AsmJsRetType::Float32x4, AsmJsType::Float32x4, AsmJsType::Float32x4));
  1400. simdFunctions[AsmJsSIMDBuiltin_float32x4_not] = SIMDFunc(PropertyIds::not, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 1, AsmJsSIMDBuiltin_float32x4_not, OpCodeAsmJs::Simd128_Not_F4, AsmJsRetType::Float32x4, AsmJsType::Float32x4));
  1401. simdFunctions[AsmJsSIMDBuiltin_float32x4_load] = SIMDFunc(PropertyIds::load, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float32x4_load, OpCodeAsmJs::Simd128_LdArr_F4, AsmJsRetType::Float32x4, AsmJsType::Void, AsmJsType::Int));
  1402. simdFunctions[AsmJsSIMDBuiltin_float32x4_load1] = SIMDFunc(PropertyIds::load1, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float32x4_load1, OpCodeAsmJs::Simd128_LdArr_F4, AsmJsRetType::Float32x4, AsmJsType::Void, AsmJsType::Int));
  1403. simdFunctions[AsmJsSIMDBuiltin_float32x4_load2] = SIMDFunc(PropertyIds::load2, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float32x4_load2, OpCodeAsmJs::Simd128_LdArr_F4, AsmJsRetType::Float32x4, AsmJsType::Void, AsmJsType::Int));
  1404. simdFunctions[AsmJsSIMDBuiltin_float32x4_load3] = SIMDFunc(PropertyIds::load3, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float32x4_load3, OpCodeAsmJs::Simd128_LdArr_F4, AsmJsRetType::Float32x4, AsmJsType::Void, AsmJsType::Int));
  1405. simdFunctions[AsmJsSIMDBuiltin_float32x4_store] = SIMDFunc(PropertyIds::store, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 3, AsmJsSIMDBuiltin_float32x4_store, OpCodeAsmJs::Simd128_StArr_F4, AsmJsRetType::Float32x4, AsmJsType::Void, AsmJsType::Int, AsmJsType::Float32x4));
  1406. simdFunctions[AsmJsSIMDBuiltin_float32x4_store1] = SIMDFunc(PropertyIds::store1, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 3, AsmJsSIMDBuiltin_float32x4_store1, OpCodeAsmJs::Simd128_StArr_F4, AsmJsRetType::Float32x4, AsmJsType::Void, AsmJsType::Int, AsmJsType::Float32x4));
  1407. simdFunctions[AsmJsSIMDBuiltin_float32x4_store2] = SIMDFunc(PropertyIds::store2, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 3, AsmJsSIMDBuiltin_float32x4_store2, OpCodeAsmJs::Simd128_StArr_F4, AsmJsRetType::Float32x4, AsmJsType::Void, AsmJsType::Int, AsmJsType::Float32x4));
  1408. simdFunctions[AsmJsSIMDBuiltin_float32x4_store3] = SIMDFunc(PropertyIds::store3, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 3, AsmJsSIMDBuiltin_float32x4_store3, OpCodeAsmJs::Simd128_StArr_F4, AsmJsRetType::Float32x4, AsmJsType::Void, AsmJsType::Int, AsmJsType::Float32x4));
  1409. /* Float64x2 builtins*/
  1410. //-------------------
  1411. simdFunctions[AsmJsSIMDBuiltin_Float64x2] = SIMDFunc(PropertyIds::Float64x2, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_Float64x2, OpCodeAsmJs::Simd128_DoublesToD2, AsmJsRetType::Float64x2, AsmJsType::MaybeDouble, AsmJsType::MaybeDouble));
  1412. simdFunctions[AsmJsSIMDBuiltin_float64x2_check] = SIMDFunc(PropertyIds::check, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 1, AsmJsSIMDBuiltin_float64x2_check, OpCodeAsmJs::Simd128_Ld_D2 /*no dynamic checks*/, AsmJsRetType::Float64x2, AsmJsType::Float64x2));
  1413. simdFunctions[AsmJsSIMDBuiltin_float64x2_splat] = SIMDFunc(PropertyIds::splat, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 1, AsmJsSIMDBuiltin_float64x2_splat, OpCodeAsmJs::Simd128_Splat_D2, AsmJsRetType::Float64x2, AsmJsType::Double));
  1414. simdFunctions[AsmJsSIMDBuiltin_float64x2_fromFloat32x4] = SIMDFunc(PropertyIds::fromFloat32x4, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 1, AsmJsSIMDBuiltin_float64x2_fromFloat32x4, OpCodeAsmJs::Simd128_FromFloat32x4_D2, AsmJsRetType::Float64x2, AsmJsType::Float32x4));
  1415. simdFunctions[AsmJsSIMDBuiltin_float64x2_fromFloat32x4Bits] = SIMDFunc(PropertyIds::fromFloat32x4Bits, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 1, AsmJsSIMDBuiltin_float64x2_fromFloat32x4Bits, OpCodeAsmJs::Simd128_FromFloat32x4Bits_D2, AsmJsRetType::Float64x2, AsmJsType::Float32x4));
  1416. simdFunctions[AsmJsSIMDBuiltin_float64x2_fromInt32x4] = SIMDFunc(PropertyIds::fromInt32x4, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 1, AsmJsSIMDBuiltin_float64x2_fromInt32x4, OpCodeAsmJs::Simd128_FromInt32x4_D2, AsmJsRetType::Float64x2, AsmJsType::Int32x4));
  1417. simdFunctions[AsmJsSIMDBuiltin_float64x2_fromInt32x4Bits] = SIMDFunc(PropertyIds::fromInt32x4Bits, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 1, AsmJsSIMDBuiltin_float64x2_fromInt32x4Bits, OpCodeAsmJs::Simd128_FromInt32x4Bits_D2, AsmJsRetType::Float64x2, AsmJsType::Int32x4));
  1418. simdFunctions[AsmJsSIMDBuiltin_float64x2_abs] = SIMDFunc(PropertyIds::abs, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 1, AsmJsSIMDBuiltin_float64x2_abs, OpCodeAsmJs::Simd128_Abs_D2, AsmJsRetType::Float64x2, AsmJsType::Float64x2));
  1419. simdFunctions[AsmJsSIMDBuiltin_float64x2_neg] = SIMDFunc(PropertyIds::neg, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 1, AsmJsSIMDBuiltin_float64x2_neg, OpCodeAsmJs::Simd128_Neg_D2, AsmJsRetType::Float64x2, AsmJsType::Float64x2));
  1420. simdFunctions[AsmJsSIMDBuiltin_float64x2_add] = SIMDFunc(PropertyIds::add, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float64x2_add, OpCodeAsmJs::Simd128_Add_D2, AsmJsRetType::Float64x2, AsmJsType::Float64x2, AsmJsType::Float64x2));
  1421. simdFunctions[AsmJsSIMDBuiltin_float64x2_sub] = SIMDFunc(PropertyIds::sub, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float64x2_sub, OpCodeAsmJs::Simd128_Sub_D2, AsmJsRetType::Float64x2, AsmJsType::Float64x2, AsmJsType::Float64x2));
  1422. simdFunctions[AsmJsSIMDBuiltin_float64x2_mul] = SIMDFunc(PropertyIds::mul, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float64x2_mul, OpCodeAsmJs::Simd128_Mul_D2, AsmJsRetType::Float64x2, AsmJsType::Float64x2, AsmJsType::Float64x2));
  1423. simdFunctions[AsmJsSIMDBuiltin_float64x2_div] = SIMDFunc(PropertyIds::div, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float64x2_div, OpCodeAsmJs::Simd128_Div_D2, AsmJsRetType::Float64x2, AsmJsType::Float64x2, AsmJsType::Float64x2));
  1424. simdFunctions[AsmJsSIMDBuiltin_float64x2_clamp] = SIMDFunc(PropertyIds::clamp, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 3, AsmJsSIMDBuiltin_float64x2_clamp, OpCodeAsmJs::Simd128_Clamp_D2, AsmJsRetType::Float64x2, AsmJsType::Float64x2, AsmJsType::Float64x2, AsmJsType::Float64x2));
  1425. simdFunctions[AsmJsSIMDBuiltin_float64x2_min] = SIMDFunc(PropertyIds::min, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float64x2_min, OpCodeAsmJs::Simd128_Min_D2, AsmJsRetType::Float64x2, AsmJsType::Float64x2, AsmJsType::Float64x2));
  1426. simdFunctions[AsmJsSIMDBuiltin_float64x2_max] = SIMDFunc(PropertyIds::max, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float64x2_max, OpCodeAsmJs::Simd128_Max_D2, AsmJsRetType::Float64x2, AsmJsType::Float64x2, AsmJsType::Float64x2));
  1427. simdFunctions[AsmJsSIMDBuiltin_float64x2_reciprocal] = SIMDFunc(PropertyIds::reciprocal, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 1, AsmJsSIMDBuiltin_float64x2_reciprocal, OpCodeAsmJs::Simd128_Rcp_D2, AsmJsRetType::Float64x2, AsmJsType::Float64x2));
  1428. simdFunctions[AsmJsSIMDBuiltin_float64x2_reciprocalSqrt] = SIMDFunc(PropertyIds::reciprocalSqrt, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 1, AsmJsSIMDBuiltin_float64x2_reciprocalSqrt, OpCodeAsmJs::Simd128_RcpSqrt_D2, AsmJsRetType::Float64x2, AsmJsType::Float64x2));
  1429. simdFunctions[AsmJsSIMDBuiltin_float64x2_sqrt] = SIMDFunc(PropertyIds::sqrt, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 1, AsmJsSIMDBuiltin_float64x2_sqrt, OpCodeAsmJs::Simd128_Sqrt_D2, AsmJsRetType::Float64x2, AsmJsType::Float64x2));
  1430. simdFunctions[AsmJsSIMDBuiltin_float64x2_swizzle] = SIMDFunc(PropertyIds::swizzle, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 3, AsmJsSIMDBuiltin_float64x2_swizzle, OpCodeAsmJs::Simd128_Swizzle_D2, AsmJsRetType::Float64x2, AsmJsType::Float64x2, AsmJsType::Int, AsmJsType::Int));
  1431. simdFunctions[AsmJsSIMDBuiltin_float64x2_shuffle] = SIMDFunc(PropertyIds::shuffle, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 4, AsmJsSIMDBuiltin_float64x2_shuffle, OpCodeAsmJs::Simd128_Shuffle_D2, AsmJsRetType::Float64x2, AsmJsType::Float64x2, AsmJsType::Float64x2, AsmJsType::Int, AsmJsType::Int));
  1432. simdFunctions[AsmJsSIMDBuiltin_float64x2_lessThan] = SIMDFunc(PropertyIds::lessThan, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float64x2_lessThan, OpCodeAsmJs::Simd128_Lt_D2, AsmJsRetType::Int32x4, AsmJsType::Float64x2, AsmJsType::Float64x2));
  1433. simdFunctions[AsmJsSIMDBuiltin_float64x2_lessThanOrEqual] = SIMDFunc(PropertyIds::lessThanOrEqual, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float64x2_lessThanOrEqual, OpCodeAsmJs::Simd128_LtEq_D2, AsmJsRetType::Int32x4, AsmJsType::Float64x2, AsmJsType::Float64x2));
  1434. simdFunctions[AsmJsSIMDBuiltin_float64x2_equal] = SIMDFunc(PropertyIds::equal, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float64x2_equal, OpCodeAsmJs::Simd128_Eq_D2, AsmJsRetType::Int32x4, AsmJsType::Float64x2, AsmJsType::Float64x2));
  1435. simdFunctions[AsmJsSIMDBuiltin_float64x2_notEqual] = SIMDFunc(PropertyIds::notEqual, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float64x2_notEqual, OpCodeAsmJs::Simd128_Neq_D2, AsmJsRetType::Int32x4, AsmJsType::Float64x2, AsmJsType::Float64x2));
  1436. simdFunctions[AsmJsSIMDBuiltin_float64x2_greaterThan] = SIMDFunc(PropertyIds::greaterThan, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float64x2_greaterThan, OpCodeAsmJs::Simd128_Gt_D2, AsmJsRetType::Int32x4, AsmJsType::Float64x2, AsmJsType::Float64x2));
  1437. simdFunctions[AsmJsSIMDBuiltin_float64x2_greaterThanOrEqual]= SIMDFunc(PropertyIds::greaterThanOrEqual, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float64x2_greaterThanOrEqual, OpCodeAsmJs::Simd128_GtEq_D2, AsmJsRetType::Int32x4, AsmJsType::Float64x2, AsmJsType::Float64x2));
  1438. simdFunctions[AsmJsSIMDBuiltin_float64x2_select] = SIMDFunc(PropertyIds::select, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 3, AsmJsSIMDBuiltin_float64x2_select, OpCodeAsmJs::Simd128_Select_D2, AsmJsRetType::Float64x2, AsmJsType::Int32x4, AsmJsType::Float64x2, AsmJsType::Float64x2));
  1439. simdFunctions[AsmJsSIMDBuiltin_float64x2_load] = SIMDFunc(PropertyIds::load, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float64x2_load, OpCodeAsmJs::Simd128_LdArr_D2, AsmJsRetType::Float64x2, AsmJsType::Void, AsmJsType::Int));
  1440. simdFunctions[AsmJsSIMDBuiltin_float64x2_load1] = SIMDFunc(PropertyIds::load1, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float64x2_load1, OpCodeAsmJs::Simd128_LdArr_D2, AsmJsRetType::Float64x2, AsmJsType::Void, AsmJsType::Int));
  1441. simdFunctions[AsmJsSIMDBuiltin_float64x2_store] = SIMDFunc(PropertyIds::store, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 3, AsmJsSIMDBuiltin_float64x2_store, OpCodeAsmJs::Simd128_StArr_D2, AsmJsRetType::Float64x2, AsmJsType::Void, AsmJsType::Int, AsmJsType::Float64x2));
  1442. simdFunctions[AsmJsSIMDBuiltin_float64x2_store1] = SIMDFunc(PropertyIds::store1, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 3, AsmJsSIMDBuiltin_float64x2_store1, OpCodeAsmJs::Simd128_StArr_D2, AsmJsRetType::Float64x2, AsmJsType::Void, AsmJsType::Int, AsmJsType::Float64x2));
  1443. {
  1444. SIMDNameMap *map = &mStdLibSIMDInt32x4Map;
  1445. for (int i = 0; i < AsmJsSIMDBuiltin_COUNT; i++)
  1446. {
  1447. if (i == AsmJsSIMDBuiltin_Float32x4)
  1448. {
  1449. map = &mStdLibSIMDFloat32x4Map;
  1450. }
  1451. if (i == AsmJsSIMDBuiltin_Float64x2)
  1452. {
  1453. map = &mStdLibSIMDFloat64x2Map;
  1454. }
  1455. if (simdFunctions[i].id && simdFunctions[i].val)
  1456. {
  1457. if (!AddStandardLibrarySIMDNameInMap(simdFunctions[i].id, simdFunctions[i].val, map))
  1458. {
  1459. AsmJSCompiler::OutputError(GetScriptContext(), L"Cannot initialize SIMD library");
  1460. return false;
  1461. }
  1462. }
  1463. }
  1464. }
  1465. return true;
  1466. }
  1467. AsmJsModuleCompiler::AsmJsModuleCompiler( ExclusiveContext *cx, AsmJSParser &parser ) :
  1468. mCx( cx )
  1469. , mCurrentParserNode( parser )
  1470. , mAllocator( L"Asmjs", cx->scriptContext->GetThreadContext()->GetPageAllocator(), Throw::OutOfMemory )
  1471. , mModuleFunctionName( nullptr )
  1472. , mStandardLibraryMathNames(&mAllocator)
  1473. , mStandardLibraryArrayNames(&mAllocator)
  1474. , mFunctionArray( &mAllocator )
  1475. , mModuleEnvironment( &mAllocator )
  1476. , mFunctionTableArray( &mAllocator )
  1477. , mInitialised(false)
  1478. , mIntVarSpace( )
  1479. , mDoubleVarSpace( )
  1480. , mExports(&mAllocator)
  1481. , mExportFuncIndex(Js::Constants::NoRegister)
  1482. , mVarImportCount(0)
  1483. , mVarCount(0)
  1484. , mFuncPtrTableCount(0)
  1485. , mCompileTime()
  1486. , mCompileTimeLastTick(GetTick())
  1487. , mMaxAstSize(0)
  1488. , mArrayViews(&mAllocator)
  1489. , mUsesChangeHeap(false)
  1490. , mUsesHeapBuffer(false)
  1491. , mMaxHeapAccess(0)
  1492. #if DBG
  1493. , mStdLibArgNameInit(false)
  1494. , mForeignArgNameInit(false)
  1495. , mBufferArgNameInit(false)
  1496. #endif
  1497. , mStdLibSIMDInt32x4Map(&mAllocator)
  1498. , mStdLibSIMDFloat32x4Map(&mAllocator)
  1499. , mStdLibSIMDFloat64x2Map(&mAllocator)
  1500. {
  1501. InitModuleNode( parser );
  1502. }
  1503. bool AsmJsModuleCompiler::AddStandardLibraryMathName( PropertyId id, const double* cstAddr, AsmJSMathBuiltinFunction mathLibFunctionName )
  1504. {
  1505. // make sure this name is unique
  1506. if( mStandardLibraryMathNames.ContainsKey( id ) )
  1507. {
  1508. return false;
  1509. }
  1510. MathBuiltin mathBuiltin(mathLibFunctionName, cstAddr);
  1511. int addResult = mStandardLibraryMathNames.AddNew( id, mathBuiltin );
  1512. if( addResult == -1 )
  1513. {
  1514. // Error adding the function
  1515. return false;
  1516. }
  1517. return true;
  1518. }
  1519. bool AsmJsModuleCompiler::AddStandardLibraryMathName(PropertyId id, AsmJsMathFunction* func, AsmJSMathBuiltinFunction mathLibFunctionName)
  1520. {
  1521. // make sure this name is unique
  1522. if( mStandardLibraryMathNames.ContainsKey( id ) )
  1523. {
  1524. return false;
  1525. }
  1526. MathBuiltin mathBuiltin(mathLibFunctionName, func);
  1527. int addResult = mStandardLibraryMathNames.AddNew( id, mathBuiltin );
  1528. if( addResult == -1 )
  1529. {
  1530. // Error adding the function
  1531. return false;
  1532. }
  1533. return true;
  1534. }
  1535. bool AsmJsModuleCompiler::AddStandardLibraryArrayName(PropertyId id, AsmJsTypedArrayFunction* func, AsmJSTypedArrayBuiltinFunction arrayLibFunctionName)
  1536. {
  1537. // make sure this name is unique
  1538. if (mStandardLibraryArrayNames.ContainsKey(id))
  1539. {
  1540. return false;
  1541. }
  1542. TypedArrayBuiltin arrayBuiltin(arrayLibFunctionName, func);
  1543. int addResult = mStandardLibraryArrayNames.AddNew(id, arrayBuiltin);
  1544. if (addResult == -1)
  1545. {
  1546. // Error adding the function
  1547. return false;
  1548. }
  1549. return true;
  1550. }
  1551. Parser * AsmJsModuleCompiler::GetParser() const
  1552. {
  1553. return mCx->byteCodeGenerator->GetParser();
  1554. }
  1555. ByteCodeGenerator* AsmJsModuleCompiler::GetByteCodeGenerator() const
  1556. {
  1557. return mCx->byteCodeGenerator;
  1558. }
  1559. ScriptContext * AsmJsModuleCompiler::GetScriptContext() const
  1560. {
  1561. return mCx->scriptContext;
  1562. }
  1563. AsmJsSymbol* AsmJsModuleCompiler::LookupIdentifier( PropertyName name, AsmJsFunc* func /*= nullptr */, AsmJsLookupSource::Source* lookupSource /*= nullptr*/ )
  1564. {
  1565. AsmJsSymbol* lookupResult = nullptr;
  1566. if (name)
  1567. {
  1568. if (func)
  1569. {
  1570. lookupResult = func->LookupIdentifier(name, lookupSource);
  1571. if (lookupResult)
  1572. {
  1573. return lookupResult;
  1574. }
  1575. }
  1576. lookupResult = mModuleEnvironment.LookupWithKey(name->GetPropertyId(), nullptr);
  1577. if (lookupSource)
  1578. {
  1579. *lookupSource = AsmJsLookupSource::AsmJsModule;
  1580. }
  1581. }
  1582. return lookupResult;
  1583. }
  1584. bool AsmJsModuleCompiler::DefineIdentifier( PropertyName name, AsmJsSymbol* symbol )
  1585. {
  1586. Assert( symbol );
  1587. if( symbol )
  1588. {
  1589. // make sure this identifier is unique
  1590. if(!LookupIdentifier( name ))
  1591. {
  1592. int addResult = mModuleEnvironment.AddNew(name->GetPropertyId(), symbol);
  1593. return addResult != -1;
  1594. }
  1595. }
  1596. return false;
  1597. }
  1598. bool AsmJsModuleCompiler::AddNumericVar( PropertyName name, ParseNode* pnode, bool isFloat, bool isMutable /*= true*/ )
  1599. {
  1600. Assert(ParserWrapper::IsNumericLiteral(pnode) || (isFloat && ParserWrapper::IsFroundNumericLiteral(pnode)));
  1601. AsmJsVar* var = Anew( &mAllocator, AsmJsVar, name, isMutable );
  1602. if( !var )
  1603. {
  1604. return false;
  1605. }
  1606. if( !DefineIdentifier( name, var ) )
  1607. {
  1608. return false;
  1609. }
  1610. ++mVarCount;
  1611. if (isFloat)
  1612. {
  1613. var->SetVarType(AsmJsVarType::Float);
  1614. var->SetLocation(mFloatVarSpace.AcquireRegister());
  1615. if (pnode->nop == knopInt)
  1616. {
  1617. var->SetConstInitialiser((float)pnode->sxInt.lw);
  1618. }
  1619. else if (ParserWrapper::IsNegativeZero(pnode))
  1620. {
  1621. var->SetConstInitialiser(-0.0f);
  1622. }
  1623. else
  1624. {
  1625. var->SetConstInitialiser((float)pnode->sxFlt.dbl);
  1626. }
  1627. }
  1628. else if (pnode->nop == knopInt)
  1629. {
  1630. var->SetVarType(AsmJsVarType::Int);
  1631. var->SetLocation(mIntVarSpace.AcquireRegister());
  1632. var->SetConstInitialiser(pnode->sxInt.lw);
  1633. }
  1634. else
  1635. {
  1636. if (ParserWrapper::IsMinInt(pnode))
  1637. {
  1638. var->SetVarType(AsmJsVarType::Int);
  1639. var->SetLocation(mIntVarSpace.AcquireRegister());
  1640. var->SetConstInitialiser(MININT);
  1641. }
  1642. else if (ParserWrapper::IsUnsigned(pnode))
  1643. {
  1644. var->SetVarType(AsmJsVarType::Int);
  1645. var->SetLocation(mIntVarSpace.AcquireRegister());
  1646. var->SetConstInitialiser((int)((uint32)pnode->sxFlt.dbl));
  1647. }
  1648. else if (pnode->sxFlt.maybeInt)
  1649. {
  1650. // this means there was an int literal not in range [-2^31,3^32)
  1651. return false;
  1652. }
  1653. else
  1654. {
  1655. var->SetVarType(AsmJsVarType::Double);
  1656. var->SetLocation(mDoubleVarSpace.AcquireRegister());
  1657. var->SetConstInitialiser(pnode->sxFlt.dbl);
  1658. }
  1659. }
  1660. return true;
  1661. }
  1662. bool AsmJsModuleCompiler::AddGlobalVarImport( PropertyName name, PropertyName field, AsmJSCoercion coercion )
  1663. {
  1664. AsmJsConstantImport* var = Anew( &mAllocator, AsmJsConstantImport, name, field );
  1665. if( !var )
  1666. {
  1667. return false;
  1668. }
  1669. if( !DefineIdentifier( name, var ) )
  1670. {
  1671. return false;
  1672. }
  1673. ++mVarImportCount;
  1674. switch( coercion )
  1675. {
  1676. case Js::AsmJS_ToInt32:
  1677. var->SetVarType( AsmJsVarType::Int );
  1678. var->SetLocation( mIntVarSpace.AcquireRegister() );
  1679. break;
  1680. case Js::AsmJS_ToNumber:
  1681. var->SetVarType( AsmJsVarType::Double );
  1682. var->SetLocation( mDoubleVarSpace.AcquireRegister() );
  1683. break;
  1684. case Js::AsmJS_FRound:
  1685. var->SetVarType( AsmJsVarType::Float );
  1686. var->SetLocation(mFloatVarSpace.AcquireRegister());
  1687. break;
  1688. case Js::AsmJS_Int32x4:
  1689. if (IsSimdjsEnabled())
  1690. {
  1691. var->SetVarType(AsmJsVarType::Int32x4);
  1692. var->SetLocation(mSimdVarSpace.AcquireRegister());
  1693. break;
  1694. }
  1695. Assert(UNREACHED);
  1696. case AsmJS_Float32x4:
  1697. if (IsSimdjsEnabled())
  1698. {
  1699. var->SetVarType(AsmJsVarType::Float32x4);
  1700. var->SetLocation(mSimdVarSpace.AcquireRegister());
  1701. break;
  1702. }
  1703. Assert(UNREACHED);
  1704. case AsmJS_Float64x2:
  1705. if (IsSimdjsEnabled())
  1706. {
  1707. var->SetVarType(AsmJsVarType::Float64x2);
  1708. var->SetLocation(mSimdVarSpace.AcquireRegister());
  1709. break;
  1710. }
  1711. Assert(UNREACHED);
  1712. default:
  1713. break;
  1714. }
  1715. return true;
  1716. }
  1717. bool AsmJsModuleCompiler::AddModuleFunctionImport( PropertyName name, PropertyName field )
  1718. {
  1719. AsmJsImportFunction* var = Anew( &mAllocator, AsmJsImportFunction, name, field, &mAllocator );
  1720. if( !var )
  1721. {
  1722. return false;
  1723. }
  1724. if( !DefineIdentifier( name, var ) )
  1725. {
  1726. return false;
  1727. }
  1728. var->SetFunctionIndex( mImportFunctions.AcquireRegister() );
  1729. return true;
  1730. }
  1731. bool AsmJsModuleCompiler::AddNumericConst( PropertyName name, const double* cst )
  1732. {
  1733. AsmJsMathConst* var = Anew( &mAllocator, AsmJsMathConst, name, cst );
  1734. if( !var )
  1735. {
  1736. return false;
  1737. }
  1738. if( !DefineIdentifier( name, var ) )
  1739. {
  1740. return false;
  1741. }
  1742. return true;
  1743. }
  1744. bool AsmJsModuleCompiler::AddArrayView( PropertyName name, ArrayBufferView::ViewType type )
  1745. {
  1746. AsmJsArrayView* view = Anew( &mAllocator, AsmJsArrayView, name, type );
  1747. if( !view )
  1748. {
  1749. return false;
  1750. }
  1751. if( !DefineIdentifier( name, view ) )
  1752. {
  1753. return false;
  1754. }
  1755. mArrayViews.Enqueue(view);
  1756. return true;
  1757. }
  1758. bool AsmJsModuleCompiler::AddFunctionTable( PropertyName name, const int size )
  1759. {
  1760. GetByteCodeGenerator()->AssignPropertyId(name);
  1761. AsmJsFunctionTable* funcTable = Anew( &mAllocator, AsmJsFunctionTable, name, &mAllocator );
  1762. if( !funcTable )
  1763. {
  1764. return false;
  1765. }
  1766. if( !DefineIdentifier( name, funcTable ) )
  1767. {
  1768. return false;
  1769. }
  1770. funcTable->SetSize( size );
  1771. int pos = mFunctionTableArray.Add( funcTable );
  1772. funcTable->SetFunctionIndex( pos );
  1773. return true;
  1774. }
  1775. bool AsmJsModuleCompiler::AddExport( PropertyName name, RegSlot location )
  1776. {
  1777. AsmJsModuleExport ex;
  1778. ex.id = name->GetPropertyId();
  1779. ex.location = location;
  1780. // return is < 0 if count overflowed 31bits
  1781. return mExports.Add( ex ) >= 0;
  1782. }
  1783. bool AsmJsModuleCompiler::SetExportFunc( AsmJsFunc* func )
  1784. {
  1785. Assert( mExports.Count() == 0 && func);
  1786. mExportFuncIndex = func->GetFunctionIndex();
  1787. return mExports.Count() == 0 && (uint32)mExportFuncIndex < (uint32)mFunctionArray.Count();
  1788. }
  1789. AsmJsFunctionDeclaration* AsmJsModuleCompiler::LookupFunction( PropertyName name )
  1790. {
  1791. if (name)
  1792. {
  1793. AsmJsSymbol* sym = LookupIdentifier(name);
  1794. if (sym)
  1795. {
  1796. switch (sym->GetSymbolType())
  1797. {
  1798. case AsmJsSymbol::SIMDBuiltinFunction:
  1799. case AsmJsSymbol::MathBuiltinFunction:
  1800. case AsmJsSymbol::ModuleFunction:
  1801. case AsmJsSymbol::ImportFunction:
  1802. case AsmJsSymbol::FuncPtrTable:
  1803. return sym->Cast<AsmJsFunctionDeclaration>();
  1804. default:
  1805. break;
  1806. }
  1807. }
  1808. }
  1809. return nullptr;
  1810. }
  1811. bool AsmJsModuleCompiler::AreAllFuncTableDefined()
  1812. {
  1813. const int size = mFunctionTableArray.Count();
  1814. for (int i = 0; i < size ; i++)
  1815. {
  1816. AsmJsFunctionTable* funcTable = mFunctionTableArray.Item( i );
  1817. if( !funcTable->IsDefined() )
  1818. {
  1819. AsmJSCompiler::OutputError(GetScriptContext(), L"Function table %s was used in a function but does not appear in the module", funcTable->GetName()->Psz());
  1820. return false;
  1821. }
  1822. }
  1823. return true;
  1824. }
  1825. void AsmJsModuleCompiler::UpdateMaxHeapAccess(uint index)
  1826. {
  1827. if (mMaxHeapAccess < index)
  1828. {
  1829. mMaxHeapAccess = index;
  1830. }
  1831. }
  1832. void AsmJsModuleCompiler::InitMemoryOffsets()
  1833. {
  1834. mModuleMemory.mArrayBufferOffset = AsmJsModuleMemory::MemoryTableBeginOffset;
  1835. mModuleMemory.mStdLibOffset = mModuleMemory.mArrayBufferOffset + 1;
  1836. mModuleMemory.mDoubleOffset = mModuleMemory.mStdLibOffset + 1;
  1837. mModuleMemory.mFuncOffset = mModuleMemory.mDoubleOffset + (mDoubleVarSpace.GetTotalVarCount() * DOUBLE_SLOTS_SPACE);
  1838. mModuleMemory.mFFIOffset = mModuleMemory.mFuncOffset + mFunctionArray.Count();
  1839. mModuleMemory.mFuncPtrOffset = mModuleMemory.mFFIOffset + mImportFunctions.GetTotalVarCount();
  1840. mModuleMemory.mFloatOffset = mModuleMemory.mFuncPtrOffset + GetFuncPtrTableCount();
  1841. mModuleMemory.mIntOffset = mModuleMemory.mFloatOffset + (int32)(mFloatVarSpace.GetTotalVarCount() * FLOAT_SLOTS_SPACE + 0.5);
  1842. mModuleMemory.mMemorySize = mModuleMemory.mIntOffset + (int32)(mIntVarSpace.GetTotalVarCount() * INT_SLOTS_SPACE + 0.5);
  1843. if (IsSimdjsEnabled())
  1844. {
  1845. mModuleMemory.mSimdOffset = (int) ::ceil(mModuleMemory.mMemorySize / SIMD_SLOTS_SPACE);
  1846. if (mSimdVarSpace.GetTotalVarCount())
  1847. {
  1848. mModuleMemory.mMemorySize = (int)((mModuleMemory.mSimdOffset + mSimdVarSpace.GetTotalVarCount()) * SIMD_SLOTS_SPACE);
  1849. // no alignment
  1850. // mModuleMemory.mMemorySize += (int)SIMD_SLOTS_SPACE;
  1851. }
  1852. }
  1853. }
  1854. void AsmJsModuleCompiler::AccumulateCompileTime()
  1855. {
  1856. Js::TickDelta td;
  1857. AsmJsCompileTime curTime = GetTick();
  1858. td = curTime - mCompileTimeLastTick;
  1859. mCompileTime = mCompileTime+td;
  1860. mCompileTimeLastTick = curTime;
  1861. }
  1862. void AsmJsModuleCompiler::AccumulateCompileTime(AsmJsCompilation::Phases phase)
  1863. {
  1864. Js::TickDelta td;
  1865. AsmJsCompileTime curTime = GetTick();
  1866. td = curTime - mCompileTimeLastTick;
  1867. mCompileTime = mCompileTime+td;
  1868. mCompileTimeLastTick = curTime;
  1869. mPhaseCompileTime[phase] = mPhaseCompileTime[phase] + td;
  1870. }
  1871. Js::AsmJsCompileTime AsmJsModuleCompiler::GetTick()
  1872. {
  1873. return Js::Tick::Now();
  1874. }
  1875. uint64 AsmJsModuleCompiler::GetCompileTime() const
  1876. {
  1877. return mCompileTime.ToMicroseconds();
  1878. }
  1879. static const wchar_t* AsmPhaseNames[AsmJsCompilation::Phases_COUNT] = {
  1880. L"Module",
  1881. L"ByteCode",
  1882. L"TemplateJIT",
  1883. };
  1884. void AsmJsModuleCompiler::PrintCompileTrace() const
  1885. {
  1886. // for testtrace, don't print time so that it can be used for baselines
  1887. if (PHASE_TESTTRACE1(AsmjsPhase))
  1888. {
  1889. AsmJSCompiler::OutputMessage(GetScriptContext(), DEIT_ASMJS_SUCCEEDED, L"Successfully compiled asm.js code");
  1890. }
  1891. else
  1892. {
  1893. uint64 us = GetCompileTime();
  1894. uint64 ms = us / 1000;
  1895. us = us % 1000;
  1896. AsmJSCompiler::OutputMessage(GetScriptContext(), DEIT_ASMJS_SUCCEEDED, L"Successfully compiled asm.js code (total compilation time %llu.%llums)", ms, us);
  1897. }
  1898. if (PHASE_TRACE1(AsmjsPhase))
  1899. {
  1900. for (int i = 0; i < AsmJsCompilation::Phases_COUNT; i++)
  1901. {
  1902. uint64 us = mPhaseCompileTime[i].ToMicroseconds();
  1903. uint64 ms = us / 1000;
  1904. us = us % 1000;
  1905. Output::Print(L"%20s : %llu.%llums\n", AsmPhaseNames[i], ms, us);
  1906. }
  1907. Output::Flush();
  1908. }
  1909. }
  1910. BVStatic<ASMMATH_BUILTIN_SIZE> AsmJsModuleCompiler::GetAsmMathBuiltinUsedBV()
  1911. {
  1912. return mAsmMathBuiltinUsedBV;
  1913. }
  1914. BVStatic<ASMARRAY_BUILTIN_SIZE> AsmJsModuleCompiler::GetAsmArrayBuiltinUsedBV()
  1915. {
  1916. return mAsmArrayBuiltinUsedBV;
  1917. }
  1918. void AsmJsModuleInfo::SetFunctionCount( int val )
  1919. {
  1920. Assert( mFunctions == nullptr );
  1921. mFunctionCount = val;
  1922. mFunctions = RecyclerNewArray( mRecycler, ModuleFunction, val );
  1923. }
  1924. void AsmJsModuleInfo::SetFunctionTableCount( int val )
  1925. {
  1926. Assert( mFunctionTables == nullptr );
  1927. mFunctionTableCount = val;
  1928. mFunctionTables = RecyclerNewArray( mRecycler, ModuleFunctionTable, val );
  1929. }
  1930. void AsmJsModuleInfo::SetFunctionImportCount( int val )
  1931. {
  1932. Assert( mFunctionImports == nullptr );
  1933. mFunctionImportCount = val;
  1934. mFunctionImports = RecyclerNewArray( mRecycler, ModuleFunctionImport, val );
  1935. }
  1936. void AsmJsModuleInfo::SetVarCount( int val )
  1937. {
  1938. Assert( mVars == nullptr );
  1939. mVarCount = val;
  1940. mVars = RecyclerNewArray( mRecycler, ModuleVar, val );
  1941. }
  1942. void AsmJsModuleInfo::SetVarImportCount( int val )
  1943. {
  1944. Assert( mVarImports == nullptr );
  1945. mVarImportCount = val;
  1946. mVarImports = RecyclerNewArray( mRecycler, ModuleVarImport, val );
  1947. }
  1948. void AsmJsModuleInfo::SetExportsCount( int count )
  1949. {
  1950. if( count )
  1951. {
  1952. mExports = RecyclerNewPlus( mRecycler, count * sizeof( PropertyId ), PropertyIdArray, count );
  1953. mExportsFunctionLocation = RecyclerNewArray( mRecycler, RegSlot, count );
  1954. }
  1955. mExportsCount = count;
  1956. }
  1957. void AsmJsModuleInfo::InitializeSlotMap(int val)
  1958. {
  1959. Assert(mSlotMap == nullptr);
  1960. mSlotsCount = val;
  1961. mSlotMap = RecyclerNew(mRecycler, AsmJsSlotMap, mRecycler);
  1962. }
  1963. void AsmJsModuleInfo::SetFunctionTableSize( int index, uint size )
  1964. {
  1965. Assert( mFunctionTables != nullptr );
  1966. Assert( index < mFunctionTableCount );
  1967. ModuleFunctionTable& table = mFunctionTables[index];
  1968. table.size = size;
  1969. table.moduleFunctionIndex = RecyclerNewArray( mRecycler, RegSlot, size );
  1970. }
  1971. void AsmJsModuleInfo::EnsureHeapAttached(ScriptFunction * func)
  1972. {
  1973. FrameDisplay* frame = func->GetEnvironment();
  1974. ArrayBuffer* moduleArrayBuffer = *(ArrayBuffer**)((Var*)frame->GetItem(0) + AsmJsModuleMemory::MemoryTableBeginOffset);
  1975. if (moduleArrayBuffer && moduleArrayBuffer->IsDetached())
  1976. {
  1977. Throw::OutOfMemory();
  1978. }
  1979. }
  1980. void * AsmJsModuleInfo::ConvertFrameForJavascript(void * asmMemory, ScriptFunction* func)
  1981. {
  1982. FunctionBody * body = func->GetFunctionBody();
  1983. AsmJsFunctionInfo * asmFuncInfo = body->GetAsmJsFunctionInfo();
  1984. FunctionBody * moduleBody = asmFuncInfo->GetModuleFunctionBody();
  1985. AsmJsModuleInfo * asmModuleInfo = moduleBody->GetAsmJsModuleInfo();
  1986. Assert(asmModuleInfo);
  1987. ScriptContext * scriptContext = func->GetScriptContext();
  1988. // AsmJsModuleEnvironment is all laid out here
  1989. Var * asmJsEnvironment = static_cast<Var*>(func->GetEnvironment()->GetItem(0));
  1990. Var * asmBufferPtr = asmJsEnvironment + asmModuleInfo->GetModuleMemory().mArrayBufferOffset;
  1991. ArrayBuffer * asmBuffer = *asmBufferPtr ? ArrayBuffer::FromVar(*asmBufferPtr) : nullptr;
  1992. Var stdLibObj = *(asmJsEnvironment + asmModuleInfo->GetModuleMemory().mStdLibOffset);
  1993. Var asmMathObject = stdLibObj ? JavascriptOperators::OP_GetProperty(stdLibObj, PropertyIds::Math, scriptContext) : nullptr;
  1994. Var * asmFFIs = asmJsEnvironment + asmModuleInfo->GetModuleMemory().mFFIOffset;
  1995. Var * asmFuncs = asmJsEnvironment + asmModuleInfo->GetModuleMemory().mFuncOffset;
  1996. Var ** asmFuncPtrs = reinterpret_cast<Var**>(asmJsEnvironment + asmModuleInfo->GetModuleMemory().mFuncPtrOffset);
  1997. double * asmDoubleVars = reinterpret_cast<double*>(asmJsEnvironment + asmModuleInfo->GetModuleMemory().mDoubleOffset);
  1998. int * asmIntVars = reinterpret_cast<int*>(asmJsEnvironment + asmModuleInfo->GetModuleMemory().mIntOffset);
  1999. float * asmFloatVars = reinterpret_cast<float*>(asmJsEnvironment + asmModuleInfo->GetModuleMemory().mFloatOffset);
  2000. AsmJsSIMDValue * asmSIMDVars = reinterpret_cast<AsmJsSIMDValue*>(asmJsEnvironment + asmModuleInfo->GetModuleMemory().mSimdOffset);
  2001. #if DEBUG
  2002. Var * slotArray = RecyclerNewArrayZ(scriptContext->GetRecycler(), Var, moduleBody->scopeSlotArraySize + ScopeSlots::FirstSlotIndex);
  2003. #else
  2004. Var * slotArray = RecyclerNewArray(scriptContext->GetRecycler(), Var, moduleBody->scopeSlotArraySize + ScopeSlots::FirstSlotIndex);
  2005. #endif
  2006. ScopeSlots scopeSlots(slotArray);
  2007. scopeSlots.SetCount(moduleBody->scopeSlotArraySize);
  2008. scopeSlots.SetScopeMetadata(moduleBody);
  2009. auto asmSlotMap = asmModuleInfo->GetAsmJsSlotMap();
  2010. Assert((uint)asmModuleInfo->GetSlotsCount() == moduleBody->scopeSlotArraySize);
  2011. Js::ActivationObject* activeScopeObject = nullptr;
  2012. if (moduleBody->GetObjectRegister() != 0)
  2013. {
  2014. activeScopeObject = static_cast<ActivationObject*>(scriptContext->GetLibrary()->CreateActivationObject());
  2015. }
  2016. PropertyId* propertyIdArray = moduleBody->GetPropertyIdsForScopeSlotArray();
  2017. for (int i = 0; i < asmModuleInfo->GetSlotsCount(); ++i)
  2018. {
  2019. AsmJsSlot * asmSlot;
  2020. bool found = asmSlotMap->TryGetValue(propertyIdArray[i], &asmSlot);
  2021. // we should have everything we need in the map
  2022. Assert(found);
  2023. Var value = nullptr;
  2024. switch (asmSlot->symType)
  2025. {
  2026. case AsmJsSymbol::ConstantImport:
  2027. case AsmJsSymbol::Variable:
  2028. {
  2029. switch (asmSlot->varType)
  2030. {
  2031. case AsmJsVarType::Double:
  2032. value = JavascriptNumber::NewWithCheck(asmDoubleVars[asmSlot->location], scriptContext);
  2033. break;
  2034. case AsmJsVarType::Float:
  2035. value = JavascriptNumber::NewWithCheck(asmFloatVars[asmSlot->location], scriptContext);
  2036. break;
  2037. case AsmJsVarType::Int:
  2038. value = JavascriptNumber::ToVar(asmIntVars[asmSlot->location], scriptContext);
  2039. break;
  2040. case AsmJsVarType::Float32x4:
  2041. value = JavascriptSIMDFloat32x4::New(&asmSIMDVars[asmSlot->location], scriptContext);
  2042. break;
  2043. case AsmJsVarType::Float64x2:
  2044. value = JavascriptSIMDFloat64x2::New(&asmSIMDVars[asmSlot->location], scriptContext);
  2045. break;
  2046. case AsmJsVarType::Int32x4:
  2047. value = JavascriptSIMDInt32x4::New(&asmSIMDVars[asmSlot->location], scriptContext);
  2048. break;
  2049. default:
  2050. Assume(UNREACHED);
  2051. }
  2052. break;
  2053. }
  2054. case AsmJsSymbol::ModuleArgument:
  2055. {
  2056. switch (asmSlot->argType)
  2057. {
  2058. case AsmJsModuleArg::ArgType::StdLib:
  2059. value = stdLibObj;
  2060. break;
  2061. case AsmJsModuleArg::ArgType::Import:
  2062. // we can't reference this inside functions (and don't hold onto it), but must set to something, so set it to be undefined
  2063. value = scriptContext->GetLibrary()->GetUndefined();
  2064. break;
  2065. case AsmJsModuleArg::ArgType::Heap:
  2066. value = asmBuffer;
  2067. break;
  2068. default:
  2069. Assume(UNREACHED);
  2070. }
  2071. break;
  2072. }
  2073. case AsmJsSymbol::ImportFunction:
  2074. value = asmFFIs[asmSlot->location];
  2075. break;
  2076. case AsmJsSymbol::FuncPtrTable:
  2077. value = JavascriptArray::OP_NewScArrayWithElements(asmSlot->funcTableSize, asmFuncPtrs[asmSlot->location], scriptContext);
  2078. break;
  2079. case AsmJsSymbol::ModuleFunction:
  2080. value = asmFuncs[asmSlot->location];
  2081. break;
  2082. case AsmJsSymbol::MathConstant:
  2083. value = JavascriptNumber::NewWithCheck(asmSlot->mathConstVal, scriptContext);
  2084. break;
  2085. case AsmJsSymbol::ArrayView:
  2086. {
  2087. AnalysisAssert(asmBuffer);
  2088. #ifdef _M_X64
  2089. const bool isOptimizedBuffer = true;
  2090. #elif _M_IX86
  2091. const bool isOptimizedBuffer = false;
  2092. #else
  2093. Assert(UNREACHED);
  2094. const bool isOptimizedBuffer = false;
  2095. #endif
  2096. Assert(isOptimizedBuffer == asmBuffer->IsValidVirtualBufferLength(asmBuffer->GetByteLength()));
  2097. switch (asmSlot->viewType)
  2098. {
  2099. case ArrayBufferView::TYPE_FLOAT32:
  2100. value = TypedArray<float, false, isOptimizedBuffer>::Create(asmBuffer, 0, asmBuffer->GetByteLength() >> 2, scriptContext->GetLibrary());
  2101. break;
  2102. case ArrayBufferView::TYPE_FLOAT64:
  2103. value = TypedArray<double, false, isOptimizedBuffer>::Create(asmBuffer, 0, asmBuffer->GetByteLength() >> 3, scriptContext->GetLibrary());
  2104. break;
  2105. case ArrayBufferView::TYPE_INT8:
  2106. value = TypedArray<int8, false, isOptimizedBuffer>::Create(asmBuffer, 0, asmBuffer->GetByteLength(), scriptContext->GetLibrary());
  2107. break;
  2108. case ArrayBufferView::TYPE_INT16:
  2109. value = TypedArray<int16, false, isOptimizedBuffer>::Create(asmBuffer, 0, asmBuffer->GetByteLength() >> 1, scriptContext->GetLibrary());
  2110. break;
  2111. case ArrayBufferView::TYPE_INT32:
  2112. value = TypedArray<int32, false, isOptimizedBuffer>::Create(asmBuffer, 0, asmBuffer->GetByteLength() >> 2, scriptContext->GetLibrary());
  2113. break;
  2114. case ArrayBufferView::TYPE_UINT8:
  2115. value = TypedArray<uint8, false, isOptimizedBuffer>::Create(asmBuffer, 0, asmBuffer->GetByteLength(), scriptContext->GetLibrary());
  2116. break;
  2117. case ArrayBufferView::TYPE_UINT16:
  2118. value = TypedArray<uint16, false, isOptimizedBuffer>::Create(asmBuffer, 0, asmBuffer->GetByteLength() >> 1, scriptContext->GetLibrary());
  2119. break;
  2120. case ArrayBufferView::TYPE_UINT32:
  2121. value = TypedArray<uint32, false, isOptimizedBuffer>::Create(asmBuffer, 0, asmBuffer->GetByteLength() >> 2, scriptContext->GetLibrary());
  2122. break;
  2123. default:
  2124. Assume(UNREACHED);
  2125. }
  2126. break;
  2127. }
  2128. case AsmJsSymbol::MathBuiltinFunction:
  2129. {
  2130. switch (asmSlot->builtinMathFunc)
  2131. {
  2132. #define ASMJS_MATH_FUNC_NAMES(name, propertyName) \
  2133. case AsmJSMathBuiltin_##name: \
  2134. value = JavascriptOperators::OP_GetProperty(asmMathObject, PropertyIds::##propertyName, scriptContext); \
  2135. break;
  2136. #include "AsmJsBuiltinNames.h"
  2137. default:
  2138. Assume(UNREACHED);
  2139. }
  2140. break;
  2141. }
  2142. case AsmJsSymbol::TypedArrayBuiltinFunction:
  2143. switch (asmSlot->builtinArrayFunc)
  2144. {
  2145. #define ASMJS_ARRAY_NAMES(name, propertyName) \
  2146. case AsmJSTypedArrayBuiltin_##name: \
  2147. value = JavascriptOperators::OP_GetProperty(stdLibObj, PropertyIds::##propertyName, scriptContext); \
  2148. break;
  2149. #include "AsmJsBuiltinNames.h"
  2150. default:
  2151. Assume(UNREACHED);
  2152. }
  2153. break;
  2154. case AsmJsSymbol::SIMDBuiltinFunction:
  2155. switch (asmSlot->builtinSIMDFunc)
  2156. {
  2157. #define ASMJS_SIMD_NAMES(name, propertyName) \
  2158. case AsmJsSIMDBuiltin_##name: \
  2159. value = JavascriptOperators::OP_GetProperty(stdLibObj, PropertyIds::##propertyName, scriptContext); \
  2160. break;
  2161. #include "AsmJsBuiltinNames.h"
  2162. default:
  2163. Assume(UNREACHED);
  2164. }
  2165. break;
  2166. default:
  2167. Assume(UNREACHED);
  2168. }
  2169. if (activeScopeObject != nullptr)
  2170. {
  2171. activeScopeObject->SetPropertyWithAttributes(
  2172. propertyIdArray[i],
  2173. value,
  2174. asmSlot->isConstVar ? PropertyConstDefaults : PropertyDynamicTypeDefaults,
  2175. nullptr);
  2176. }
  2177. else
  2178. {
  2179. // ensure we aren't multiply writing to a slot
  2180. Assert(scopeSlots.Get(i) == nullptr);
  2181. scopeSlots.Set(i, value);
  2182. }
  2183. }
  2184. if (activeScopeObject != nullptr)
  2185. {
  2186. return (void*)activeScopeObject;
  2187. }
  2188. else
  2189. {
  2190. return (void*)slotArray;
  2191. }
  2192. }
  2193. bool AsmJsModuleCompiler::LookupStdLibSIMDNameInMap(PropertyName name, AsmJsSIMDFunction **simdFunc, SIMDNameMap* map) const
  2194. {
  2195. return map->TryGetValue(name->GetPropertyId(), simdFunc);
  2196. }
  2197. bool AsmJsModuleCompiler::AddStandardLibrarySIMDNameInMap(PropertyId id, AsmJsSIMDFunction *simdFunc, SIMDNameMap* map)
  2198. {
  2199. //SimdBuiltin simdBuiltin(simdFunc->GetSimdBuiltInFunction(), simdFunc);
  2200. if (map->ContainsKey(id))
  2201. {
  2202. return nullptr;
  2203. }
  2204. return map->AddNew(id, simdFunc) == -1 ? false : true;
  2205. }
  2206. bool AsmJsModuleCompiler::LookupStdLibSIMDName(PropertyId baseId, PropertyName fieldName, AsmJsSIMDFunction **simdFunc)
  2207. {
  2208. switch (baseId)
  2209. {
  2210. case PropertyIds::Int32x4:
  2211. return LookupStdLibSIMDNameInMap(fieldName, simdFunc, &mStdLibSIMDInt32x4Map);
  2212. case PropertyIds::Float32x4:
  2213. return LookupStdLibSIMDNameInMap(fieldName, simdFunc, &mStdLibSIMDFloat32x4Map);
  2214. case PropertyIds::Float64x2:
  2215. return LookupStdLibSIMDNameInMap(fieldName, simdFunc, &mStdLibSIMDFloat64x2Map);
  2216. default:
  2217. AssertMsg(false, "Invalid SIMD type");
  2218. return false;
  2219. }
  2220. }
  2221. bool AsmJsModuleCompiler::LookupStdLibSIMDName(AsmJsSIMDBuiltinFunction baseId, PropertyName fieldName, AsmJsSIMDFunction **simdFunc)
  2222. {
  2223. switch (baseId)
  2224. {
  2225. case AsmJsSIMDBuiltin_Int32x4:
  2226. return LookupStdLibSIMDNameInMap(fieldName, simdFunc, &mStdLibSIMDInt32x4Map);
  2227. case AsmJsSIMDBuiltin_Float32x4:
  2228. return LookupStdLibSIMDNameInMap(fieldName, simdFunc, &mStdLibSIMDFloat32x4Map);
  2229. case AsmJsSIMDBuiltin_Float64x2:
  2230. return LookupStdLibSIMDNameInMap(fieldName, simdFunc, &mStdLibSIMDFloat64x2Map);
  2231. default:
  2232. AssertMsg(false, "Invalid SIMD type");
  2233. return false;
  2234. }
  2235. }
  2236. AsmJsSIMDFunction* AsmJsModuleCompiler::LookupSimdConstructor(PropertyName name)
  2237. {
  2238. AsmJsFunctionDeclaration *func = LookupFunction(name);
  2239. if (func == nullptr || func->GetSymbolType() != AsmJsSymbol::SIMDBuiltinFunction)
  2240. {
  2241. return nullptr;
  2242. }
  2243. AsmJsSIMDFunction *simdFunc = func->Cast<AsmJsSIMDFunction>();
  2244. if (simdFunc->IsConstructor())
  2245. {
  2246. return simdFunc;
  2247. }
  2248. return nullptr;
  2249. }
  2250. AsmJsSIMDFunction* AsmJsModuleCompiler::LookupSimdTypeCheck(PropertyName name)
  2251. {
  2252. AsmJsFunctionDeclaration *func = LookupFunction(name);
  2253. if (func == nullptr || func->GetSymbolType() != AsmJsSymbol::SIMDBuiltinFunction)
  2254. {
  2255. return nullptr;
  2256. }
  2257. AsmJsSIMDFunction *simdFunc = func->Cast<AsmJsSIMDFunction>();
  2258. if (simdFunc->IsTypeCheck())
  2259. {
  2260. return simdFunc;
  2261. }
  2262. return nullptr;
  2263. }
  2264. AsmJsSIMDFunction* AsmJsModuleCompiler::LookupSimdOperation(PropertyName name)
  2265. {
  2266. AsmJsFunctionDeclaration *func = LookupFunction(name);
  2267. if (func == nullptr || func->GetSymbolType() != AsmJsSymbol::SIMDBuiltinFunction)
  2268. {
  2269. return nullptr;
  2270. }
  2271. AsmJsSIMDFunction *simdFunc = func->Cast<AsmJsSIMDFunction>();
  2272. if (simdFunc->GetSimdBuiltInFunction() != AsmJsSIMDBuiltin_Int32x4 &&
  2273. simdFunc->GetSimdBuiltInFunction() != AsmJsSIMDBuiltin_Float32x4 &&
  2274. simdFunc->GetSimdBuiltInFunction() != AsmJsSIMDBuiltin_Float64x2)
  2275. {
  2276. return simdFunc;
  2277. }
  2278. return nullptr;
  2279. }
  2280. bool AsmJsModuleCompiler::AddSimdValueVar(PropertyName name, ParseNode* pnode, AsmJsSIMDFunction* simdFunc)
  2281. {
  2282. AssertMsg(simdFunc->GetSymbolType() == AsmJsSymbol::SIMDBuiltinFunction, "Expecting SIMD builtin");
  2283. AssertMsg(simdFunc->IsConstructor(), "Expecting constructor function");
  2284. AsmJsSIMDValue value;
  2285. AsmJsVarType type = simdFunc->GetConstructorVarType();
  2286. // e.g. var g1 = f4(1.0, 2.0, 3.0, 4.0);
  2287. if (!ValidateSimdConstructor(pnode, simdFunc, value))
  2288. {
  2289. return false;
  2290. }
  2291. AsmJsVar* var = Anew(&mAllocator, AsmJsVar, name);
  2292. if (!var || !DefineIdentifier(name, var))
  2293. {
  2294. return false;
  2295. }
  2296. ++mVarCount;
  2297. var->SetVarType(type);
  2298. var->SetConstInitialiser(value);
  2299. // acquire register
  2300. var->SetLocation(mSimdVarSpace.AcquireRegister());
  2301. return true;
  2302. }
  2303. bool AsmJsModuleCompiler::ValidateSimdConstructor(ParseNode* pnode, AsmJsSIMDFunction* simdFunc, AsmJsSIMDValue& value)
  2304. {
  2305. Assert(pnode->nop == knopCall);
  2306. uint argCount = pnode->sxCall.argCount;
  2307. ParseNode* argNode = pnode->sxCall.pnodeArgs;
  2308. ParseNode *arg = argNode;
  2309. uint nop = 0;
  2310. AsmJsSIMDBuiltinFunction simdBuiltin = simdFunc->GetSimdBuiltInFunction();
  2311. if (!simdFunc->IsConstructor(argCount))
  2312. {
  2313. return Fail(pnode, L"Invalid SIMD constructor or wrong number of arguments.");
  2314. }
  2315. switch (simdBuiltin)
  2316. {
  2317. case AsmJsSIMDBuiltin_Float64x2:
  2318. case AsmJsSIMDBuiltin_Float32x4:
  2319. nop = (uint)knopFlt;
  2320. break;
  2321. case AsmJsSIMDBuiltin_Int32x4:
  2322. nop = (uint)knopInt;
  2323. break;
  2324. default:
  2325. Assert(UNREACHED);
  2326. }
  2327. Assert(simdBuiltin == AsmJsSIMDBuiltin_Float64x2 || simdBuiltin == AsmJsSIMDBuiltin_Float32x4 || simdBuiltin == AsmJsSIMDBuiltin_Int32x4);
  2328. if (simdFunc->GetArgCount() != argCount)
  2329. {
  2330. return Fail(pnode, L"Invalid number of arguments to SIMD constructor.");
  2331. }
  2332. for (uint i = 0; i < argCount; i++)
  2333. {
  2334. arg = argNode;
  2335. if (argNode->nop == knopList)
  2336. {
  2337. arg = ParserWrapper::GetBinaryLeft(argNode);
  2338. argNode = ParserWrapper::GetBinaryRight(argNode);
  2339. }
  2340. Assert(arg);
  2341. // store to SIMD Value
  2342. if (arg->nop == nop)
  2343. {
  2344. if (nop == (uint)knopInt)
  2345. {
  2346. value.i32[i] = arg->sxInt.lw;
  2347. }
  2348. else if (nop == (uint)knopFlt)
  2349. {
  2350. if (simdBuiltin == AsmJsSIMDBuiltin_Float32x4)
  2351. {
  2352. value.f32[i] = (float)arg->sxFlt.dbl;
  2353. }
  2354. else // float64x2
  2355. {
  2356. value.f64[i] = arg->sxFlt.dbl;
  2357. }
  2358. }
  2359. }
  2360. else
  2361. {
  2362. return Fail(pnode, L"Invalid argument type to SIMD constructor.");
  2363. }
  2364. }
  2365. return true;
  2366. }
  2367. };
  2368. #endif