llvm_backend_proc.cpp 106 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342
  1. LLVMValueRef lb_call_intrinsic(lbProcedure *p, const char *name, LLVMValueRef* args, unsigned arg_count, LLVMTypeRef* types, unsigned type_count)
  2. {
  3. unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
  4. GB_ASSERT_MSG(id != 0, "Unable to find %s", name);
  5. LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, type_count);
  6. LLVMTypeRef call_type = LLVMIntrinsicGetType(p->module->ctx, id, types, type_count);
  7. return LLVMBuildCall2(p->builder, call_type, ip, args, arg_count, "");
  8. }
  9. void lb_mem_copy_overlapping(lbProcedure *p, lbValue dst, lbValue src, lbValue len, bool is_volatile) {
  10. dst = lb_emit_conv(p, dst, t_rawptr);
  11. src = lb_emit_conv(p, src, t_rawptr);
  12. len = lb_emit_conv(p, len, t_int);
  13. char const *name = "llvm.memmove";
  14. if (LLVMIsConstant(len.value)) {
  15. i64 const_len = cast(i64)LLVMConstIntGetSExtValue(len.value);
  16. if (const_len <= 4*build_context.word_size) {
  17. name = "llvm.memmove.inline";
  18. }
  19. }
  20. LLVMTypeRef types[3] = {
  21. lb_type(p->module, t_rawptr),
  22. lb_type(p->module, t_rawptr),
  23. lb_type(p->module, t_int)
  24. };
  25. LLVMValueRef args[4] = {
  26. dst.value,
  27. src.value,
  28. len.value,
  29. LLVMConstInt(LLVMInt1TypeInContext(p->module->ctx), 0, is_volatile)
  30. };
  31. lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
  32. }
  33. void lb_mem_copy_non_overlapping(lbProcedure *p, lbValue dst, lbValue src, lbValue len, bool is_volatile) {
  34. dst = lb_emit_conv(p, dst, t_rawptr);
  35. src = lb_emit_conv(p, src, t_rawptr);
  36. len = lb_emit_conv(p, len, t_int);
  37. char const *name = "llvm.memcpy";
  38. if (LLVMIsConstant(len.value)) {
  39. i64 const_len = cast(i64)LLVMConstIntGetSExtValue(len.value);
  40. if (const_len <= 4*build_context.word_size) {
  41. name = "llvm.memcpy.inline";
  42. }
  43. }
  44. LLVMTypeRef types[3] = {
  45. lb_type(p->module, t_rawptr),
  46. lb_type(p->module, t_rawptr),
  47. lb_type(p->module, t_int)
  48. };
  49. LLVMValueRef args[4] = {
  50. dst.value,
  51. src.value,
  52. len.value,
  53. LLVMConstInt(LLVMInt1TypeInContext(p->module->ctx), 0, is_volatile) };
  54. lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
  55. }
  56. lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool ignore_body) {
  57. GB_ASSERT(entity != nullptr);
  58. GB_ASSERT(entity->kind == Entity_Procedure);
  59. if (!entity->Procedure.is_foreign) {
  60. GB_ASSERT_MSG(entity->flags & EntityFlag_ProcBodyChecked, "%.*s :: %s", LIT(entity->token.string), type_to_string(entity->type));
  61. }
  62. String link_name = {};
  63. if (ignore_body) {
  64. lbModule *other_module = lb_pkg_module(m->gen, entity->pkg);
  65. link_name = lb_get_entity_name(other_module, entity);
  66. } else {
  67. link_name = lb_get_entity_name(m, entity);
  68. }
  69. {
  70. StringHashKey key = string_hash_string(link_name);
  71. lbValue *found = string_map_get(&m->members, key);
  72. if (found) {
  73. lb_add_entity(m, entity, *found);
  74. return string_map_must_get(&m->procedures, key);
  75. }
  76. }
  77. lbProcedure *p = gb_alloc_item(permanent_allocator(), lbProcedure);
  78. p->module = m;
  79. entity->code_gen_module = m;
  80. entity->code_gen_procedure = p;
  81. p->entity = entity;
  82. p->name = link_name;
  83. DeclInfo *decl = entity->decl_info;
  84. ast_node(pl, ProcLit, decl->proc_lit);
  85. Type *pt = base_type(entity->type);
  86. GB_ASSERT(pt->kind == Type_Proc);
  87. p->type = entity->type;
  88. p->type_expr = decl->type_expr;
  89. p->body = pl->body;
  90. p->inlining = pl->inlining;
  91. p->is_foreign = entity->Procedure.is_foreign;
  92. p->is_export = entity->Procedure.is_export;
  93. p->is_entry_point = false;
  94. gbAllocator a = heap_allocator();
  95. p->children.allocator = a;
  96. p->defer_stmts.allocator = a;
  97. p->blocks.allocator = a;
  98. p->branch_blocks.allocator = a;
  99. p->context_stack.allocator = a;
  100. p->scope_stack.allocator = a;
  101. map_init(&p->selector_values, a, 0);
  102. map_init(&p->selector_addr, a, 0);
  103. map_init(&p->tuple_fix_map, a, 0);
  104. if (p->is_foreign) {
  105. lb_add_foreign_library_path(p->module, entity->Procedure.foreign_library);
  106. }
  107. char *c_link_name = alloc_cstring(permanent_allocator(), p->name);
  108. LLVMTypeRef func_type = lb_get_procedure_raw_type(m, p->type);
  109. p->value = LLVMAddFunction(m->mod, c_link_name, func_type);
  110. lb_ensure_abi_function_type(m, p);
  111. lb_add_function_type_attributes(p->value, p->abi_function_type, p->abi_function_type->calling_convention);
  112. if (pt->Proc.diverging) {
  113. lb_add_attribute_to_proc(m, p->value, "noreturn");
  114. }
  115. if (pt->Proc.calling_convention == ProcCC_Naked) {
  116. lb_add_attribute_to_proc(m, p->value, "naked");
  117. }
  118. if (!entity->Procedure.is_foreign && build_context.disable_red_zone) {
  119. lb_add_attribute_to_proc(m, p->value, "noredzone");
  120. }
  121. switch (p->inlining) {
  122. case ProcInlining_inline:
  123. lb_add_attribute_to_proc(m, p->value, "alwaysinline");
  124. break;
  125. case ProcInlining_no_inline:
  126. lb_add_attribute_to_proc(m, p->value, "noinline");
  127. break;
  128. }
  129. switch (entity->Procedure.optimization_mode) {
  130. case ProcedureOptimizationMode_None:
  131. break;
  132. case ProcedureOptimizationMode_Minimal:
  133. lb_add_attribute_to_proc(m, p->value, "optnone");
  134. lb_add_attribute_to_proc(m, p->value, "noinline");
  135. break;
  136. case ProcedureOptimizationMode_Size:
  137. lb_add_attribute_to_proc(m, p->value, "optsize");
  138. break;
  139. case ProcedureOptimizationMode_Speed:
  140. // TODO(bill): handle this correctly
  141. lb_add_attribute_to_proc(m, p->value, "optsize");
  142. break;
  143. }
  144. if (!entity->Procedure.target_feature_disabled &&
  145. entity->Procedure.target_feature.len != 0) {
  146. auto features = split_by_comma(entity->Procedure.target_feature);
  147. for_array(i, features) {
  148. String feature = features[i];
  149. LLVMAttributeRef ref = LLVMCreateStringAttribute(
  150. m->ctx,
  151. cast(char const *)feature.text, cast(unsigned)feature.len,
  152. "", 0);
  153. LLVMAddAttributeAtIndex(p->value, LLVMAttributeIndex_FunctionIndex, ref);
  154. }
  155. }
  156. if (entity->flags & EntityFlag_Cold) {
  157. lb_add_attribute_to_proc(m, p->value, "cold");
  158. }
  159. lbValue proc_value = {p->value, p->type};
  160. lb_add_entity(m, entity, proc_value);
  161. lb_add_member(m, p->name, proc_value);
  162. lb_add_procedure_value(m, p);
  163. if (p->is_export) {
  164. LLVMSetLinkage(p->value, LLVMDLLExportLinkage);
  165. LLVMSetDLLStorageClass(p->value, LLVMDLLExportStorageClass);
  166. LLVMSetVisibility(p->value, LLVMDefaultVisibility);
  167. lb_set_wasm_export_attributes(p->value, p->name);
  168. } else if (!p->is_foreign) {
  169. if (!USE_SEPARATE_MODULES) {
  170. LLVMSetLinkage(p->value, LLVMInternalLinkage);
  171. // NOTE(bill): if a procedure is defined in package runtime and uses a custom link name,
  172. // then it is very likely it is required by LLVM and thus cannot have internal linkage
  173. if (entity->pkg != nullptr && entity->pkg->kind == Package_Runtime && p->body != nullptr) {
  174. GB_ASSERT(entity->kind == Entity_Procedure);
  175. String link_name = entity->Procedure.link_name;
  176. if (entity->flags & EntityFlag_CustomLinkName &&
  177. link_name != "") {
  178. if (string_starts_with(link_name, str_lit("__"))) {
  179. LLVMSetLinkage(p->value, LLVMExternalLinkage);
  180. } else {
  181. LLVMSetLinkage(p->value, LLVMInternalLinkage);
  182. }
  183. }
  184. }
  185. }
  186. }
  187. lb_set_linkage_from_entity_flags(p->module, p->value, entity->flags);
  188. if (p->is_foreign) {
  189. lb_set_wasm_import_attributes(p->value, entity, p->name);
  190. }
  191. // NOTE(bill): offset==0 is the return value
  192. isize offset = 1;
  193. if (pt->Proc.return_by_pointer) {
  194. offset = 2;
  195. }
  196. isize parameter_index = 0;
  197. if (pt->Proc.param_count) {
  198. TypeTuple *params = &pt->Proc.params->Tuple;
  199. for (isize i = 0; i < pt->Proc.param_count; i++) {
  200. Entity *e = params->variables[i];
  201. if (e->kind != Entity_Variable) {
  202. continue;
  203. }
  204. if (i+1 == params->variables.count && pt->Proc.c_vararg) {
  205. continue;
  206. }
  207. if (e->flags&EntityFlag_NoAlias) {
  208. lb_add_proc_attribute_at_index(p, offset+parameter_index, "noalias");
  209. }
  210. parameter_index += 1;
  211. }
  212. }
  213. if (ignore_body) {
  214. p->body = nullptr;
  215. LLVMSetLinkage(p->value, LLVMExternalLinkage);
  216. }
  217. if (m->debug_builder) { // Debug Information
  218. Type *bt = base_type(p->type);
  219. unsigned line = cast(unsigned)entity->token.pos.line;
  220. LLVMMetadataRef scope = nullptr;
  221. LLVMMetadataRef file = nullptr;
  222. LLVMMetadataRef type = nullptr;
  223. scope = p->module->debug_compile_unit;
  224. type = lb_debug_type_internal_proc(m, bt);
  225. Ast *ident = entity->identifier.load();
  226. if (entity->file != nullptr) {
  227. file = lb_get_llvm_metadata(m, entity->file);
  228. scope = file;
  229. } else if (ident != nullptr && ident->file_id != 0) {
  230. file = lb_get_llvm_metadata(m, ident->file());
  231. scope = file;
  232. } else if (entity->scope != nullptr) {
  233. file = lb_get_llvm_metadata(m, entity->scope->file);
  234. scope = file;
  235. }
  236. GB_ASSERT_MSG(file != nullptr, "%.*s", LIT(entity->token.string));
  237. // LLVMBool is_local_to_unit = !entity->Procedure.is_export;
  238. LLVMBool is_local_to_unit = false;
  239. LLVMBool is_definition = p->body != nullptr;
  240. unsigned scope_line = line;
  241. u32 flags = LLVMDIFlagStaticMember;
  242. LLVMBool is_optimized = false;
  243. if (bt->Proc.diverging) {
  244. flags |= LLVMDIFlagNoReturn;
  245. }
  246. if (p->body == nullptr) {
  247. flags |= LLVMDIFlagPrototyped;
  248. is_optimized = false;
  249. }
  250. if (p->body != nullptr) {
  251. // String debug_name = entity->token.string.text;
  252. String debug_name = p->name;
  253. p->debug_info = LLVMDIBuilderCreateFunction(m->debug_builder, scope,
  254. cast(char const *)debug_name.text, debug_name.len,
  255. cast(char const *)p->name.text, p->name.len,
  256. file, line, type,
  257. is_local_to_unit, is_definition,
  258. scope_line, cast(LLVMDIFlags)flags, is_optimized
  259. );
  260. GB_ASSERT(p->debug_info != nullptr);
  261. LLVMSetSubprogram(p->value, p->debug_info);
  262. lb_set_llvm_metadata(m, p, p->debug_info);
  263. }
  264. }
  265. return p;
  266. }
  267. lbProcedure *lb_create_dummy_procedure(lbModule *m, String link_name, Type *type) {
  268. {
  269. lbValue *found = string_map_get(&m->members, link_name);
  270. GB_ASSERT_MSG(found == nullptr, "failed to create dummy procedure for: %.*s", LIT(link_name));
  271. }
  272. lbProcedure *p = gb_alloc_item(permanent_allocator(), lbProcedure);
  273. p->module = m;
  274. p->name = link_name;
  275. p->type = type;
  276. p->type_expr = nullptr;
  277. p->body = nullptr;
  278. p->tags = 0;
  279. p->inlining = ProcInlining_none;
  280. p->is_foreign = false;
  281. p->is_export = false;
  282. p->is_entry_point = false;
  283. gbAllocator a = permanent_allocator();
  284. p->children.allocator = a;
  285. p->defer_stmts.allocator = a;
  286. p->blocks.allocator = a;
  287. p->branch_blocks.allocator = a;
  288. p->context_stack.allocator = a;
  289. map_init(&p->tuple_fix_map, a, 0);
  290. char *c_link_name = alloc_cstring(permanent_allocator(), p->name);
  291. LLVMTypeRef func_type = lb_get_procedure_raw_type(m, p->type);
  292. p->value = LLVMAddFunction(m->mod, c_link_name, func_type);
  293. Type *pt = p->type;
  294. lbCallingConventionKind cc_kind = lbCallingConvention_C;
  295. // TODO(bill): Clean up this logic
  296. if (!is_arch_wasm()) {
  297. cc_kind = lb_calling_convention_map[pt->Proc.calling_convention];
  298. }
  299. LLVMSetFunctionCallConv(p->value, cc_kind);
  300. lbValue proc_value = {p->value, p->type};
  301. lb_add_member(m, p->name, proc_value);
  302. lb_add_procedure_value(m, p);
  303. // NOTE(bill): offset==0 is the return value
  304. isize offset = 1;
  305. if (pt->Proc.return_by_pointer) {
  306. lb_add_proc_attribute_at_index(p, 1, "sret");
  307. lb_add_proc_attribute_at_index(p, 1, "noalias");
  308. offset = 2;
  309. }
  310. isize parameter_index = 0;
  311. if (pt->Proc.calling_convention == ProcCC_Odin) {
  312. lb_add_proc_attribute_at_index(p, offset+parameter_index, "noalias");
  313. lb_add_proc_attribute_at_index(p, offset+parameter_index, "nonnull");
  314. lb_add_proc_attribute_at_index(p, offset+parameter_index, "nocapture");
  315. }
  316. return p;
  317. }
  318. lbValue lb_value_param(lbProcedure *p, Entity *e, Type *abi_type, i32 index, lbParamPasskind *kind_) {
  319. lbParamPasskind kind = lbParamPass_Value;
  320. if (e != nullptr && !are_types_identical(abi_type, e->type)) {
  321. if (is_type_pointer(abi_type)) {
  322. GB_ASSERT(e->kind == Entity_Variable);
  323. Type *av = core_type(type_deref(abi_type));
  324. if (are_types_identical(av, core_type(e->type))) {
  325. kind = lbParamPass_Pointer;
  326. if (e->flags&EntityFlag_Value) {
  327. kind = lbParamPass_ConstRef;
  328. }
  329. } else {
  330. kind = lbParamPass_BitCast;
  331. }
  332. } else if (is_type_integer(abi_type)) {
  333. kind = lbParamPass_Integer;
  334. } else if (abi_type == t_llvm_bool) {
  335. kind = lbParamPass_Value;
  336. } else if (is_type_boolean(abi_type)) {
  337. kind = lbParamPass_Integer;
  338. } else if (is_type_simd_vector(abi_type)) {
  339. kind = lbParamPass_BitCast;
  340. } else if (is_type_float(abi_type)) {
  341. kind = lbParamPass_BitCast;
  342. } else if (is_type_tuple(abi_type)) {
  343. kind = lbParamPass_Tuple;
  344. } else if (is_type_proc(abi_type)) {
  345. kind = lbParamPass_Value;
  346. } else {
  347. GB_PANIC("Invalid abi type pass kind %s", type_to_string(abi_type));
  348. }
  349. }
  350. if (kind_) *kind_ = kind;
  351. lbValue res = {};
  352. res.value = LLVMGetParam(p->value, cast(unsigned)index);
  353. res.type = abi_type;
  354. return res;
  355. }
  356. void lb_start_block(lbProcedure *p, lbBlock *b) {
  357. GB_ASSERT(b != nullptr);
  358. if (!b->appended) {
  359. b->appended = true;
  360. LLVMAppendExistingBasicBlock(p->value, b->block);
  361. }
  362. LLVMPositionBuilderAtEnd(p->builder, b->block);
  363. p->curr_block = b;
  364. }
  365. void lb_set_debug_position_to_procedure_begin(lbProcedure *p) {
  366. if (p->debug_info == nullptr) {
  367. return;
  368. }
  369. TokenPos pos = {};
  370. if (p->body != nullptr) {
  371. pos = ast_token(p->body).pos;
  372. } else if (p->type_expr != nullptr) {
  373. pos = ast_token(p->type_expr).pos;
  374. } else if (p->entity != nullptr) {
  375. pos = p->entity->token.pos;
  376. }
  377. if (pos.file_id != 0) {
  378. LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_token_pos(p, pos));
  379. }
  380. }
  381. void lb_set_debug_position_to_procedure_end(lbProcedure *p) {
  382. if (p->debug_info == nullptr) {
  383. return;
  384. }
  385. TokenPos pos = {};
  386. if (p->body != nullptr) {
  387. pos = ast_end_token(p->body).pos;
  388. } else if (p->type_expr != nullptr) {
  389. pos = ast_end_token(p->type_expr).pos;
  390. } else if (p->entity != nullptr) {
  391. pos = p->entity->token.pos;
  392. }
  393. if (pos.file_id != 0) {
  394. LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_token_pos(p, pos));
  395. }
  396. }
  397. void lb_begin_procedure_body(lbProcedure *p) {
  398. DeclInfo *decl = decl_info_of_entity(p->entity);
  399. if (decl != nullptr) {
  400. for_array(i, decl->labels) {
  401. BlockLabel bl = decl->labels[i];
  402. lbBranchBlocks bb = {bl.label, nullptr, nullptr};
  403. array_add(&p->branch_blocks, bb);
  404. }
  405. }
  406. p->builder = LLVMCreateBuilderInContext(p->module->ctx);
  407. p->decl_block = lb_create_block(p, "decls", true);
  408. p->entry_block = lb_create_block(p, "entry", true);
  409. lb_start_block(p, p->entry_block);
  410. map_init(&p->direct_parameters, heap_allocator());
  411. GB_ASSERT(p->type != nullptr);
  412. lb_ensure_abi_function_type(p->module, p);
  413. {
  414. lbFunctionType *ft = p->abi_function_type;
  415. unsigned param_offset = 0;
  416. lbValue return_ptr_value = {};
  417. if (ft->ret.kind == lbArg_Indirect) {
  418. // NOTE(bill): this must be parameter 0
  419. String name = str_lit("agg.result");
  420. if (ft->multiple_return_original_type &&
  421. p->type->Proc.has_named_results) {
  422. auto const &variables = p->type->Proc.results->Tuple.variables;
  423. Entity *e = variables[variables.count-1];
  424. if (!is_blank_ident(e->token)) {
  425. name = e->token.string;
  426. }
  427. }
  428. Type *return_ptr_type = reduce_tuple_to_single_type(p->type->Proc.results);
  429. bool split_returns = ft->multiple_return_original_type != nullptr;
  430. if (split_returns) {
  431. GB_ASSERT(is_type_tuple(return_ptr_type));
  432. auto const &variables = return_ptr_type->Tuple.variables;
  433. return_ptr_type = variables[variables.count-1]->type;
  434. }
  435. Type *ptr_type = alloc_type_pointer(return_ptr_type);
  436. Entity *e = alloc_entity_param(nullptr, make_token_ident(name), ptr_type, false, false);
  437. e->flags |= EntityFlag_NoAlias;
  438. return_ptr_value.value = LLVMGetParam(p->value, 0);
  439. LLVMSetValueName2(return_ptr_value.value, cast(char const *)name.text, name.len);
  440. return_ptr_value.type = ptr_type;
  441. p->return_ptr = lb_addr(return_ptr_value);
  442. lb_add_entity(p->module, e, return_ptr_value);
  443. param_offset += 1;
  444. }
  445. if (p->type->Proc.params != nullptr) {
  446. TypeTuple *params = &p->type->Proc.params->Tuple;
  447. unsigned param_index = 0;
  448. for_array(i, params->variables) {
  449. Entity *e = params->variables[i];
  450. if (e->kind != Entity_Variable) {
  451. continue;
  452. }
  453. lbArgType *arg_type = &ft->args[param_index];
  454. defer (param_index += 1);
  455. if (arg_type->kind == lbArg_Ignore) {
  456. continue;
  457. } else if (arg_type->kind == lbArg_Direct) {
  458. if (e->token.string.len != 0 && !is_blank_ident(e->token.string)) {
  459. LLVMTypeRef param_type = lb_type(p->module, e->type);
  460. LLVMValueRef original_value = LLVMGetParam(p->value, param_offset+param_index);
  461. LLVMValueRef value = OdinLLVMBuildTransmute(p, original_value, param_type);
  462. lbValue param = {};
  463. param.value = value;
  464. param.type = e->type;
  465. map_set(&p->direct_parameters, e, param);
  466. lbValue ptr = lb_address_from_load_or_generate_local(p, param);
  467. GB_ASSERT(LLVMIsAAllocaInst(ptr.value));
  468. lb_add_entity(p->module, e, ptr);
  469. lbBlock *block = p->decl_block;
  470. if (original_value != value) {
  471. block = p->curr_block;
  472. }
  473. LLVMValueRef debug_storage_value = value;
  474. if (original_value != value && LLVMIsALoadInst(value)) {
  475. debug_storage_value = LLVMGetOperand(value, 0);
  476. }
  477. lb_add_debug_param_variable(p, debug_storage_value, e->type, e->token, param_index+1, block, arg_type->kind);
  478. }
  479. } else if (arg_type->kind == lbArg_Indirect) {
  480. if (e->token.string.len != 0 && !is_blank_ident(e->token.string)) {
  481. lbValue ptr = {};
  482. ptr.value = LLVMGetParam(p->value, param_offset+param_index);
  483. ptr.type = alloc_type_pointer(e->type);
  484. lb_add_entity(p->module, e, ptr);
  485. lb_add_debug_param_variable(p, ptr.value, e->type, e->token, param_index+1, p->decl_block, arg_type->kind);
  486. }
  487. }
  488. }
  489. }
  490. if (p->type->Proc.has_named_results) {
  491. GB_ASSERT(p->type->Proc.result_count > 0);
  492. TypeTuple *results = &p->type->Proc.results->Tuple;
  493. for_array(i, results->variables) {
  494. Entity *e = results->variables[i];
  495. GB_ASSERT(e->kind == Entity_Variable);
  496. if (e->token.string != "") {
  497. GB_ASSERT(!is_blank_ident(e->token));
  498. lbAddr res = {};
  499. if (p->entity && p->entity->decl_info &&
  500. p->entity->decl_info->defer_use_checked &&
  501. p->entity->decl_info->defer_used == 0) {
  502. // NOTE(bill): this is a bodge to get around the issue of the problem BELOW
  503. // We check to see if we ever use a defer statement ever within a procedure and if it
  504. // if it never happens, see if you can possibly do take the return value pointer
  505. //
  506. // NOTE(bill): this could be buggy in that I have missed a case where `defer` was used
  507. //
  508. // TODO(bill): This could be optimized to check to see where a `defer` only uses
  509. // the variable in question
  510. bool has_return_ptr = p->return_ptr.addr.value != nullptr;
  511. lbValue ptr = {};
  512. if (ft->multiple_return_original_type != nullptr) {
  513. isize the_offset = -1;
  514. if (i+1 < results->variables.count) {
  515. the_offset = cast(isize)param_offset + ft->original_arg_count + i;
  516. } else if (has_return_ptr) {
  517. GB_ASSERT(i+1 == results->variables.count);
  518. the_offset = 0;
  519. }
  520. if (the_offset >= 0) {
  521. lbValue ptr = {};
  522. ptr.value = LLVMGetParam(p->value, cast(unsigned)the_offset);
  523. ptr.type = alloc_type_pointer(e->type);
  524. }
  525. } else if (has_return_ptr) {
  526. lbValue ptr = p->return_ptr.addr;
  527. if (results->variables.count > 1) {
  528. ptr = lb_emit_tuple_ep(p, ptr, cast(i32)i);
  529. }
  530. GB_ASSERT(is_type_pointer(ptr.type));
  531. GB_ASSERT(are_types_identical(type_deref(ptr.type), e->type));
  532. }
  533. if (ptr.value != nullptr) {
  534. lb_add_entity(p->module, e, ptr);
  535. lb_add_debug_local_variable(p, ptr.value, e->type, e->token);
  536. // NOTE(bill): no need to zero on the callee side as it is zeroed on the caller side
  537. res = lb_addr(ptr);
  538. }
  539. }
  540. if (res.addr.type == nullptr) {
  541. // NOTE(bill): Don't even bother trying to optimize this with the return ptr value
  542. // This will violate the defer rules if you do:
  543. // foo :: proc() -> (x, y: T) {
  544. // defer x = ... // defer is executed after the `defer`
  545. // return // the values returned should be zeroed
  546. // }
  547. // NOTE(bill): REALLY, don't even bother.
  548. //
  549. // IMPORTANT NOTE(bill): REALLY, don't even bother!!!!!!
  550. res = lb_add_local(p, e->type, e);
  551. }
  552. if (e->Variable.param_value.kind != ParameterValue_Invalid) {
  553. lbValue c = lb_handle_param_value(p, e->type, e->Variable.param_value, e->token.pos);
  554. lb_addr_store(p, res, c);
  555. }
  556. }
  557. }
  558. }
  559. }
  560. if (p->type->Proc.calling_convention == ProcCC_Odin) {
  561. lb_push_context_onto_stack_from_implicit_parameter(p);
  562. }
  563. lb_set_debug_position_to_procedure_begin(p);
  564. if (p->debug_info != nullptr) {
  565. if (p->context_stack.count != 0) {
  566. p->curr_block = p->decl_block;
  567. lb_add_debug_context_variable(p, lb_find_or_generate_context_ptr(p));
  568. }
  569. }
  570. lb_start_block(p, p->entry_block);
  571. }
  572. void lb_end_procedure_body(lbProcedure *p) {
  573. lb_set_debug_position_to_procedure_begin(p);
  574. LLVMPositionBuilderAtEnd(p->builder, p->decl_block->block);
  575. LLVMBuildBr(p->builder, p->entry_block->block);
  576. LLVMPositionBuilderAtEnd(p->builder, p->curr_block->block);
  577. LLVMValueRef instr = nullptr;
  578. // Make sure there is a "ret void" at the end of a procedure with no return type
  579. if (p->type->Proc.result_count == 0) {
  580. instr = LLVMGetLastInstruction(p->curr_block->block);
  581. if (!lb_is_instr_terminating(instr)) {
  582. lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
  583. lb_set_debug_position_to_procedure_end(p);
  584. LLVMBuildRetVoid(p->builder);
  585. }
  586. }
  587. LLVMBasicBlockRef first_block = LLVMGetFirstBasicBlock(p->value);
  588. LLVMBasicBlockRef block = nullptr;
  589. // Make sure every block terminates, and if not, make it unreachable
  590. for (block = first_block; block != nullptr; block = LLVMGetNextBasicBlock(block)) {
  591. instr = LLVMGetLastInstruction(block);
  592. if (instr == nullptr || !lb_is_instr_terminating(instr)) {
  593. LLVMPositionBuilderAtEnd(p->builder, block);
  594. LLVMBuildUnreachable(p->builder);
  595. }
  596. }
  597. p->curr_block = nullptr;
  598. p->state_flags = 0;
  599. }
  600. void lb_end_procedure(lbProcedure *p) {
  601. LLVMDisposeBuilder(p->builder);
  602. }
  603. void lb_build_nested_proc(lbProcedure *p, AstProcLit *pd, Entity *e) {
  604. GB_ASSERT(pd->body != nullptr);
  605. lbModule *m = p->module;
  606. auto *min_dep_set = &m->info->minimum_dependency_set;
  607. if (ptr_set_exists(min_dep_set, e) == false) {
  608. // NOTE(bill): Nothing depends upon it so doesn't need to be built
  609. return;
  610. }
  611. // NOTE(bill): Generate a new name
  612. // parent.name-guid
  613. String original_name = e->token.string;
  614. String pd_name = original_name;
  615. if (e->Procedure.link_name.len > 0) {
  616. pd_name = e->Procedure.link_name;
  617. }
  618. isize name_len = p->name.len + 1 + pd_name.len + 1 + 10 + 1;
  619. char *name_text = gb_alloc_array(permanent_allocator(), char, name_len);
  620. i32 guid = cast(i32)p->children.count;
  621. name_len = gb_snprintf(name_text, name_len, "%.*s.%.*s-%d", LIT(p->name), LIT(pd_name), guid);
  622. String name = make_string(cast(u8 *)name_text, name_len-1);
  623. e->Procedure.link_name = name;
  624. lbProcedure *nested_proc = lb_create_procedure(p->module, e);
  625. e->code_gen_procedure = nested_proc;
  626. lbValue value = {};
  627. value.value = nested_proc->value;
  628. value.type = nested_proc->type;
  629. lb_add_entity(m, e, value);
  630. array_add(&p->children, nested_proc);
  631. array_add(&m->procedures_to_generate, nested_proc);
  632. }
  633. Array<lbValue> lb_value_to_array(lbProcedure *p, lbValue value) {
  634. Array<lbValue> array = {};
  635. Type *t = base_type(value.type);
  636. if (t == nullptr) {
  637. // Do nothing
  638. } else if (is_type_tuple(t)) {
  639. array = array_make<lbValue>(permanent_allocator(), 0, t->Tuple.variables.count);
  640. lb_append_tuple_values(p, &array, value);
  641. } else {
  642. array = array_make<lbValue>(permanent_allocator(), 1);
  643. array[0] = value;
  644. }
  645. return array;
  646. }
  647. lbValue lb_emit_call_internal(lbProcedure *p, lbValue value, lbValue return_ptr, Array<lbValue> const &processed_args, Type *abi_rt, lbAddr context_ptr, ProcInlining inlining) {
  648. GB_ASSERT(p->module->ctx == LLVMGetTypeContext(LLVMTypeOf(value.value)));
  649. unsigned arg_count = cast(unsigned)processed_args.count;
  650. if (return_ptr.value != nullptr) {
  651. arg_count += 1;
  652. }
  653. if (context_ptr.addr.value != nullptr) {
  654. arg_count += 1;
  655. }
  656. LLVMValueRef *args = gb_alloc_array(permanent_allocator(), LLVMValueRef, arg_count);
  657. isize arg_index = 0;
  658. if (return_ptr.value != nullptr) {
  659. args[arg_index++] = return_ptr.value;
  660. }
  661. for_array(i, processed_args) {
  662. lbValue arg = processed_args[i];
  663. if (is_type_proc(arg.type)) {
  664. arg.value = LLVMBuildPointerCast(p->builder, arg.value, lb_type(p->module, arg.type), "");
  665. }
  666. args[arg_index++] = arg.value;
  667. }
  668. if (context_ptr.addr.value != nullptr) {
  669. LLVMValueRef cp = context_ptr.addr.value;
  670. cp = LLVMBuildPointerCast(p->builder, cp, lb_type(p->module, t_rawptr), "");
  671. args[arg_index++] = cp;
  672. }
  673. GB_ASSERT(arg_index == arg_count);
  674. LLVMBasicBlockRef curr_block = LLVMGetInsertBlock(p->builder);
  675. GB_ASSERT(curr_block != p->decl_block->block);
  676. {
  677. Type *proc_type = base_type(value.type);
  678. GB_ASSERT(proc_type->kind == Type_Proc);
  679. LLVMTypeRef fnp = lb_type_internal_for_procedures_raw(p->module, proc_type);
  680. LLVMTypeRef ftp = LLVMPointerType(fnp, 0);
  681. LLVMValueRef fn = value.value;
  682. if (!lb_is_type_kind(LLVMTypeOf(value.value), LLVMFunctionTypeKind)) {
  683. fn = LLVMBuildPointerCast(p->builder, fn, ftp, "");
  684. }
  685. GB_ASSERT_MSG(lb_is_type_kind(fnp, LLVMFunctionTypeKind), "%s", LLVMPrintTypeToString(fnp));
  686. lbFunctionType *ft = map_must_get(&p->module->function_type_map, base_type(value.type));
  687. {
  688. unsigned param_count = LLVMCountParamTypes(fnp);
  689. GB_ASSERT(arg_count >= param_count);
  690. LLVMTypeRef *param_types = gb_alloc_array(temporary_allocator(), LLVMTypeRef, param_count);
  691. LLVMGetParamTypes(fnp, param_types);
  692. for (unsigned i = 0; i < param_count; i++) {
  693. LLVMTypeRef param_type = param_types[i];
  694. LLVMTypeRef arg_type = LLVMTypeOf(args[i]);
  695. // LLVMTypeKind param_kind = LLVMGetTypeKind(param_type);
  696. // LLVMTypeKind arg_kind = LLVMGetTypeKind(arg_type);
  697. GB_ASSERT_MSG(
  698. arg_type == param_type,
  699. "Parameter types do not match: %s != %s, argument: %s\n\t%s",
  700. LLVMPrintTypeToString(arg_type),
  701. LLVMPrintTypeToString(param_type),
  702. LLVMPrintValueToString(args[i]),
  703. LLVMPrintTypeToString(fnp)
  704. );
  705. }
  706. }
  707. LLVMValueRef ret = LLVMBuildCall2(p->builder, fnp, fn, args, arg_count, "");
  708. LLVMAttributeIndex param_offset = LLVMAttributeIndex_FirstArgIndex;
  709. if (return_ptr.value != nullptr) {
  710. param_offset += 1;
  711. LLVMAddCallSiteAttribute(ret, 1, lb_create_enum_attribute_with_type(p->module->ctx, "sret", LLVMTypeOf(args[0])));
  712. }
  713. for_array(i, ft->args) {
  714. LLVMAttributeRef attribute = ft->args[i].attribute;
  715. if (attribute != nullptr) {
  716. LLVMAddCallSiteAttribute(ret, param_offset + cast(LLVMAttributeIndex)i, attribute);
  717. }
  718. }
  719. switch (inlining) {
  720. case ProcInlining_none:
  721. break;
  722. case ProcInlining_inline:
  723. LLVMAddCallSiteAttribute(ret, LLVMAttributeIndex_FunctionIndex, lb_create_enum_attribute(p->module->ctx, "alwaysinline"));
  724. break;
  725. case ProcInlining_no_inline:
  726. LLVMAddCallSiteAttribute(ret, LLVMAttributeIndex_FunctionIndex, lb_create_enum_attribute(p->module->ctx, "noinline"));
  727. break;
  728. }
  729. lbValue res = {};
  730. res.value = ret;
  731. res.type = abi_rt;
  732. return res;
  733. }
  734. }
  735. lbValue lb_lookup_runtime_procedure(lbModule *m, String const &name) {
  736. AstPackage *pkg = m->info->runtime_package;
  737. Entity *e = scope_lookup_current(pkg->scope, name);
  738. return lb_find_procedure_value_from_entity(m, e);
  739. }
  740. lbValue lb_emit_runtime_call(lbProcedure *p, char const *c_name, Array<lbValue> const &args) {
  741. String name = make_string_c(c_name);
  742. lbValue proc = lb_lookup_runtime_procedure(p->module, name);
  743. return lb_emit_call(p, proc, args);
  744. }
  745. lbValue lb_emit_conjugate(lbProcedure *p, lbValue val, Type *type) {
  746. lbValue res = {};
  747. Type *t = val.type;
  748. if (is_type_complex(t)) {
  749. res = lb_addr_get_ptr(p, lb_add_local_generated(p, type, false));
  750. lbValue real = lb_emit_struct_ev(p, val, 0);
  751. lbValue imag = lb_emit_struct_ev(p, val, 1);
  752. imag = lb_emit_unary_arith(p, Token_Sub, imag, imag.type);
  753. lb_emit_store(p, lb_emit_struct_ep(p, res, 0), real);
  754. lb_emit_store(p, lb_emit_struct_ep(p, res, 1), imag);
  755. } else if (is_type_quaternion(t)) {
  756. // @QuaternionLayout
  757. res = lb_addr_get_ptr(p, lb_add_local_generated(p, type, false));
  758. lbValue real = lb_emit_struct_ev(p, val, 3);
  759. lbValue imag = lb_emit_struct_ev(p, val, 0);
  760. lbValue jmag = lb_emit_struct_ev(p, val, 1);
  761. lbValue kmag = lb_emit_struct_ev(p, val, 2);
  762. imag = lb_emit_unary_arith(p, Token_Sub, imag, imag.type);
  763. jmag = lb_emit_unary_arith(p, Token_Sub, jmag, jmag.type);
  764. kmag = lb_emit_unary_arith(p, Token_Sub, kmag, kmag.type);
  765. lb_emit_store(p, lb_emit_struct_ep(p, res, 3), real);
  766. lb_emit_store(p, lb_emit_struct_ep(p, res, 0), imag);
  767. lb_emit_store(p, lb_emit_struct_ep(p, res, 1), jmag);
  768. lb_emit_store(p, lb_emit_struct_ep(p, res, 2), kmag);
  769. } else if (is_type_array_like(t)) {
  770. res = lb_addr_get_ptr(p, lb_add_local_generated(p, type, true));
  771. Type *elem_type = base_array_type(t);
  772. i64 count = get_array_type_count(t);
  773. for (i64 i = 0; i < count; i++) {
  774. lbValue dst = lb_emit_array_epi(p, res, i);
  775. lbValue elem = lb_emit_struct_ev(p, val, cast(i32)i);
  776. elem = lb_emit_conjugate(p, elem, elem_type);
  777. lb_emit_store(p, dst, elem);
  778. }
  779. } else if (is_type_matrix(t)) {
  780. Type *mt = base_type(t);
  781. GB_ASSERT(mt->kind == Type_Matrix);
  782. Type *elem_type = mt->Matrix.elem;
  783. res = lb_addr_get_ptr(p, lb_add_local_generated(p, type, true));
  784. for (i64 j = 0; j < mt->Matrix.column_count; j++) {
  785. for (i64 i = 0; i < mt->Matrix.row_count; i++) {
  786. lbValue dst = lb_emit_matrix_epi(p, res, i, j);
  787. lbValue elem = lb_emit_matrix_ev(p, val, i, j);
  788. elem = lb_emit_conjugate(p, elem, elem_type);
  789. lb_emit_store(p, dst, elem);
  790. }
  791. }
  792. }
  793. return lb_emit_load(p, res);
  794. }
  795. lbValue lb_emit_call(lbProcedure *p, lbValue value, Array<lbValue> const &args, ProcInlining inlining) {
  796. lbModule *m = p->module;
  797. Type *pt = base_type(value.type);
  798. GB_ASSERT(pt->kind == Type_Proc);
  799. Type *results = pt->Proc.results;
  800. lbAddr context_ptr = {};
  801. if (pt->Proc.calling_convention == ProcCC_Odin) {
  802. context_ptr = lb_find_or_generate_context_ptr(p);
  803. }
  804. defer (if (pt->Proc.diverging) {
  805. LLVMBuildUnreachable(p->builder);
  806. });
  807. bool is_c_vararg = pt->Proc.c_vararg;
  808. isize param_count = pt->Proc.param_count;
  809. if (is_c_vararg) {
  810. GB_ASSERT(param_count-1 <= args.count);
  811. param_count -= 1;
  812. } else {
  813. GB_ASSERT_MSG(param_count == args.count, "%td == %td (%s)", param_count, args.count, LLVMPrintValueToString(value.value));
  814. }
  815. lbValue result = {};
  816. auto processed_args = array_make<lbValue>(permanent_allocator(), 0, args.count);
  817. {
  818. bool is_odin_cc = is_calling_convention_odin(pt->Proc.calling_convention);
  819. lbFunctionType *ft = lb_get_function_type(m, pt);
  820. bool return_by_pointer = ft->ret.kind == lbArg_Indirect;
  821. bool split_returns = ft->multiple_return_original_type != nullptr;
  822. unsigned param_index = 0;
  823. for (isize i = 0; i < param_count; i++) {
  824. Entity *e = pt->Proc.params->Tuple.variables[i];
  825. if (e->kind != Entity_Variable) {
  826. continue;
  827. }
  828. GB_ASSERT(e->flags & EntityFlag_Param);
  829. Type *original_type = e->type;
  830. lbArgType *arg = &ft->args[param_index];
  831. if (arg->kind == lbArg_Ignore) {
  832. continue;
  833. }
  834. lbValue x = lb_emit_conv(p, args[i], original_type);
  835. LLVMTypeRef xt = lb_type(p->module, x.type);
  836. if (arg->kind == lbArg_Direct) {
  837. LLVMTypeRef abi_type = arg->cast_type;
  838. if (!abi_type) {
  839. abi_type = arg->type;
  840. }
  841. if (xt == abi_type) {
  842. array_add(&processed_args, x);
  843. } else {
  844. x.value = OdinLLVMBuildTransmute(p, x.value, abi_type);
  845. array_add(&processed_args, x);
  846. }
  847. } else if (arg->kind == lbArg_Indirect) {
  848. lbValue ptr = {};
  849. if (arg->is_byval) {
  850. if (is_odin_cc && are_types_identical(original_type, t_source_code_location)) {
  851. ptr = lb_address_from_load_or_generate_local(p, x);
  852. } else {
  853. ptr = lb_copy_value_to_ptr(p, x, original_type, arg->byval_alignment);
  854. }
  855. } else if (is_odin_cc) {
  856. // NOTE(bill): Odin parameters are immutable so the original value can be passed if possible
  857. // i.e. `T const &` in C++
  858. ptr = lb_address_from_load_or_generate_local(p, x);
  859. } else {
  860. ptr = lb_copy_value_to_ptr(p, x, original_type, 16);
  861. }
  862. array_add(&processed_args, ptr);
  863. }
  864. param_index += 1;
  865. }
  866. if (is_c_vararg) {
  867. for (isize i = processed_args.count; i < args.count; i++) {
  868. array_add(&processed_args, args[i]);
  869. }
  870. }
  871. if (inlining == ProcInlining_none) {
  872. inlining = p->inlining;
  873. }
  874. Type *rt = reduce_tuple_to_single_type(results);
  875. Type *original_rt = rt;
  876. if (split_returns) {
  877. GB_ASSERT(rt->kind == Type_Tuple);
  878. for (isize j = 0; j < rt->Tuple.variables.count-1; j++) {
  879. Type *partial_return_type = rt->Tuple.variables[j]->type;
  880. lbValue partial_return_ptr = lb_add_local(p, partial_return_type, nullptr, true, false).addr;
  881. array_add(&processed_args, partial_return_ptr);
  882. }
  883. rt = reduce_tuple_to_single_type(rt->Tuple.variables[rt->Tuple.variables.count-1]->type);
  884. }
  885. if (return_by_pointer) {
  886. lbValue return_ptr = lb_add_local_generated(p, rt, true).addr;
  887. lb_emit_call_internal(p, value, return_ptr, processed_args, nullptr, context_ptr, inlining);
  888. result = lb_emit_load(p, return_ptr);
  889. } else if (rt != nullptr) {
  890. result = lb_emit_call_internal(p, value, {}, processed_args, rt, context_ptr, inlining);
  891. if (ft->ret.cast_type) {
  892. result.value = OdinLLVMBuildTransmute(p, result.value, ft->ret.cast_type);
  893. }
  894. result.value = OdinLLVMBuildTransmute(p, result.value, ft->ret.type);
  895. result.type = rt;
  896. if (LLVMTypeOf(result.value) == LLVMInt1TypeInContext(p->module->ctx)) {
  897. result.type = t_llvm_bool;
  898. }
  899. if (!is_type_tuple(rt)) {
  900. result = lb_emit_conv(p, result, rt);
  901. }
  902. } else {
  903. lb_emit_call_internal(p, value, {}, processed_args, nullptr, context_ptr, inlining);
  904. }
  905. if (original_rt != rt) {
  906. GB_ASSERT(split_returns);
  907. GB_ASSERT(is_type_tuple(original_rt));
  908. // IMPORTANT NOTE(bill, 2022-11-24)
  909. // result_ptr is a dummy value which is only used to reference a tuple
  910. // value for the "tuple-fix"
  911. //
  912. // The reason for the fake stack allocation is to have a unique pointer
  913. // for the value to be used as a key within the procedure itself
  914. lbValue result_ptr = lb_add_local_generated(p, original_rt, false).addr;
  915. isize ret_count = original_rt->Tuple.variables.count;
  916. auto tuple_fix_values = slice_make<lbValue>(permanent_allocator(), ret_count);
  917. auto tuple_geps = slice_make<lbValue>(permanent_allocator(), ret_count);
  918. isize offset = ft->original_arg_count;
  919. for (isize j = 0; j < ret_count-1; j++) {
  920. lbValue ret_arg_ptr = processed_args[offset + j];
  921. lbValue ret_arg = lb_emit_load(p, ret_arg_ptr);
  922. tuple_fix_values[j] = ret_arg;
  923. }
  924. tuple_fix_values[ret_count-1] = result;
  925. #if 0
  926. for (isize j = 0; j < ret_count; j++) {
  927. tuple_geps[j] = lb_emit_struct_ep(p, result_ptr, cast(i32)j);
  928. }
  929. for (isize j = 0; j < ret_count; j++) {
  930. lb_emit_store(p, tuple_geps[j], tuple_fix_values[j]);
  931. }
  932. #endif
  933. result = lb_emit_load(p, result_ptr);
  934. lbTupleFix tf = {tuple_fix_values};
  935. map_set(&p->tuple_fix_map, result_ptr.value, tf);
  936. map_set(&p->tuple_fix_map, result.value, tf);
  937. }
  938. }
  939. Entity **found = map_get(&p->module->procedure_values, value.value);
  940. if (found != nullptr) {
  941. Entity *e = *found;
  942. if (e != nullptr && entity_has_deferred_procedure(e)) {
  943. DeferredProcedureKind kind = e->Procedure.deferred_procedure.kind;
  944. Entity *deferred_entity = e->Procedure.deferred_procedure.entity;
  945. lbValue deferred = lb_find_procedure_value_from_entity(p->module, deferred_entity);
  946. auto in_args = args;
  947. Array<lbValue> result_as_args = {};
  948. switch (kind) {
  949. case DeferredProcedure_none:
  950. break;
  951. case DeferredProcedure_in:
  952. result_as_args = in_args;
  953. break;
  954. case DeferredProcedure_out:
  955. result_as_args = lb_value_to_array(p, result);
  956. break;
  957. case DeferredProcedure_in_out:
  958. {
  959. auto out_args = lb_value_to_array(p, result);
  960. array_init(&result_as_args, permanent_allocator(), in_args.count + out_args.count);
  961. array_copy(&result_as_args, in_args, 0);
  962. array_copy(&result_as_args, out_args, in_args.count);
  963. }
  964. break;
  965. }
  966. lb_add_defer_proc(p, p->scope_index, deferred, result_as_args);
  967. }
  968. }
  969. return result;
  970. }
  971. LLVMValueRef llvm_splat_float(i64 count, LLVMTypeRef type, f64 value) {
  972. LLVMValueRef v = LLVMConstReal(type, value);
  973. LLVMValueRef *values = gb_alloc_array(temporary_allocator(), LLVMValueRef, count);
  974. for (i64 i = 0; i < count; i++) {
  975. values[i] = v;
  976. }
  977. return LLVMConstVector(values, cast(unsigned)count);
  978. }
  979. LLVMValueRef llvm_splat_int(i64 count, LLVMTypeRef type, i64 value, bool is_signed=false) {
  980. LLVMValueRef v = LLVMConstInt(type, value, is_signed);
  981. LLVMValueRef *values = gb_alloc_array(temporary_allocator(), LLVMValueRef, count);
  982. for (i64 i = 0; i < count; i++) {
  983. values[i] = v;
  984. }
  985. return LLVMConstVector(values, cast(unsigned)count);
  986. }
  987. lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv, BuiltinProcId builtin_id) {
  988. ast_node(ce, CallExpr, expr);
  989. lbModule *m = p->module;
  990. lbValue res = {};
  991. res.type = tv.type;
  992. lbValue arg0 = {}; if (ce->args.count > 0) arg0 = lb_build_expr(p, ce->args[0]);
  993. lbValue arg1 = {}; if (ce->args.count > 1) arg1 = lb_build_expr(p, ce->args[1]);
  994. lbValue arg2 = {}; if (ce->args.count > 2) arg2 = lb_build_expr(p, ce->args[2]);
  995. Type *elem = base_array_type(arg0.type);
  996. bool is_float = is_type_float(elem);
  997. bool is_signed = !is_type_unsigned(elem);
  998. LLVMOpcode op_code = cast(LLVMOpcode)0;
  999. switch (builtin_id) {
  1000. case BuiltinProc_simd_add:
  1001. case BuiltinProc_simd_sub:
  1002. case BuiltinProc_simd_mul:
  1003. case BuiltinProc_simd_div:
  1004. case BuiltinProc_simd_rem:
  1005. if (is_float) {
  1006. switch (builtin_id) {
  1007. case BuiltinProc_simd_add: op_code = LLVMFAdd; break;
  1008. case BuiltinProc_simd_sub: op_code = LLVMFSub; break;
  1009. case BuiltinProc_simd_mul: op_code = LLVMFMul; break;
  1010. case BuiltinProc_simd_div: op_code = LLVMFDiv; break;
  1011. }
  1012. } else {
  1013. switch (builtin_id) {
  1014. case BuiltinProc_simd_add: op_code = LLVMAdd; break;
  1015. case BuiltinProc_simd_sub: op_code = LLVMSub; break;
  1016. case BuiltinProc_simd_mul: op_code = LLVMMul; break;
  1017. case BuiltinProc_simd_div:
  1018. if (is_signed) {
  1019. op_code = LLVMSDiv;
  1020. } else {
  1021. op_code = LLVMUDiv;
  1022. }
  1023. break;
  1024. case BuiltinProc_simd_rem:
  1025. if (is_signed) {
  1026. op_code = LLVMSRem;
  1027. } else {
  1028. op_code = LLVMURem;
  1029. }
  1030. break;
  1031. }
  1032. }
  1033. if (op_code) {
  1034. res.value = LLVMBuildBinOp(p->builder, op_code, arg0.value, arg1.value, "");
  1035. return res;
  1036. }
  1037. break;
  1038. case BuiltinProc_simd_shl: // Odin logic
  1039. case BuiltinProc_simd_shr: // Odin logic
  1040. case BuiltinProc_simd_shl_masked: // C logic
  1041. case BuiltinProc_simd_shr_masked: // C logic
  1042. {
  1043. i64 sz = type_size_of(elem);
  1044. GB_ASSERT(arg0.type->kind == Type_SimdVector);
  1045. i64 count = arg0.type->SimdVector.count;
  1046. Type *elem1 = base_array_type(arg1.type);
  1047. bool is_masked = false;
  1048. switch (builtin_id) {
  1049. case BuiltinProc_simd_shl: op_code = LLVMShl; is_masked = false; break;
  1050. case BuiltinProc_simd_shr: op_code = is_signed ? LLVMAShr : LLVMLShr; is_masked = false; break;
  1051. case BuiltinProc_simd_shl_masked: op_code = LLVMShl; is_masked = true; break;
  1052. case BuiltinProc_simd_shr_masked: op_code = is_signed ? LLVMAShr : LLVMLShr; is_masked = true; break;
  1053. }
  1054. if (op_code) {
  1055. LLVMValueRef bits = llvm_splat_int(count, lb_type(m, elem1), sz*8 - 1);
  1056. if (is_masked) {
  1057. // C logic
  1058. LLVMValueRef shift = LLVMBuildAnd(p->builder, arg1.value, bits, "");
  1059. res.value = LLVMBuildBinOp(p->builder, op_code, arg0.value, shift, "");
  1060. } else {
  1061. // Odin logic
  1062. LLVMValueRef zero = lb_const_nil(m, arg1.type).value;
  1063. LLVMValueRef mask = LLVMBuildICmp(p->builder, LLVMIntULE, arg1.value, bits, "");
  1064. LLVMValueRef shift = LLVMBuildBinOp(p->builder, op_code, arg0.value, arg1.value, "");
  1065. res.value = LLVMBuildSelect(p->builder, mask, shift, zero, "");
  1066. }
  1067. return res;
  1068. }
  1069. }
  1070. break;
  1071. case BuiltinProc_simd_and:
  1072. case BuiltinProc_simd_or:
  1073. case BuiltinProc_simd_xor:
  1074. case BuiltinProc_simd_and_not:
  1075. switch (builtin_id) {
  1076. case BuiltinProc_simd_and: op_code = LLVMAnd; break;
  1077. case BuiltinProc_simd_or: op_code = LLVMOr; break;
  1078. case BuiltinProc_simd_xor: op_code = LLVMXor; break;
  1079. case BuiltinProc_simd_and_not:
  1080. op_code = LLVMAnd;
  1081. arg1.value = LLVMBuildNot(p->builder, arg1.value, "");
  1082. break;
  1083. }
  1084. if (op_code) {
  1085. res.value = LLVMBuildBinOp(p->builder, op_code, arg0.value, arg1.value, "");
  1086. return res;
  1087. }
  1088. break;
  1089. case BuiltinProc_simd_neg:
  1090. if (is_float) {
  1091. res.value = LLVMBuildFNeg(p->builder, arg0.value, "");
  1092. } else {
  1093. res.value = LLVMBuildNeg(p->builder, arg0.value, "");
  1094. }
  1095. return res;
  1096. case BuiltinProc_simd_abs:
  1097. if (is_float) {
  1098. LLVMValueRef pos = arg0.value;
  1099. LLVMValueRef neg = LLVMBuildFNeg(p->builder, pos, "");
  1100. LLVMValueRef cond = LLVMBuildFCmp(p->builder, LLVMRealOGT, pos, neg, "");
  1101. res.value = LLVMBuildSelect(p->builder, cond, pos, neg, "");
  1102. } else {
  1103. LLVMValueRef pos = arg0.value;
  1104. LLVMValueRef neg = LLVMBuildNeg(p->builder, pos, "");
  1105. LLVMValueRef cond = LLVMBuildICmp(p->builder, is_signed ? LLVMIntSGT : LLVMIntUGT, pos, neg, "");
  1106. res.value = LLVMBuildSelect(p->builder, cond, pos, neg, "");
  1107. }
  1108. return res;
  1109. case BuiltinProc_simd_min:
  1110. if (is_float) {
  1111. LLVMValueRef cond = LLVMBuildFCmp(p->builder, LLVMRealOLT, arg0.value, arg1.value, "");
  1112. res.value = LLVMBuildSelect(p->builder, cond, arg0.value, arg1.value, "");
  1113. } else {
  1114. LLVMValueRef cond = LLVMBuildICmp(p->builder, is_signed ? LLVMIntSLT : LLVMIntULT, arg0.value, arg1.value, "");
  1115. res.value = LLVMBuildSelect(p->builder, cond, arg0.value, arg1.value, "");
  1116. }
  1117. return res;
  1118. case BuiltinProc_simd_max:
  1119. if (is_float) {
  1120. LLVMValueRef cond = LLVMBuildFCmp(p->builder, LLVMRealOGT, arg0.value, arg1.value, "");
  1121. res.value = LLVMBuildSelect(p->builder, cond, arg0.value, arg1.value, "");
  1122. } else {
  1123. LLVMValueRef cond = LLVMBuildICmp(p->builder, is_signed ? LLVMIntSGT : LLVMIntUGT, arg0.value, arg1.value, "");
  1124. res.value = LLVMBuildSelect(p->builder, cond, arg0.value, arg1.value, "");
  1125. }
  1126. return res;
  1127. case BuiltinProc_simd_lanes_eq:
  1128. case BuiltinProc_simd_lanes_ne:
  1129. case BuiltinProc_simd_lanes_lt:
  1130. case BuiltinProc_simd_lanes_le:
  1131. case BuiltinProc_simd_lanes_gt:
  1132. case BuiltinProc_simd_lanes_ge:
  1133. if (is_float) {
  1134. LLVMRealPredicate pred = cast(LLVMRealPredicate)0;
  1135. switch (builtin_id) {
  1136. case BuiltinProc_simd_lanes_eq: pred = LLVMRealOEQ; break;
  1137. case BuiltinProc_simd_lanes_ne: pred = LLVMRealONE; break;
  1138. case BuiltinProc_simd_lanes_lt: pred = LLVMRealOLT; break;
  1139. case BuiltinProc_simd_lanes_le: pred = LLVMRealOLE; break;
  1140. case BuiltinProc_simd_lanes_gt: pred = LLVMRealOGT; break;
  1141. case BuiltinProc_simd_lanes_ge: pred = LLVMRealOGE; break;
  1142. }
  1143. if (pred) {
  1144. res.value = LLVMBuildFCmp(p->builder, pred, arg0.value, arg1.value, "");
  1145. res.value = LLVMBuildSExtOrBitCast(p->builder, res.value, lb_type(m, tv.type), "");
  1146. return res;
  1147. }
  1148. } else {
  1149. LLVMIntPredicate pred = cast(LLVMIntPredicate)0;
  1150. switch (builtin_id) {
  1151. case BuiltinProc_simd_lanes_eq: pred = LLVMIntEQ; break;
  1152. case BuiltinProc_simd_lanes_ne: pred = LLVMIntNE; break;
  1153. case BuiltinProc_simd_lanes_lt: pred = is_signed ? LLVMIntSLT :LLVMIntULT; break;
  1154. case BuiltinProc_simd_lanes_le: pred = is_signed ? LLVMIntSLE :LLVMIntULE; break;
  1155. case BuiltinProc_simd_lanes_gt: pred = is_signed ? LLVMIntSGT :LLVMIntUGT; break;
  1156. case BuiltinProc_simd_lanes_ge: pred = is_signed ? LLVMIntSGE :LLVMIntUGE; break;
  1157. }
  1158. if (pred) {
  1159. res.value = LLVMBuildICmp(p->builder, pred, arg0.value, arg1.value, "");
  1160. res.value = LLVMBuildSExtOrBitCast(p->builder, res.value, lb_type(m, tv.type), "");
  1161. return res;
  1162. }
  1163. }
  1164. break;
  1165. case BuiltinProc_simd_extract:
  1166. res.value = LLVMBuildExtractElement(p->builder, arg0.value, arg1.value, "");
  1167. return res;
  1168. case BuiltinProc_simd_replace:
  1169. res.value = LLVMBuildInsertElement(p->builder, arg0.value, arg2.value, arg1.value, "");
  1170. return res;
  1171. case BuiltinProc_simd_reduce_add_ordered:
  1172. case BuiltinProc_simd_reduce_mul_ordered:
  1173. {
  1174. LLVMTypeRef llvm_elem = lb_type(m, elem);
  1175. LLVMValueRef args[2] = {};
  1176. isize args_count = 0;
  1177. char const *name = nullptr;
  1178. switch (builtin_id) {
  1179. case BuiltinProc_simd_reduce_add_ordered:
  1180. if (is_float) {
  1181. name = "llvm.vector.reduce.fadd";
  1182. args[args_count++] = LLVMConstReal(llvm_elem, 0.0);
  1183. } else {
  1184. name = "llvm.vector.reduce.add";
  1185. }
  1186. break;
  1187. case BuiltinProc_simd_reduce_mul_ordered:
  1188. if (is_float) {
  1189. name = "llvm.vector.reduce.fmul";
  1190. args[args_count++] = LLVMConstReal(llvm_elem, 1.0);
  1191. } else {
  1192. name = "llvm.vector.reduce.mul";
  1193. }
  1194. break;
  1195. }
  1196. args[args_count++] = arg0.value;
  1197. LLVMTypeRef types[1] = {lb_type(p->module, arg0.type)};
  1198. res.value = lb_call_intrinsic(p, name, args, cast(unsigned)args_count, types, gb_count_of(types));
  1199. return res;
  1200. }
  1201. case BuiltinProc_simd_reduce_min:
  1202. case BuiltinProc_simd_reduce_max:
  1203. case BuiltinProc_simd_reduce_and:
  1204. case BuiltinProc_simd_reduce_or:
  1205. case BuiltinProc_simd_reduce_xor:
  1206. {
  1207. char const *name = nullptr;
  1208. switch (builtin_id) {
  1209. case BuiltinProc_simd_reduce_min:
  1210. if (is_float) {
  1211. name = "llvm.vector.reduce.fmin";
  1212. } else if (is_signed) {
  1213. name = "llvm.vector.reduce.smin";
  1214. } else {
  1215. name = "llvm.vector.reduce.umin";
  1216. }
  1217. break;
  1218. case BuiltinProc_simd_reduce_max:
  1219. if (is_float) {
  1220. name = "llvm.vector.reduce.fmax";
  1221. } else if (is_signed) {
  1222. name = "llvm.vector.reduce.smax";
  1223. } else {
  1224. name = "llvm.vector.reduce.umax";
  1225. }
  1226. break;
  1227. case BuiltinProc_simd_reduce_and: name = "llvm.vector.reduce.and"; break;
  1228. case BuiltinProc_simd_reduce_or: name = "llvm.vector.reduce.or"; break;
  1229. case BuiltinProc_simd_reduce_xor: name = "llvm.vector.reduce.xor"; break;
  1230. }
  1231. LLVMTypeRef types[1] = { lb_type(p->module, arg0.type) };
  1232. LLVMValueRef args[1] = { arg0.value };
  1233. res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
  1234. return res;
  1235. }
  1236. case BuiltinProc_simd_shuffle:
  1237. {
  1238. Type *vt = arg0.type;
  1239. GB_ASSERT(vt->kind == Type_SimdVector);
  1240. i64 indices_count = ce->args.count-2;
  1241. i64 max_count = vt->SimdVector.count*2;
  1242. GB_ASSERT(indices_count <= max_count);
  1243. LLVMValueRef *values = gb_alloc_array(temporary_allocator(), LLVMValueRef, indices_count);
  1244. for (isize i = 0; i < indices_count; i++) {
  1245. lbValue idx = lb_build_expr(p, ce->args[i+2]);
  1246. GB_ASSERT(LLVMIsConstant(idx.value));
  1247. values[i] = idx.value;
  1248. }
  1249. LLVMValueRef indices = LLVMConstVector(values, cast(unsigned)indices_count);
  1250. res.value = LLVMBuildShuffleVector(p->builder, arg0.value, arg1.value, indices, "");
  1251. return res;
  1252. }
  1253. case BuiltinProc_simd_select:
  1254. {
  1255. LLVMValueRef cond = arg0.value;
  1256. LLVMValueRef x = lb_build_expr(p, ce->args[1]).value;
  1257. LLVMValueRef y = lb_build_expr(p, ce->args[2]).value;
  1258. cond = LLVMBuildICmp(p->builder, LLVMIntNE, cond, LLVMConstNull(LLVMTypeOf(cond)), "");
  1259. res.value = LLVMBuildSelect(p->builder, cond, x, y, "");
  1260. return res;
  1261. }
  1262. case BuiltinProc_simd_ceil:
  1263. case BuiltinProc_simd_floor:
  1264. case BuiltinProc_simd_trunc:
  1265. case BuiltinProc_simd_nearest:
  1266. {
  1267. char const *name = nullptr;
  1268. switch (builtin_id) {
  1269. case BuiltinProc_simd_ceil: name = "llvm.ceil"; break;
  1270. case BuiltinProc_simd_floor: name = "llvm.floor"; break;
  1271. case BuiltinProc_simd_trunc: name = "llvm.trunc"; break;
  1272. case BuiltinProc_simd_nearest: name = "llvm.nearbyint"; break;
  1273. }
  1274. LLVMTypeRef types[1] = { lb_type(p->module, arg0.type) };
  1275. LLVMValueRef args[1] = { arg0.value };
  1276. res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
  1277. return res;
  1278. }
  1279. case BuiltinProc_simd_lanes_reverse:
  1280. {
  1281. i64 count = get_array_type_count(arg0.type);
  1282. LLVMValueRef *values = gb_alloc_array(temporary_allocator(), LLVMValueRef, count);
  1283. LLVMTypeRef llvm_u32 = lb_type(m, t_u32);
  1284. for (i64 i = 0; i < count; i++) {
  1285. values[i] = LLVMConstInt(llvm_u32, count-1-i, false);
  1286. }
  1287. LLVMValueRef mask = LLVMConstVector(values, cast(unsigned)count);
  1288. LLVMValueRef v = arg0.value;
  1289. res.value = LLVMBuildShuffleVector(p->builder, v, v, mask, "");
  1290. return res;
  1291. }
  1292. case BuiltinProc_simd_lanes_rotate_left:
  1293. case BuiltinProc_simd_lanes_rotate_right:
  1294. {
  1295. i64 count = get_array_type_count(arg0.type);
  1296. GB_ASSERT(is_power_of_two(count));
  1297. BigInt bi_count = {};
  1298. big_int_from_i64(&bi_count, count);
  1299. TypeAndValue const &tv = ce->args[1]->tav;
  1300. ExactValue val = exact_value_to_integer(tv.value);
  1301. GB_ASSERT(val.kind == ExactValue_Integer);
  1302. BigInt *bi = &val.value_integer;
  1303. if (builtin_id == BuiltinProc_simd_lanes_rotate_right) {
  1304. big_int_neg(bi, bi);
  1305. }
  1306. big_int_rem(bi, bi, &bi_count);
  1307. big_int_dealloc(&bi_count);
  1308. i64 left = big_int_to_i64(bi);
  1309. LLVMValueRef *values = gb_alloc_array(temporary_allocator(), LLVMValueRef, count);
  1310. LLVMTypeRef llvm_u32 = lb_type(m, t_u32);
  1311. for (i64 i = 0; i < count; i++) {
  1312. u64 idx = cast(u64)(i+left) & cast(u64)(count-1);
  1313. values[i] = LLVMConstInt(llvm_u32, idx, false);
  1314. }
  1315. LLVMValueRef mask = LLVMConstVector(values, cast(unsigned)count);
  1316. LLVMValueRef v = arg0.value;
  1317. res.value = LLVMBuildShuffleVector(p->builder, v, v, mask, "");
  1318. return res;
  1319. }
  1320. case BuiltinProc_simd_add_sat:
  1321. case BuiltinProc_simd_sub_sat:
  1322. {
  1323. char const *name = nullptr;
  1324. switch (builtin_id) {
  1325. case BuiltinProc_simd_add_sat: name = is_signed ? "llvm.sadd.sat" : "llvm.uadd.sat"; break;
  1326. case BuiltinProc_simd_sub_sat: name = is_signed ? "llvm.ssub.sat" : "llvm.usub.sat"; break;
  1327. }
  1328. LLVMTypeRef types[1] = {lb_type(p->module, arg0.type)};
  1329. LLVMValueRef args[2] = { arg0.value, arg1.value };
  1330. res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
  1331. return res;
  1332. }
  1333. case BuiltinProc_simd_clamp:
  1334. {
  1335. LLVMValueRef v = arg0.value;
  1336. LLVMValueRef min = arg1.value;
  1337. LLVMValueRef max = arg2.value;
  1338. if (is_float) {
  1339. v = LLVMBuildSelect(p->builder, LLVMBuildFCmp(p->builder, LLVMRealOLT, v, min, ""), min, v, "");
  1340. res.value = LLVMBuildSelect(p->builder, LLVMBuildFCmp(p->builder, LLVMRealOGT, v, max, ""), max, v, "");
  1341. } else if (is_signed) {
  1342. v = LLVMBuildSelect(p->builder, LLVMBuildICmp(p->builder, LLVMIntSLT, v, min, ""), min, v, "");
  1343. res.value = LLVMBuildSelect(p->builder, LLVMBuildICmp(p->builder, LLVMIntSGT, v, max, ""), max, v, "");
  1344. } else {
  1345. v = LLVMBuildSelect(p->builder, LLVMBuildICmp(p->builder, LLVMIntULT, v, min, ""), min, v, "");
  1346. res.value = LLVMBuildSelect(p->builder, LLVMBuildICmp(p->builder, LLVMIntUGT, v, max, ""), max, v, "");
  1347. }
  1348. return res;
  1349. }
  1350. case BuiltinProc_simd_to_bits:
  1351. {
  1352. res.value = LLVMBuildBitCast(p->builder, arg0.value, lb_type(m, tv.type), "");
  1353. return res;
  1354. }
  1355. }
  1356. GB_PANIC("Unhandled simd intrinsic: '%.*s'", LIT(builtin_procs[builtin_id].name));
  1357. return {};
  1358. }
  1359. lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv, BuiltinProcId id) {
  1360. ast_node(ce, CallExpr, expr);
  1361. if (BuiltinProc__simd_begin < id && id < BuiltinProc__simd_end) {
  1362. return lb_build_builtin_simd_proc(p, expr, tv, id);
  1363. }
  1364. switch (id) {
  1365. case BuiltinProc_DIRECTIVE: {
  1366. ast_node(bd, BasicDirective, ce->proc);
  1367. String name = bd->name.string;
  1368. GB_ASSERT(name == "location");
  1369. String procedure = p->entity->token.string;
  1370. TokenPos pos = ast_token(ce->proc).pos;
  1371. if (ce->args.count > 0) {
  1372. Ast *ident = unselector_expr(ce->args[0]);
  1373. GB_ASSERT(ident->kind == Ast_Ident);
  1374. Entity *e = entity_of_node(ident);
  1375. GB_ASSERT(e != nullptr);
  1376. if (e->parent_proc_decl != nullptr && e->parent_proc_decl->entity != nullptr) {
  1377. procedure = e->parent_proc_decl->entity->token.string;
  1378. } else {
  1379. procedure = str_lit("");
  1380. }
  1381. pos = e->token.pos;
  1382. }
  1383. return lb_emit_source_code_location_as_global(p, procedure, pos);
  1384. }
  1385. case BuiltinProc_type_info_of: {
  1386. Ast *arg = ce->args[0];
  1387. TypeAndValue tav = type_and_value_of_expr(arg);
  1388. if (tav.mode == Addressing_Type) {
  1389. Type *t = default_type(type_of_expr(arg));
  1390. return lb_type_info(p->module, t);
  1391. }
  1392. GB_ASSERT(is_type_typeid(tav.type));
  1393. auto args = array_make<lbValue>(permanent_allocator(), 1);
  1394. args[0] = lb_build_expr(p, arg);
  1395. return lb_emit_runtime_call(p, "__type_info_of", args);
  1396. }
  1397. case BuiltinProc_typeid_of: {
  1398. Ast *arg = ce->args[0];
  1399. TypeAndValue tav = type_and_value_of_expr(arg);
  1400. GB_ASSERT(tav.mode == Addressing_Type);
  1401. Type *t = default_type(type_of_expr(arg));
  1402. return lb_typeid(p->module, t);
  1403. }
  1404. case BuiltinProc_len: {
  1405. lbValue v = lb_build_expr(p, ce->args[0]);
  1406. Type *t = base_type(v.type);
  1407. if (is_type_pointer(t)) {
  1408. // IMPORTANT TODO(bill): Should there be a nil pointer check?
  1409. v = lb_emit_load(p, v);
  1410. t = type_deref(t);
  1411. }
  1412. if (is_type_cstring(t)) {
  1413. return lb_cstring_len(p, v);
  1414. } else if (is_type_string(t)) {
  1415. return lb_string_len(p, v);
  1416. } else if (is_type_array(t)) {
  1417. GB_PANIC("Array lengths are constant");
  1418. } else if (is_type_slice(t) || is_type_relative_slice(t)) {
  1419. return lb_slice_len(p, v);
  1420. } else if (is_type_dynamic_array(t)) {
  1421. return lb_dynamic_array_len(p, v);
  1422. } else if (is_type_map(t)) {
  1423. return lb_map_len(p, v);
  1424. } else if (is_type_soa_struct(t)) {
  1425. return lb_soa_struct_len(p, v);
  1426. }
  1427. GB_PANIC("Unreachable");
  1428. break;
  1429. }
  1430. case BuiltinProc_cap: {
  1431. lbValue v = lb_build_expr(p, ce->args[0]);
  1432. Type *t = base_type(v.type);
  1433. if (is_type_pointer(t)) {
  1434. // IMPORTANT TODO(bill): Should there be a nil pointer check?
  1435. v = lb_emit_load(p, v);
  1436. t = type_deref(t);
  1437. }
  1438. if (is_type_string(t)) {
  1439. GB_PANIC("Unreachable");
  1440. } else if (is_type_array(t)) {
  1441. GB_PANIC("Array lengths are constant");
  1442. } else if (is_type_slice(t) || is_type_relative_slice(t)) {
  1443. return lb_slice_len(p, v);
  1444. } else if (is_type_dynamic_array(t)) {
  1445. return lb_dynamic_array_cap(p, v);
  1446. } else if (is_type_map(t)) {
  1447. return lb_map_cap(p, v);
  1448. } else if (is_type_soa_struct(t)) {
  1449. return lb_soa_struct_cap(p, v);
  1450. }
  1451. GB_PANIC("Unreachable");
  1452. break;
  1453. }
  1454. case BuiltinProc_swizzle: {
  1455. isize index_count = ce->args.count-1;
  1456. if (is_type_simd_vector(tv.type)) {
  1457. lbValue vec = lb_build_expr(p, ce->args[0]);
  1458. if (index_count == 0) {
  1459. return vec;
  1460. }
  1461. unsigned mask_len = cast(unsigned)index_count;
  1462. LLVMValueRef *mask_elems = gb_alloc_array(permanent_allocator(), LLVMValueRef, index_count);
  1463. for (isize i = 1; i < ce->args.count; i++) {
  1464. TypeAndValue tv = type_and_value_of_expr(ce->args[i]);
  1465. GB_ASSERT(is_type_integer(tv.type));
  1466. GB_ASSERT(tv.value.kind == ExactValue_Integer);
  1467. u32 index = cast(u32)big_int_to_i64(&tv.value.value_integer);
  1468. mask_elems[i-1] = LLVMConstInt(lb_type(p->module, t_u32), index, false);
  1469. }
  1470. LLVMValueRef mask = LLVMConstVector(mask_elems, mask_len);
  1471. LLVMValueRef v1 = vec.value;
  1472. LLVMValueRef v2 = vec.value;
  1473. lbValue res = {};
  1474. res.type = tv.type;
  1475. res.value = LLVMBuildShuffleVector(p->builder, v1, v2, mask, "");
  1476. return res;
  1477. }
  1478. lbAddr addr = lb_build_array_swizzle_addr(p, ce, tv);
  1479. return lb_addr_load(p, addr);
  1480. }
  1481. case BuiltinProc_complex: {
  1482. lbValue real = lb_build_expr(p, ce->args[0]);
  1483. lbValue imag = lb_build_expr(p, ce->args[1]);
  1484. lbAddr dst_addr = lb_add_local_generated(p, tv.type, false);
  1485. lbValue dst = lb_addr_get_ptr(p, dst_addr);
  1486. Type *ft = base_complex_elem_type(tv.type);
  1487. real = lb_emit_conv(p, real, ft);
  1488. imag = lb_emit_conv(p, imag, ft);
  1489. lb_emit_store(p, lb_emit_struct_ep(p, dst, 0), real);
  1490. lb_emit_store(p, lb_emit_struct_ep(p, dst, 1), imag);
  1491. return lb_emit_load(p, dst);
  1492. }
  1493. case BuiltinProc_quaternion: {
  1494. lbValue real = lb_build_expr(p, ce->args[0]);
  1495. lbValue imag = lb_build_expr(p, ce->args[1]);
  1496. lbValue jmag = lb_build_expr(p, ce->args[2]);
  1497. lbValue kmag = lb_build_expr(p, ce->args[3]);
  1498. // @QuaternionLayout
  1499. lbAddr dst_addr = lb_add_local_generated(p, tv.type, false);
  1500. lbValue dst = lb_addr_get_ptr(p, dst_addr);
  1501. Type *ft = base_complex_elem_type(tv.type);
  1502. real = lb_emit_conv(p, real, ft);
  1503. imag = lb_emit_conv(p, imag, ft);
  1504. jmag = lb_emit_conv(p, jmag, ft);
  1505. kmag = lb_emit_conv(p, kmag, ft);
  1506. lb_emit_store(p, lb_emit_struct_ep(p, dst, 3), real);
  1507. lb_emit_store(p, lb_emit_struct_ep(p, dst, 0), imag);
  1508. lb_emit_store(p, lb_emit_struct_ep(p, dst, 1), jmag);
  1509. lb_emit_store(p, lb_emit_struct_ep(p, dst, 2), kmag);
  1510. return lb_emit_load(p, dst);
  1511. }
  1512. case BuiltinProc_real: {
  1513. lbValue val = lb_build_expr(p, ce->args[0]);
  1514. if (is_type_complex(val.type)) {
  1515. lbValue real = lb_emit_struct_ev(p, val, 0);
  1516. return lb_emit_conv(p, real, tv.type);
  1517. } else if (is_type_quaternion(val.type)) {
  1518. // @QuaternionLayout
  1519. lbValue real = lb_emit_struct_ev(p, val, 3);
  1520. return lb_emit_conv(p, real, tv.type);
  1521. }
  1522. GB_PANIC("invalid type for real");
  1523. return {};
  1524. }
  1525. case BuiltinProc_imag: {
  1526. lbValue val = lb_build_expr(p, ce->args[0]);
  1527. if (is_type_complex(val.type)) {
  1528. lbValue imag = lb_emit_struct_ev(p, val, 1);
  1529. return lb_emit_conv(p, imag, tv.type);
  1530. } else if (is_type_quaternion(val.type)) {
  1531. // @QuaternionLayout
  1532. lbValue imag = lb_emit_struct_ev(p, val, 0);
  1533. return lb_emit_conv(p, imag, tv.type);
  1534. }
  1535. GB_PANIC("invalid type for imag");
  1536. return {};
  1537. }
  1538. case BuiltinProc_jmag: {
  1539. lbValue val = lb_build_expr(p, ce->args[0]);
  1540. if (is_type_quaternion(val.type)) {
  1541. // @QuaternionLayout
  1542. lbValue imag = lb_emit_struct_ev(p, val, 1);
  1543. return lb_emit_conv(p, imag, tv.type);
  1544. }
  1545. GB_PANIC("invalid type for jmag");
  1546. return {};
  1547. }
  1548. case BuiltinProc_kmag: {
  1549. lbValue val = lb_build_expr(p, ce->args[0]);
  1550. if (is_type_quaternion(val.type)) {
  1551. // @QuaternionLayout
  1552. lbValue imag = lb_emit_struct_ev(p, val, 2);
  1553. return lb_emit_conv(p, imag, tv.type);
  1554. }
  1555. GB_PANIC("invalid type for kmag");
  1556. return {};
  1557. }
  1558. case BuiltinProc_conj: {
  1559. lbValue val = lb_build_expr(p, ce->args[0]);
  1560. return lb_emit_conjugate(p, val, tv.type);
  1561. }
  1562. case BuiltinProc_expand_to_tuple: {
  1563. lbValue val = lb_build_expr(p, ce->args[0]);
  1564. Type *t = base_type(val.type);
  1565. if (!is_type_tuple(tv.type)) {
  1566. if (t->kind == Type_Struct) {
  1567. GB_ASSERT(t->Struct.fields.count == 1);
  1568. return lb_emit_struct_ev(p, val, 0);
  1569. } else if (t->kind == Type_Array) {
  1570. GB_ASSERT(t->Array.count == 1);
  1571. return lb_emit_struct_ev(p, val, 0);
  1572. } else {
  1573. GB_PANIC("Unknown type of expand_to_tuple");
  1574. }
  1575. }
  1576. GB_ASSERT(is_type_tuple(tv.type));
  1577. // NOTE(bill): Doesn't need to be zero because it will be initialized in the loops
  1578. lbValue tuple = lb_addr_get_ptr(p, lb_add_local_generated(p, tv.type, false));
  1579. if (t->kind == Type_Struct) {
  1580. for_array(src_index, t->Struct.fields) {
  1581. Entity *field = t->Struct.fields[src_index];
  1582. i32 field_index = field->Variable.field_index;
  1583. lbValue f = lb_emit_struct_ev(p, val, field_index);
  1584. lbValue ep = lb_emit_struct_ep(p, tuple, cast(i32)src_index);
  1585. lb_emit_store(p, ep, f);
  1586. }
  1587. } else if (is_type_array_like(t)) {
  1588. // TODO(bill): Clean-up this code
  1589. lbValue ap = lb_address_from_load_or_generate_local(p, val);
  1590. i32 n = cast(i32)get_array_type_count(t);
  1591. for (i32 i = 0; i < n; i++) {
  1592. lbValue f = lb_emit_load(p, lb_emit_array_epi(p, ap, i));
  1593. lbValue ep = lb_emit_struct_ep(p, tuple, i);
  1594. lb_emit_store(p, ep, f);
  1595. }
  1596. } else {
  1597. GB_PANIC("Unknown type of expand_to_tuple");
  1598. }
  1599. return lb_emit_load(p, tuple);
  1600. }
  1601. case BuiltinProc_min: {
  1602. Type *t = type_of_expr(expr);
  1603. if (ce->args.count == 2) {
  1604. return lb_emit_min(p, t, lb_build_expr(p, ce->args[0]), lb_build_expr(p, ce->args[1]));
  1605. } else {
  1606. lbValue x = lb_build_expr(p, ce->args[0]);
  1607. for (isize i = 1; i < ce->args.count; i++) {
  1608. x = lb_emit_min(p, t, x, lb_build_expr(p, ce->args[i]));
  1609. }
  1610. return x;
  1611. }
  1612. }
  1613. case BuiltinProc_max: {
  1614. Type *t = type_of_expr(expr);
  1615. if (ce->args.count == 2) {
  1616. return lb_emit_max(p, t, lb_build_expr(p, ce->args[0]), lb_build_expr(p, ce->args[1]));
  1617. } else {
  1618. lbValue x = lb_build_expr(p, ce->args[0]);
  1619. for (isize i = 1; i < ce->args.count; i++) {
  1620. x = lb_emit_max(p, t, x, lb_build_expr(p, ce->args[i]));
  1621. }
  1622. return x;
  1623. }
  1624. }
  1625. case BuiltinProc_abs: {
  1626. lbValue x = lb_build_expr(p, ce->args[0]);
  1627. Type *t = x.type;
  1628. if (is_type_unsigned(t)) {
  1629. return x;
  1630. }
  1631. if (is_type_quaternion(t)) {
  1632. i64 sz = 8*type_size_of(t);
  1633. auto args = array_make<lbValue>(permanent_allocator(), 1);
  1634. args[0] = x;
  1635. switch (sz) {
  1636. case 64: return lb_emit_runtime_call(p, "abs_quaternion64", args);
  1637. case 128: return lb_emit_runtime_call(p, "abs_quaternion128", args);
  1638. case 256: return lb_emit_runtime_call(p, "abs_quaternion256", args);
  1639. }
  1640. GB_PANIC("Unknown complex type");
  1641. } else if (is_type_complex(t)) {
  1642. i64 sz = 8*type_size_of(t);
  1643. auto args = array_make<lbValue>(permanent_allocator(), 1);
  1644. args[0] = x;
  1645. switch (sz) {
  1646. case 32: return lb_emit_runtime_call(p, "abs_complex32", args);
  1647. case 64: return lb_emit_runtime_call(p, "abs_complex64", args);
  1648. case 128: return lb_emit_runtime_call(p, "abs_complex128", args);
  1649. }
  1650. GB_PANIC("Unknown complex type");
  1651. }
  1652. lbValue zero = lb_const_nil(p->module, t);
  1653. lbValue cond = lb_emit_comp(p, Token_Lt, x, zero);
  1654. lbValue neg = lb_emit_unary_arith(p, Token_Sub, x, t);
  1655. return lb_emit_select(p, cond, neg, x);
  1656. }
  1657. case BuiltinProc_clamp:
  1658. return lb_emit_clamp(p, type_of_expr(expr),
  1659. lb_build_expr(p, ce->args[0]),
  1660. lb_build_expr(p, ce->args[1]),
  1661. lb_build_expr(p, ce->args[2]));
  1662. case BuiltinProc_soa_zip:
  1663. return lb_soa_zip(p, ce, tv);
  1664. case BuiltinProc_soa_unzip:
  1665. return lb_soa_unzip(p, ce, tv);
  1666. case BuiltinProc_transpose:
  1667. {
  1668. lbValue m = lb_build_expr(p, ce->args[0]);
  1669. return lb_emit_matrix_tranpose(p, m, tv.type);
  1670. }
  1671. case BuiltinProc_outer_product:
  1672. {
  1673. lbValue a = lb_build_expr(p, ce->args[0]);
  1674. lbValue b = lb_build_expr(p, ce->args[1]);
  1675. return lb_emit_outer_product(p, a, b, tv.type);
  1676. }
  1677. case BuiltinProc_hadamard_product:
  1678. {
  1679. lbValue a = lb_build_expr(p, ce->args[0]);
  1680. lbValue b = lb_build_expr(p, ce->args[1]);
  1681. if (is_type_array(tv.type)) {
  1682. return lb_emit_arith(p, Token_Mul, a, b, tv.type);
  1683. }
  1684. GB_ASSERT(is_type_matrix(tv.type));
  1685. return lb_emit_arith_matrix(p, Token_Mul, a, b, tv.type, true);
  1686. }
  1687. case BuiltinProc_matrix_flatten:
  1688. {
  1689. lbValue m = lb_build_expr(p, ce->args[0]);
  1690. return lb_emit_matrix_flatten(p, m, tv.type);
  1691. }
  1692. case BuiltinProc_unreachable:
  1693. lb_emit_unreachable(p);
  1694. return {};
  1695. case BuiltinProc_raw_data:
  1696. {
  1697. lbValue x = lb_build_expr(p, ce->args[0]);
  1698. Type *t = base_type(x.type);
  1699. lbValue res = {};
  1700. switch (t->kind) {
  1701. case Type_Slice:
  1702. res = lb_slice_elem(p, x);
  1703. res = lb_emit_conv(p, res, tv.type);
  1704. break;
  1705. case Type_DynamicArray:
  1706. res = lb_dynamic_array_elem(p, x);
  1707. res = lb_emit_conv(p, res, tv.type);
  1708. break;
  1709. case Type_Basic:
  1710. if (t->Basic.kind == Basic_string) {
  1711. res = lb_string_elem(p, x);
  1712. res = lb_emit_conv(p, res, tv.type);
  1713. } else if (t->Basic.kind == Basic_cstring) {
  1714. res = lb_emit_conv(p, x, tv.type);
  1715. }
  1716. break;
  1717. case Type_Pointer:
  1718. case Type_MultiPointer:
  1719. res = lb_emit_conv(p, x, tv.type);
  1720. break;
  1721. }
  1722. GB_ASSERT(res.value != nullptr);
  1723. return res;
  1724. }
  1725. // "Intrinsics"
  1726. case BuiltinProc_alloca:
  1727. {
  1728. lbValue sz = lb_build_expr(p, ce->args[0]);
  1729. i64 al = exact_value_to_i64(type_and_value_of_expr(ce->args[1]).value);
  1730. lbValue res = {};
  1731. res.type = t_u8_ptr;
  1732. res.value = LLVMBuildArrayAlloca(p->builder, lb_type(p->module, t_u8), sz.value, "");
  1733. LLVMSetAlignment(res.value, cast(unsigned)al);
  1734. return res;
  1735. }
  1736. case BuiltinProc_cpu_relax:
  1737. if (build_context.metrics.arch == TargetArch_i386 ||
  1738. build_context.metrics.arch == TargetArch_amd64) {
  1739. LLVMTypeRef func_type = LLVMFunctionType(LLVMVoidTypeInContext(p->module->ctx), nullptr, 0, false);
  1740. LLVMValueRef the_asm = llvm_get_inline_asm(func_type, str_lit("pause"), {}, true);
  1741. GB_ASSERT(the_asm != nullptr);
  1742. LLVMBuildCall2(p->builder, func_type, the_asm, nullptr, 0, "");
  1743. } else if (build_context.metrics.arch == TargetArch_arm64) {
  1744. LLVMTypeRef func_type = LLVMFunctionType(LLVMVoidTypeInContext(p->module->ctx), nullptr, 0, false);
  1745. // NOTE(bill, 2022-03-30): `isb` appears to a better option that `yield`
  1746. // See: https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8258604
  1747. LLVMValueRef the_asm = llvm_get_inline_asm(func_type, str_lit("isb"), {}, true);
  1748. GB_ASSERT(the_asm != nullptr);
  1749. LLVMBuildCall2(p->builder, func_type, the_asm, nullptr, 0, "");
  1750. } else {
  1751. // NOTE: default to something to prevent optimization
  1752. LLVMTypeRef func_type = LLVMFunctionType(LLVMVoidTypeInContext(p->module->ctx), nullptr, 0, false);
  1753. LLVMValueRef the_asm = llvm_get_inline_asm(func_type, str_lit(""), {}, true);
  1754. GB_ASSERT(the_asm != nullptr);
  1755. LLVMBuildCall2(p->builder, func_type, the_asm, nullptr, 0, "");
  1756. }
  1757. return {};
  1758. case BuiltinProc_debug_trap:
  1759. case BuiltinProc_trap:
  1760. {
  1761. char const *name = nullptr;
  1762. switch (id) {
  1763. case BuiltinProc_debug_trap: name = "llvm.debugtrap"; break;
  1764. case BuiltinProc_trap: name = "llvm.trap"; break;
  1765. }
  1766. lb_call_intrinsic(p, name, nullptr, 0, nullptr, 0);
  1767. if (id == BuiltinProc_trap) {
  1768. LLVMBuildUnreachable(p->builder);
  1769. }
  1770. return {};
  1771. }
  1772. case BuiltinProc_read_cycle_counter:
  1773. {
  1774. lbValue res = {};
  1775. res.type = tv.type;
  1776. if (build_context.metrics.arch == TargetArch_arm64) {
  1777. LLVMTypeRef func_type = LLVMFunctionType(LLVMInt64TypeInContext(p->module->ctx), nullptr, 0, false);
  1778. bool has_side_effects = false;
  1779. LLVMValueRef the_asm = llvm_get_inline_asm(func_type, str_lit("mrs x9, cntvct_el0"), str_lit("=r"), has_side_effects);
  1780. GB_ASSERT(the_asm != nullptr);
  1781. res.value = LLVMBuildCall2(p->builder, func_type, the_asm, nullptr, 0, "");
  1782. } else {
  1783. char const *name = "llvm.readcyclecounter";
  1784. res.value = lb_call_intrinsic(p, name, nullptr, 0, nullptr, 0);
  1785. }
  1786. return res;
  1787. }
  1788. case BuiltinProc_count_trailing_zeros:
  1789. return lb_emit_count_trailing_zeros(p, lb_build_expr(p, ce->args[0]), tv.type);
  1790. case BuiltinProc_count_leading_zeros:
  1791. return lb_emit_count_leading_zeros(p, lb_build_expr(p, ce->args[0]), tv.type);
  1792. case BuiltinProc_count_ones:
  1793. return lb_emit_count_ones(p, lb_build_expr(p, ce->args[0]), tv.type);
  1794. case BuiltinProc_count_zeros:
  1795. return lb_emit_count_zeros(p, lb_build_expr(p, ce->args[0]), tv.type);
  1796. case BuiltinProc_reverse_bits:
  1797. return lb_emit_reverse_bits(p, lb_build_expr(p, ce->args[0]), tv.type);
  1798. case BuiltinProc_byte_swap:
  1799. {
  1800. lbValue x = lb_build_expr(p, ce->args[0]);
  1801. x = lb_emit_conv(p, x, tv.type);
  1802. return lb_emit_byte_swap(p, x, tv.type);
  1803. }
  1804. case BuiltinProc_overflow_add:
  1805. case BuiltinProc_overflow_sub:
  1806. case BuiltinProc_overflow_mul:
  1807. {
  1808. Type *main_type = tv.type;
  1809. Type *type = main_type;
  1810. if (is_type_tuple(main_type)) {
  1811. type = main_type->Tuple.variables[0]->type;
  1812. }
  1813. lbValue x = lb_build_expr(p, ce->args[0]);
  1814. lbValue y = lb_build_expr(p, ce->args[1]);
  1815. x = lb_emit_conv(p, x, type);
  1816. y = lb_emit_conv(p, y, type);
  1817. char const *name = nullptr;
  1818. if (is_type_unsigned(type)) {
  1819. switch (id) {
  1820. case BuiltinProc_overflow_add: name = "llvm.uadd.with.overflow"; break;
  1821. case BuiltinProc_overflow_sub: name = "llvm.usub.with.overflow"; break;
  1822. case BuiltinProc_overflow_mul: name = "llvm.umul.with.overflow"; break;
  1823. }
  1824. } else {
  1825. switch (id) {
  1826. case BuiltinProc_overflow_add: name = "llvm.sadd.with.overflow"; break;
  1827. case BuiltinProc_overflow_sub: name = "llvm.ssub.with.overflow"; break;
  1828. case BuiltinProc_overflow_mul: name = "llvm.smul.with.overflow"; break;
  1829. }
  1830. }
  1831. LLVMTypeRef types[1] = {lb_type(p->module, type)};
  1832. LLVMValueRef args[2] = { x.value, y.value };
  1833. lbValue res = {};
  1834. res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
  1835. if (is_type_tuple(main_type)) {
  1836. Type *res_type = nullptr;
  1837. gbAllocator a = permanent_allocator();
  1838. res_type = alloc_type_tuple();
  1839. slice_init(&res_type->Tuple.variables, a, 2);
  1840. res_type->Tuple.variables[0] = alloc_entity_field(nullptr, blank_token, type, false, 0);
  1841. res_type->Tuple.variables[1] = alloc_entity_field(nullptr, blank_token, t_llvm_bool, false, 1);
  1842. res.type = res_type;
  1843. } else {
  1844. res.value = LLVMBuildExtractValue(p->builder, res.value, 0, "");
  1845. res.type = type;
  1846. }
  1847. return res;
  1848. }
  1849. case BuiltinProc_sqrt:
  1850. {
  1851. Type *type = tv.type;
  1852. lbValue x = lb_build_expr(p, ce->args[0]);
  1853. x = lb_emit_conv(p, x, type);
  1854. char const *name = "llvm.sqrt";
  1855. LLVMTypeRef types[1] = {lb_type(p->module, type)};
  1856. LLVMValueRef args[1] = { x.value };
  1857. lbValue res = {};
  1858. res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
  1859. res.type = type;
  1860. return res;
  1861. }
  1862. case BuiltinProc_fused_mul_add:
  1863. {
  1864. Type *type = tv.type;
  1865. lbValue x = lb_emit_conv(p, lb_build_expr(p, ce->args[0]), type);
  1866. lbValue y = lb_emit_conv(p, lb_build_expr(p, ce->args[1]), type);
  1867. lbValue z = lb_emit_conv(p, lb_build_expr(p, ce->args[2]), type);
  1868. char const *name = "llvm.fma";
  1869. LLVMTypeRef types[1] = {lb_type(p->module, type)};
  1870. LLVMValueRef args[3] = { x.value, y.value, z.value };
  1871. lbValue res = {};
  1872. res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
  1873. res.type = type;
  1874. return res;
  1875. }
  1876. case BuiltinProc_mem_copy:
  1877. {
  1878. lbValue dst = lb_build_expr(p, ce->args[0]);
  1879. lbValue src = lb_build_expr(p, ce->args[1]);
  1880. lbValue len = lb_build_expr(p, ce->args[2]);
  1881. lb_mem_copy_overlapping(p, dst, src, len, false);
  1882. return {};
  1883. }
  1884. case BuiltinProc_mem_copy_non_overlapping:
  1885. {
  1886. lbValue dst = lb_build_expr(p, ce->args[0]);
  1887. lbValue src = lb_build_expr(p, ce->args[1]);
  1888. lbValue len = lb_build_expr(p, ce->args[2]);
  1889. lb_mem_copy_non_overlapping(p, dst, src, len, false);
  1890. return {};
  1891. }
  1892. case BuiltinProc_mem_zero:
  1893. {
  1894. lbValue ptr = lb_build_expr(p, ce->args[0]);
  1895. lbValue len = lb_build_expr(p, ce->args[1]);
  1896. ptr = lb_emit_conv(p, ptr, t_rawptr);
  1897. len = lb_emit_conv(p, len, t_int);
  1898. unsigned alignment = 1;
  1899. lb_mem_zero_ptr_internal(p, ptr.value, len.value, alignment, false);
  1900. return {};
  1901. }
  1902. case BuiltinProc_mem_zero_volatile:
  1903. {
  1904. lbValue ptr = lb_build_expr(p, ce->args[0]);
  1905. lbValue len = lb_build_expr(p, ce->args[1]);
  1906. ptr = lb_emit_conv(p, ptr, t_rawptr);
  1907. len = lb_emit_conv(p, len, t_int);
  1908. unsigned alignment = 1;
  1909. lb_mem_zero_ptr_internal(p, ptr.value, len.value, alignment, true);
  1910. return {};
  1911. }
  1912. case BuiltinProc_ptr_offset:
  1913. {
  1914. lbValue ptr = lb_build_expr(p, ce->args[0]);
  1915. lbValue len = lb_build_expr(p, ce->args[1]);
  1916. len = lb_emit_conv(p, len, t_int);
  1917. return lb_emit_ptr_offset(p, ptr, len);
  1918. }
  1919. case BuiltinProc_ptr_sub:
  1920. {
  1921. Type *elem0 = type_deref(type_of_expr(ce->args[0]));
  1922. Type *elem1 = type_deref(type_of_expr(ce->args[1]));
  1923. GB_ASSERT(are_types_identical(elem0, elem1));
  1924. Type *elem = elem0;
  1925. lbValue ptr0 = lb_emit_conv(p, lb_build_expr(p, ce->args[0]), t_uintptr);
  1926. lbValue ptr1 = lb_emit_conv(p, lb_build_expr(p, ce->args[1]), t_uintptr);
  1927. lbValue diff = lb_emit_arith(p, Token_Sub, ptr0, ptr1, t_uintptr);
  1928. diff = lb_emit_conv(p, diff, t_int);
  1929. return lb_emit_arith(p, Token_Quo, diff, lb_const_int(p->module, t_int, type_size_of(elem)), t_int);
  1930. }
  1931. // TODO(bill): Which is correct?
  1932. case BuiltinProc_atomic_thread_fence:
  1933. LLVMBuildFence(p->builder, llvm_atomic_ordering_from_odin(ce->args[0]), false, "");
  1934. return {};
  1935. case BuiltinProc_atomic_signal_fence:
  1936. LLVMBuildFence(p->builder, llvm_atomic_ordering_from_odin(ce->args[0]), true, "");
  1937. return {};
  1938. case BuiltinProc_volatile_store:
  1939. case BuiltinProc_non_temporal_store:
  1940. case BuiltinProc_atomic_store:
  1941. case BuiltinProc_atomic_store_explicit: {
  1942. lbValue dst = lb_build_expr(p, ce->args[0]);
  1943. lbValue val = lb_build_expr(p, ce->args[1]);
  1944. val = lb_emit_conv(p, val, type_deref(dst.type));
  1945. LLVMValueRef instr = LLVMBuildStore(p->builder, val.value, dst.value);
  1946. switch (id) {
  1947. case BuiltinProc_non_temporal_store:
  1948. {
  1949. unsigned kind_id = LLVMGetMDKindIDInContext(p->module->ctx, "nontemporal", 11);
  1950. LLVMMetadataRef node = LLVMValueAsMetadata(LLVMConstInt(lb_type(p->module, t_u32), 1, false));
  1951. LLVMSetMetadata(instr, kind_id, LLVMMetadataAsValue(p->module->ctx, node));
  1952. }
  1953. break;
  1954. case BuiltinProc_volatile_store: LLVMSetVolatile(instr, true); break;
  1955. case BuiltinProc_atomic_store: LLVMSetOrdering(instr, LLVMAtomicOrderingSequentiallyConsistent); break;
  1956. case BuiltinProc_atomic_store_explicit: LLVMSetOrdering(instr, llvm_atomic_ordering_from_odin(ce->args[2])); break;
  1957. }
  1958. LLVMSetAlignment(instr, cast(unsigned)type_align_of(type_deref(dst.type)));
  1959. return {};
  1960. }
  1961. case BuiltinProc_volatile_load:
  1962. case BuiltinProc_non_temporal_load:
  1963. case BuiltinProc_atomic_load:
  1964. case BuiltinProc_atomic_load_explicit: {
  1965. lbValue dst = lb_build_expr(p, ce->args[0]);
  1966. LLVMValueRef instr = LLVMBuildLoad2(p->builder, lb_type(p->module, type_deref(dst.type)), dst.value, "");
  1967. switch (id) {
  1968. case BuiltinProc_non_temporal_load:
  1969. {
  1970. unsigned kind_id = LLVMGetMDKindIDInContext(p->module->ctx, "nontemporal", 11);
  1971. LLVMMetadataRef node = LLVMValueAsMetadata(LLVMConstInt(lb_type(p->module, t_u32), 1, false));
  1972. LLVMSetMetadata(instr, kind_id, LLVMMetadataAsValue(p->module->ctx, node));
  1973. }
  1974. break;
  1975. break;
  1976. case BuiltinProc_volatile_load: LLVMSetVolatile(instr, true); break;
  1977. case BuiltinProc_atomic_load: LLVMSetOrdering(instr, LLVMAtomicOrderingSequentiallyConsistent); break;
  1978. case BuiltinProc_atomic_load_explicit: LLVMSetOrdering(instr, llvm_atomic_ordering_from_odin(ce->args[1])); break;
  1979. }
  1980. LLVMSetAlignment(instr, cast(unsigned)type_align_of(type_deref(dst.type)));
  1981. lbValue res = {};
  1982. res.value = instr;
  1983. res.type = type_deref(dst.type);
  1984. return res;
  1985. }
  1986. case BuiltinProc_unaligned_store:
  1987. {
  1988. lbValue dst = lb_build_expr(p, ce->args[0]);
  1989. lbValue src = lb_build_expr(p, ce->args[1]);
  1990. src = lb_address_from_load_or_generate_local(p, src);
  1991. Type *t = type_deref(dst.type);
  1992. lb_mem_copy_non_overlapping(p, dst, src, lb_const_int(p->module, t_int, type_size_of(t)), false);
  1993. return {};
  1994. }
  1995. case BuiltinProc_unaligned_load:
  1996. {
  1997. lbValue src = lb_build_expr(p, ce->args[0]);
  1998. Type *t = type_deref(src.type);
  1999. lbAddr dst = lb_add_local_generated(p, t, false);
  2000. lb_mem_copy_non_overlapping(p, dst.addr, src, lb_const_int(p->module, t_int, type_size_of(t)), false);
  2001. return lb_addr_load(p, dst);
  2002. }
  2003. case BuiltinProc_atomic_add:
  2004. case BuiltinProc_atomic_sub:
  2005. case BuiltinProc_atomic_and:
  2006. case BuiltinProc_atomic_nand:
  2007. case BuiltinProc_atomic_or:
  2008. case BuiltinProc_atomic_xor:
  2009. case BuiltinProc_atomic_exchange:
  2010. case BuiltinProc_atomic_add_explicit:
  2011. case BuiltinProc_atomic_sub_explicit:
  2012. case BuiltinProc_atomic_and_explicit:
  2013. case BuiltinProc_atomic_nand_explicit:
  2014. case BuiltinProc_atomic_or_explicit:
  2015. case BuiltinProc_atomic_xor_explicit:
  2016. case BuiltinProc_atomic_exchange_explicit: {
  2017. lbValue dst = lb_build_expr(p, ce->args[0]);
  2018. lbValue val = lb_build_expr(p, ce->args[1]);
  2019. val = lb_emit_conv(p, val, type_deref(dst.type));
  2020. LLVMAtomicRMWBinOp op = {};
  2021. LLVMAtomicOrdering ordering = {};
  2022. switch (id) {
  2023. case BuiltinProc_atomic_add: op = LLVMAtomicRMWBinOpAdd; ordering = LLVMAtomicOrderingSequentiallyConsistent; break;
  2024. case BuiltinProc_atomic_sub: op = LLVMAtomicRMWBinOpSub; ordering = LLVMAtomicOrderingSequentiallyConsistent; break;
  2025. case BuiltinProc_atomic_and: op = LLVMAtomicRMWBinOpAnd; ordering = LLVMAtomicOrderingSequentiallyConsistent; break;
  2026. case BuiltinProc_atomic_nand: op = LLVMAtomicRMWBinOpNand; ordering = LLVMAtomicOrderingSequentiallyConsistent; break;
  2027. case BuiltinProc_atomic_or: op = LLVMAtomicRMWBinOpOr; ordering = LLVMAtomicOrderingSequentiallyConsistent; break;
  2028. case BuiltinProc_atomic_xor: op = LLVMAtomicRMWBinOpXor; ordering = LLVMAtomicOrderingSequentiallyConsistent; break;
  2029. case BuiltinProc_atomic_exchange: op = LLVMAtomicRMWBinOpXchg; ordering = LLVMAtomicOrderingSequentiallyConsistent; break;
  2030. case BuiltinProc_atomic_add_explicit: op = LLVMAtomicRMWBinOpAdd; ordering = llvm_atomic_ordering_from_odin(ce->args[2]); break;
  2031. case BuiltinProc_atomic_sub_explicit: op = LLVMAtomicRMWBinOpSub; ordering = llvm_atomic_ordering_from_odin(ce->args[2]); break;
  2032. case BuiltinProc_atomic_and_explicit: op = LLVMAtomicRMWBinOpAnd; ordering = llvm_atomic_ordering_from_odin(ce->args[2]); break;
  2033. case BuiltinProc_atomic_nand_explicit: op = LLVMAtomicRMWBinOpNand; ordering = llvm_atomic_ordering_from_odin(ce->args[2]); break;
  2034. case BuiltinProc_atomic_or_explicit: op = LLVMAtomicRMWBinOpOr; ordering = llvm_atomic_ordering_from_odin(ce->args[2]); break;
  2035. case BuiltinProc_atomic_xor_explicit: op = LLVMAtomicRMWBinOpXor; ordering = llvm_atomic_ordering_from_odin(ce->args[2]); break;
  2036. case BuiltinProc_atomic_exchange_explicit: op = LLVMAtomicRMWBinOpXchg; ordering = llvm_atomic_ordering_from_odin(ce->args[2]); break;
  2037. }
  2038. lbValue res = {};
  2039. res.value = LLVMBuildAtomicRMW(p->builder, op, dst.value, val.value, ordering, false);
  2040. res.type = tv.type;
  2041. return res;
  2042. }
  2043. case BuiltinProc_atomic_compare_exchange_strong:
  2044. case BuiltinProc_atomic_compare_exchange_weak:
  2045. case BuiltinProc_atomic_compare_exchange_strong_explicit:
  2046. case BuiltinProc_atomic_compare_exchange_weak_explicit: {
  2047. lbValue address = lb_build_expr(p, ce->args[0]);
  2048. Type *elem = type_deref(address.type);
  2049. lbValue old_value = lb_build_expr(p, ce->args[1]);
  2050. lbValue new_value = lb_build_expr(p, ce->args[2]);
  2051. old_value = lb_emit_conv(p, old_value, elem);
  2052. new_value = lb_emit_conv(p, new_value, elem);
  2053. LLVMAtomicOrdering success_ordering = {};
  2054. LLVMAtomicOrdering failure_ordering = {};
  2055. LLVMBool weak = false;
  2056. switch (id) {
  2057. case BuiltinProc_atomic_compare_exchange_strong: success_ordering = LLVMAtomicOrderingSequentiallyConsistent; failure_ordering = LLVMAtomicOrderingSequentiallyConsistent; weak = false; break;
  2058. case BuiltinProc_atomic_compare_exchange_weak: success_ordering = LLVMAtomicOrderingSequentiallyConsistent; failure_ordering = LLVMAtomicOrderingSequentiallyConsistent; weak = true; break;
  2059. case BuiltinProc_atomic_compare_exchange_strong_explicit: success_ordering = llvm_atomic_ordering_from_odin(ce->args[3]); failure_ordering = llvm_atomic_ordering_from_odin(ce->args[4]); weak = false; break;
  2060. case BuiltinProc_atomic_compare_exchange_weak_explicit: success_ordering = llvm_atomic_ordering_from_odin(ce->args[3]); failure_ordering = llvm_atomic_ordering_from_odin(ce->args[4]); weak = true; break;
  2061. }
  2062. // TODO(bill): Figure out how to make it weak
  2063. LLVMBool single_threaded = false;
  2064. LLVMValueRef value = LLVMBuildAtomicCmpXchg(
  2065. p->builder, address.value,
  2066. old_value.value, new_value.value,
  2067. success_ordering,
  2068. failure_ordering,
  2069. single_threaded
  2070. );
  2071. LLVMSetWeak(value, weak);
  2072. if (is_type_tuple(tv.type)) {
  2073. Type *fix_typed = alloc_type_tuple();
  2074. slice_init(&fix_typed->Tuple.variables, permanent_allocator(), 2);
  2075. fix_typed->Tuple.variables[0] = tv.type->Tuple.variables[0];
  2076. fix_typed->Tuple.variables[1] = alloc_entity_field(nullptr, blank_token, t_llvm_bool, false, 1);
  2077. lbValue res = {};
  2078. res.value = value;
  2079. res.type = fix_typed;
  2080. return res;
  2081. } else {
  2082. lbValue res = {};
  2083. res.value = LLVMBuildExtractValue(p->builder, value, 0, "");
  2084. res.type = tv.type;
  2085. return res;
  2086. }
  2087. }
  2088. case BuiltinProc_type_equal_proc:
  2089. return lb_equal_proc_for_type(p->module, ce->args[0]->tav.type);
  2090. case BuiltinProc_type_hasher_proc:
  2091. return lb_hasher_proc_for_type(p->module, ce->args[0]->tav.type);
  2092. case BuiltinProc_type_map_info:
  2093. return lb_gen_map_info_ptr(p->module, ce->args[0]->tav.type);
  2094. case BuiltinProc_type_map_cell_info:
  2095. return lb_gen_map_cell_info_ptr(p->module, ce->args[0]->tav.type);
  2096. case BuiltinProc_fixed_point_mul:
  2097. case BuiltinProc_fixed_point_div:
  2098. case BuiltinProc_fixed_point_mul_sat:
  2099. case BuiltinProc_fixed_point_div_sat:
  2100. {
  2101. Type *platform_type = integer_endian_type_to_platform_type(tv.type);
  2102. lbValue x = lb_emit_conv(p, lb_build_expr(p, ce->args[0]), platform_type);
  2103. lbValue y = lb_emit_conv(p, lb_build_expr(p, ce->args[1]), platform_type);
  2104. lbValue scale = lb_emit_conv(p, lb_build_expr(p, ce->args[2]), t_i32);
  2105. char const *name = nullptr;
  2106. if (is_type_unsigned(tv.type)) {
  2107. switch (id) {
  2108. case BuiltinProc_fixed_point_mul: name = "llvm.umul.fix"; break;
  2109. case BuiltinProc_fixed_point_div: name = "llvm.udiv.fix"; break;
  2110. case BuiltinProc_fixed_point_mul_sat: name = "llvm.umul.fix.sat"; break;
  2111. case BuiltinProc_fixed_point_div_sat: name = "llvm.udiv.fix.sat"; break;
  2112. }
  2113. } else {
  2114. switch (id) {
  2115. case BuiltinProc_fixed_point_mul: name = "llvm.smul.fix"; break;
  2116. case BuiltinProc_fixed_point_div: name = "llvm.sdiv.fix"; break;
  2117. case BuiltinProc_fixed_point_mul_sat: name = "llvm.smul.fix.sat"; break;
  2118. case BuiltinProc_fixed_point_div_sat: name = "llvm.sdiv.fix.sat"; break;
  2119. }
  2120. }
  2121. GB_ASSERT(name != nullptr);
  2122. LLVMTypeRef types[1] = {lb_type(p->module, platform_type)};
  2123. lbValue res = {};
  2124. LLVMValueRef args[3] = {
  2125. x.value,
  2126. y.value,
  2127. scale.value };
  2128. res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
  2129. res.type = platform_type;
  2130. return lb_emit_conv(p, res, tv.type);
  2131. }
  2132. case BuiltinProc_expect:
  2133. {
  2134. Type *t = default_type(tv.type);
  2135. lbValue x = lb_emit_conv(p, lb_build_expr(p, ce->args[0]), t);
  2136. lbValue y = lb_emit_conv(p, lb_build_expr(p, ce->args[1]), t);
  2137. char const *name = "llvm.expect";
  2138. LLVMTypeRef types[1] = {lb_type(p->module, t)};
  2139. lbValue res = {};
  2140. LLVMValueRef args[2] = { x.value, y.value };
  2141. res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
  2142. res.type = t;
  2143. return lb_emit_conv(p, res, t);
  2144. }
  2145. case BuiltinProc_prefetch_read_instruction:
  2146. case BuiltinProc_prefetch_read_data:
  2147. case BuiltinProc_prefetch_write_instruction:
  2148. case BuiltinProc_prefetch_write_data:
  2149. {
  2150. lbValue ptr = lb_emit_conv(p, lb_build_expr(p, ce->args[0]), t_rawptr);
  2151. unsigned long long locality = cast(unsigned long long)exact_value_to_i64(ce->args[1]->tav.value);
  2152. unsigned long long rw = 0;
  2153. unsigned long long cache = 0;
  2154. switch (id) {
  2155. case BuiltinProc_prefetch_read_instruction:
  2156. rw = 0;
  2157. cache = 0;
  2158. break;
  2159. case BuiltinProc_prefetch_read_data:
  2160. rw = 0;
  2161. cache = 1;
  2162. break;
  2163. case BuiltinProc_prefetch_write_instruction:
  2164. rw = 1;
  2165. cache = 0;
  2166. break;
  2167. case BuiltinProc_prefetch_write_data:
  2168. rw = 1;
  2169. cache = 1;
  2170. break;
  2171. }
  2172. char const *name = "llvm.prefetch";
  2173. LLVMTypeRef types[1] = {lb_type(p->module, t_rawptr)};
  2174. LLVMTypeRef llvm_i32 = lb_type(p->module, t_i32);
  2175. LLVMValueRef args[4] = {};
  2176. args[0] = ptr.value;
  2177. args[1] = LLVMConstInt(llvm_i32, rw, false);
  2178. args[2] = LLVMConstInt(llvm_i32, locality, false);
  2179. args[3] = LLVMConstInt(llvm_i32, cache, false);
  2180. lbValue res = {};
  2181. res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
  2182. res.type = nullptr;
  2183. return res;
  2184. }
  2185. case BuiltinProc___entry_point:
  2186. if (p->module->info->entry_point) {
  2187. lbValue entry_point = lb_find_procedure_value_from_entity(p->module, p->module->info->entry_point);
  2188. GB_ASSERT(entry_point.value != nullptr);
  2189. lb_emit_call(p, entry_point, {});
  2190. }
  2191. return {};
  2192. case BuiltinProc_syscall:
  2193. {
  2194. unsigned arg_count = cast(unsigned)ce->args.count;
  2195. LLVMValueRef *args = gb_alloc_array(permanent_allocator(), LLVMValueRef, arg_count);
  2196. for_array(i, ce->args) {
  2197. lbValue arg = lb_build_expr(p, ce->args[i]);
  2198. arg = lb_emit_conv(p, arg, t_uintptr);
  2199. args[i] = arg.value;
  2200. }
  2201. LLVMTypeRef llvm_uintptr = lb_type(p->module, t_uintptr);
  2202. LLVMTypeRef *llvm_arg_types = gb_alloc_array(permanent_allocator(), LLVMTypeRef, arg_count);
  2203. for (unsigned i = 0; i < arg_count; i++) {
  2204. llvm_arg_types[i] = llvm_uintptr;
  2205. }
  2206. LLVMTypeRef func_type = LLVMFunctionType(llvm_uintptr, llvm_arg_types, arg_count, false);
  2207. LLVMValueRef inline_asm = nullptr;
  2208. switch (build_context.metrics.arch) {
  2209. case TargetArch_amd64:
  2210. {
  2211. GB_ASSERT(arg_count <= 7);
  2212. char asm_string[] = "syscall";
  2213. gbString constraints = gb_string_make(heap_allocator(), "={rax}");
  2214. for (unsigned i = 0; i < arg_count; i++) {
  2215. constraints = gb_string_appendc(constraints, ",{");
  2216. static char const *regs[] = {
  2217. "rax",
  2218. "rdi",
  2219. "rsi",
  2220. "rdx",
  2221. "r10",
  2222. "r8",
  2223. "r9"
  2224. };
  2225. constraints = gb_string_appendc(constraints, regs[i]);
  2226. constraints = gb_string_appendc(constraints, "}");
  2227. }
  2228. // The SYSCALL instruction stores the address of the
  2229. // following instruction into RCX, and RFLAGS in R11.
  2230. //
  2231. // RSP is not saved, but at least on Linux it appears
  2232. // that the kernel system-call handler does the right
  2233. // thing.
  2234. //
  2235. // Some but not all system calls will additionally
  2236. // clobber memory.
  2237. //
  2238. // TODO: FreeBSD is different and will also clobber
  2239. // R8, R9, and R10. Additionally CF is used to
  2240. // indicate an error instead of -errno.
  2241. constraints = gb_string_appendc(constraints, ",~{rcx},~{r11},~{memory}");
  2242. inline_asm = llvm_get_inline_asm(func_type, make_string_c(asm_string), make_string_c(constraints));
  2243. }
  2244. break;
  2245. case TargetArch_i386:
  2246. {
  2247. GB_ASSERT(arg_count <= 7);
  2248. char asm_string_default[] = "int $0x80";
  2249. char *asm_string = asm_string_default;
  2250. gbString constraints = gb_string_make(heap_allocator(), "={eax}");
  2251. for (unsigned i = 0; i < gb_min(arg_count, 6); i++) {
  2252. constraints = gb_string_appendc(constraints, ",{");
  2253. static char const *regs[] = {
  2254. "eax",
  2255. "ebx",
  2256. "ecx",
  2257. "edx",
  2258. "esi",
  2259. "edi",
  2260. };
  2261. constraints = gb_string_appendc(constraints, regs[i]);
  2262. constraints = gb_string_appendc(constraints, "}");
  2263. }
  2264. if (arg_count == 7) {
  2265. char asm_string7[] = "push %[arg6]\npush %%ebp\nmov 4(%%esp), %%ebp\nint $0x80\npop %%ebp\nadd $4, %%esp";
  2266. asm_string = asm_string7;
  2267. constraints = gb_string_appendc(constraints, ",rm");
  2268. }
  2269. inline_asm = llvm_get_inline_asm(func_type, make_string_c(asm_string), make_string_c(constraints));
  2270. }
  2271. break;
  2272. case TargetArch_arm64:
  2273. {
  2274. GB_ASSERT(arg_count <= 7);
  2275. if(build_context.metrics.os == TargetOs_darwin) {
  2276. char asm_string[] = "svc #0x80";
  2277. gbString constraints = gb_string_make(heap_allocator(), "={x0}");
  2278. for (unsigned i = 0; i < arg_count; i++) {
  2279. constraints = gb_string_appendc(constraints, ",{");
  2280. static char const *regs[] = {
  2281. "x16",
  2282. "x0",
  2283. "x1",
  2284. "x2",
  2285. "x3",
  2286. "x4",
  2287. "x5",
  2288. };
  2289. constraints = gb_string_appendc(constraints, regs[i]);
  2290. constraints = gb_string_appendc(constraints, "}");
  2291. }
  2292. inline_asm = llvm_get_inline_asm(func_type, make_string_c(asm_string), make_string_c(constraints));
  2293. } else {
  2294. char asm_string[] = "svc #0";
  2295. gbString constraints = gb_string_make(heap_allocator(), "={x0}");
  2296. for (unsigned i = 0; i < arg_count; i++) {
  2297. constraints = gb_string_appendc(constraints, ",{");
  2298. static char const *regs[] = {
  2299. "x8",
  2300. "x0",
  2301. "x1",
  2302. "x2",
  2303. "x3",
  2304. "x4",
  2305. "x5",
  2306. };
  2307. constraints = gb_string_appendc(constraints, regs[i]);
  2308. constraints = gb_string_appendc(constraints, "}");
  2309. }
  2310. inline_asm = llvm_get_inline_asm(func_type, make_string_c(asm_string), make_string_c(constraints));
  2311. }
  2312. }
  2313. break;
  2314. case TargetArch_arm32:
  2315. {
  2316. // TODO(bill): Check this is correct
  2317. GB_ASSERT(arg_count <= 7);
  2318. char asm_string[] = "svc #0";
  2319. gbString constraints = gb_string_make(heap_allocator(), "={r0}");
  2320. for (unsigned i = 0; i < arg_count; i++) {
  2321. constraints = gb_string_appendc(constraints, ",{");
  2322. static char const *regs[] = {
  2323. "r8",
  2324. "r0",
  2325. "r1",
  2326. "r2",
  2327. "r3",
  2328. "r4",
  2329. "r5",
  2330. };
  2331. constraints = gb_string_appendc(constraints, regs[i]);
  2332. constraints = gb_string_appendc(constraints, "}");
  2333. }
  2334. inline_asm = llvm_get_inline_asm(func_type, make_string_c(asm_string), make_string_c(constraints));
  2335. }
  2336. break;
  2337. default:
  2338. GB_PANIC("Unsupported platform");
  2339. }
  2340. lbValue res = {};
  2341. res.value = LLVMBuildCall2(p->builder, func_type, inline_asm, args, arg_count, "");
  2342. res.type = t_uintptr;
  2343. return res;
  2344. }
  2345. case BuiltinProc_objc_send:
  2346. return lb_handle_objc_send(p, expr);
  2347. case BuiltinProc_objc_find_selector: return lb_handle_objc_find_selector(p, expr);
  2348. case BuiltinProc_objc_find_class: return lb_handle_objc_find_class(p, expr);
  2349. case BuiltinProc_objc_register_selector: return lb_handle_objc_register_selector(p, expr);
  2350. case BuiltinProc_objc_register_class: return lb_handle_objc_register_class(p, expr);
  2351. case BuiltinProc_constant_utf16_cstring:
  2352. {
  2353. auto const encode_surrogate_pair = [](Rune r, u16 *r1, u16 *r2) {
  2354. if (r < 0x10000 || r > 0x10ffff) {
  2355. *r1 = 0xfffd;
  2356. *r2 = 0xfffd;
  2357. } else {
  2358. r -= 0x10000;
  2359. *r1 = 0xd800 + ((r>>10)&0x3ff);
  2360. *r2 = 0xdc00 + (r&0x3ff);
  2361. }
  2362. };
  2363. lbModule *m = p->module;
  2364. auto tav = type_and_value_of_expr(ce->args[0]);
  2365. GB_ASSERT(tav.value.kind == ExactValue_String);
  2366. String value = tav.value.value_string;
  2367. LLVMTypeRef llvm_u16 = lb_type(m, t_u16);
  2368. isize max_len = value.len*2 + 1;
  2369. LLVMValueRef *buffer = gb_alloc_array(temporary_allocator(), LLVMValueRef, max_len);
  2370. isize n = 0;
  2371. while (value.len > 0) {
  2372. Rune r = 0;
  2373. isize w = gb_utf8_decode(value.text, value.len, &r);
  2374. value.text += w;
  2375. value.len -= w;
  2376. if ((0 <= r && r < 0xd800) || (0xe000 <= r && r < 0x10000)) {
  2377. buffer[n++] = LLVMConstInt(llvm_u16, cast(u16)r, false);
  2378. } else if (0x10000 <= r && r <= 0x10ffff) {
  2379. u16 r1, r2;
  2380. encode_surrogate_pair(r, &r1, &r2);
  2381. buffer[n++] = LLVMConstInt(llvm_u16, r1, false);
  2382. buffer[n++] = LLVMConstInt(llvm_u16, r2, false);
  2383. } else {
  2384. buffer[n++] = LLVMConstInt(llvm_u16, 0xfffd, false);
  2385. }
  2386. }
  2387. buffer[n++] = LLVMConstInt(llvm_u16, 0, false);
  2388. LLVMValueRef array = LLVMConstArray(llvm_u16, buffer, cast(unsigned int)n);
  2389. char *name = nullptr;
  2390. {
  2391. isize max_len = 7+8+1;
  2392. name = gb_alloc_array(permanent_allocator(), char, max_len);
  2393. u32 id = m->gen->global_array_index.fetch_add(1);
  2394. isize len = gb_snprintf(name, max_len, "csbs$%x", id);
  2395. len -= 1;
  2396. }
  2397. LLVMTypeRef type = LLVMTypeOf(array);
  2398. LLVMValueRef global_data = LLVMAddGlobal(m->mod, type, name);
  2399. LLVMSetInitializer(global_data, array);
  2400. LLVMSetLinkage(global_data, LLVMInternalLinkage);
  2401. LLVMValueRef indices[] = {
  2402. LLVMConstInt(lb_type(m, t_u32), 0, false),
  2403. LLVMConstInt(lb_type(m, t_u32), 0, false),
  2404. };
  2405. lbValue res = {};
  2406. res.type = tv.type;
  2407. res.value = LLVMBuildInBoundsGEP2(p->builder, type, global_data, indices, gb_count_of(indices), "");
  2408. return res;
  2409. }
  2410. case BuiltinProc_wasm_memory_grow:
  2411. {
  2412. char const *name = "llvm.wasm.memory.grow";
  2413. LLVMTypeRef types[1] = {
  2414. lb_type(p->module, t_uintptr),
  2415. };
  2416. LLVMValueRef args[2] = {};
  2417. args[0] = lb_emit_conv(p, lb_build_expr(p, ce->args[0]), t_uintptr).value;
  2418. args[1] = lb_emit_conv(p, lb_build_expr(p, ce->args[1]), t_uintptr).value;
  2419. lbValue res = {};
  2420. res.type = tv.type;
  2421. res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
  2422. return res;
  2423. }
  2424. case BuiltinProc_wasm_memory_size:
  2425. {
  2426. char const *name = "llvm.wasm.memory.size";
  2427. LLVMTypeRef types[1] = {
  2428. lb_type(p->module, t_uintptr),
  2429. };
  2430. LLVMValueRef args[1] = {};
  2431. args[0] = lb_emit_conv(p, lb_build_expr(p, ce->args[0]), t_uintptr).value;
  2432. lbValue res = {};
  2433. res.type = tv.type;
  2434. res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
  2435. return res;
  2436. }
  2437. case BuiltinProc_wasm_memory_atomic_wait32:
  2438. {
  2439. char const *name = "llvm.wasm.memory.atomic.wait32";
  2440. LLVMTypeRef types[1] = {
  2441. lb_type(p->module, t_u32),
  2442. };
  2443. Type *t_u32_ptr = alloc_type_pointer(t_u32);
  2444. LLVMValueRef args[3] = {};
  2445. args[0] = lb_emit_conv(p, lb_build_expr(p, ce->args[0]), t_u32_ptr).value;
  2446. args[1] = lb_emit_conv(p, lb_build_expr(p, ce->args[1]), t_u32).value;
  2447. args[2] = lb_emit_conv(p, lb_build_expr(p, ce->args[2]), t_i64).value;
  2448. lbValue res = {};
  2449. res.type = tv.type;
  2450. res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
  2451. return res;
  2452. }
  2453. case BuiltinProc_wasm_memory_atomic_notify32:
  2454. {
  2455. char const *name = "llvm.wasm.memory.atomic.notify";
  2456. LLVMTypeRef types[1] = {
  2457. lb_type(p->module, t_u32),
  2458. };
  2459. Type *t_u32_ptr = alloc_type_pointer(t_u32);
  2460. LLVMValueRef args[2] = {
  2461. lb_emit_conv(p, lb_build_expr(p, ce->args[0]), t_u32_ptr).value,
  2462. lb_emit_conv(p, lb_build_expr(p, ce->args[1]), t_u32).value };
  2463. lbValue res = {};
  2464. res.type = tv.type;
  2465. res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
  2466. return res;
  2467. }
  2468. case BuiltinProc_x86_cpuid:
  2469. {
  2470. Type *param_types[2] = {t_u32, t_u32};
  2471. Type *type = alloc_type_proc_from_types(param_types, gb_count_of(param_types), tv.type, false, ProcCC_None);
  2472. LLVMTypeRef func_type = lb_get_procedure_raw_type(p->module, type);
  2473. LLVMValueRef the_asm = llvm_get_inline_asm(
  2474. func_type,
  2475. str_lit("cpuid"),
  2476. str_lit("={ax},={bx},={cx},={dx},{ax},{cx}"),
  2477. true
  2478. );
  2479. GB_ASSERT(the_asm != nullptr);
  2480. LLVMValueRef args[2] = {};
  2481. args[0] = lb_emit_conv(p, lb_build_expr(p, ce->args[0]), t_u32).value;
  2482. args[1] = lb_emit_conv(p, lb_build_expr(p, ce->args[1]), t_u32).value;
  2483. lbValue res = {};
  2484. res.type = tv.type;
  2485. res.value = LLVMBuildCall2(p->builder, func_type, the_asm, args, gb_count_of(args), "");
  2486. return res;
  2487. }
  2488. case BuiltinProc_x86_xgetbv:
  2489. {
  2490. Type *type = alloc_type_proc_from_types(&t_u32, 1, tv.type, false, ProcCC_None);
  2491. LLVMTypeRef func_type = lb_get_procedure_raw_type(p->module, type);
  2492. LLVMValueRef the_asm = llvm_get_inline_asm(
  2493. func_type,
  2494. str_lit("xgetbv"),
  2495. str_lit("={ax},={dx},{cx}"),
  2496. true
  2497. );
  2498. GB_ASSERT(the_asm != nullptr);
  2499. LLVMValueRef args[1] = {};
  2500. args[0] = lb_emit_conv(p, lb_build_expr(p, ce->args[0]), t_u32).value;
  2501. lbValue res = {};
  2502. res.type = tv.type;
  2503. res.value = LLVMBuildCall2(p->builder, func_type, the_asm, args, gb_count_of(args), "");
  2504. return res;
  2505. }
  2506. case BuiltinProc_valgrind_client_request:
  2507. {
  2508. lbValue args[7] = {};
  2509. for (isize i = 0; i < 7; i++) {
  2510. args[i] = lb_emit_conv(p, lb_build_expr(p, ce->args[i]), t_uintptr);
  2511. }
  2512. if (!build_context.ODIN_VALGRIND_SUPPORT) {
  2513. return args[0];
  2514. }
  2515. lbValue array = lb_generate_local_array(p, t_uintptr, 6, false);
  2516. for (isize i = 0; i < 6; i++) {
  2517. lbValue gep = lb_emit_array_epi(p, array, i);
  2518. lb_emit_store(p, gep, args[i+1]);
  2519. }
  2520. switch (build_context.metrics.arch) {
  2521. case TargetArch_amd64:
  2522. {
  2523. Type *param_types[2] = {};
  2524. param_types[0] = t_uintptr;
  2525. param_types[1] = array.type;
  2526. Type *type = alloc_type_proc_from_types(param_types, gb_count_of(param_types), t_uintptr, false, ProcCC_None);
  2527. LLVMTypeRef func_type = lb_get_procedure_raw_type(p->module, type);
  2528. LLVMValueRef the_asm = llvm_get_inline_asm(
  2529. func_type,
  2530. str_lit("rolq $3, %rdi; rolq $13, %rdi\n rolq $61, %rdi; rolq $51, %rdi\n xchgq %rbx, %rbx"),
  2531. str_lit("={rdx},{rdx},{rax},cc,memory"),
  2532. true
  2533. );
  2534. LLVMValueRef asm_args[2] = {};
  2535. asm_args[0] = args[0].value;
  2536. asm_args[1] = array.value;
  2537. lbValue res = {};
  2538. res.type = t_uintptr;
  2539. res.value = LLVMBuildCall2(p->builder, func_type, the_asm, asm_args, gb_count_of(asm_args), "");
  2540. return res;
  2541. }
  2542. break;
  2543. default:
  2544. GB_PANIC("Unsupported architecture: %.*s", LIT(target_arch_names[build_context.metrics.arch]));
  2545. break;
  2546. }
  2547. }
  2548. }
  2549. GB_PANIC("Unhandled built-in procedure %.*s", LIT(builtin_procs[id].name));
  2550. return {};
  2551. }
  2552. lbValue lb_handle_param_value(lbProcedure *p, Type *parameter_type, ParameterValue const &param_value, TokenPos const &pos) {
  2553. switch (param_value.kind) {
  2554. case ParameterValue_Constant:
  2555. if (is_type_constant_type(parameter_type)) {
  2556. auto res = lb_const_value(p->module, parameter_type, param_value.value);
  2557. return res;
  2558. } else {
  2559. ExactValue ev = param_value.value;
  2560. lbValue arg = {};
  2561. Type *type = type_of_expr(param_value.original_ast_expr);
  2562. if (type != nullptr) {
  2563. arg = lb_const_value(p->module, type, ev);
  2564. } else {
  2565. arg = lb_const_value(p->module, parameter_type, param_value.value);
  2566. }
  2567. return lb_emit_conv(p, arg, parameter_type);
  2568. }
  2569. case ParameterValue_Nil:
  2570. return lb_const_nil(p->module, parameter_type);
  2571. case ParameterValue_Location:
  2572. {
  2573. String proc_name = {};
  2574. if (p->entity != nullptr) {
  2575. proc_name = p->entity->token.string;
  2576. }
  2577. return lb_emit_source_code_location_as_global(p, proc_name, pos);
  2578. }
  2579. case ParameterValue_Value:
  2580. return lb_build_expr(p, param_value.ast_value);
  2581. }
  2582. return lb_const_nil(p->module, parameter_type);
  2583. }
  2584. lbValue lb_build_call_expr_internal(lbProcedure *p, Ast *expr);
  2585. lbValue lb_build_call_expr(lbProcedure *p, Ast *expr) {
  2586. expr = unparen_expr(expr);
  2587. ast_node(ce, CallExpr, expr);
  2588. lbValue res = lb_build_call_expr_internal(p, expr);
  2589. if (ce->optional_ok_one) { // TODO(bill): Minor hack for #optional_ok procedures
  2590. GB_ASSERT(is_type_tuple(res.type));
  2591. GB_ASSERT(res.type->Tuple.variables.count == 2);
  2592. return lb_emit_struct_ev(p, res, 0);
  2593. }
  2594. return res;
  2595. }
  2596. lbValue lb_build_call_expr_internal(lbProcedure *p, Ast *expr) {
  2597. lbModule *m = p->module;
  2598. TypeAndValue tv = type_and_value_of_expr(expr);
  2599. ast_node(ce, CallExpr, expr);
  2600. TypeAndValue proc_tv = type_and_value_of_expr(ce->proc);
  2601. AddressingMode proc_mode = proc_tv.mode;
  2602. if (proc_mode == Addressing_Type) {
  2603. GB_ASSERT(ce->args.count == 1);
  2604. lbValue x = lb_build_expr(p, ce->args[0]);
  2605. lbValue y = lb_emit_conv(p, x, tv.type);
  2606. return y;
  2607. }
  2608. Ast *proc_expr = unparen_expr(ce->proc);
  2609. if (proc_mode == Addressing_Builtin) {
  2610. Entity *e = entity_of_node(proc_expr);
  2611. BuiltinProcId id = BuiltinProc_Invalid;
  2612. if (e != nullptr) {
  2613. id = cast(BuiltinProcId)e->Builtin.id;
  2614. } else {
  2615. id = BuiltinProc_DIRECTIVE;
  2616. }
  2617. return lb_build_builtin_proc(p, expr, tv, id);
  2618. }
  2619. // NOTE(bill): Regular call
  2620. lbValue value = {};
  2621. Entity *proc_entity = entity_of_node(proc_expr);
  2622. if (proc_entity != nullptr) {
  2623. if (proc_entity->flags & EntityFlag_Disabled) {
  2624. GB_ASSERT(tv.type == nullptr);
  2625. return {};
  2626. }
  2627. }
  2628. if (proc_expr->tav.mode == Addressing_Constant) {
  2629. ExactValue v = proc_expr->tav.value;
  2630. switch (v.kind) {
  2631. case ExactValue_Integer:
  2632. {
  2633. u64 u = big_int_to_u64(&v.value_integer);
  2634. lbValue x = {};
  2635. x.value = LLVMConstInt(lb_type(m, t_uintptr), u, false);
  2636. x.type = t_uintptr;
  2637. x = lb_emit_conv(p, x, t_rawptr);
  2638. value = lb_emit_conv(p, x, proc_expr->tav.type);
  2639. break;
  2640. }
  2641. case ExactValue_Pointer:
  2642. {
  2643. u64 u = cast(u64)v.value_pointer;
  2644. lbValue x = {};
  2645. x.value = LLVMConstInt(lb_type(m, t_uintptr), u, false);
  2646. x.type = t_uintptr;
  2647. x = lb_emit_conv(p, x, t_rawptr);
  2648. value = lb_emit_conv(p, x, proc_expr->tav.type);
  2649. break;
  2650. }
  2651. }
  2652. }
  2653. if (value.value == nullptr) {
  2654. value = lb_build_expr(p, proc_expr);
  2655. }
  2656. GB_ASSERT(value.value != nullptr);
  2657. Type *proc_type_ = base_type(value.type);
  2658. GB_ASSERT(proc_type_->kind == Type_Proc);
  2659. TypeProc *pt = &proc_type_->Proc;
  2660. if (is_call_expr_field_value(ce)) {
  2661. auto args = array_make<lbValue>(permanent_allocator(), pt->param_count);
  2662. for_array(arg_index, ce->args) {
  2663. Ast *arg = ce->args[arg_index];
  2664. ast_node(fv, FieldValue, arg);
  2665. GB_ASSERT(fv->field->kind == Ast_Ident);
  2666. String name = fv->field->Ident.token.string;
  2667. isize index = lookup_procedure_parameter(pt, name);
  2668. GB_ASSERT(index >= 0);
  2669. TypeAndValue tav = type_and_value_of_expr(fv->value);
  2670. if (tav.mode == Addressing_Type) {
  2671. args[index] = lb_const_nil(m, tav.type);
  2672. } else {
  2673. args[index] = lb_build_expr(p, fv->value);
  2674. }
  2675. }
  2676. TypeTuple *params = &pt->params->Tuple;
  2677. for (isize i = 0; i < args.count; i++) {
  2678. Entity *e = params->variables[i];
  2679. if (e->kind == Entity_TypeName) {
  2680. args[i] = lb_const_nil(m, e->type);
  2681. } else if (e->kind == Entity_Constant) {
  2682. continue;
  2683. } else {
  2684. GB_ASSERT(e->kind == Entity_Variable);
  2685. if (args[i].value == nullptr) {
  2686. args[i] = lb_handle_param_value(p, e->type, e->Variable.param_value, ast_token(expr).pos);
  2687. } else {
  2688. args[i] = lb_emit_conv(p, args[i], e->type);
  2689. }
  2690. }
  2691. }
  2692. for (isize i = 0; i < args.count; i++) {
  2693. Entity *e = params->variables[i];
  2694. if (args[i].type == nullptr) {
  2695. continue;
  2696. } else if (is_type_untyped_nil(args[i].type)) {
  2697. args[i] = lb_const_nil(m, e->type);
  2698. } else if (is_type_untyped_undef(args[i].type)) {
  2699. args[i] = lb_const_undef(m, e->type);
  2700. }
  2701. }
  2702. return lb_emit_call(p, value, args, ce->inlining);
  2703. }
  2704. isize arg_index = 0;
  2705. isize arg_count = 0;
  2706. for_array(i, ce->args) {
  2707. Ast *arg = ce->args[i];
  2708. TypeAndValue tav = type_and_value_of_expr(arg);
  2709. GB_ASSERT_MSG(tav.mode != Addressing_Invalid, "%s %s %d", expr_to_string(arg), expr_to_string(expr), tav.mode);
  2710. GB_ASSERT_MSG(tav.mode != Addressing_ProcGroup, "%s", expr_to_string(arg));
  2711. Type *at = tav.type;
  2712. if (is_type_tuple(at)) {
  2713. arg_count += at->Tuple.variables.count;
  2714. } else {
  2715. arg_count++;
  2716. }
  2717. }
  2718. isize param_count = 0;
  2719. if (pt->params) {
  2720. GB_ASSERT(pt->params->kind == Type_Tuple);
  2721. param_count = pt->params->Tuple.variables.count;
  2722. }
  2723. auto args = array_make<lbValue>(permanent_allocator(), cast(isize)gb_max(param_count, arg_count));
  2724. isize variadic_index = pt->variadic_index;
  2725. bool variadic = pt->variadic && variadic_index >= 0;
  2726. bool vari_expand = ce->ellipsis.pos.line != 0;
  2727. bool is_c_vararg = pt->c_vararg;
  2728. String proc_name = {};
  2729. if (p->entity != nullptr) {
  2730. proc_name = p->entity->token.string;
  2731. }
  2732. TokenPos pos = ast_token(ce->proc).pos;
  2733. TypeTuple *param_tuple = nullptr;
  2734. if (pt->params) {
  2735. GB_ASSERT(pt->params->kind == Type_Tuple);
  2736. param_tuple = &pt->params->Tuple;
  2737. }
  2738. for_array(i, ce->args) {
  2739. Ast *arg = ce->args[i];
  2740. TypeAndValue arg_tv = type_and_value_of_expr(arg);
  2741. if (arg_tv.mode == Addressing_Type) {
  2742. args[arg_index++] = lb_const_nil(m, arg_tv.type);
  2743. } else {
  2744. lbValue a = lb_build_expr(p, arg);
  2745. Type *at = a.type;
  2746. if (at->kind == Type_Tuple) {
  2747. lbTupleFix *tf = map_get(&p->tuple_fix_map, a.value);
  2748. if (tf) {
  2749. for_array(j, tf->values) {
  2750. args[arg_index++] = tf->values[j];
  2751. }
  2752. } else {
  2753. for_array(j, at->Tuple.variables) {
  2754. lbValue v = lb_emit_struct_ev(p, a, cast(i32)j);
  2755. args[arg_index++] = v;
  2756. }
  2757. }
  2758. } else {
  2759. args[arg_index++] = a;
  2760. }
  2761. }
  2762. }
  2763. if (param_count > 0) {
  2764. GB_ASSERT_MSG(pt->params != nullptr, "%s %td", expr_to_string(expr), pt->param_count);
  2765. GB_ASSERT(param_count < 1000000);
  2766. if (arg_count < param_count) {
  2767. isize end = cast(isize)param_count;
  2768. if (variadic) {
  2769. end = variadic_index;
  2770. }
  2771. while (arg_index < end) {
  2772. Entity *e = param_tuple->variables[arg_index];
  2773. GB_ASSERT(e->kind == Entity_Variable);
  2774. args[arg_index++] = lb_handle_param_value(p, e->type, e->Variable.param_value, ast_token(expr).pos);
  2775. }
  2776. }
  2777. if (is_c_vararg) {
  2778. GB_ASSERT(variadic);
  2779. GB_ASSERT(!vari_expand);
  2780. isize i = 0;
  2781. for (; i < variadic_index; i++) {
  2782. Entity *e = param_tuple->variables[i];
  2783. if (e->kind == Entity_Variable) {
  2784. args[i] = lb_emit_conv(p, args[i], e->type);
  2785. }
  2786. }
  2787. Type *variadic_type = param_tuple->variables[i]->type;
  2788. GB_ASSERT(is_type_slice(variadic_type));
  2789. variadic_type = base_type(variadic_type)->Slice.elem;
  2790. if (!is_type_any(variadic_type)) {
  2791. for (; i < arg_count; i++) {
  2792. args[i] = lb_emit_conv(p, args[i], variadic_type);
  2793. }
  2794. } else {
  2795. for (; i < arg_count; i++) {
  2796. args[i] = lb_emit_conv(p, args[i], default_type(args[i].type));
  2797. }
  2798. }
  2799. } else if (variadic) {
  2800. isize i = 0;
  2801. for (; i < variadic_index; i++) {
  2802. Entity *e = param_tuple->variables[i];
  2803. if (e->kind == Entity_Variable) {
  2804. args[i] = lb_emit_conv(p, args[i], e->type);
  2805. }
  2806. }
  2807. if (!vari_expand) {
  2808. Type *variadic_type = param_tuple->variables[i]->type;
  2809. GB_ASSERT(is_type_slice(variadic_type));
  2810. variadic_type = base_type(variadic_type)->Slice.elem;
  2811. for (; i < arg_count; i++) {
  2812. args[i] = lb_emit_conv(p, args[i], variadic_type);
  2813. }
  2814. }
  2815. } else {
  2816. for (isize i = 0; i < param_count; i++) {
  2817. Entity *e = param_tuple->variables[i];
  2818. if (e->kind == Entity_Variable) {
  2819. if (args[i].value == nullptr) {
  2820. continue;
  2821. }
  2822. GB_ASSERT_MSG(args[i].value != nullptr, "%.*s", LIT(e->token.string));
  2823. args[i] = lb_emit_conv(p, args[i], e->type);
  2824. }
  2825. }
  2826. }
  2827. if (variadic && !vari_expand && !is_c_vararg) {
  2828. // variadic call argument generation
  2829. Type *slice_type = param_tuple->variables[variadic_index]->type;
  2830. Type *elem_type = base_type(slice_type)->Slice.elem;
  2831. lbAddr slice = lb_add_local_generated(p, slice_type, true);
  2832. isize slice_len = arg_count+1 - (variadic_index+1);
  2833. if (slice_len > 0) {
  2834. lbAddr base_array = lb_add_local_generated(p, alloc_type_array(elem_type, slice_len), true);
  2835. for (isize i = variadic_index, j = 0; i < arg_count; i++, j++) {
  2836. lbValue addr = lb_emit_array_epi(p, base_array.addr, cast(i32)j);
  2837. lb_emit_store(p, addr, args[i]);
  2838. }
  2839. lbValue base_elem = lb_emit_array_epi(p, base_array.addr, 0);
  2840. lbValue len = lb_const_int(m, t_int, slice_len);
  2841. lb_fill_slice(p, slice, base_elem, len);
  2842. }
  2843. arg_count = param_count;
  2844. args[variadic_index] = lb_addr_load(p, slice);
  2845. }
  2846. }
  2847. if (variadic && variadic_index+1 < param_count) {
  2848. for (isize i = variadic_index+1; i < param_count; i++) {
  2849. Entity *e = param_tuple->variables[i];
  2850. args[i] = lb_handle_param_value(p, e->type, e->Variable.param_value, ast_token(expr).pos);
  2851. }
  2852. }
  2853. isize final_count = param_count;
  2854. if (is_c_vararg) {
  2855. final_count = arg_count;
  2856. }
  2857. if (param_tuple != nullptr) {
  2858. for (isize i = 0; i < gb_min(args.count, param_tuple->variables.count); i++) {
  2859. Entity *e = param_tuple->variables[i];
  2860. if (args[i].type == nullptr) {
  2861. continue;
  2862. } else if (is_type_untyped_nil(args[i].type)) {
  2863. args[i] = lb_const_nil(m, e->type);
  2864. } else if (is_type_untyped_undef(args[i].type)) {
  2865. args[i] = lb_const_undef(m, e->type);
  2866. }
  2867. }
  2868. }
  2869. auto call_args = array_slice(args, 0, final_count);
  2870. return lb_emit_call(p, value, call_args, ce->inlining);
  2871. }