codegen.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689
  1. #include "ssa.cpp"
  2. #include "print_llvm.cpp"
  3. struct ssaGen {
  4. ssaModule module;
  5. gbFile output_file;
  6. };
  7. b32 ssa_gen_init(ssaGen *s, Checker *c) {
  8. if (global_error_collector.count != 0)
  9. return false;
  10. isize tc = c->parser->total_token_count;
  11. if (tc < 2) {
  12. return false;
  13. }
  14. ssa_init_module(&s->module, c);
  15. s->module.generate_debug_info = false;
  16. // TODO(bill): generate appropriate output name
  17. int pos = cast(int)string_extension_position(c->parser->init_fullpath);
  18. gbFileError err = gb_file_create(&s->output_file, gb_bprintf("%.*s.ll", pos, c->parser->init_fullpath.text));
  19. if (err != gbFileError_None) {
  20. return false;
  21. }
  22. return true;
  23. }
  24. void ssa_gen_destroy(ssaGen *s) {
  25. ssa_destroy_module(&s->module);
  26. gb_file_close(&s->output_file);
  27. }
  28. String ssa_mangle_name(ssaGen *s, String path, String name) {
  29. // NOTE(bill): prefix names not in the init scope
  30. // TODO(bill): make robust and not just rely on the file's name
  31. ssaModule *m = &s->module;
  32. CheckerInfo *info = m->info;
  33. gbAllocator a = m->allocator;
  34. AstFile *file = *map_get(&info->files, hash_string(path));
  35. char *str = gb_alloc_array(a, char, path.len+1);
  36. gb_memcopy(str, path.text, path.len);
  37. str[path.len] = 0;
  38. for (isize i = 0; i < path.len; i++) {
  39. if (str[i] == '\\') {
  40. str[i] = '/';
  41. }
  42. }
  43. char const *base = gb_path_base_name(str);
  44. char const *ext = gb_path_extension(base);
  45. isize base_len = ext-1-base;
  46. isize max_len = base_len + 1 + 10 + 1 + name.len;
  47. u8 *new_name = gb_alloc_array(a, u8, max_len);
  48. isize new_name_len = gb_snprintf(
  49. cast(char *)new_name, max_len,
  50. "%.*s-%u.%.*s",
  51. cast(int)base_len, base,
  52. file->id,
  53. LIT(name));
  54. return make_string(new_name, new_name_len-1);
  55. }
  56. void ssa_gen_tree(ssaGen *s) {
  57. ssaModule *m = &s->module;
  58. CheckerInfo *info = m->info;
  59. gbAllocator a = m->allocator;
  60. if (v_zero == NULL) {
  61. v_zero = ssa_make_const_int (m->allocator, 0);
  62. v_one = ssa_make_const_int (m->allocator, 1);
  63. v_zero32 = ssa_make_const_i32 (m->allocator, 0);
  64. v_one32 = ssa_make_const_i32 (m->allocator, 1);
  65. v_two32 = ssa_make_const_i32 (m->allocator, 2);
  66. v_false = ssa_make_const_bool(m->allocator, false);
  67. v_true = ssa_make_const_bool(m->allocator, true);
  68. }
  69. isize global_variable_max_count = 0;
  70. Entity *entry_point = NULL;
  71. for_array(i, info->entities.entries) {
  72. auto *entry = &info->entities.entries[i];
  73. Entity *e = cast(Entity *)cast(uintptr)entry->key.key;
  74. String name = e->token.string;
  75. if (e->kind == Entity_Variable) {
  76. global_variable_max_count++;
  77. } else if (e->kind == Entity_Procedure) {
  78. if (e->scope->is_init && name == "main") {
  79. entry_point = e;
  80. }
  81. }
  82. }
  83. struct ssaGlobalVariable {
  84. ssaValue *var, *init;
  85. DeclInfo *decl;
  86. };
  87. Array<ssaGlobalVariable> global_variables;
  88. array_init(&global_variables, m->tmp_allocator, global_variable_max_count);
  89. auto min_dep_map = generate_minimum_dependency_map(info, entry_point);
  90. defer (map_destroy(&min_dep_map));
  91. for_array(i, info->entities.entries) {
  92. auto *entry = &info->entities.entries[i];
  93. Entity *e = cast(Entity *)cast(uintptr)entry->key.key;
  94. String name = e->token.string;
  95. DeclInfo *decl = entry->value;
  96. Scope *scope = e->scope;
  97. if (!scope->is_file) {
  98. continue;
  99. }
  100. if (map_get(&min_dep_map, hash_pointer(e)) == NULL) {
  101. // NOTE(bill): Nothing depends upon it so doesn't need to be built
  102. continue;
  103. }
  104. if (!scope->is_global && !scope->is_init) {
  105. name = ssa_mangle_name(s, e->token.pos.file, name);
  106. }
  107. switch (e->kind) {
  108. case Entity_TypeName:
  109. GB_ASSERT(e->type->kind == Type_Named);
  110. map_set(&m->type_names, hash_pointer(e->type), name);
  111. ssa_gen_global_type_name(m, e, name);
  112. break;
  113. case Entity_Variable: {
  114. ssaValue *g = ssa_make_value_global(a, e, NULL);
  115. if (decl->var_decl_tags & VarDeclTag_thread_local) {
  116. g->Global.is_thread_local = true;
  117. }
  118. ssaGlobalVariable var = {};
  119. var.var = g;
  120. var.decl = decl;
  121. if (decl->init_expr != NULL) {
  122. TypeAndValue *tav = map_get(&info->types, hash_pointer(decl->init_expr));
  123. if (tav != NULL) {
  124. if (tav->value.kind != ExactValue_Invalid) {
  125. ExactValue v = tav->value;
  126. if (v.kind != ExactValue_String) {
  127. g->Global.value = ssa_add_module_constant(m, tav->type, v);
  128. }
  129. }
  130. }
  131. }
  132. if (g->Global.value == NULL) {
  133. array_add(&global_variables, var);
  134. }
  135. map_set(&m->values, hash_pointer(e), g);
  136. map_set(&m->members, hash_string(name), g);
  137. } break;
  138. case Entity_Procedure: {
  139. auto *pd = &decl->proc_decl->ProcDecl;
  140. String original_name = name;
  141. AstNode *body = pd->body;
  142. if (pd->tags & ProcTag_foreign) {
  143. name = pd->name->Ident.string;
  144. }
  145. if (pd->foreign_name.len > 0) {
  146. name = pd->foreign_name;
  147. } else if (pd->link_name.len > 0) {
  148. name = pd->link_name;
  149. }
  150. ssaValue *p = ssa_make_value_procedure(a, m, e, e->type, decl->type_expr, body, name);
  151. p->Proc.tags = pd->tags;
  152. map_set(&m->values, hash_pointer(e), p);
  153. HashKey hash_name = hash_string(name);
  154. if (map_get(&m->members, hash_name) == NULL) {
  155. map_set(&m->members, hash_name, p);
  156. }
  157. } break;
  158. }
  159. }
  160. for_array(i, m->members.entries) {
  161. auto *entry = &m->members.entries[i];
  162. ssaValue *v = entry->value;
  163. if (v->kind == ssaValue_Proc)
  164. ssa_build_proc(v, NULL);
  165. }
  166. ssaDebugInfo *compile_unit = m->debug_info.entries[0].value;
  167. GB_ASSERT(compile_unit->kind == ssaDebugInfo_CompileUnit);
  168. ssaDebugInfo *all_procs = ssa_alloc_debug_info(m->allocator, ssaDebugInfo_AllProcs);
  169. isize all_proc_max_count = 0;
  170. for_array(i, m->debug_info.entries) {
  171. auto *entry = &m->debug_info.entries[i];
  172. ssaDebugInfo *di = entry->value;
  173. di->id = i;
  174. if (di->kind == ssaDebugInfo_Proc) {
  175. all_proc_max_count++;
  176. }
  177. }
  178. array_init(&all_procs->AllProcs.procs, m->allocator, all_proc_max_count);
  179. map_set(&m->debug_info, hash_pointer(all_procs), all_procs); // NOTE(bill): This doesn't need to be mapped
  180. compile_unit->CompileUnit.all_procs = all_procs;
  181. for_array(i, m->debug_info.entries) {
  182. auto *entry = &m->debug_info.entries[i];
  183. ssaDebugInfo *di = entry->value;
  184. di->id = i;
  185. if (di->kind == ssaDebugInfo_Proc) {
  186. array_add(&all_procs->AllProcs.procs, di);
  187. }
  188. }
  189. { // Startup Runtime
  190. // Cleanup(bill): probably better way of doing code insertion
  191. String name = make_string(SSA_STARTUP_RUNTIME_PROC_NAME);
  192. Type *proc_type = make_type_proc(a, gb_alloc_item(a, Scope),
  193. NULL, 0,
  194. NULL, 0, false);
  195. AstNode *body = gb_alloc_item(a, AstNode);
  196. ssaValue *p = ssa_make_value_procedure(a, m, NULL, proc_type, NULL, body, name);
  197. Token token = {};
  198. token.string = name;
  199. Entity *e = make_entity_procedure(a, NULL, token, proc_type);
  200. map_set(&m->values, hash_pointer(e), p);
  201. map_set(&m->members, hash_string(name), p);
  202. ssaProcedure *proc = &p->Proc;
  203. proc->tags = ProcTag_no_inline; // TODO(bill): is no_inline a good idea?
  204. ssa_begin_procedure_body(proc);
  205. // TODO(bill): Should do a dependency graph do check which order to initialize them in?
  206. for_array(i, global_variables) {
  207. ssaGlobalVariable *var = &global_variables[i];
  208. if (var->decl->init_expr != NULL) {
  209. var->init = ssa_build_expr(proc, var->decl->init_expr);
  210. }
  211. }
  212. // NOTE(bill): Initialize constants first
  213. for_array(i, global_variables) {
  214. ssaGlobalVariable *var = &global_variables[i];
  215. if (var->init != NULL) {
  216. if (var->init->kind == ssaValue_Constant) {
  217. ssa_emit_store(proc, var->var, var->init);
  218. }
  219. }
  220. }
  221. for_array(i, global_variables) {
  222. ssaGlobalVariable *var = &global_variables[i];
  223. if (var->init != NULL) {
  224. if (var->init->kind != ssaValue_Constant) {
  225. ssa_emit_store(proc, var->var, var->init);
  226. }
  227. }
  228. }
  229. { // NOTE(bill): Setup type_info data
  230. // TODO(bill): Try and make a lot of this constant aggregate literals in LLVM IR
  231. ssaValue *type_info_data = NULL;
  232. ssaValue *type_info_member_data = NULL;
  233. ssaValue **found = NULL;
  234. found = map_get(&proc->module->members, hash_string(make_string(SSA_TYPE_INFO_DATA_NAME)));
  235. GB_ASSERT(found != NULL);
  236. type_info_data = *found;
  237. found = map_get(&proc->module->members, hash_string(make_string(SSA_TYPE_INFO_DATA_MEMBER_NAME)));
  238. GB_ASSERT(found != NULL);
  239. type_info_member_data = *found;
  240. CheckerInfo *info = proc->module->info;
  241. // Useful types
  242. Type *t_int_ptr = make_type_pointer(a, t_int);
  243. Type *t_i64_ptr = make_type_pointer(a, t_i64);
  244. Type *t_bool_ptr = make_type_pointer(a, t_bool);
  245. Type *t_string_ptr = make_type_pointer(a, t_string);
  246. Type *t_type_info_ptr_ptr = make_type_pointer(a, t_type_info_ptr);
  247. Type *t_i64_slice_ptr = make_type_pointer(a, make_type_slice(a, t_i64));
  248. Type *t_string_slice_ptr = make_type_pointer(a, make_type_slice(a, t_string));
  249. auto get_type_info_ptr = [](ssaProcedure *proc, ssaValue *type_info_data, Type *type) -> ssaValue * {
  250. return ssa_emit_struct_gep(proc, type_info_data,
  251. ssa_type_info_index(proc->module->info, type),
  252. t_type_info_ptr);
  253. };
  254. isize type_info_member_index = 0;
  255. auto type_info_member_offset = [](ssaProcedure *proc, ssaValue *data, isize count, isize *index) -> ssaValue * {
  256. ssaValue *offset = ssa_emit_struct_gep(proc, data, *index, t_type_info_member_ptr);
  257. *index += count;
  258. return offset;
  259. };
  260. for_array(type_info_map_index, info->type_info_map.entries) {
  261. auto *entry = &info->type_info_map.entries[type_info_map_index];
  262. Type *t = cast(Type *)cast(uintptr)entry->key.key;
  263. t = default_type(t);
  264. isize entry_index = entry->value;
  265. ssaValue *tag = NULL;
  266. switch (t->kind) {
  267. case Type_Named: {
  268. tag = ssa_add_local_generated(proc, t_type_info_named);
  269. // TODO(bill): Which is better? The mangled name or actual name?
  270. // ssaValue *gsa = ssa_add_global_string_array(proc, make_exact_value_string(t->Named.name));
  271. ssaValue *gsa = ssa_add_global_string_array(m, t->Named.type_name->token.string);
  272. ssaValue *elem = ssa_array_elem(proc, gsa);
  273. ssaValue *len = ssa_array_len(proc, ssa_emit_load(proc, gsa));
  274. ssaValue *name = ssa_emit_string(proc, elem, len);
  275. ssaValue *gep = get_type_info_ptr(proc, type_info_data, t->Named.base);
  276. ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero, t_string_ptr), name);
  277. ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_one32, t_type_info_ptr), gep);
  278. } break;
  279. case Type_Basic:
  280. switch (t->Basic.kind) {
  281. case Basic_bool:
  282. tag = ssa_add_local_generated(proc, t_type_info_boolean);
  283. break;
  284. case Basic_i8:
  285. case Basic_i16:
  286. case Basic_i32:
  287. case Basic_i64:
  288. case Basic_u8:
  289. case Basic_u16:
  290. case Basic_u32:
  291. case Basic_u64:
  292. case Basic_int:
  293. case Basic_uint: {
  294. tag = ssa_add_local_generated(proc, t_type_info_integer);
  295. b32 is_unsigned = (t->Basic.flags & BasicFlag_Unsigned) != 0;
  296. ssaValue *bits = ssa_make_const_int(a, type_size_of(m->sizes, a, t));
  297. ssaValue *is_signed = ssa_make_const_bool(a, !is_unsigned);
  298. ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero32, t_int_ptr), bits);
  299. ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_one32, t_bool_ptr), is_signed);
  300. } break;
  301. case Basic_f32:
  302. case Basic_f64: {
  303. tag = ssa_add_local_generated(proc, t_type_info_float);
  304. ssaValue *bits = ssa_make_const_int(a, type_size_of(m->sizes, a, t));
  305. ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero32, t_int_ptr), bits);
  306. } break;
  307. case Basic_rawptr:
  308. tag = ssa_add_local_generated(proc, t_type_info_pointer);
  309. break;
  310. case Basic_string:
  311. tag = ssa_add_local_generated(proc, t_type_info_string);
  312. break;
  313. }
  314. break;
  315. case Type_Pointer: {
  316. tag = ssa_add_local_generated(proc, t_type_info_pointer);
  317. ssaValue *gep = get_type_info_ptr(proc, type_info_data, t->Pointer.elem);
  318. ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero32, t_type_info_ptr_ptr), gep);
  319. } break;
  320. case Type_Maybe: {
  321. tag = ssa_add_local_generated(proc, t_type_info_maybe);
  322. ssaValue *gep = get_type_info_ptr(proc, type_info_data, t->Maybe.elem);
  323. ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero32, t_type_info_ptr_ptr), gep);
  324. } break;
  325. case Type_Array: {
  326. tag = ssa_add_local_generated(proc, t_type_info_array);
  327. ssaValue *gep = get_type_info_ptr(proc, type_info_data, t->Array.elem);
  328. ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero32, t_type_info_ptr_ptr), gep);
  329. isize ez = type_size_of(m->sizes, a, t->Array.elem);
  330. ssaValue *elem_size = ssa_emit_struct_gep(proc, tag, v_one32, t_int_ptr);
  331. ssa_emit_store(proc, elem_size, ssa_make_const_int(a, ez));
  332. ssaValue *count = ssa_emit_struct_gep(proc, tag, v_two32, t_int_ptr);
  333. ssa_emit_store(proc, count, ssa_make_const_int(a, t->Array.count));
  334. } break;
  335. case Type_Slice: {
  336. tag = ssa_add_local_generated(proc, t_type_info_slice);
  337. ssaValue *gep = get_type_info_ptr(proc, type_info_data, t->Slice.elem);
  338. ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero32, t_type_info_ptr_ptr), gep);
  339. isize ez = type_size_of(m->sizes, a, t->Slice.elem);
  340. ssaValue *elem_size = ssa_emit_struct_gep(proc, tag, v_one32, t_int_ptr);
  341. ssa_emit_store(proc, elem_size, ssa_make_const_int(a, ez));
  342. } break;
  343. case Type_Vector: {
  344. tag = ssa_add_local_generated(proc, t_type_info_vector);
  345. ssaValue *gep = get_type_info_ptr(proc, type_info_data, t->Vector.elem);
  346. ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero32, t_type_info_ptr_ptr), gep);
  347. isize ez = type_size_of(m->sizes, a, t->Vector.elem);
  348. ssaValue *elem_size = ssa_emit_struct_gep(proc, tag, v_one32, t_int_ptr);
  349. ssa_emit_store(proc, elem_size, ssa_make_const_int(a, ez));
  350. ssaValue *count = ssa_emit_struct_gep(proc, tag, v_two32, t_int_ptr);
  351. ssa_emit_store(proc, count, ssa_make_const_int(a, t->Vector.count));
  352. } break;
  353. case Type_Record: {
  354. switch (t->Record.kind) {
  355. case TypeRecord_Struct: {
  356. tag = ssa_add_local_generated(proc, t_type_info_struct);
  357. {
  358. ssaValue *packed = ssa_make_const_bool(a, t->Record.struct_is_packed);
  359. ssaValue *ordered = ssa_make_const_bool(a, t->Record.struct_is_ordered);
  360. ssaValue *size = ssa_make_const_int(a, type_size_of(m->sizes, a, t));
  361. ssaValue *align = ssa_make_const_int(a, type_align_of(m->sizes, a, t));
  362. ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 1, t_int_ptr), size);
  363. ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 2, t_int_ptr), align);
  364. ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 3, t_bool_ptr), packed);
  365. ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 4, t_bool_ptr), ordered);
  366. }
  367. ssaValue *memory = type_info_member_offset(proc, type_info_member_data, t->Record.field_count, &type_info_member_index);
  368. type_set_offsets(m->sizes, a, t); // NOTE(bill): Just incase the offsets have not been set yet
  369. for (isize i = 0; i < t->Record.field_count; i++) {
  370. // TODO(bill): Order fields in source order not layout order
  371. Entity *f = t->Record.fields_in_src_order[i];
  372. ssaValue *tip = get_type_info_ptr(proc, type_info_data, f->type);
  373. i64 foffset = t->Record.struct_offsets[f->Variable.field_index];
  374. GB_ASSERT(f->kind == Entity_Variable && f->Variable.field);
  375. isize source_index = f->Variable.field_index;
  376. ssaValue *field = ssa_emit_ptr_offset(proc, memory, ssa_make_const_int(a, source_index));
  377. ssaValue *name = ssa_emit_struct_gep(proc, field, v_zero32, t_string_ptr);
  378. ssaValue *type_info = ssa_emit_struct_gep(proc, field, v_one32, t_type_info_ptr_ptr);
  379. ssaValue *offset = ssa_emit_struct_gep(proc, field, v_two32, t_int_ptr);
  380. if (f->token.string.len > 0) {
  381. ssa_emit_store(proc, name, ssa_emit_global_string(proc, f->token.string));
  382. }
  383. ssa_emit_store(proc, type_info, tip);
  384. ssa_emit_store(proc, offset, ssa_make_const_int(a, foffset));
  385. }
  386. Type *slice_type = make_type_slice(a, t_type_info_member);
  387. Type *slice_type_ptr = make_type_pointer(a, slice_type);
  388. ssaValue *slice = ssa_emit_struct_gep(proc, tag, v_zero32, slice_type_ptr);
  389. ssaValue *field_count = ssa_make_const_int(a, t->Record.field_count);
  390. ssaValue *elem = ssa_emit_struct_gep(proc, slice, v_zero32, make_type_pointer(a, t_type_info_member_ptr));
  391. ssaValue *len = ssa_emit_struct_gep(proc, slice, v_one32, make_type_pointer(a, t_int_ptr));
  392. ssaValue *cap = ssa_emit_struct_gep(proc, slice, v_two32, make_type_pointer(a, t_int_ptr));
  393. ssa_emit_store(proc, elem, memory);
  394. ssa_emit_store(proc, len, field_count);
  395. ssa_emit_store(proc, cap, field_count);
  396. } break;
  397. case TypeRecord_Union:
  398. tag = ssa_add_local_generated(proc, t_type_info_union);
  399. {
  400. ssaValue *size = ssa_make_const_int(a, type_size_of(m->sizes, a, t));
  401. ssaValue *align = ssa_make_const_int(a, type_align_of(m->sizes, a, t));
  402. ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 1, t_int_ptr), size);
  403. ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 2, t_int_ptr), align);
  404. }
  405. break;
  406. case TypeRecord_RawUnion: {
  407. tag = ssa_add_local_generated(proc, t_type_info_raw_union);
  408. {
  409. ssaValue *size = ssa_make_const_int(a, type_size_of(m->sizes, a, t));
  410. ssaValue *align = ssa_make_const_int(a, type_align_of(m->sizes, a, t));
  411. ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 1, t_int_ptr), size);
  412. ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 2, t_int_ptr), align);
  413. }
  414. ssaValue *memory = type_info_member_offset(proc, type_info_member_data, t->Record.field_count, &type_info_member_index);
  415. for (isize i = 0; i < t->Record.field_count; i++) {
  416. ssaValue *field = ssa_emit_ptr_offset(proc, memory, ssa_make_const_int(a, i));
  417. ssaValue *name = ssa_emit_struct_gep(proc, field, v_zero32, t_string_ptr);
  418. ssaValue *type_info = ssa_emit_struct_gep(proc, field, v_one32, t_type_info_ptr_ptr);
  419. ssaValue *offset = ssa_emit_struct_gep(proc, field, v_two32, t_int_ptr);
  420. Entity *f = t->Record.fields[i];
  421. ssaValue *tip = get_type_info_ptr(proc, type_info_data, f->type);
  422. if (f->token.string.len > 0) {
  423. ssa_emit_store(proc, name, ssa_emit_global_string(proc, f->token.string));
  424. }
  425. ssa_emit_store(proc, type_info, tip);
  426. ssa_emit_store(proc, offset, ssa_make_const_int(a, 0));
  427. }
  428. Type *slice_type = make_type_slice(a, t_type_info_member);
  429. Type *slice_type_ptr = make_type_pointer(a, slice_type);
  430. ssaValue *slice = ssa_emit_struct_gep(proc, tag, v_zero32, slice_type_ptr);
  431. ssaValue *field_count = ssa_make_const_int(a, t->Record.field_count);
  432. ssaValue *elem = ssa_emit_struct_gep(proc, slice, v_zero32, make_type_pointer(a, t_type_info_member_ptr));
  433. ssaValue *len = ssa_emit_struct_gep(proc, slice, v_one32, make_type_pointer(a, t_int_ptr));
  434. ssaValue *cap = ssa_emit_struct_gep(proc, slice, v_two32, make_type_pointer(a, t_int_ptr));
  435. ssa_emit_store(proc, elem, memory);
  436. ssa_emit_store(proc, len, field_count);
  437. ssa_emit_store(proc, cap, field_count);
  438. } break;
  439. case TypeRecord_Enum: {
  440. tag = ssa_add_local_generated(proc, t_type_info_enum);
  441. Type *enum_base = t->Record.enum_base;
  442. if (enum_base == NULL) {
  443. enum_base = t_int;
  444. }
  445. ssaValue *base = ssa_emit_struct_gep(proc, tag, v_zero32, t_type_info_ptr_ptr);
  446. ssa_emit_store(proc, base, get_type_info_ptr(proc, type_info_data, enum_base));
  447. if (t->Record.other_field_count > 0) {
  448. Entity **fields = t->Record.other_fields;
  449. isize count = t->Record.other_field_count;
  450. ssaValue *value_array = NULL;
  451. ssaValue *name_array = NULL;
  452. {
  453. Token token = {Token_Identifier};
  454. i32 id = cast(i32)entry_index;
  455. char name_base[] = "__$enum_values";
  456. isize name_len = gb_size_of(name_base) + 10;
  457. token.string.text = gb_alloc_array(a, u8, name_len);
  458. token.string.len = gb_snprintf(cast(char *)token.string.text, name_len,
  459. "%s-%d", name_base, id)-1;
  460. Entity *e = make_entity_variable(a, NULL, token, make_type_array(a, t_i64, count));
  461. value_array = ssa_make_value_global(a, e, NULL);
  462. value_array->Global.is_private = true;
  463. ssa_module_add_value(m, e, value_array);
  464. map_set(&m->members, hash_string(token.string), value_array);
  465. }
  466. {
  467. Token token = {Token_Identifier};
  468. i32 id = cast(i32)entry_index;
  469. char name_base[] = "__$enum_names";
  470. isize name_len = gb_size_of(name_base) + 10;
  471. token.string.text = gb_alloc_array(a, u8, name_len);
  472. token.string.len = gb_snprintf(cast(char *)token.string.text, name_len,
  473. "%s-%d", name_base, id)-1;
  474. Entity *e = make_entity_variable(a, NULL, token, make_type_array(a, t_string, count));
  475. name_array = ssa_make_value_global(a, e, NULL);
  476. name_array->Global.is_private = true;
  477. ssa_module_add_value(m, e, name_array);
  478. map_set(&m->members, hash_string(token.string), name_array);
  479. }
  480. for (isize i = 0; i < count; i++) {
  481. ssaValue *value_gep = ssa_emit_struct_gep(proc, value_array, i, t_i64_ptr);
  482. ssaValue *name_gep = ssa_emit_struct_gep(proc, name_array, i, t_string_ptr);
  483. ssa_emit_store(proc, value_gep, ssa_make_const_i64(a, fields[i]->Constant.value.value_integer));
  484. ssa_emit_store(proc, name_gep, ssa_emit_global_string(proc, fields[i]->token.string));
  485. }
  486. ssaValue *v_count = ssa_make_const_int(a, count);
  487. ssaValue *values = ssa_emit_struct_gep(proc, tag, v_one32, t_i64_slice_ptr);
  488. ssaValue *names = ssa_emit_struct_gep(proc, tag, v_two32, t_string_slice_ptr);
  489. ssaValue *value_slice = ssa_add_local_generated(proc, type_deref(t_i64_slice_ptr));
  490. ssaValue *name_slice = ssa_add_local_generated(proc, type_deref(t_string_slice_ptr));
  491. ssa_emit_store(proc, ssa_emit_struct_gep(proc, value_slice, v_zero32, t_i64_ptr), ssa_array_elem(proc, value_array));
  492. ssa_emit_store(proc, ssa_emit_struct_gep(proc, value_slice, v_one32, t_int_ptr), v_count);
  493. ssa_emit_store(proc, ssa_emit_struct_gep(proc, value_slice, v_two32, t_int_ptr), v_count);
  494. ssa_emit_store(proc, ssa_emit_struct_gep(proc, name_slice, v_zero32, t_string_ptr), ssa_array_elem(proc, name_array));
  495. ssa_emit_store(proc, ssa_emit_struct_gep(proc, name_slice, v_one32, t_int_ptr), v_count);
  496. ssa_emit_store(proc, ssa_emit_struct_gep(proc, name_slice, v_two32, t_int_ptr), v_count);
  497. ssa_emit_store(proc, values, ssa_emit_load(proc, value_slice));
  498. ssa_emit_store(proc, names, ssa_emit_load(proc, name_slice));
  499. }
  500. } break;
  501. }
  502. } break;
  503. case Type_Tuple: {
  504. tag = ssa_add_local_generated(proc, t_type_info_tuple);
  505. {
  506. ssaValue *align = ssa_make_const_int(a, type_align_of(m->sizes, a, t));
  507. ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 2, t_int_ptr), align);
  508. }
  509. ssaValue *memory = type_info_member_offset(proc, type_info_member_data, t->Tuple.variable_count, &type_info_member_index);
  510. for (isize i = 0; i < t->Tuple.variable_count; i++) {
  511. ssaValue *field = ssa_emit_ptr_offset(proc, memory, ssa_make_const_int(a, i));
  512. ssaValue *name = ssa_emit_struct_gep(proc, field, v_zero32, t_string_ptr);
  513. ssaValue *type_info = ssa_emit_struct_gep(proc, field, v_one32, t_type_info_ptr_ptr);
  514. // NOTE(bill): offset is not used for tuples
  515. Entity *f = t->Tuple.variables[i];
  516. ssaValue *tip = get_type_info_ptr(proc, type_info_data, f->type);
  517. if (f->token.string.len > 0) {
  518. ssa_emit_store(proc, name, ssa_emit_global_string(proc, f->token.string));
  519. }
  520. ssa_emit_store(proc, type_info, tip);
  521. }
  522. Type *slice_type = make_type_slice(a, t_type_info_member);
  523. Type *slice_type_ptr = make_type_pointer(a, slice_type);
  524. ssaValue *slice = ssa_emit_struct_gep(proc, tag, v_zero32, slice_type_ptr);
  525. ssaValue *variable_count = ssa_make_const_int(a, t->Tuple.variable_count);
  526. ssaValue *elem = ssa_emit_struct_gep(proc, slice, v_zero32, make_type_pointer(a, t_type_info_member_ptr));
  527. ssaValue *len = ssa_emit_struct_gep(proc, slice, v_one32, make_type_pointer(a, t_int_ptr));
  528. ssaValue *cap = ssa_emit_struct_gep(proc, slice, v_two32, make_type_pointer(a, t_int_ptr));
  529. ssa_emit_store(proc, elem, memory);
  530. ssa_emit_store(proc, len, variable_count);
  531. ssa_emit_store(proc, cap, variable_count);
  532. } break;
  533. case Type_Proc: {
  534. tag = ssa_add_local_generated(proc, t_type_info_procedure);
  535. ssaValue *params = ssa_emit_struct_gep(proc, tag, v_zero32, t_type_info_ptr_ptr);
  536. ssaValue *results = ssa_emit_struct_gep(proc, tag, v_one32, t_type_info_ptr_ptr);
  537. ssaValue *variadic = ssa_emit_struct_gep(proc, tag, v_two32, t_bool_ptr);
  538. if (t->Proc.params) {
  539. ssa_emit_store(proc, params, get_type_info_ptr(proc, type_info_data, t->Proc.params));
  540. }
  541. if (t->Proc.results) {
  542. ssa_emit_store(proc, results, get_type_info_ptr(proc, type_info_data, t->Proc.results));
  543. }
  544. ssa_emit_store(proc, variadic, ssa_make_const_bool(a, t->Proc.variadic));
  545. // TODO(bill): Type_Info for procedures
  546. } break;
  547. }
  548. if (tag != NULL) {
  549. ssaValue *gep = ssa_emit_struct_gep(proc, type_info_data, entry_index, t_type_info_ptr);
  550. ssaValue *val = ssa_emit_conv(proc, ssa_emit_load(proc, tag), t_type_info);
  551. ssa_emit_store(proc, gep, val);
  552. }
  553. }
  554. }
  555. ssa_end_procedure_body(proc);
  556. }
  557. for_array(i, m->procs) {
  558. ssa_build_proc(m->procs[i], m->procs[i]->Proc.parent);
  559. }
  560. // m->layout = make_string("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64");
  561. }
  562. void ssa_gen_ir(ssaGen *s) {
  563. ssaFileBuffer buf = {};
  564. ssa_file_buffer_init(&buf, &s->output_file);
  565. defer (ssa_file_buffer_destroy(&buf));
  566. ssa_print_llvm_ir(&buf, &s->module);
  567. }