| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663 |
- /*
- * Copyright (C) 2019 Intel Corporation. All rights reserved.
- * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- */
- #include "aot_llvm.h"
- #include "aot_compiler.h"
- #include "aot_emit_exception.h"
- #include "../aot/aot_runtime.h"
- #include "../aot/aot_intrinsic.h"
- #if WASM_ENABLE_DEBUG_AOT != 0
- #include "debug/dwarf_extractor.h"
- #endif
- LLVMTypeRef
- wasm_type_to_llvm_type(AOTLLVMTypes *llvm_types, uint8 wasm_type)
- {
- switch (wasm_type) {
- case VALUE_TYPE_I32:
- case VALUE_TYPE_FUNCREF:
- case VALUE_TYPE_EXTERNREF:
- return llvm_types->int32_type;
- case VALUE_TYPE_I64:
- return llvm_types->int64_type;
- case VALUE_TYPE_F32:
- return llvm_types->float32_type;
- case VALUE_TYPE_F64:
- return llvm_types->float64_type;
- case VALUE_TYPE_V128:
- return llvm_types->i64x2_vec_type;
- case VALUE_TYPE_VOID:
- return llvm_types->void_type;
- default:
- break;
- }
- return NULL;
- }
- /**
- * Add LLVM function
- */
- static LLVMValueRef
- aot_add_llvm_func(AOTCompContext *comp_ctx, LLVMModuleRef module,
- AOTFuncType *aot_func_type, uint32 func_index,
- LLVMTypeRef *p_func_type)
- {
- LLVMValueRef func = NULL;
- LLVMTypeRef *param_types, ret_type, func_type;
- LLVMValueRef local_value;
- LLVMTypeRef func_type_wrapper;
- LLVMValueRef func_wrapper;
- LLVMBasicBlockRef func_begin;
- char func_name[48];
- uint64 size;
- uint32 i, j = 0, param_count = (uint64)aot_func_type->param_count;
- /* exec env as first parameter */
- param_count++;
- /* Extra wasm function results(except the first one)'s address are
- * appended to aot function parameters. */
- if (aot_func_type->result_count > 1)
- param_count += aot_func_type->result_count - 1;
- /* Initialize parameter types of the LLVM function */
- size = sizeof(LLVMTypeRef) * ((uint64)param_count);
- if (size >= UINT32_MAX
- || !(param_types = wasm_runtime_malloc((uint32)size))) {
- aot_set_last_error("allocate memory failed.");
- return NULL;
- }
- /* exec env as first parameter */
- param_types[j++] = comp_ctx->exec_env_type;
- for (i = 0; i < aot_func_type->param_count; i++)
- param_types[j++] = TO_LLVM_TYPE(aot_func_type->types[i]);
- /* Extra results' address */
- for (i = 1; i < aot_func_type->result_count; i++, j++) {
- param_types[j] =
- TO_LLVM_TYPE(aot_func_type->types[aot_func_type->param_count + i]);
- if (!(param_types[j] = LLVMPointerType(param_types[j], 0))) {
- aot_set_last_error("llvm get pointer type failed.");
- goto fail;
- }
- }
- /* Resolve return type of the LLVM function */
- if (aot_func_type->result_count)
- ret_type =
- TO_LLVM_TYPE(aot_func_type->types[aot_func_type->param_count]);
- else
- ret_type = VOID_TYPE;
- /* Resolve function prototype */
- if (!(func_type =
- LLVMFunctionType(ret_type, param_types, param_count, false))) {
- aot_set_last_error("create LLVM function type failed.");
- goto fail;
- }
- /* Add LLVM function */
- snprintf(func_name, sizeof(func_name), "%s%d", AOT_FUNC_PREFIX, func_index);
- if (!(func = LLVMAddFunction(module, func_name, func_type))) {
- aot_set_last_error("add LLVM function failed.");
- goto fail;
- }
- j = 0;
- local_value = LLVMGetParam(func, j++);
- LLVMSetValueName(local_value, "exec_env");
- /* Set parameter names */
- for (i = 0; i < aot_func_type->param_count; i++) {
- local_value = LLVMGetParam(func, j++);
- LLVMSetValueName(local_value, "");
- }
- if (p_func_type)
- *p_func_type = func_type;
- if (comp_ctx->is_jit_mode) {
- func_type_wrapper = LLVMFunctionType(VOID_TYPE, NULL, 0, false);
- if (!func_type_wrapper) {
- aot_set_last_error("create LLVM function type failed.");
- goto fail;
- }
- snprintf(func_name, sizeof(func_name), "%s%d%s", AOT_FUNC_PREFIX,
- func_index, "_wrapper");
- if (!(func_wrapper =
- LLVMAddFunction(module, func_name, func_type_wrapper))) {
- aot_set_last_error("add LLVM function failed.");
- goto fail;
- }
- if (!(func_begin = LLVMAppendBasicBlockInContext(
- comp_ctx->context, func_wrapper, "func_begin"))) {
- aot_set_last_error("add LLVM basic block failed.");
- goto fail;
- }
- LLVMPositionBuilderAtEnd(comp_ctx->builder, func_begin);
- if (!LLVMBuildRetVoid(comp_ctx->builder)) {
- aot_set_last_error("llvm build ret failed.");
- goto fail;
- }
- }
- fail:
- wasm_runtime_free(param_types);
- return func;
- }
- static void
- free_block_memory(AOTBlock *block)
- {
- if (block->param_types)
- wasm_runtime_free(block->param_types);
- if (block->result_types)
- wasm_runtime_free(block->result_types);
- wasm_runtime_free(block);
- }
- /**
- * Create first AOTBlock, or function block for the function
- */
- static AOTBlock *
- aot_create_func_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
- AOTFunc *func, AOTFuncType *aot_func_type)
- {
- AOTBlock *aot_block;
- uint32 param_count = aot_func_type->param_count,
- result_count = aot_func_type->result_count;
- /* Allocate memory */
- if (!(aot_block = wasm_runtime_malloc(sizeof(AOTBlock)))) {
- aot_set_last_error("allocate memory failed.");
- return NULL;
- }
- memset(aot_block, 0, sizeof(AOTBlock));
- if (param_count
- && !(aot_block->param_types = wasm_runtime_malloc(param_count))) {
- aot_set_last_error("allocate memory failed.");
- goto fail;
- }
- if (result_count) {
- if (!(aot_block->result_types = wasm_runtime_malloc(result_count))) {
- aot_set_last_error("allocate memory failed.");
- goto fail;
- }
- }
- /* Set block data */
- aot_block->label_type = LABEL_TYPE_FUNCTION;
- aot_block->param_count = param_count;
- if (param_count) {
- bh_memcpy_s(aot_block->param_types, param_count, aot_func_type->types,
- param_count);
- }
- aot_block->result_count = result_count;
- if (result_count) {
- bh_memcpy_s(aot_block->result_types, result_count,
- aot_func_type->types + param_count, result_count);
- }
- aot_block->wasm_code_end = func->code + func->code_size;
- /* Add function entry block */
- if (!(aot_block->llvm_entry_block = LLVMAppendBasicBlockInContext(
- comp_ctx->context, func_ctx->func, "func_begin"))) {
- aot_set_last_error("add LLVM basic block failed.");
- goto fail;
- }
- return aot_block;
- fail:
- free_block_memory(aot_block);
- return NULL;
- }
- static bool
- create_memory_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
- LLVMTypeRef int8_ptr_type, uint32 func_index)
- {
- LLVMValueRef offset, mem_info_base;
- uint32 memory_count;
- WASMModule *module = comp_ctx->comp_data->wasm_module;
- WASMFunction *func = module->functions[func_index];
- LLVMTypeRef bound_check_type;
- bool mem_space_unchanged =
- (!func->has_op_memory_grow && !func->has_op_func_call)
- || (!module->possible_memory_grow);
- #if WASM_ENABLE_SHARED_MEMORY != 0
- bool is_shared_memory;
- #endif
- func_ctx->mem_space_unchanged = mem_space_unchanged;
- memory_count = module->memory_count + module->import_memory_count;
- /* If the module dosen't have memory, reserve
- one mem_info space with empty content */
- if (memory_count == 0)
- memory_count = 1;
- if (!(func_ctx->mem_info =
- wasm_runtime_malloc(sizeof(AOTMemInfo) * memory_count))) {
- return false;
- }
- memset(func_ctx->mem_info, 0, sizeof(AOTMemInfo));
- /* Currently we only create memory info for memory 0 */
- /* Load memory base address */
- #if WASM_ENABLE_SHARED_MEMORY != 0
- is_shared_memory =
- comp_ctx->comp_data->memories[0].memory_flags & 0x02 ? true : false;
- if (is_shared_memory) {
- LLVMValueRef shared_mem_addr;
- offset = I32_CONST(offsetof(AOTModuleInstance, memories));
- if (!offset) {
- aot_set_last_error("create llvm const failed.");
- return false;
- }
- /* aot_inst->memories */
- if (!(shared_mem_addr = LLVMBuildInBoundsGEP2(
- comp_ctx->builder, INT8_TYPE, func_ctx->aot_inst, &offset, 1,
- "shared_mem_addr_offset"))) {
- aot_set_last_error("llvm build in bounds gep failed");
- return false;
- }
- if (!(shared_mem_addr =
- LLVMBuildBitCast(comp_ctx->builder, shared_mem_addr,
- int8_ptr_type, "shared_mem_addr_ptr"))) {
- aot_set_last_error("llvm build bit cast failed");
- return false;
- }
- /* aot_inst->memories[0] */
- if (!(shared_mem_addr =
- LLVMBuildLoad2(comp_ctx->builder, OPQ_PTR_TYPE,
- shared_mem_addr, "shared_mem_addr"))) {
- aot_set_last_error("llvm build load failed");
- return false;
- }
- if (!(shared_mem_addr =
- LLVMBuildBitCast(comp_ctx->builder, shared_mem_addr,
- int8_ptr_type, "shared_mem_addr_ptr"))) {
- aot_set_last_error("llvm build bit cast failed");
- return false;
- }
- if (!(shared_mem_addr =
- LLVMBuildLoad2(comp_ctx->builder, OPQ_PTR_TYPE,
- shared_mem_addr, "shared_mem_addr"))) {
- aot_set_last_error("llvm build load failed");
- return false;
- }
- /* memories[0]->memory_data */
- offset = I32_CONST(offsetof(AOTMemoryInstance, memory_data));
- if (!(func_ctx->mem_info[0].mem_base_addr = LLVMBuildInBoundsGEP2(
- comp_ctx->builder, INT8_TYPE, shared_mem_addr, &offset, 1,
- "mem_base_addr_offset"))) {
- aot_set_last_error("llvm build in bounds gep failed");
- return false;
- }
- /* memories[0]->cur_page_count */
- offset = I32_CONST(offsetof(AOTMemoryInstance, cur_page_count));
- if (!(func_ctx->mem_info[0].mem_cur_page_count_addr =
- LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
- shared_mem_addr, &offset, 1,
- "mem_cur_page_offset"))) {
- aot_set_last_error("llvm build in bounds gep failed");
- return false;
- }
- /* memories[0]->memory_data_size */
- offset = I32_CONST(offsetof(AOTMemoryInstance, memory_data_size));
- if (!(func_ctx->mem_info[0].mem_data_size_addr = LLVMBuildInBoundsGEP2(
- comp_ctx->builder, INT8_TYPE, shared_mem_addr, &offset, 1,
- "mem_data_size_offset"))) {
- aot_set_last_error("llvm build in bounds gep failed");
- return false;
- }
- }
- else
- #endif
- {
- uint32 offset_of_global_table_data;
- if (comp_ctx->is_jit_mode)
- offset_of_global_table_data =
- offsetof(WASMModuleInstance, global_table_data);
- else
- offset_of_global_table_data =
- offsetof(AOTModuleInstance, global_table_data);
- offset = I32_CONST(offset_of_global_table_data
- + offsetof(AOTMemoryInstance, memory_data));
- if (!(func_ctx->mem_info[0].mem_base_addr = LLVMBuildInBoundsGEP2(
- comp_ctx->builder, INT8_TYPE, func_ctx->aot_inst, &offset, 1,
- "mem_base_addr_offset"))) {
- aot_set_last_error("llvm build in bounds gep failed");
- return false;
- }
- offset = I32_CONST(offset_of_global_table_data
- + offsetof(AOTMemoryInstance, cur_page_count));
- if (!(func_ctx->mem_info[0].mem_cur_page_count_addr =
- LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
- func_ctx->aot_inst, &offset, 1,
- "mem_cur_page_offset"))) {
- aot_set_last_error("llvm build in bounds gep failed");
- return false;
- }
- offset = I32_CONST(offset_of_global_table_data
- + offsetof(AOTMemoryInstance, memory_data_size));
- if (!(func_ctx->mem_info[0].mem_data_size_addr = LLVMBuildInBoundsGEP2(
- comp_ctx->builder, INT8_TYPE, func_ctx->aot_inst, &offset, 1,
- "mem_data_size_offset"))) {
- aot_set_last_error("llvm build in bounds gep failed");
- return false;
- }
- }
- /* Store mem info base address before cast */
- mem_info_base = func_ctx->mem_info[0].mem_base_addr;
- if (!(func_ctx->mem_info[0].mem_base_addr = LLVMBuildBitCast(
- comp_ctx->builder, func_ctx->mem_info[0].mem_base_addr,
- int8_ptr_type, "mem_base_addr_ptr"))) {
- aot_set_last_error("llvm build bit cast failed");
- return false;
- }
- if (!(func_ctx->mem_info[0].mem_cur_page_count_addr = LLVMBuildBitCast(
- comp_ctx->builder, func_ctx->mem_info[0].mem_cur_page_count_addr,
- INT32_PTR_TYPE, "mem_cur_page_ptr"))) {
- aot_set_last_error("llvm build bit cast failed");
- return false;
- }
- if (!(func_ctx->mem_info[0].mem_data_size_addr = LLVMBuildBitCast(
- comp_ctx->builder, func_ctx->mem_info[0].mem_data_size_addr,
- INT32_PTR_TYPE, "mem_data_size_ptr"))) {
- aot_set_last_error("llvm build bit cast failed");
- return false;
- }
- if (mem_space_unchanged) {
- if (!(func_ctx->mem_info[0].mem_base_addr = LLVMBuildLoad2(
- comp_ctx->builder, OPQ_PTR_TYPE,
- func_ctx->mem_info[0].mem_base_addr, "mem_base_addr"))) {
- aot_set_last_error("llvm build load failed");
- return false;
- }
- if (!(func_ctx->mem_info[0].mem_cur_page_count_addr =
- LLVMBuildLoad2(comp_ctx->builder, I32_TYPE,
- func_ctx->mem_info[0].mem_cur_page_count_addr,
- "mem_cur_page_count"))) {
- aot_set_last_error("llvm build load failed");
- return false;
- }
- if (!(func_ctx->mem_info[0].mem_data_size_addr = LLVMBuildLoad2(
- comp_ctx->builder, I32_TYPE,
- func_ctx->mem_info[0].mem_data_size_addr, "mem_data_size"))) {
- aot_set_last_error("llvm build load failed");
- return false;
- }
- }
- #if WASM_ENABLE_SHARED_MEMORY != 0
- else if (is_shared_memory) {
- /* The base address for shared memory will never changed,
- we can load the value here */
- if (!(func_ctx->mem_info[0].mem_base_addr = LLVMBuildLoad2(
- comp_ctx->builder, OPQ_PTR_TYPE,
- func_ctx->mem_info[0].mem_base_addr, "mem_base_addr"))) {
- aot_set_last_error("llvm build load failed");
- return false;
- }
- }
- #endif
- bound_check_type = (comp_ctx->pointer_size == sizeof(uint64))
- ? INT64_PTR_TYPE
- : INT32_PTR_TYPE;
- /* Load memory bound check constants */
- offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_1byte)
- - offsetof(AOTMemoryInstance, memory_data));
- if (!(func_ctx->mem_info[0].mem_bound_check_1byte =
- LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, mem_info_base,
- &offset, 1, "bound_check_1byte_offset"))) {
- aot_set_last_error("llvm build in bounds gep failed");
- return false;
- }
- if (!(func_ctx->mem_info[0].mem_bound_check_1byte = LLVMBuildBitCast(
- comp_ctx->builder, func_ctx->mem_info[0].mem_bound_check_1byte,
- bound_check_type, "bound_check_1byte_ptr"))) {
- aot_set_last_error("llvm build bit cast failed");
- return false;
- }
- if (mem_space_unchanged) {
- if (!(func_ctx->mem_info[0].mem_bound_check_1byte = LLVMBuildLoad2(
- comp_ctx->builder,
- (comp_ctx->pointer_size == sizeof(uint64)) ? I64_TYPE
- : I32_TYPE,
- func_ctx->mem_info[0].mem_bound_check_1byte,
- "bound_check_1byte"))) {
- aot_set_last_error("llvm build load failed");
- return false;
- }
- }
- offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_2bytes)
- - offsetof(AOTMemoryInstance, memory_data));
- if (!(func_ctx->mem_info[0].mem_bound_check_2bytes =
- LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, mem_info_base,
- &offset, 1, "bound_check_2bytes_offset"))) {
- aot_set_last_error("llvm build in bounds gep failed");
- return false;
- }
- if (!(func_ctx->mem_info[0].mem_bound_check_2bytes = LLVMBuildBitCast(
- comp_ctx->builder, func_ctx->mem_info[0].mem_bound_check_2bytes,
- bound_check_type, "bound_check_2bytes_ptr"))) {
- aot_set_last_error("llvm build bit cast failed");
- return false;
- }
- if (mem_space_unchanged) {
- if (!(func_ctx->mem_info[0].mem_bound_check_2bytes = LLVMBuildLoad2(
- comp_ctx->builder,
- (comp_ctx->pointer_size == sizeof(uint64)) ? I64_TYPE
- : I32_TYPE,
- func_ctx->mem_info[0].mem_bound_check_2bytes,
- "bound_check_2bytes"))) {
- aot_set_last_error("llvm build load failed");
- return false;
- }
- }
- offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_4bytes)
- - offsetof(AOTMemoryInstance, memory_data));
- if (!(func_ctx->mem_info[0].mem_bound_check_4bytes =
- LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, mem_info_base,
- &offset, 1, "bound_check_4bytes_offset"))) {
- aot_set_last_error("llvm build in bounds gep failed");
- return false;
- }
- if (!(func_ctx->mem_info[0].mem_bound_check_4bytes = LLVMBuildBitCast(
- comp_ctx->builder, func_ctx->mem_info[0].mem_bound_check_4bytes,
- bound_check_type, "bound_check_4bytes_ptr"))) {
- aot_set_last_error("llvm build bit cast failed");
- return false;
- }
- if (mem_space_unchanged) {
- if (!(func_ctx->mem_info[0].mem_bound_check_4bytes = LLVMBuildLoad2(
- comp_ctx->builder,
- (comp_ctx->pointer_size == sizeof(uint64)) ? I64_TYPE
- : I32_TYPE,
- func_ctx->mem_info[0].mem_bound_check_4bytes,
- "bound_check_4bytes"))) {
- aot_set_last_error("llvm build load failed");
- return false;
- }
- }
- offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_8bytes)
- - offsetof(AOTMemoryInstance, memory_data));
- if (!(func_ctx->mem_info[0].mem_bound_check_8bytes =
- LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, mem_info_base,
- &offset, 1, "bound_check_8bytes_offset"))) {
- aot_set_last_error("llvm build in bounds gep failed");
- return false;
- }
- if (!(func_ctx->mem_info[0].mem_bound_check_8bytes = LLVMBuildBitCast(
- comp_ctx->builder, func_ctx->mem_info[0].mem_bound_check_8bytes,
- bound_check_type, "bound_check_8bytes_ptr"))) {
- aot_set_last_error("llvm build bit cast failed");
- return false;
- }
- if (mem_space_unchanged) {
- if (!(func_ctx->mem_info[0].mem_bound_check_8bytes = LLVMBuildLoad2(
- comp_ctx->builder,
- (comp_ctx->pointer_size == sizeof(uint64)) ? I64_TYPE
- : I32_TYPE,
- func_ctx->mem_info[0].mem_bound_check_8bytes,
- "bound_check_8bytes"))) {
- aot_set_last_error("llvm build load failed");
- return false;
- }
- }
- offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_16bytes)
- - offsetof(AOTMemoryInstance, memory_data));
- if (!(func_ctx->mem_info[0].mem_bound_check_16bytes = LLVMBuildInBoundsGEP2(
- comp_ctx->builder, INT8_TYPE, mem_info_base, &offset, 1,
- "bound_check_16bytes_offset"))) {
- aot_set_last_error("llvm build in bounds gep failed");
- return false;
- }
- if (!(func_ctx->mem_info[0].mem_bound_check_16bytes = LLVMBuildBitCast(
- comp_ctx->builder, func_ctx->mem_info[0].mem_bound_check_16bytes,
- bound_check_type, "bound_check_16bytes_ptr"))) {
- aot_set_last_error("llvm build bit cast failed");
- return false;
- }
- if (mem_space_unchanged) {
- if (!(func_ctx->mem_info[0].mem_bound_check_16bytes = LLVMBuildLoad2(
- comp_ctx->builder,
- (comp_ctx->pointer_size == sizeof(uint64)) ? I64_TYPE
- : I32_TYPE,
- func_ctx->mem_info[0].mem_bound_check_16bytes,
- "bound_check_16bytes"))) {
- aot_set_last_error("llvm build load failed");
- return false;
- }
- }
- return true;
- }
- static bool
- create_cur_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
- {
- LLVMValueRef offset;
- offset = I32_CONST(offsetof(AOTModuleInstance, cur_exception));
- func_ctx->cur_exception =
- LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, func_ctx->aot_inst,
- &offset, 1, "cur_exception");
- if (!func_ctx->cur_exception) {
- aot_set_last_error("llvm build in bounds gep failed.");
- return false;
- }
- return true;
- }
- static bool
- create_func_type_indexes(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
- {
- LLVMValueRef offset, func_type_indexes_ptr;
- LLVMTypeRef int32_ptr_type;
- offset = I32_CONST(offsetof(AOTModuleInstance, func_type_indexes));
- func_type_indexes_ptr =
- LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, func_ctx->aot_inst,
- &offset, 1, "func_type_indexes_ptr");
- if (!func_type_indexes_ptr) {
- aot_set_last_error("llvm build add failed.");
- return false;
- }
- if (!(int32_ptr_type = LLVMPointerType(INT32_PTR_TYPE, 0))) {
- aot_set_last_error("llvm get pointer type failed.");
- return false;
- }
- func_ctx->func_type_indexes =
- LLVMBuildBitCast(comp_ctx->builder, func_type_indexes_ptr,
- int32_ptr_type, "func_type_indexes_tmp");
- if (!func_ctx->func_type_indexes) {
- aot_set_last_error("llvm build bit cast failed.");
- return false;
- }
- func_ctx->func_type_indexes =
- LLVMBuildLoad2(comp_ctx->builder, INT32_PTR_TYPE,
- func_ctx->func_type_indexes, "func_type_indexes");
- if (!func_ctx->func_type_indexes) {
- aot_set_last_error("llvm build load failed.");
- return false;
- }
- return true;
- }
- static bool
- create_func_ptrs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
- {
- LLVMValueRef offset;
- offset = I32_CONST(offsetof(AOTModuleInstance, func_ptrs));
- func_ctx->func_ptrs =
- LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, func_ctx->aot_inst,
- &offset, 1, "func_ptrs_offset");
- if (!func_ctx->func_ptrs) {
- aot_set_last_error("llvm build in bounds gep failed.");
- return false;
- }
- func_ctx->func_ptrs =
- LLVMBuildBitCast(comp_ctx->builder, func_ctx->func_ptrs,
- comp_ctx->exec_env_type, "func_ptrs_tmp");
- if (!func_ctx->func_ptrs) {
- aot_set_last_error("llvm build bit cast failed.");
- return false;
- }
- func_ctx->func_ptrs = LLVMBuildLoad2(comp_ctx->builder, OPQ_PTR_TYPE,
- func_ctx->func_ptrs, "func_ptrs_ptr");
- if (!func_ctx->func_ptrs) {
- aot_set_last_error("llvm build load failed.");
- return false;
- }
- func_ctx->func_ptrs =
- LLVMBuildBitCast(comp_ctx->builder, func_ctx->func_ptrs,
- comp_ctx->exec_env_type, "func_ptrs");
- if (!func_ctx->func_ptrs) {
- aot_set_last_error("llvm build bit cast failed.");
- return false;
- }
- return true;
- }
- /**
- * Create function compiler context
- */
- static AOTFuncContext *
- aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx,
- AOTFunc *func, uint32 func_index)
- {
- AOTFuncContext *func_ctx;
- AOTFuncType *aot_func_type = comp_data->func_types[func->func_type_index];
- AOTBlock *aot_block;
- LLVMTypeRef int8_ptr_type, int32_ptr_type;
- LLVMValueRef aot_inst_offset = I32_TWO, aot_inst_addr;
- LLVMValueRef argv_buf_offset = I32_THREE, argv_buf_addr;
- LLVMValueRef stack_bound_offset = I32_FOUR, stack_bound_addr;
- LLVMValueRef aux_stack_bound_offset = I32_SIX, aux_stack_bound_addr;
- LLVMValueRef aux_stack_bottom_offset = I32_SEVEN, aux_stack_bottom_addr;
- LLVMValueRef native_symbol_offset = I32_EIGHT, native_symbol_addr;
- char local_name[32];
- uint64 size;
- uint32 i, j = 0;
- /* Allocate memory for the function context */
- size = offsetof(AOTFuncContext, locals)
- + sizeof(LLVMValueRef)
- * ((uint64)aot_func_type->param_count + func->local_count);
- if (size >= UINT32_MAX || !(func_ctx = wasm_runtime_malloc((uint32)size))) {
- aot_set_last_error("allocate memory failed.");
- return NULL;
- }
- memset(func_ctx, 0, (uint32)size);
- func_ctx->aot_func = func;
- func_ctx->module = comp_ctx->module;
- /* Add LLVM function */
- if (!(func_ctx->func =
- aot_add_llvm_func(comp_ctx, func_ctx->module, aot_func_type,
- func_index, &func_ctx->func_type)))
- goto fail;
- /* Create function's first AOTBlock */
- if (!(aot_block =
- aot_create_func_block(comp_ctx, func_ctx, func, aot_func_type)))
- goto fail;
- #if WASM_ENABLE_DEBUG_AOT != 0
- func_ctx->debug_func = dwarf_gen_func_info(comp_ctx, func_ctx);
- #endif
- aot_block_stack_push(&func_ctx->block_stack, aot_block);
- /* Add local variables */
- LLVMPositionBuilderAtEnd(comp_ctx->builder, aot_block->llvm_entry_block);
- /* Save the pameters for fast access */
- func_ctx->exec_env = LLVMGetParam(func_ctx->func, j++);
- /* Get aot inst address, the layout of exec_env is:
- exec_env->next, exec_env->prev, exec_env->module_inst, and argv_buf */
- if (!(aot_inst_addr = LLVMBuildInBoundsGEP2(
- comp_ctx->builder, OPQ_PTR_TYPE, func_ctx->exec_env,
- &aot_inst_offset, 1, "aot_inst_addr"))) {
- aot_set_last_error("llvm build in bounds gep failed");
- goto fail;
- }
- /* Load aot inst */
- if (!(func_ctx->aot_inst = LLVMBuildLoad2(comp_ctx->builder, OPQ_PTR_TYPE,
- aot_inst_addr, "aot_inst"))) {
- aot_set_last_error("llvm build load failed");
- goto fail;
- }
- /* Get argv buffer address */
- if (!(argv_buf_addr = LLVMBuildInBoundsGEP2(
- comp_ctx->builder, OPQ_PTR_TYPE, func_ctx->exec_env,
- &argv_buf_offset, 1, "argv_buf_addr"))) {
- aot_set_last_error("llvm build in bounds gep failed");
- goto fail;
- }
- if (!(int32_ptr_type = LLVMPointerType(INT32_PTR_TYPE, 0))) {
- aot_set_last_error("llvm add pointer type failed");
- goto fail;
- }
- /* Convert to int32 pointer type */
- if (!(argv_buf_addr = LLVMBuildBitCast(comp_ctx->builder, argv_buf_addr,
- int32_ptr_type, "argv_buf_ptr"))) {
- aot_set_last_error("llvm build load failed");
- goto fail;
- }
- if (!(func_ctx->argv_buf = LLVMBuildLoad2(comp_ctx->builder, INT32_PTR_TYPE,
- argv_buf_addr, "argv_buf"))) {
- aot_set_last_error("llvm build load failed");
- goto fail;
- }
- /* Get native stack boundary address */
- if (!(stack_bound_addr = LLVMBuildInBoundsGEP2(
- comp_ctx->builder, OPQ_PTR_TYPE, func_ctx->exec_env,
- &stack_bound_offset, 1, "stack_bound_addr"))) {
- aot_set_last_error("llvm build in bounds gep failed");
- goto fail;
- }
- if (!(func_ctx->native_stack_bound =
- LLVMBuildLoad2(comp_ctx->builder, OPQ_PTR_TYPE, stack_bound_addr,
- "native_stack_bound"))) {
- aot_set_last_error("llvm build load failed");
- goto fail;
- }
- /* Get aux stack boundary address */
- if (!(aux_stack_bound_addr = LLVMBuildInBoundsGEP2(
- comp_ctx->builder, OPQ_PTR_TYPE, func_ctx->exec_env,
- &aux_stack_bound_offset, 1, "aux_stack_bound_addr"))) {
- aot_set_last_error("llvm build in bounds gep failed");
- goto fail;
- }
- if (!(aux_stack_bound_addr =
- LLVMBuildBitCast(comp_ctx->builder, aux_stack_bound_addr,
- INT32_PTR_TYPE, "aux_stack_bound_ptr"))) {
- aot_set_last_error("llvm build bit cast failed");
- goto fail;
- }
- if (!(func_ctx->aux_stack_bound =
- LLVMBuildLoad2(comp_ctx->builder, I32_TYPE, aux_stack_bound_addr,
- "aux_stack_bound"))) {
- aot_set_last_error("llvm build load failed");
- goto fail;
- }
- /* Get aux stack bottom address */
- if (!(aux_stack_bottom_addr = LLVMBuildInBoundsGEP2(
- comp_ctx->builder, OPQ_PTR_TYPE, func_ctx->exec_env,
- &aux_stack_bottom_offset, 1, "aux_stack_bottom_addr"))) {
- aot_set_last_error("llvm build in bounds gep failed");
- goto fail;
- }
- if (!(aux_stack_bottom_addr =
- LLVMBuildBitCast(comp_ctx->builder, aux_stack_bottom_addr,
- INT32_PTR_TYPE, "aux_stack_bottom_ptr"))) {
- aot_set_last_error("llvm build bit cast failed");
- goto fail;
- }
- if (!(func_ctx->aux_stack_bottom =
- LLVMBuildLoad2(comp_ctx->builder, I32_TYPE, aux_stack_bottom_addr,
- "aux_stack_bottom"))) {
- aot_set_last_error("llvm build load failed");
- goto fail;
- }
- if (!(native_symbol_addr = LLVMBuildInBoundsGEP2(
- comp_ctx->builder, OPQ_PTR_TYPE, func_ctx->exec_env,
- &native_symbol_offset, 1, "native_symbol_addr"))) {
- aot_set_last_error("llvm build in bounds gep failed");
- goto fail;
- }
- if (!(func_ctx->native_symbol =
- LLVMBuildLoad2(comp_ctx->builder, OPQ_PTR_TYPE,
- native_symbol_addr, "native_symbol_tmp"))) {
- aot_set_last_error("llvm build bit cast failed");
- goto fail;
- }
- if (!(func_ctx->native_symbol =
- LLVMBuildBitCast(comp_ctx->builder, func_ctx->native_symbol,
- comp_ctx->exec_env_type, "native_symbol"))) {
- aot_set_last_error("llvm build bit cast failed");
- goto fail;
- }
- for (i = 0; i < aot_func_type->param_count; i++, j++) {
- snprintf(local_name, sizeof(local_name), "l%d", i);
- func_ctx->locals[i] =
- LLVMBuildAlloca(comp_ctx->builder,
- TO_LLVM_TYPE(aot_func_type->types[i]), local_name);
- if (!func_ctx->locals[i]) {
- aot_set_last_error("llvm build alloca failed.");
- goto fail;
- }
- if (!LLVMBuildStore(comp_ctx->builder, LLVMGetParam(func_ctx->func, j),
- func_ctx->locals[i])) {
- aot_set_last_error("llvm build store failed.");
- goto fail;
- }
- }
- for (i = 0; i < func->local_count; i++) {
- LLVMTypeRef local_type;
- LLVMValueRef local_value = NULL;
- snprintf(local_name, sizeof(local_name), "l%d",
- aot_func_type->param_count + i);
- local_type = TO_LLVM_TYPE(func->local_types[i]);
- func_ctx->locals[aot_func_type->param_count + i] =
- LLVMBuildAlloca(comp_ctx->builder, local_type, local_name);
- if (!func_ctx->locals[aot_func_type->param_count + i]) {
- aot_set_last_error("llvm build alloca failed.");
- goto fail;
- }
- switch (func->local_types[i]) {
- case VALUE_TYPE_I32:
- local_value = I32_ZERO;
- break;
- case VALUE_TYPE_I64:
- local_value = I64_ZERO;
- break;
- case VALUE_TYPE_F32:
- local_value = F32_ZERO;
- break;
- case VALUE_TYPE_F64:
- local_value = F64_ZERO;
- break;
- case VALUE_TYPE_V128:
- local_value = V128_i64x2_ZERO;
- break;
- case VALUE_TYPE_FUNCREF:
- case VALUE_TYPE_EXTERNREF:
- local_value = REF_NULL;
- break;
- default:
- bh_assert(0);
- break;
- }
- if (!LLVMBuildStore(comp_ctx->builder, local_value,
- func_ctx->locals[aot_func_type->param_count + i])) {
- aot_set_last_error("llvm build store failed.");
- goto fail;
- }
- }
- if (aot_func_type->param_count + func->local_count > 0) {
- func_ctx->last_alloca =
- func_ctx
- ->locals[aot_func_type->param_count + func->local_count - 1];
- if (!(func_ctx->last_alloca =
- LLVMBuildBitCast(comp_ctx->builder, func_ctx->last_alloca,
- INT8_PTR_TYPE, "stack_ptr"))) {
- aot_set_last_error("llvm build bit cast failed.");
- goto fail;
- }
- }
- else {
- if (!(func_ctx->last_alloca =
- LLVMBuildAlloca(comp_ctx->builder, INT8_TYPE, "stack_ptr"))) {
- aot_set_last_error("llvm build alloca failed.");
- goto fail;
- }
- }
- if (!(int8_ptr_type = LLVMPointerType(INT8_PTR_TYPE, 0))) {
- aot_set_last_error("llvm add pointer type failed.");
- goto fail;
- }
- /* Create base addr, end addr, data size of mem, heap */
- if (!create_memory_info(comp_ctx, func_ctx, int8_ptr_type, func_index))
- goto fail;
- /* Load current exception */
- if (!create_cur_exception(comp_ctx, func_ctx))
- goto fail;
- /* Load function type indexes */
- if (!create_func_type_indexes(comp_ctx, func_ctx))
- goto fail;
- /* Load function pointers */
- if (!create_func_ptrs(comp_ctx, func_ctx))
- goto fail;
- return func_ctx;
- fail:
- if (func_ctx->mem_info)
- wasm_runtime_free(func_ctx->mem_info);
- aot_block_stack_destroy(&func_ctx->block_stack);
- wasm_runtime_free(func_ctx);
- return NULL;
- }
- static void
- aot_destroy_func_contexts(AOTFuncContext **func_ctxes, uint32 count)
- {
- uint32 i;
- for (i = 0; i < count; i++)
- if (func_ctxes[i]) {
- if (func_ctxes[i]->mem_info)
- wasm_runtime_free(func_ctxes[i]->mem_info);
- aot_block_stack_destroy(&func_ctxes[i]->block_stack);
- aot_checked_addr_list_destroy(func_ctxes[i]);
- wasm_runtime_free(func_ctxes[i]);
- }
- wasm_runtime_free(func_ctxes);
- }
- /**
- * Create function compiler contexts
- */
- static AOTFuncContext **
- aot_create_func_contexts(AOTCompData *comp_data, AOTCompContext *comp_ctx)
- {
- AOTFuncContext **func_ctxes;
- uint64 size;
- uint32 i;
- /* Allocate memory */
- size = sizeof(AOTFuncContext *) * (uint64)comp_data->func_count;
- if (size >= UINT32_MAX
- || !(func_ctxes = wasm_runtime_malloc((uint32)size))) {
- aot_set_last_error("allocate memory failed.");
- return NULL;
- }
- memset(func_ctxes, 0, size);
- /* Create each function context */
- for (i = 0; i < comp_data->func_count; i++) {
- AOTFunc *func = comp_data->funcs[i];
- if (!(func_ctxes[i] =
- aot_create_func_context(comp_data, comp_ctx, func, i))) {
- aot_destroy_func_contexts(func_ctxes, comp_data->func_count);
- return NULL;
- }
- }
- return func_ctxes;
- }
- static bool
- aot_set_llvm_basic_types(AOTLLVMTypes *basic_types, LLVMContextRef context)
- {
- basic_types->int1_type = LLVMInt1TypeInContext(context);
- basic_types->int8_type = LLVMInt8TypeInContext(context);
- basic_types->int16_type = LLVMInt16TypeInContext(context);
- basic_types->int32_type = LLVMInt32TypeInContext(context);
- basic_types->int64_type = LLVMInt64TypeInContext(context);
- basic_types->float32_type = LLVMFloatTypeInContext(context);
- basic_types->float64_type = LLVMDoubleTypeInContext(context);
- basic_types->void_type = LLVMVoidTypeInContext(context);
- basic_types->meta_data_type = LLVMMetadataTypeInContext(context);
- basic_types->int8_ptr_type = LLVMPointerType(basic_types->int8_type, 0);
- if (basic_types->int8_ptr_type) {
- basic_types->int8_pptr_type =
- LLVMPointerType(basic_types->int8_ptr_type, 0);
- }
- basic_types->int16_ptr_type = LLVMPointerType(basic_types->int16_type, 0);
- basic_types->int32_ptr_type = LLVMPointerType(basic_types->int32_type, 0);
- basic_types->int64_ptr_type = LLVMPointerType(basic_types->int64_type, 0);
- basic_types->float32_ptr_type =
- LLVMPointerType(basic_types->float32_type, 0);
- basic_types->float64_ptr_type =
- LLVMPointerType(basic_types->float64_type, 0);
- basic_types->i8x16_vec_type = LLVMVectorType(basic_types->int8_type, 16);
- basic_types->i16x8_vec_type = LLVMVectorType(basic_types->int16_type, 8);
- basic_types->i32x4_vec_type = LLVMVectorType(basic_types->int32_type, 4);
- basic_types->i64x2_vec_type = LLVMVectorType(basic_types->int64_type, 2);
- basic_types->f32x4_vec_type = LLVMVectorType(basic_types->float32_type, 4);
- basic_types->f64x2_vec_type = LLVMVectorType(basic_types->float64_type, 2);
- basic_types->v128_type = basic_types->i64x2_vec_type;
- basic_types->v128_ptr_type = LLVMPointerType(basic_types->v128_type, 0);
- basic_types->i1x2_vec_type = LLVMVectorType(basic_types->int1_type, 2);
- basic_types->funcref_type = LLVMInt32TypeInContext(context);
- basic_types->externref_type = LLVMInt32TypeInContext(context);
- return (basic_types->int8_ptr_type && basic_types->int8_pptr_type
- && basic_types->int16_ptr_type && basic_types->int32_ptr_type
- && basic_types->int64_ptr_type && basic_types->float32_ptr_type
- && basic_types->float64_ptr_type && basic_types->i8x16_vec_type
- && basic_types->i16x8_vec_type && basic_types->i32x4_vec_type
- && basic_types->i64x2_vec_type && basic_types->f32x4_vec_type
- && basic_types->f64x2_vec_type && basic_types->i1x2_vec_type
- && basic_types->meta_data_type && basic_types->funcref_type
- && basic_types->externref_type)
- ? true
- : false;
- }
- static bool
- aot_create_llvm_consts(AOTLLVMConsts *consts, AOTCompContext *comp_ctx)
- {
- #define CREATE_I1_CONST(name, value) \
- if (!(consts->i1_##name = \
- LLVMConstInt(comp_ctx->basic_types.int1_type, value, true))) \
- return false;
- CREATE_I1_CONST(zero, 0)
- CREATE_I1_CONST(one, 1)
- #undef CREATE_I1_CONST
- if (!(consts->i8_zero = I8_CONST(0)))
- return false;
- if (!(consts->f32_zero = F32_CONST(0)))
- return false;
- if (!(consts->f64_zero = F64_CONST(0)))
- return false;
- #define CREATE_I32_CONST(name, value) \
- if (!(consts->i32_##name = LLVMConstInt(I32_TYPE, value, true))) \
- return false;
- CREATE_I32_CONST(min, (uint32)INT32_MIN)
- CREATE_I32_CONST(neg_one, (uint32)-1)
- CREATE_I32_CONST(zero, 0)
- CREATE_I32_CONST(one, 1)
- CREATE_I32_CONST(two, 2)
- CREATE_I32_CONST(three, 3)
- CREATE_I32_CONST(four, 4)
- CREATE_I32_CONST(five, 5)
- CREATE_I32_CONST(six, 6)
- CREATE_I32_CONST(seven, 7)
- CREATE_I32_CONST(eight, 8)
- CREATE_I32_CONST(nine, 9)
- CREATE_I32_CONST(ten, 10)
- CREATE_I32_CONST(eleven, 11)
- CREATE_I32_CONST(twelve, 12)
- CREATE_I32_CONST(thirteen, 13)
- CREATE_I32_CONST(fourteen, 14)
- CREATE_I32_CONST(fifteen, 15)
- CREATE_I32_CONST(31, 31)
- CREATE_I32_CONST(32, 32)
- #undef CREATE_I32_CONST
- #define CREATE_I64_CONST(name, value) \
- if (!(consts->i64_##name = LLVMConstInt(I64_TYPE, value, true))) \
- return false;
- CREATE_I64_CONST(min, (uint64)INT64_MIN)
- CREATE_I64_CONST(neg_one, (uint64)-1)
- CREATE_I64_CONST(zero, 0)
- CREATE_I64_CONST(63, 63)
- CREATE_I64_CONST(64, 64)
- #undef CREATE_I64_CONST
- #define CREATE_V128_CONST(name, type) \
- if (!(consts->name##_vec_zero = LLVMConstNull(type))) \
- return false; \
- if (!(consts->name##_undef = LLVMGetUndef(type))) \
- return false;
- CREATE_V128_CONST(i8x16, V128_i8x16_TYPE)
- CREATE_V128_CONST(i16x8, V128_i16x8_TYPE)
- CREATE_V128_CONST(i32x4, V128_i32x4_TYPE)
- CREATE_V128_CONST(i64x2, V128_i64x2_TYPE)
- CREATE_V128_CONST(f32x4, V128_f32x4_TYPE)
- CREATE_V128_CONST(f64x2, V128_f64x2_TYPE)
- #undef CREATE_V128_CONST
- #define CREATE_VEC_ZERO_MASK(slot) \
- { \
- LLVMTypeRef type = LLVMVectorType(I32_TYPE, slot); \
- if (!type || !(consts->i32x##slot##_zero = LLVMConstNull(type))) \
- return false; \
- }
- CREATE_VEC_ZERO_MASK(16)
- CREATE_VEC_ZERO_MASK(8)
- CREATE_VEC_ZERO_MASK(4)
- CREATE_VEC_ZERO_MASK(2)
- #undef CREATE_VEC_ZERO_MASK
- return true;
- }
- typedef struct ArchItem {
- char *arch;
- bool support_eb;
- } ArchItem;
- /* clang-format off */
- static ArchItem valid_archs[] = {
- { "x86_64", false },
- { "i386", false },
- { "xtensa", false },
- { "mips", true },
- { "mipsel", false },
- { "aarch64v8", false },
- { "aarch64v8.1", false },
- { "aarch64v8.2", false },
- { "aarch64v8.3", false },
- { "aarch64v8.4", false },
- { "aarch64v8.5", false },
- { "aarch64_bev8", false }, /* big endian */
- { "aarch64_bev8.1", false },
- { "aarch64_bev8.2", false },
- { "aarch64_bev8.3", false },
- { "aarch64_bev8.4", false },
- { "aarch64_bev8.5", false },
- { "armv4", true },
- { "armv4t", true },
- { "armv5t", true },
- { "armv5te", true },
- { "armv5tej", true },
- { "armv6", true },
- { "armv6kz", true },
- { "armv6t2", true },
- { "armv6k", true },
- { "armv7", true },
- { "armv6m", true },
- { "armv6sm", true },
- { "armv7em", true },
- { "armv8a", true },
- { "armv8r", true },
- { "armv8m.base", true },
- { "armv8m.main", true },
- { "armv8.1m.main", true },
- { "thumbv4", true },
- { "thumbv4t", true },
- { "thumbv5t", true },
- { "thumbv5te", true },
- { "thumbv5tej", true },
- { "thumbv6", true },
- { "thumbv6kz", true },
- { "thumbv6t2", true },
- { "thumbv6k", true },
- { "thumbv7", true },
- { "thumbv6m", true },
- { "thumbv6sm", true },
- { "thumbv7em", true },
- { "thumbv8a", true },
- { "thumbv8r", true },
- { "thumbv8m.base", true },
- { "thumbv8m.main", true },
- { "thumbv8.1m.main", true },
- { "riscv32", true },
- { "riscv64", true },
- { "arc", true }
- };
- static const char *valid_abis[] = {
- "gnu",
- "eabi",
- "gnueabihf",
- "msvc",
- "ilp32",
- "ilp32f",
- "ilp32d",
- "lp64",
- "lp64f",
- "lp64d"
- };
- /* clang-format on */
- static void
- print_supported_targets()
- {
- uint32 i;
- os_printf("Supported targets:\n");
- for (i = 0; i < sizeof(valid_archs) / sizeof(ArchItem); i++) {
- os_printf("%s ", valid_archs[i].arch);
- if (valid_archs[i].support_eb)
- os_printf("%seb ", valid_archs[i].arch);
- }
- os_printf("\n");
- }
- static void
- print_supported_abis()
- {
- uint32 i;
- os_printf("Supported ABI: ");
- for (i = 0; i < sizeof(valid_abis) / sizeof(const char *); i++)
- os_printf("%s ", valid_abis[i]);
- os_printf("\n");
- }
- static bool
- check_target_arch(const char *target_arch)
- {
- uint32 i;
- char *arch;
- bool support_eb;
- for (i = 0; i < sizeof(valid_archs) / sizeof(ArchItem); i++) {
- arch = valid_archs[i].arch;
- support_eb = valid_archs[i].support_eb;
- if (!strncmp(target_arch, arch, strlen(arch))
- && ((support_eb
- && (!strcmp(target_arch + strlen(arch), "eb")
- || !strcmp(target_arch + strlen(arch), "")))
- || (!support_eb && !strcmp(target_arch + strlen(arch), "")))) {
- return true;
- }
- }
- return false;
- }
- static bool
- check_target_abi(const char *target_abi)
- {
- uint32 i;
- for (i = 0; i < sizeof(valid_abis) / sizeof(char *); i++) {
- if (!strcmp(target_abi, valid_abis[i]))
- return true;
- }
- return false;
- }
- static void
- get_target_arch_from_triple(const char *triple, char *arch_buf, uint32 buf_size)
- {
- uint32 i = 0;
- while (*triple != '-' && *triple != '\0' && i < buf_size - 1)
- arch_buf[i++] = *triple++;
- /* Make sure buffer is long enough */
- bh_assert(*triple == '-' || *triple == '\0');
- }
- void
- aot_handle_llvm_errmsg(const char *string, LLVMErrorRef err)
- {
- char *err_msg = LLVMGetErrorMessage(err);
- aot_set_last_error_v("%s: %s", string, err_msg);
- LLVMDisposeErrorMessage(err_msg);
- }
- #ifndef NDEBUG
- static LLVMErrorRef
- run_pass(void *ctx, LLVMModuleRef module)
- {
- /*AOTCompContext *comp_ctx = (AOTCompContext *)ctx;*/
- size_t len;
- LOG_VERBOSE("--- In IRTransformLayer @ T#%ld---",
- LLVMGetModuleIdentifier(module, &len), pthread_self());
- /* TODO: enable this for JIT mode after fixing LLVM issues */
- /*aot_apply_llvm_new_pass_manager(comp_ctx, module);*/
- bh_print_time("Begin to generate machine code");
- return LLVMErrorSuccess;
- }
- static LLVMErrorRef
- do_ir_transform(void *ctx, LLVMOrcThreadSafeModuleRef *module,
- LLVMOrcMaterializationResponsibilityRef mr)
- {
- (void)mr;
- return LLVMOrcThreadSafeModuleWithModuleDo(*module, run_pass, ctx);
- }
- static LLVMErrorRef
- do_obj_transform(void *Ctx, LLVMMemoryBufferRef *ObjInOut)
- {
- bh_print_time("Finish generating machine code");
- LOG_VERBOSE("--- In ObjectTransformLayer @ T#%ld ---", pthread_self());
- (void)Ctx;
- (void)ObjInOut;
- return LLVMErrorSuccess;
- }
- #endif
- static bool
- create_target_machine_detect_host(AOTCompContext *comp_ctx)
- {
- char *triple = NULL;
- LLVMTargetRef target = NULL;
- char *err_msg = NULL;
- char *cpu = NULL;
- char *features = NULL;
- LLVMTargetMachineRef target_machine = NULL;
- bool ret = false;
- triple = LLVMGetDefaultTargetTriple();
- if (triple == NULL) {
- aot_set_last_error("failed to get default target triple.");
- goto fail;
- }
- if (LLVMGetTargetFromTriple(triple, &target, &err_msg) != 0) {
- aot_set_last_error_v("failed to get llvm target from triple %s.",
- err_msg);
- LLVMDisposeMessage(err_msg);
- goto fail;
- }
- if (!LLVMTargetHasJIT(target)) {
- aot_set_last_error("unspported JIT on this platform.");
- goto fail;
- }
- cpu = LLVMGetHostCPUName();
- if (cpu == NULL) {
- aot_set_last_error("failed to get host cpu information.");
- goto fail;
- }
- features = LLVMGetHostCPUFeatures();
- if (features == NULL) {
- aot_set_last_error("failed to get host cpu features.");
- goto fail;
- }
- LOG_VERBOSE("LLVM ORCJIT detected CPU \"%s\", with features \"%s\"\n", cpu,
- features);
- /* create TargetMachine */
- target_machine = LLVMCreateTargetMachine(
- target, triple, cpu, features, LLVMCodeGenLevelDefault,
- LLVMRelocDefault, LLVMCodeModelJITDefault);
- if (!target_machine) {
- aot_set_last_error("failed to create target machine.");
- goto fail;
- }
- comp_ctx->target_machine = target_machine;
- /* Save target arch */
- get_target_arch_from_triple(triple, comp_ctx->target_arch,
- sizeof(comp_ctx->target_arch));
- ret = true;
- fail:
- if (triple)
- LLVMDisposeMessage(triple);
- if (features)
- LLVMDisposeMessage(features);
- if (cpu)
- LLVMDisposeMessage(cpu);
- return ret;
- }
- static bool
- orc_jit_create(AOTCompContext *comp_ctx)
- {
- LLVMErrorRef err;
- LLVMOrcLLLazyJITRef orc_jit = NULL;
- LLVMOrcLLLazyJITBuilderRef builder = NULL;
- LLVMOrcJITTargetMachineBuilderRef jtmb = NULL;
- bool ret = false;
- builder = LLVMOrcCreateLLLazyJITBuilder();
- if (builder == NULL) {
- aot_set_last_error("failed to create jit builder.");
- goto fail;
- }
- err = LLVMOrcJITTargetMachineBuilderDetectHost(&jtmb);
- if (err != LLVMErrorSuccess) {
- aot_handle_llvm_errmsg(
- "quited to create LLVMOrcJITTargetMachineBuilderRef", err);
- goto fail;
- }
- LLVMOrcLLLazyJITBuilderSetNumCompileThreads(
- builder, WASM_ORC_JIT_COMPILE_THREAD_NUM);
- /* Ownership transfer:
- LLVMOrcJITTargetMachineBuilderRef -> LLVMOrcLLJITBuilderRef */
- LLVMOrcLLLazyJITBuilderSetJITTargetMachineBuilder(builder, jtmb);
- err = LLVMOrcCreateLLLazyJIT(&orc_jit, builder);
- if (err != LLVMErrorSuccess) {
- aot_handle_llvm_errmsg("quited to create llvm lazy orcjit instance",
- err);
- goto fail;
- }
- /* Ownership transfer: LLVMOrcLLJITBuilderRef -> LLVMOrcLLJITRef */
- builder = NULL;
- #ifndef NDEBUG
- /* Setup TransformLayer */
- LLVMOrcIRTransformLayerSetTransform(
- LLVMOrcLLLazyJITGetIRTransformLayer(orc_jit), *do_ir_transform,
- comp_ctx);
- LLVMOrcObjectTransformLayerSetTransform(
- LLVMOrcLLLazyJITGetObjTransformLayer(orc_jit), *do_obj_transform,
- comp_ctx);
- #endif
- /* Ownership transfer: local -> AOTCompContext */
- comp_ctx->orc_jit = orc_jit;
- orc_jit = NULL;
- ret = true;
- fail:
- if (builder)
- LLVMOrcDisposeLLLazyJITBuilder(builder);
- if (orc_jit)
- LLVMOrcDisposeLLLazyJIT(orc_jit);
- return ret;
- }
- AOTCompContext *
- aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option)
- {
- AOTCompContext *comp_ctx, *ret = NULL;
- LLVMTargetRef target;
- char *triple = NULL, *triple_norm, *arch, *abi;
- char *cpu = NULL, *features, buf[128];
- char *triple_norm_new = NULL, *cpu_new = NULL;
- char *err = NULL, *fp_round = "round.tonearest",
- *fp_exce = "fpexcept.strict";
- char triple_buf[32] = { 0 }, features_buf[128] = { 0 };
- uint32 opt_level, size_level, i;
- LLVMCodeModel code_model;
- LLVMTargetDataRef target_data_ref;
- /* Initialize LLVM environment */
- LLVMInitializeCore(LLVMGetGlobalPassRegistry());
- /* To all available target */
- LLVMInitializeAllTargetInfos();
- LLVMInitializeAllTargets();
- LLVMInitializeAllTargetMCs();
- LLVMInitializeAllAsmPrinters();
- LLVMInitializeAllAsmParsers();
- /* Allocate memory */
- if (!(comp_ctx = wasm_runtime_malloc(sizeof(AOTCompContext)))) {
- aot_set_last_error("allocate memory failed.");
- return NULL;
- }
- memset(comp_ctx, 0, sizeof(AOTCompContext));
- comp_ctx->comp_data = comp_data;
- /* Create LLVM context, module and builder */
- comp_ctx->orc_thread_safe_context = LLVMOrcCreateNewThreadSafeContext();
- if (!comp_ctx->orc_thread_safe_context) {
- aot_set_last_error("create LLVM ThreadSafeContext failed.");
- goto fail;
- }
- /* Get a reference to the underlying LLVMContext, note:
- different from non LAZY JIT mode, no need to dispose this context,
- if will be disposed when the thread safe context is disposed */
- if (!(comp_ctx->context = LLVMOrcThreadSafeContextGetContext(
- comp_ctx->orc_thread_safe_context))) {
- aot_set_last_error("get context from LLVM ThreadSafeContext failed.");
- goto fail;
- }
- if (!(comp_ctx->builder = LLVMCreateBuilderInContext(comp_ctx->context))) {
- aot_set_last_error("create LLVM builder failed.");
- goto fail;
- }
- /* Create LLVM module for each jit function, note:
- different from non ORC JIT mode, no need to dispose it,
- it will be disposed when the thread safe context is disposed */
- if (!(comp_ctx->module = LLVMModuleCreateWithNameInContext(
- "WASM Module", comp_ctx->context))) {
- aot_set_last_error("create LLVM module failed.");
- goto fail;
- }
- if (BH_LIST_ERROR == bh_list_init(&comp_ctx->native_symbols)) {
- goto fail;
- }
- #if WASM_ENABLE_DEBUG_AOT != 0
- if (!(comp_ctx->debug_builder = LLVMCreateDIBuilder(comp_ctx->module))) {
- aot_set_last_error("create LLVM Debug Infor builder failed.");
- goto fail;
- }
- LLVMAddModuleFlag(
- comp_ctx->module, LLVMModuleFlagBehaviorWarning, "Debug Info Version",
- strlen("Debug Info Version"),
- LLVMValueAsMetadata(LLVMConstInt(LLVMInt32Type(), 3, false)));
- comp_ctx->debug_file = dwarf_gen_file_info(comp_ctx);
- if (!comp_ctx->debug_file) {
- aot_set_last_error("dwarf generate file info failed");
- goto fail;
- }
- comp_ctx->debug_comp_unit = dwarf_gen_comp_unit_info(comp_ctx);
- if (!comp_ctx->debug_comp_unit) {
- aot_set_last_error("dwarf generate compile unit info failed");
- goto fail;
- }
- #endif
- if (option->enable_bulk_memory)
- comp_ctx->enable_bulk_memory = true;
- if (option->enable_thread_mgr)
- comp_ctx->enable_thread_mgr = true;
- if (option->enable_tail_call)
- comp_ctx->enable_tail_call = true;
- if (option->enable_ref_types)
- comp_ctx->enable_ref_types = true;
- if (option->enable_aux_stack_frame)
- comp_ctx->enable_aux_stack_frame = true;
- if (option->enable_aux_stack_check)
- comp_ctx->enable_aux_stack_check = true;
- if (option->is_indirect_mode)
- comp_ctx->is_indirect_mode = true;
- if (option->disable_llvm_intrinsics)
- comp_ctx->disable_llvm_intrinsics = true;
- if (option->disable_llvm_lto)
- comp_ctx->disable_llvm_lto = true;
- comp_ctx->opt_level = option->opt_level;
- comp_ctx->size_level = option->size_level;
- comp_ctx->custom_sections_wp = option->custom_sections;
- comp_ctx->custom_sections_count = option->custom_sections_count;
- if (option->is_jit_mode) {
- comp_ctx->is_jit_mode = true;
- /* Create TargetMachine */
- if (!create_target_machine_detect_host(comp_ctx))
- goto fail;
- /* Create LLJIT Instance */
- if (!orc_jit_create(comp_ctx))
- goto fail;
- #ifndef OS_ENABLE_HW_BOUND_CHECK
- comp_ctx->enable_bound_check = true;
- #else
- comp_ctx->enable_bound_check = false;
- #endif
- }
- else {
- /* Create LLVM target machine */
- arch = option->target_arch;
- abi = option->target_abi;
- cpu = option->target_cpu;
- features = option->cpu_features;
- opt_level = option->opt_level;
- size_level = option->size_level;
- /* verify external llc compiler */
- comp_ctx->external_llc_compiler = getenv("WAMRC_LLC_COMPILER");
- if (comp_ctx->external_llc_compiler) {
- #if defined(_WIN32) || defined(_WIN32_)
- comp_ctx->external_llc_compiler = NULL;
- LOG_WARNING("External LLC compiler not supported on Windows.");
- #else
- if (access(comp_ctx->external_llc_compiler, X_OK) != 0) {
- LOG_WARNING("WAMRC_LLC_COMPILER [%s] not found, fallback to "
- "default pipeline",
- comp_ctx->external_llc_compiler);
- comp_ctx->external_llc_compiler = NULL;
- }
- else {
- comp_ctx->llc_compiler_flags = getenv("WAMRC_LLC_FLAGS");
- LOG_VERBOSE("Using external LLC compiler [%s]",
- comp_ctx->external_llc_compiler);
- }
- #endif
- }
- /* verify external asm compiler */
- if (!comp_ctx->external_llc_compiler) {
- comp_ctx->external_asm_compiler = getenv("WAMRC_ASM_COMPILER");
- if (comp_ctx->external_asm_compiler) {
- #if defined(_WIN32) || defined(_WIN32_)
- comp_ctx->external_asm_compiler = NULL;
- LOG_WARNING("External ASM compiler not supported on Windows.");
- #else
- if (access(comp_ctx->external_asm_compiler, X_OK) != 0) {
- LOG_WARNING(
- "WAMRC_ASM_COMPILER [%s] not found, fallback to "
- "default pipeline",
- comp_ctx->external_asm_compiler);
- comp_ctx->external_asm_compiler = NULL;
- }
- else {
- comp_ctx->asm_compiler_flags = getenv("WAMRC_ASM_FLAGS");
- LOG_VERBOSE("Using external ASM compiler [%s]",
- comp_ctx->external_asm_compiler);
- }
- #endif
- }
- }
- if (arch) {
- /* Add default sub-arch if not specified */
- if (!strcmp(arch, "arm"))
- arch = "armv4";
- else if (!strcmp(arch, "armeb"))
- arch = "armv4eb";
- else if (!strcmp(arch, "thumb"))
- arch = "thumbv4t";
- else if (!strcmp(arch, "thumbeb"))
- arch = "thumbv4teb";
- else if (!strcmp(arch, "aarch64"))
- arch = "aarch64v8";
- else if (!strcmp(arch, "aarch64_be"))
- arch = "aarch64_bev8";
- }
- /* Check target arch */
- if (arch && !check_target_arch(arch)) {
- if (!strcmp(arch, "help"))
- print_supported_targets();
- else
- aot_set_last_error(
- "Invalid target. "
- "Use --target=help to list all supported targets");
- goto fail;
- }
- /* Check target ABI */
- if (abi && !check_target_abi(abi)) {
- if (!strcmp(abi, "help"))
- print_supported_abis();
- else
- aot_set_last_error(
- "Invalid target ABI. "
- "Use --target-abi=help to list all supported ABI");
- goto fail;
- }
- /* Set default abi for riscv target */
- if (arch && !strncmp(arch, "riscv", 5) && !abi) {
- if (!strcmp(arch, "riscv64"))
- abi = "lp64d";
- else
- abi = "ilp32d";
- }
- #if defined(__APPLE__) || defined(__MACH__)
- if (!abi) {
- /* On MacOS platform, set abi to "gnu" to avoid generating
- object file of Mach-O binary format which is unsupported */
- abi = "gnu";
- if (!arch && !cpu && !features) {
- /* Get CPU name of the host machine to avoid checking
- SIMD capability failed */
- if (!(cpu = cpu_new = LLVMGetHostCPUName())) {
- aot_set_last_error("llvm get host cpu name failed.");
- goto fail;
- }
- }
- }
- #endif
- if (abi) {
- /* Construct target triple: <arch>-<vendor>-<sys>-<abi> */
- const char *vendor_sys;
- char *arch1 = arch, default_arch[32] = { 0 };
- if (!arch1) {
- char *default_triple = LLVMGetDefaultTargetTriple();
- if (!default_triple) {
- aot_set_last_error(
- "llvm get default target triple failed.");
- goto fail;
- }
- vendor_sys = strstr(default_triple, "-");
- bh_assert(vendor_sys);
- bh_memcpy_s(default_arch, sizeof(default_arch), default_triple,
- (uint32)(vendor_sys - default_triple));
- arch1 = default_arch;
- LLVMDisposeMessage(default_triple);
- }
- /**
- * Set <vendor>-<sys> according to abi to generate the object file
- * with the correct file format which might be different from the
- * default object file format of the host, e.g., generating AOT file
- * for Windows/MacOS under Linux host, or generating AOT file for
- * Linux/MacOS under Windows host.
- */
- if (!strcmp(abi, "msvc")) {
- if (!strcmp(arch1, "i386"))
- vendor_sys = "-pc-win32-";
- else
- vendor_sys = "-pc-windows-";
- }
- else {
- vendor_sys = "-pc-linux-";
- }
- bh_assert(strlen(arch1) + strlen(vendor_sys) + strlen(abi)
- < sizeof(triple_buf));
- bh_memcpy_s(triple_buf, (uint32)sizeof(triple_buf), arch1,
- (uint32)strlen(arch1));
- bh_memcpy_s(triple_buf + strlen(arch1),
- (uint32)(sizeof(triple_buf) - strlen(arch1)),
- vendor_sys, (uint32)strlen(vendor_sys));
- bh_memcpy_s(triple_buf + strlen(arch1) + strlen(vendor_sys),
- (uint32)(sizeof(triple_buf) - strlen(arch1)
- - strlen(vendor_sys)),
- abi, (uint32)strlen(abi));
- triple = triple_buf;
- }
- else if (arch) {
- /* Construct target triple: <arch>-<vendor>-<sys>-<abi> */
- const char *vendor_sys;
- char *default_triple = LLVMGetDefaultTargetTriple();
- if (!default_triple) {
- aot_set_last_error("llvm get default target triple failed.");
- goto fail;
- }
- if (strstr(default_triple, "windows")) {
- vendor_sys = "-pc-windows-";
- if (!abi)
- abi = "msvc";
- }
- else if (strstr(default_triple, "win32")) {
- vendor_sys = "-pc-win32-";
- if (!abi)
- abi = "msvc";
- }
- else {
- vendor_sys = "-pc-linux-";
- if (!abi)
- abi = "gnu";
- }
- LLVMDisposeMessage(default_triple);
- bh_assert(strlen(arch) + strlen(vendor_sys) + strlen(abi)
- < sizeof(triple_buf));
- bh_memcpy_s(triple_buf, (uint32)sizeof(triple_buf), arch,
- (uint32)strlen(arch));
- bh_memcpy_s(triple_buf + strlen(arch),
- (uint32)(sizeof(triple_buf) - strlen(arch)), vendor_sys,
- (uint32)strlen(vendor_sys));
- bh_memcpy_s(triple_buf + strlen(arch) + strlen(vendor_sys),
- (uint32)(sizeof(triple_buf) - strlen(arch)
- - strlen(vendor_sys)),
- abi, (uint32)strlen(abi));
- triple = triple_buf;
- }
- if (!cpu && features) {
- aot_set_last_error("cpu isn't specified for cpu features.");
- goto fail;
- }
- if (!triple && !cpu) {
- /* Get a triple for the host machine */
- if (!(triple_norm = triple_norm_new =
- LLVMGetDefaultTargetTriple())) {
- aot_set_last_error("llvm get default target triple failed.");
- goto fail;
- }
- /* Get CPU name of the host machine */
- if (!(cpu = cpu_new = LLVMGetHostCPUName())) {
- aot_set_last_error("llvm get host cpu name failed.");
- goto fail;
- }
- }
- else if (triple) {
- /* Normalize a target triple */
- if (!(triple_norm = triple_norm_new =
- LLVMNormalizeTargetTriple(triple))) {
- snprintf(buf, sizeof(buf),
- "llvm normlalize target triple (%s) failed.", triple);
- aot_set_last_error(buf);
- goto fail;
- }
- if (!cpu)
- cpu = "";
- }
- else {
- /* triple is NULL, cpu isn't NULL */
- snprintf(buf, sizeof(buf), "target isn't specified for cpu %s.",
- cpu);
- aot_set_last_error(buf);
- goto fail;
- }
- /* Add module flag and cpu feature for riscv target */
- if (arch && !strncmp(arch, "riscv", 5)) {
- LLVMMetadataRef meta_target_abi;
- if (!(meta_target_abi = LLVMMDStringInContext2(comp_ctx->context,
- abi, strlen(abi)))) {
- aot_set_last_error("create metadata string failed.");
- goto fail;
- }
- LLVMAddModuleFlag(comp_ctx->module, LLVMModuleFlagBehaviorError,
- "target-abi", strlen("target-abi"),
- meta_target_abi);
- if (!strcmp(abi, "lp64d") || !strcmp(abi, "ilp32d")) {
- if (features) {
- snprintf(features_buf, sizeof(features_buf), "%s%s",
- features, ",+d");
- features = features_buf;
- }
- else
- features = "+d";
- }
- }
- if (!features)
- features = "";
- /* Get target with triple, note that LLVMGetTargetFromTriple()
- return 0 when success, but not true. */
- if (LLVMGetTargetFromTriple(triple_norm, &target, &err) != 0) {
- if (err) {
- LLVMDisposeMessage(err);
- err = NULL;
- }
- snprintf(buf, sizeof(buf),
- "llvm get target from triple (%s) failed", triple_norm);
- aot_set_last_error(buf);
- goto fail;
- }
- /* Save target arch */
- get_target_arch_from_triple(triple_norm, comp_ctx->target_arch,
- sizeof(comp_ctx->target_arch));
- if (option->bounds_checks == 1 || option->bounds_checks == 0) {
- /* Set by user */
- comp_ctx->enable_bound_check =
- (option->bounds_checks == 1) ? true : false;
- }
- else {
- /* Unset by user, use default value */
- if (strstr(comp_ctx->target_arch, "64")
- && !option->is_sgx_platform) {
- comp_ctx->enable_bound_check = false;
- }
- else {
- comp_ctx->enable_bound_check = true;
- }
- }
- os_printf("Create AoT compiler with:\n");
- os_printf(" target: %s\n", comp_ctx->target_arch);
- os_printf(" target cpu: %s\n", cpu);
- os_printf(" cpu features: %s\n", features);
- os_printf(" opt level: %d\n", opt_level);
- os_printf(" size level: %d\n", size_level);
- switch (option->output_format) {
- case AOT_LLVMIR_UNOPT_FILE:
- os_printf(" output format: unoptimized LLVM IR\n");
- break;
- case AOT_LLVMIR_OPT_FILE:
- os_printf(" output format: optimized LLVM IR\n");
- break;
- case AOT_FORMAT_FILE:
- os_printf(" output format: AoT file\n");
- break;
- case AOT_OBJECT_FILE:
- os_printf(" output format: native object file\n");
- break;
- }
- if (!LLVMTargetHasTargetMachine(target)) {
- snprintf(buf, sizeof(buf),
- "no target machine for this target (%s).", triple_norm);
- aot_set_last_error(buf);
- goto fail;
- }
- /* Report error if target isn't arc and hasn't asm backend.
- For arc target, as it cannot emit to memory buffer of elf file
- currently, we let it emit to assembly file instead, and then call
- arc-gcc to compile
- asm file to elf file, and read elf file to memory buffer. */
- if (strncmp(comp_ctx->target_arch, "arc", 3)
- && !LLVMTargetHasAsmBackend(target)) {
- snprintf(buf, sizeof(buf), "no asm backend for this target (%s).",
- LLVMGetTargetName(target));
- aot_set_last_error(buf);
- goto fail;
- }
- /* Set code model */
- if (size_level == 0)
- code_model = LLVMCodeModelLarge;
- else if (size_level == 1)
- code_model = LLVMCodeModelMedium;
- else if (size_level == 2)
- code_model = LLVMCodeModelKernel;
- else
- code_model = LLVMCodeModelSmall;
- /* Create the target machine */
- if (!(comp_ctx->target_machine = LLVMCreateTargetMachine(
- target, triple_norm, cpu, features, opt_level,
- LLVMRelocStatic, code_model))) {
- aot_set_last_error("create LLVM target machine failed.");
- goto fail;
- }
- }
- if (option->enable_simd && strcmp(comp_ctx->target_arch, "x86_64") != 0
- && strncmp(comp_ctx->target_arch, "aarch64", 7) != 0) {
- /* Disable simd if it isn't supported by target arch */
- option->enable_simd = false;
- }
- if (option->enable_simd) {
- char *tmp;
- bool check_simd_ret;
- comp_ctx->enable_simd = true;
- if (!(tmp = LLVMGetTargetMachineCPU(comp_ctx->target_machine))) {
- aot_set_last_error("get CPU from Target Machine fail");
- goto fail;
- }
- check_simd_ret =
- aot_check_simd_compatibility(comp_ctx->target_arch, tmp);
- LLVMDisposeMessage(tmp);
- if (!check_simd_ret) {
- aot_set_last_error("SIMD compatibility check failed, "
- "try adding --cpu=<cpu> to specify a cpu "
- "or adding --disable-simd to disable SIMD");
- goto fail;
- }
- }
- if (!(target_data_ref =
- LLVMCreateTargetDataLayout(comp_ctx->target_machine))) {
- aot_set_last_error("create LLVM target data layout failed.");
- goto fail;
- }
- comp_ctx->pointer_size = LLVMPointerSize(target_data_ref);
- LLVMDisposeTargetData(target_data_ref);
- comp_ctx->optimize = true;
- if (option->output_format == AOT_LLVMIR_UNOPT_FILE)
- comp_ctx->optimize = false;
- /* Create metadata for llvm float experimental constrained intrinsics */
- if (!(comp_ctx->fp_rounding_mode = LLVMMDStringInContext(
- comp_ctx->context, fp_round, (uint32)strlen(fp_round)))
- || !(comp_ctx->fp_exception_behavior = LLVMMDStringInContext(
- comp_ctx->context, fp_exce, (uint32)strlen(fp_exce)))) {
- aot_set_last_error("create float llvm metadata failed.");
- goto fail;
- }
- if (!aot_set_llvm_basic_types(&comp_ctx->basic_types, comp_ctx->context)) {
- aot_set_last_error("create LLVM basic types failed.");
- goto fail;
- }
- if (!aot_create_llvm_consts(&comp_ctx->llvm_consts, comp_ctx)) {
- aot_set_last_error("create LLVM const values failed.");
- goto fail;
- }
- /* set exec_env data type to int8** */
- comp_ctx->exec_env_type = comp_ctx->basic_types.int8_pptr_type;
- /* set aot_inst data type to int8* */
- comp_ctx->aot_inst_type = INT8_PTR_TYPE;
- /* Create function context for each function */
- comp_ctx->func_ctx_count = comp_data->func_count;
- if (comp_data->func_count > 0
- && !(comp_ctx->func_ctxes =
- aot_create_func_contexts(comp_data, comp_ctx)))
- goto fail;
- if (cpu) {
- uint32 len = (uint32)strlen(cpu) + 1;
- if (!(comp_ctx->target_cpu = wasm_runtime_malloc(len))) {
- aot_set_last_error("allocate memory failed");
- goto fail;
- }
- bh_memcpy_s(comp_ctx->target_cpu, len, cpu, len);
- }
- if (comp_ctx->disable_llvm_intrinsics)
- aot_intrinsic_fill_capability_flags(comp_ctx);
- ret = comp_ctx;
- fail:
- if (triple_norm_new)
- LLVMDisposeMessage(triple_norm_new);
- if (cpu_new)
- LLVMDisposeMessage(cpu_new);
- if (!ret)
- aot_destroy_comp_context(comp_ctx);
- (void)i;
- return ret;
- }
- void
- aot_destroy_comp_context(AOTCompContext *comp_ctx)
- {
- if (!comp_ctx)
- return;
- if (comp_ctx->target_machine)
- LLVMDisposeTargetMachine(comp_ctx->target_machine);
- if (comp_ctx->builder)
- LLVMDisposeBuilder(comp_ctx->builder);
- if (comp_ctx->orc_thread_safe_context)
- LLVMOrcDisposeThreadSafeContext(comp_ctx->orc_thread_safe_context);
- /* Note: don't dispose comp_ctx->context and comp_ctx->module as
- they are disposed when disposing the thread safe context */
- /* Has to be the last one */
- if (comp_ctx->orc_jit)
- LLVMOrcDisposeLLLazyJIT(comp_ctx->orc_jit);
- LLVMShutdown();
- if (comp_ctx->func_ctxes)
- aot_destroy_func_contexts(comp_ctx->func_ctxes,
- comp_ctx->func_ctx_count);
- if (bh_list_length(&comp_ctx->native_symbols) > 0) {
- AOTNativeSymbol *sym = bh_list_first_elem(&comp_ctx->native_symbols);
- while (sym) {
- AOTNativeSymbol *t = bh_list_elem_next(sym);
- bh_list_remove(&comp_ctx->native_symbols, sym);
- wasm_runtime_free(sym);
- sym = t;
- }
- }
- if (comp_ctx->target_cpu) {
- wasm_runtime_free(comp_ctx->target_cpu);
- }
- wasm_runtime_free(comp_ctx);
- }
- static bool
- insert_native_symbol(AOTCompContext *comp_ctx, const char *symbol, int32 idx)
- {
- AOTNativeSymbol *sym = wasm_runtime_malloc(sizeof(AOTNativeSymbol));
- if (!sym) {
- aot_set_last_error("alloc native symbol failed.");
- return false;
- }
- memset(sym, 0, sizeof(AOTNativeSymbol));
- bh_assert(strlen(symbol) <= sizeof(sym->symbol));
- snprintf(sym->symbol, sizeof(sym->symbol), "%s", symbol);
- sym->index = idx;
- if (BH_LIST_ERROR == bh_list_insert(&comp_ctx->native_symbols, sym)) {
- wasm_runtime_free(sym);
- aot_set_last_error("insert native symbol to list failed.");
- return false;
- }
- return true;
- }
- int32
- aot_get_native_symbol_index(AOTCompContext *comp_ctx, const char *symbol)
- {
- int32 idx = -1;
- AOTNativeSymbol *sym = NULL;
- sym = bh_list_first_elem(&comp_ctx->native_symbols);
- /* Lookup an existing symobl record */
- while (sym) {
- if (strcmp(sym->symbol, symbol) == 0) {
- idx = sym->index;
- break;
- }
- sym = bh_list_elem_next(sym);
- }
- /* Given symbol is not exist in list, then we alloc a new index for it */
- if (idx < 0) {
- if (comp_ctx->pointer_size == sizeof(uint32)
- && !strncmp(symbol, "f64#", 4)) {
- idx = bh_list_length(&comp_ctx->native_symbols);
- /* Add 4 bytes padding on 32-bit target to make sure that
- the f64 const is stored on 8-byte aligned address */
- if ((idx & 1) && !strncmp(comp_ctx->target_arch, "i386", 4)) {
- if (!insert_native_symbol(comp_ctx, "__ignore", idx)) {
- return -1;
- }
- }
- }
- idx = bh_list_length(&comp_ctx->native_symbols);
- if (!insert_native_symbol(comp_ctx, symbol, idx)) {
- return -1;
- }
- if (comp_ctx->pointer_size == sizeof(uint32)
- && !strncmp(symbol, "f64#", 4)) {
- /* f64 const occupies 2 pointer slots on 32-bit target */
- if (!insert_native_symbol(comp_ctx, "__ignore", idx + 1)) {
- return -1;
- }
- }
- }
- return idx;
- }
- void
- aot_value_stack_push(AOTValueStack *stack, AOTValue *value)
- {
- if (!stack->value_list_head)
- stack->value_list_head = stack->value_list_end = value;
- else {
- stack->value_list_end->next = value;
- value->prev = stack->value_list_end;
- stack->value_list_end = value;
- }
- }
- AOTValue *
- aot_value_stack_pop(AOTValueStack *stack)
- {
- AOTValue *value = stack->value_list_end;
- bh_assert(stack->value_list_end);
- if (stack->value_list_head == stack->value_list_end)
- stack->value_list_head = stack->value_list_end = NULL;
- else {
- stack->value_list_end = stack->value_list_end->prev;
- stack->value_list_end->next = NULL;
- value->prev = NULL;
- }
- return value;
- }
- void
- aot_value_stack_destroy(AOTValueStack *stack)
- {
- AOTValue *value = stack->value_list_head, *p;
- while (value) {
- p = value->next;
- wasm_runtime_free(value);
- value = p;
- }
- stack->value_list_head = NULL;
- stack->value_list_end = NULL;
- }
- void
- aot_block_stack_push(AOTBlockStack *stack, AOTBlock *block)
- {
- if (!stack->block_list_head)
- stack->block_list_head = stack->block_list_end = block;
- else {
- stack->block_list_end->next = block;
- block->prev = stack->block_list_end;
- stack->block_list_end = block;
- }
- }
- AOTBlock *
- aot_block_stack_pop(AOTBlockStack *stack)
- {
- AOTBlock *block = stack->block_list_end;
- bh_assert(stack->block_list_end);
- if (stack->block_list_head == stack->block_list_end)
- stack->block_list_head = stack->block_list_end = NULL;
- else {
- stack->block_list_end = stack->block_list_end->prev;
- stack->block_list_end->next = NULL;
- block->prev = NULL;
- }
- return block;
- }
- void
- aot_block_stack_destroy(AOTBlockStack *stack)
- {
- AOTBlock *block = stack->block_list_head, *p;
- while (block) {
- p = block->next;
- aot_value_stack_destroy(&block->value_stack);
- aot_block_destroy(block);
- block = p;
- }
- stack->block_list_head = NULL;
- stack->block_list_end = NULL;
- }
- void
- aot_block_destroy(AOTBlock *block)
- {
- aot_value_stack_destroy(&block->value_stack);
- if (block->param_types)
- wasm_runtime_free(block->param_types);
- if (block->param_phis)
- wasm_runtime_free(block->param_phis);
- if (block->else_param_phis)
- wasm_runtime_free(block->else_param_phis);
- if (block->result_types)
- wasm_runtime_free(block->result_types);
- if (block->result_phis)
- wasm_runtime_free(block->result_phis);
- wasm_runtime_free(block);
- }
- bool
- aot_checked_addr_list_add(AOTFuncContext *func_ctx, uint32 local_idx,
- uint32 offset, uint32 bytes)
- {
- AOTCheckedAddr *node = func_ctx->checked_addr_list;
- if (!(node = wasm_runtime_malloc(sizeof(AOTCheckedAddr)))) {
- aot_set_last_error("allocate memory failed.");
- return false;
- }
- node->local_idx = local_idx;
- node->offset = offset;
- node->bytes = bytes;
- node->next = func_ctx->checked_addr_list;
- func_ctx->checked_addr_list = node;
- return true;
- }
- void
- aot_checked_addr_list_del(AOTFuncContext *func_ctx, uint32 local_idx)
- {
- AOTCheckedAddr *node = func_ctx->checked_addr_list;
- AOTCheckedAddr *node_prev = NULL, *node_next;
- while (node) {
- node_next = node->next;
- if (node->local_idx == local_idx) {
- if (!node_prev)
- func_ctx->checked_addr_list = node_next;
- else
- node_prev->next = node_next;
- wasm_runtime_free(node);
- }
- else {
- node_prev = node;
- }
- node = node_next;
- }
- }
- bool
- aot_checked_addr_list_find(AOTFuncContext *func_ctx, uint32 local_idx,
- uint32 offset, uint32 bytes)
- {
- AOTCheckedAddr *node = func_ctx->checked_addr_list;
- while (node) {
- if (node->local_idx == local_idx && node->offset == offset
- && node->bytes >= bytes) {
- return true;
- }
- node = node->next;
- }
- return false;
- }
- void
- aot_checked_addr_list_destroy(AOTFuncContext *func_ctx)
- {
- AOTCheckedAddr *node = func_ctx->checked_addr_list, *node_next;
- while (node) {
- node_next = node->next;
- wasm_runtime_free(node);
- node = node_next;
- }
- func_ctx->checked_addr_list = NULL;
- }
- bool
- aot_build_zero_function_ret(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
- AOTFuncType *func_type)
- {
- LLVMValueRef ret = NULL;
- if (func_type->result_count) {
- switch (func_type->types[func_type->param_count]) {
- case VALUE_TYPE_I32:
- ret = LLVMBuildRet(comp_ctx->builder, I32_ZERO);
- break;
- case VALUE_TYPE_I64:
- ret = LLVMBuildRet(comp_ctx->builder, I64_ZERO);
- break;
- case VALUE_TYPE_F32:
- ret = LLVMBuildRet(comp_ctx->builder, F32_ZERO);
- break;
- case VALUE_TYPE_F64:
- ret = LLVMBuildRet(comp_ctx->builder, F64_ZERO);
- break;
- case VALUE_TYPE_V128:
- ret =
- LLVMBuildRet(comp_ctx->builder, LLVM_CONST(i64x2_vec_zero));
- break;
- case VALUE_TYPE_FUNCREF:
- case VALUE_TYPE_EXTERNREF:
- ret = LLVMBuildRet(comp_ctx->builder, REF_NULL);
- break;
- default:
- bh_assert(0);
- }
- }
- else {
- ret = LLVMBuildRetVoid(comp_ctx->builder);
- }
- if (!ret) {
- aot_set_last_error("llvm build ret failed.");
- return false;
- }
- #if WASM_ENABLE_DEBUG_AOT != 0
- LLVMMetadataRef return_location =
- dwarf_gen_func_ret_location(comp_ctx, func_ctx);
- LLVMInstructionSetDebugLoc(ret, return_location);
- #endif
- return true;
- }
- static LLVMValueRef
- __call_llvm_intrinsic(const AOTCompContext *comp_ctx,
- const AOTFuncContext *func_ctx, const char *name,
- LLVMTypeRef ret_type, LLVMTypeRef *param_types,
- int param_count, LLVMValueRef *param_values)
- {
- LLVMValueRef func, ret;
- LLVMTypeRef func_type;
- const char *symname;
- int32 func_idx;
- if (comp_ctx->disable_llvm_intrinsics
- && aot_intrinsic_check_capability(comp_ctx, name)) {
- if (func_ctx == NULL) {
- aot_set_last_error_v("invalid func_ctx for intrinsic: %s", name);
- return NULL;
- }
- if (!(func_type = LLVMFunctionType(ret_type, param_types,
- (uint32)param_count, false))) {
- aot_set_last_error("create LLVM intrinsic function type failed.");
- return NULL;
- }
- if (!(func_type = LLVMPointerType(func_type, 0))) {
- aot_set_last_error(
- "create LLVM intrinsic function pointer type failed.");
- return NULL;
- }
- if (!(symname = aot_intrinsic_get_symbol(name))) {
- aot_set_last_error_v("runtime intrinsic not implemented: %s\n",
- name);
- return NULL;
- }
- func_idx =
- aot_get_native_symbol_index((AOTCompContext *)comp_ctx, symname);
- if (func_idx < 0) {
- aot_set_last_error_v("get runtime intrinsc index failed: %s\n",
- name);
- return NULL;
- }
- if (!(func = aot_get_func_from_table(comp_ctx, func_ctx->native_symbol,
- func_type, func_idx))) {
- aot_set_last_error_v("get runtime intrinsc failed: %s\n", name);
- return NULL;
- }
- }
- else {
- /* Declare llvm intrinsic function if necessary */
- if (!(func = LLVMGetNamedFunction(func_ctx->module, name))) {
- if (!(func_type = LLVMFunctionType(ret_type, param_types,
- (uint32)param_count, false))) {
- aot_set_last_error(
- "create LLVM intrinsic function type failed.");
- return NULL;
- }
- if (!(func = LLVMAddFunction(func_ctx->module, name, func_type))) {
- aot_set_last_error("add LLVM intrinsic function failed.");
- return NULL;
- }
- }
- }
- #if LLVM_VERSION_MAJOR >= 14
- func_type =
- LLVMFunctionType(ret_type, param_types, (uint32)param_count, false);
- #endif
- /* Call the LLVM intrinsic function */
- if (!(ret = LLVMBuildCall2(comp_ctx->builder, func_type, func, param_values,
- (uint32)param_count, "call"))) {
- aot_set_last_error("llvm build intrinsic call failed.");
- return NULL;
- }
- return ret;
- }
- LLVMValueRef
- aot_call_llvm_intrinsic(const AOTCompContext *comp_ctx,
- const AOTFuncContext *func_ctx, const char *intrinsic,
- LLVMTypeRef ret_type, LLVMTypeRef *param_types,
- int param_count, ...)
- {
- LLVMValueRef *param_values, ret;
- va_list argptr;
- uint64 total_size;
- int i = 0;
- /* Create param values */
- total_size = sizeof(LLVMValueRef) * (uint64)param_count;
- if (total_size >= UINT32_MAX
- || !(param_values = wasm_runtime_malloc((uint32)total_size))) {
- aot_set_last_error("allocate memory for param values failed.");
- return false;
- }
- /* Load each param value */
- va_start(argptr, param_count);
- while (i < param_count)
- param_values[i++] = va_arg(argptr, LLVMValueRef);
- va_end(argptr);
- ret = __call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic, ret_type,
- param_types, param_count, param_values);
- wasm_runtime_free(param_values);
- return ret;
- }
- LLVMValueRef
- aot_call_llvm_intrinsic_v(const AOTCompContext *comp_ctx,
- const AOTFuncContext *func_ctx, const char *intrinsic,
- LLVMTypeRef ret_type, LLVMTypeRef *param_types,
- int param_count, va_list param_value_list)
- {
- LLVMValueRef *param_values, ret;
- uint64 total_size;
- int i = 0;
- /* Create param values */
- total_size = sizeof(LLVMValueRef) * (uint64)param_count;
- if (total_size >= UINT32_MAX
- || !(param_values = wasm_runtime_malloc((uint32)total_size))) {
- aot_set_last_error("allocate memory for param values failed.");
- return false;
- }
- /* Load each param value */
- while (i < param_count)
- param_values[i++] = va_arg(param_value_list, LLVMValueRef);
- ret = __call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic, ret_type,
- param_types, param_count, param_values);
- wasm_runtime_free(param_values);
- return ret;
- }
- LLVMValueRef
- aot_get_func_from_table(const AOTCompContext *comp_ctx, LLVMValueRef base,
- LLVMTypeRef func_type, int32 index)
- {
- LLVMValueRef func;
- LLVMValueRef func_addr;
- if (!(func_addr = I32_CONST(index))) {
- aot_set_last_error("construct function index failed.");
- goto fail;
- }
- if (!(func_addr =
- LLVMBuildInBoundsGEP2(comp_ctx->builder, OPQ_PTR_TYPE, base,
- &func_addr, 1, "func_addr"))) {
- aot_set_last_error("get function addr by index failed.");
- goto fail;
- }
- func =
- LLVMBuildLoad2(comp_ctx->builder, OPQ_PTR_TYPE, func_addr, "func_tmp");
- if (func == NULL) {
- aot_set_last_error("get function pointer failed.");
- goto fail;
- }
- if (!(func =
- LLVMBuildBitCast(comp_ctx->builder, func, func_type, "func"))) {
- aot_set_last_error("cast function fialed.");
- goto fail;
- }
- return func;
- fail:
- return NULL;
- }
- LLVMValueRef
- aot_load_const_from_table(AOTCompContext *comp_ctx, LLVMValueRef base,
- const WASMValue *value, uint8 value_type)
- {
- LLVMValueRef const_index, const_addr, const_value;
- LLVMTypeRef const_ptr_type, const_type;
- char buf[128] = { 0 };
- int32 index;
- switch (value_type) {
- case VALUE_TYPE_I32:
- /* Store the raw int bits of i32 const as a hex string */
- snprintf(buf, sizeof(buf), "i32#%08" PRIX32, value->i32);
- const_ptr_type = INT32_PTR_TYPE;
- const_type = I32_TYPE;
- break;
- case VALUE_TYPE_I64:
- /* Store the raw int bits of i64 const as a hex string */
- snprintf(buf, sizeof(buf), "i64#%016" PRIX64, value->i64);
- const_ptr_type = INT64_PTR_TYPE;
- const_type = I64_TYPE;
- break;
- case VALUE_TYPE_F32:
- /* Store the raw int bits of f32 const as a hex string */
- snprintf(buf, sizeof(buf), "f32#%08" PRIX32, value->i32);
- const_ptr_type = F32_PTR_TYPE;
- const_type = F32_TYPE;
- break;
- case VALUE_TYPE_F64:
- /* Store the raw int bits of f64 const as a hex string */
- snprintf(buf, sizeof(buf), "f64#%016" PRIX64, value->i64);
- const_ptr_type = F64_PTR_TYPE;
- const_type = F64_TYPE;
- break;
- default:
- bh_assert(0);
- return NULL;
- }
- /* Load f32/f64 const from exec_env->native_symbol[index] */
- index = aot_get_native_symbol_index(comp_ctx, buf);
- if (index < 0) {
- return NULL;
- }
- if (!(const_index = I32_CONST(index))) {
- aot_set_last_error("construct const index failed.");
- return NULL;
- }
- if (!(const_addr =
- LLVMBuildInBoundsGEP2(comp_ctx->builder, OPQ_PTR_TYPE, base,
- &const_index, 1, "const_addr_tmp"))) {
- aot_set_last_error("get const addr by index failed.");
- return NULL;
- }
- if (!(const_addr = LLVMBuildBitCast(comp_ctx->builder, const_addr,
- const_ptr_type, "const_addr"))) {
- aot_set_last_error("cast const fialed.");
- return NULL;
- }
- if (!(const_value = LLVMBuildLoad2(comp_ctx->builder, const_type,
- const_addr, "const_value"))) {
- aot_set_last_error("load const failed.");
- return NULL;
- }
- (void)const_type;
- return const_value;
- }
|