codegen.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  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 (c->error_collector.count != 0)
  9. return false;
  10. gb_for_array(i, c->parser->files) {
  11. AstFile *f = &c->parser->files[i];
  12. if (f->error_collector.count != 0)
  13. return false;
  14. if (f->tokenizer.error_count != 0)
  15. return false;
  16. }
  17. isize tc = c->parser->total_token_count;
  18. if (tc < 2) {
  19. return false;
  20. }
  21. ssa_init_module(&s->module, c);
  22. // TODO(bill): generate appropriate output name
  23. isize pos = string_extension_position(c->parser->init_fullpath);
  24. gbFileError err = gb_file_create(&s->output_file, gb_bprintf("%.*s.ll", pos, c->parser->init_fullpath.text));
  25. if (err != gbFileError_None)
  26. return false;
  27. return true;
  28. }
  29. void ssa_gen_destroy(ssaGen *s) {
  30. ssa_destroy_module(&s->module);
  31. gb_file_close(&s->output_file);
  32. }
  33. void ssa_gen_tree(ssaGen *s) {
  34. if (v_zero == NULL) {
  35. v_zero = ssa_make_const_int (gb_heap_allocator(), 0);
  36. v_one = ssa_make_const_int (gb_heap_allocator(), 1);
  37. v_zero32 = ssa_make_const_i32 (gb_heap_allocator(), 0);
  38. v_one32 = ssa_make_const_i32 (gb_heap_allocator(), 1);
  39. v_two32 = ssa_make_const_i32 (gb_heap_allocator(), 2);
  40. v_false = ssa_make_const_bool(gb_heap_allocator(), false);
  41. v_true = ssa_make_const_bool(gb_heap_allocator(), true);
  42. }
  43. struct ssaGlobalVariable {
  44. ssaValue *var, *init;
  45. DeclInfo *decl;
  46. };
  47. ssaModule *m = &s->module;
  48. CheckerInfo *info = m->info;
  49. gbAllocator a = m->allocator;
  50. gbArray(ssaGlobalVariable) global_variables;
  51. gb_array_init(global_variables, gb_heap_allocator());
  52. defer (gb_array_free(global_variables));
  53. gb_for_array(i, info->entities.entries) {
  54. auto *entry = &info->entities.entries[i];
  55. Entity *e = cast(Entity *)cast(uintptr)entry->key.key;
  56. String name = e->token.string;
  57. DeclInfo *decl = entry->value;
  58. Scope *scope = e->scope;
  59. if (scope->is_global ||
  60. scope->is_init) {
  61. } else {
  62. // NOTE(bill): prefix names not in the init scope
  63. // TODO(bill): make robust and not just rely on the file's name
  64. String path = e->token.pos.file;
  65. char *str = gb_alloc_array(a, char, path.len+1);
  66. gb_memcopy(str, path.text, path.len);
  67. str[path.len] = 0;
  68. for (isize i = 0; i < path.len; i++) {
  69. if (str[i] == '\\') {
  70. str[i] = '/';
  71. }
  72. }
  73. char const *base = gb_path_base_name(str);
  74. char const *ext = gb_path_extension(base);
  75. isize base_len = ext-1-base;
  76. isize new_len = base_len + 1 + name.len;
  77. u8 *new_name = gb_alloc_array(a, u8, new_len);
  78. gb_memcopy(new_name, base, base_len);
  79. new_name[base_len] = '.';
  80. gb_memcopy(new_name+base_len+1, name.text, name.len);
  81. name = make_string(new_name, new_len);
  82. // gb_printf("%.*s\n", new_len, new_name);
  83. }
  84. switch (e->kind) {
  85. case Entity_TypeName:
  86. GB_ASSERT(e->type->kind == Type_Named);
  87. // HACK(bill): Rename type's name for ssa gen
  88. e->type->Named.name = name;
  89. ssa_gen_global_type_name(m, e, name);
  90. break;
  91. case Entity_Variable: {
  92. ssaValue *g = ssa_make_value_global(a, e, NULL);
  93. if (decl->var_decl_tags & VarDeclTag_thread_local) {
  94. g->Global.is_thread_local = true;
  95. }
  96. ssaGlobalVariable var = {};
  97. var.var = g;
  98. var.decl = decl;
  99. if (decl->init_expr != NULL) {
  100. TypeAndValue *tav = map_get(&info->types, hash_pointer(decl->init_expr));
  101. if (tav != NULL && tav->value.kind != ExactValue_Invalid) {
  102. ExactValue v = tav->value;
  103. if (v.kind == ExactValue_String) {
  104. // NOTE(bill): The printer will fix the value correctly
  105. g->Global.value = ssa_add_global_string_array(m, v.value_string);
  106. } else {
  107. g->Global.value = ssa_make_value_constant(a, tav->type, v);
  108. }
  109. }
  110. }
  111. if (g->Global.value == NULL) {
  112. gb_array_append(global_variables, var);
  113. }
  114. map_set(&m->values, hash_pointer(e), g);
  115. map_set(&m->members, hash_string(name), g);
  116. } break;
  117. case Entity_Procedure: {
  118. auto *pd = &decl->proc_decl->ProcDecl;
  119. String original_name = name;
  120. AstNode *body = pd->body;
  121. if (pd->tags & ProcTag_foreign) {
  122. name = pd->name->Ident.string;
  123. }
  124. if (pd->foreign_name.len > 0) {
  125. name = pd->foreign_name;
  126. }
  127. ssaValue *p = ssa_make_value_procedure(a, m, e->type, decl->type_expr, body, name);
  128. p->Proc.tags = pd->tags;
  129. map_set(&m->values, hash_pointer(e), p);
  130. HashKey hash_name = hash_string(name);
  131. if (map_get(&m->members, hash_name) == NULL) {
  132. map_set(&m->members, hash_name, p);
  133. }
  134. } break;
  135. }
  136. }
  137. gb_for_array(i, m->members.entries) {
  138. auto *entry = &m->members.entries[i];
  139. ssaValue *v = entry->value;
  140. if (v->kind == ssaValue_Proc)
  141. ssa_build_proc(v, NULL);
  142. }
  143. { // Startup Runtime
  144. // Cleanup(bill): probably better way of doing code insertion
  145. String name = make_string(SSA_STARTUP_RUNTIME_PROC_NAME);
  146. Type *proc_type = make_type_proc(a, gb_alloc_item(a, Scope),
  147. NULL, 0,
  148. NULL, 0, false);
  149. AstNode *body = gb_alloc_item(a, AstNode);
  150. ssaValue *p = ssa_make_value_procedure(a, m, proc_type, NULL, body, name);
  151. Token token = {};
  152. token.string = name;
  153. Entity *e = make_entity_procedure(a, NULL, token, proc_type);
  154. map_set(&m->values, hash_pointer(e), p);
  155. map_set(&m->members, hash_string(name), p);
  156. ssaProcedure *proc = &p->Proc;
  157. proc->tags = ProcTag_no_inline; // TODO(bill): is no_inline a good idea?
  158. ssa_begin_procedure_body(proc);
  159. // TODO(bill): Should do a dependency graph do check which order to initialize them in?
  160. gb_for_array(i, global_variables) {
  161. ssaGlobalVariable *var = &global_variables[i];
  162. if (var->decl->init_expr != NULL) {
  163. var->init = ssa_build_expr(proc, var->decl->init_expr);
  164. }
  165. }
  166. // NOTE(bill): Initialize constants first
  167. gb_for_array(i, global_variables) {
  168. ssaGlobalVariable *var = &global_variables[i];
  169. if (var->init != NULL) {
  170. if (var->init->kind == ssaValue_Constant) {
  171. ssa_emit_store(proc, var->var, var->init);
  172. }
  173. }
  174. }
  175. gb_for_array(i, global_variables) {
  176. ssaGlobalVariable *var = &global_variables[i];
  177. if (var->init != NULL) {
  178. if (var->init->kind != ssaValue_Constant) {
  179. ssa_emit_store(proc, var->var, var->init);
  180. }
  181. }
  182. }
  183. { // NOTE(bill): Setup type_info data
  184. ssaValue *type_info_data = NULL;
  185. ssaValue *type_info_member_data = NULL;
  186. ssaValue **found = NULL;
  187. found = map_get(&proc->module->members, hash_string(make_string(SSA_TYPE_INFO_DATA_NAME)));
  188. GB_ASSERT(found != NULL);
  189. type_info_data = *found;
  190. found = map_get(&proc->module->members, hash_string(make_string(SSA_TYPE_INFO_DATA_MEMBER_NAME)));
  191. GB_ASSERT(found != NULL);
  192. type_info_member_data = *found;
  193. CheckerInfo *info = proc->module->info;
  194. // Useful types
  195. Type *t_int_ptr = make_type_pointer(a, t_int);
  196. Type *t_bool_ptr = make_type_pointer(a, t_bool);
  197. Type *t_string_ptr = make_type_pointer(a, t_string);
  198. Type *t_type_info_ptr_ptr = make_type_pointer(a, t_type_info_ptr);
  199. auto get_type_info_ptr = [](ssaProcedure *proc, ssaValue *type_info_data, Type *type) -> ssaValue * {
  200. return ssa_emit_struct_gep(proc, type_info_data,
  201. ssa_type_info_index(proc->module->info, type),
  202. t_type_info_ptr);
  203. };
  204. isize type_info_member_index = 0;
  205. auto type_info_member_offset = [](ssaProcedure *proc, ssaValue *data, isize count, isize *index) -> ssaValue * {
  206. ssaValue *offset = ssa_emit_struct_gep(proc, data, *index, t_type_info_member_ptr);
  207. *index += count;
  208. return offset;
  209. };
  210. gb_for_array(entry_index, info->type_info_map.entries) {
  211. auto *entry = &info->type_info_map.entries[entry_index];
  212. Type *t = cast(Type *)cast(uintptr)entry->key.key;
  213. ssaValue *tag = NULL;
  214. switch (t->kind) {
  215. case Type_Named: {
  216. tag = ssa_add_local_generated(proc, t_type_info_named);
  217. // TODO(bill): Which is better? The mangled name or actual name?
  218. // ssaValue *gsa = ssa_add_global_string_array(proc, make_exact_value_string(t->Named.name));
  219. ssaValue *gsa = ssa_add_global_string_array(m, t->Named.type_name->token.string);
  220. ssaValue *elem = ssa_array_elem(proc, gsa);
  221. ssaValue *len = ssa_array_len(proc, ssa_emit_load(proc, gsa));
  222. ssaValue *name = ssa_emit_string(proc, elem, len);
  223. ssaValue *gep = get_type_info_ptr(proc, type_info_data, t->Named.base);
  224. ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero, t_string_ptr), name);
  225. ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_one32, t_type_info_ptr), gep);
  226. } break;
  227. case Type_Basic:
  228. switch (t->Basic.kind) {
  229. case Basic_bool:
  230. tag = ssa_add_local_generated(proc, t_type_info_boolean);
  231. break;
  232. case Basic_i8:
  233. case Basic_i16:
  234. case Basic_i32:
  235. case Basic_i64:
  236. case Basic_i128:
  237. case Basic_u8:
  238. case Basic_u16:
  239. case Basic_u32:
  240. case Basic_u64:
  241. case Basic_u128:
  242. case Basic_int:
  243. case Basic_uint: {
  244. tag = ssa_add_local_generated(proc, t_type_info_integer);
  245. b32 is_unsigned = (basic_types[t->Basic.kind].flags & BasicFlag_Unsigned) != 0;
  246. ssaValue *bits = ssa_make_const_int(a, type_size_of(m->sizes, a, t));
  247. ssaValue *is_signed = ssa_make_const_bool(a, !is_unsigned);
  248. ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero32, t_int_ptr), bits);
  249. ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_one32, t_bool_ptr), is_signed);
  250. } break;
  251. case Basic_f32:
  252. case Basic_f64: {
  253. tag = ssa_add_local_generated(proc, t_type_info_float);
  254. ssaValue *bits = ssa_make_const_int(a, type_size_of(m->sizes, a, t));
  255. ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero32, t_int_ptr), bits);
  256. } break;
  257. case Basic_rawptr:
  258. tag = ssa_add_local_generated(proc, t_type_info_pointer);
  259. break;
  260. case Basic_string:
  261. tag = ssa_add_local_generated(proc, t_type_info_string);
  262. break;
  263. }
  264. break;
  265. case Type_Pointer: {
  266. tag = ssa_add_local_generated(proc, t_type_info_pointer);
  267. ssaValue *gep = get_type_info_ptr(proc, type_info_data, t->Pointer.elem);
  268. ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero32, t_type_info_ptr_ptr), gep);
  269. } break;
  270. case Type_Array: {
  271. tag = ssa_add_local_generated(proc, t_type_info_array);
  272. ssaValue *gep = get_type_info_ptr(proc, type_info_data, t->Array.elem);
  273. ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero32, t_type_info_ptr_ptr), gep);
  274. isize ez = type_size_of(m->sizes, a, t->Array.elem);
  275. ssaValue *elem_size = ssa_emit_struct_gep(proc, tag, v_one32, t_int_ptr);
  276. ssa_emit_store(proc, elem_size, ssa_make_const_int(a, ez));
  277. ssaValue *count = ssa_emit_struct_gep(proc, tag, v_two32, t_int_ptr);
  278. ssa_emit_store(proc, count, ssa_make_const_int(a, t->Array.count));
  279. } break;
  280. case Type_Slice: {
  281. tag = ssa_add_local_generated(proc, t_type_info_slice);
  282. ssaValue *gep = get_type_info_ptr(proc, type_info_data, t->Slice.elem);
  283. ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero32, t_type_info_ptr_ptr), gep);
  284. isize ez = type_size_of(m->sizes, a, t->Slice.elem);
  285. ssaValue *elem_size = ssa_emit_struct_gep(proc, tag, v_one32, t_int_ptr);
  286. ssa_emit_store(proc, elem_size, ssa_make_const_int(a, ez));
  287. } break;
  288. case Type_Vector: {
  289. tag = ssa_add_local_generated(proc, t_type_info_vector);
  290. ssaValue *gep = get_type_info_ptr(proc, type_info_data, t->Vector.elem);
  291. ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero32, t_type_info_ptr_ptr), gep);
  292. isize ez = type_size_of(m->sizes, a, t->Vector.elem);
  293. ssaValue *elem_size = ssa_emit_struct_gep(proc, tag, v_one32, t_int_ptr);
  294. ssa_emit_store(proc, elem_size, ssa_make_const_int(a, ez));
  295. ssaValue *count = ssa_emit_struct_gep(proc, tag, v_two32, t_int_ptr);
  296. ssa_emit_store(proc, count, ssa_make_const_int(a, t->Vector.count));
  297. } break;
  298. case Type_Record: {
  299. switch (t->Record.kind) {
  300. case TypeRecord_Struct: {
  301. tag = ssa_add_local_generated(proc, t_type_info_struct);
  302. {
  303. ssaValue *packed = ssa_make_const_bool(a, t->Record.struct_is_packed);
  304. ssaValue *ordered = ssa_make_const_bool(a, t->Record.struct_is_ordered);
  305. ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_one32, t_bool_ptr), packed);
  306. ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_two32, t_bool_ptr), ordered);
  307. }
  308. ssaValue *memory = type_info_member_offset(proc, type_info_member_data, t->Record.field_count, &type_info_member_index);
  309. type_set_offsets(m->sizes, a, t); // NOTE(bill): Just incase the offsets have not been set yet
  310. for (isize i = 0; i < t->Record.field_count; i++) {
  311. // NOTE(bill): Order fields in source order not layout order
  312. Entity *f = t->Record.fields[i];
  313. ssaValue *tip = get_type_info_ptr(proc, type_info_data, f->type);
  314. i64 foffset = t->Record.struct_offsets[i];
  315. GB_ASSERT(f->kind == Entity_Variable && f->Variable.is_field);
  316. isize source_index = f->Variable.field_index;
  317. ssaValue *field = ssa_emit_ptr_offset(proc, memory, ssa_make_const_int(a, source_index));
  318. ssaValue *name = ssa_emit_struct_gep(proc, field, v_zero32, t_string_ptr);
  319. ssaValue *type_info = ssa_emit_struct_gep(proc, field, v_one32, t_type_info_ptr_ptr);
  320. ssaValue *offset = ssa_emit_struct_gep(proc, field, v_two32, t_int_ptr);
  321. if (f->token.string.len > 0) {
  322. ssa_emit_store(proc, name, ssa_emit_global_string(proc, f->token.string));
  323. }
  324. ssa_emit_store(proc, type_info, tip);
  325. ssa_emit_store(proc, offset, ssa_make_const_int(a, foffset));
  326. }
  327. Type *slice_type = make_type_slice(a, t_type_info_member);
  328. Type *slice_type_ptr = make_type_pointer(a, slice_type);
  329. ssaValue *slice = ssa_emit_struct_gep(proc, tag, v_zero32, slice_type_ptr);
  330. ssaValue *field_count = ssa_make_const_int(a, t->Record.field_count);
  331. ssaValue *elem = ssa_emit_struct_gep(proc, slice, v_zero32, make_type_pointer(a, t_type_info_member_ptr));
  332. ssaValue *len = ssa_emit_struct_gep(proc, slice, v_one32, make_type_pointer(a, t_int_ptr));
  333. ssaValue *cap = ssa_emit_struct_gep(proc, slice, v_two32, make_type_pointer(a, t_int_ptr));
  334. ssa_emit_store(proc, elem, memory);
  335. ssa_emit_store(proc, len, field_count);
  336. ssa_emit_store(proc, cap, field_count);
  337. } break;
  338. case TypeRecord_Union:
  339. tag = ssa_add_local_generated(proc, t_type_info_union);
  340. break;
  341. case TypeRecord_RawUnion: {
  342. tag = ssa_add_local_generated(proc, t_type_info_raw_union);
  343. ssaValue *memory = type_info_member_offset(proc, type_info_member_data, t->Record.field_count, &type_info_member_index);
  344. for (isize i = 0; i < t->Record.field_count; i++) {
  345. ssaValue *field = ssa_emit_ptr_offset(proc, memory, ssa_make_const_int(a, i));
  346. ssaValue *name = ssa_emit_struct_gep(proc, field, v_zero32, t_string_ptr);
  347. ssaValue *type_info = ssa_emit_struct_gep(proc, field, v_one32, t_type_info_ptr_ptr);
  348. ssaValue *offset = ssa_emit_struct_gep(proc, field, v_two32, t_int_ptr);
  349. Entity *f = t->Record.fields[i];
  350. ssaValue *tip = get_type_info_ptr(proc, type_info_data, f->type);
  351. if (f->token.string.len > 0) {
  352. ssa_emit_store(proc, name, ssa_emit_global_string(proc, f->token.string));
  353. }
  354. ssa_emit_store(proc, type_info, tip);
  355. ssa_emit_store(proc, offset, ssa_make_const_int(a, 0));
  356. }
  357. Type *slice_type = make_type_slice(a, t_type_info_member);
  358. Type *slice_type_ptr = make_type_pointer(a, slice_type);
  359. ssaValue *slice = ssa_emit_struct_gep(proc, tag, v_zero32, slice_type_ptr);
  360. ssaValue *field_count = ssa_make_const_int(a, t->Record.field_count);
  361. ssaValue *elem = ssa_emit_struct_gep(proc, slice, v_zero32, make_type_pointer(a, t_type_info_member_ptr));
  362. ssaValue *len = ssa_emit_struct_gep(proc, slice, v_one32, make_type_pointer(a, t_int_ptr));
  363. ssaValue *cap = ssa_emit_struct_gep(proc, slice, v_two32, make_type_pointer(a, t_int_ptr));
  364. ssa_emit_store(proc, elem, memory);
  365. ssa_emit_store(proc, len, field_count);
  366. ssa_emit_store(proc, cap, field_count);
  367. } break;
  368. case TypeRecord_Enum: {
  369. tag = ssa_add_local_generated(proc, t_type_info_enum);
  370. Type *enum_base = t->Record.enum_base;
  371. if (enum_base == NULL) {
  372. enum_base = t_int;
  373. }
  374. ssaValue *gep = get_type_info_ptr(proc, type_info_data, enum_base);
  375. ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero32, t_type_info_ptr_ptr), gep);
  376. } break;
  377. }
  378. } break;
  379. case Type_Tuple: {
  380. tag = ssa_add_local_generated(proc, t_type_info_tuple);
  381. ssaValue *memory = type_info_member_offset(proc, type_info_member_data, t->Tuple.variable_count, &type_info_member_index);
  382. for (isize i = 0; i < t->Tuple.variable_count; i++) {
  383. ssaValue *field = ssa_emit_ptr_offset(proc, memory, ssa_make_const_int(a, i));
  384. ssaValue *name = ssa_emit_struct_gep(proc, field, v_zero32, t_string_ptr);
  385. ssaValue *type_info = ssa_emit_struct_gep(proc, field, v_one32, t_type_info_ptr_ptr);
  386. // NOTE(bill): offset is not used for tuples
  387. Entity *f = t->Tuple.variables[i];
  388. ssaValue *tip = get_type_info_ptr(proc, type_info_data, f->type);
  389. if (f->token.string.len > 0) {
  390. ssa_emit_store(proc, name, ssa_emit_global_string(proc, f->token.string));
  391. }
  392. ssa_emit_store(proc, type_info, tip);
  393. }
  394. Type *slice_type = make_type_slice(a, t_type_info_member);
  395. Type *slice_type_ptr = make_type_pointer(a, slice_type);
  396. ssaValue *slice = ssa_emit_struct_gep(proc, tag, v_zero32, slice_type_ptr);
  397. ssaValue *variable_count = ssa_make_const_int(a, t->Tuple.variable_count);
  398. ssaValue *elem = ssa_emit_struct_gep(proc, slice, v_zero32, make_type_pointer(a, t_type_info_member_ptr));
  399. ssaValue *len = ssa_emit_struct_gep(proc, slice, v_one32, make_type_pointer(a, t_int_ptr));
  400. ssaValue *cap = ssa_emit_struct_gep(proc, slice, v_two32, make_type_pointer(a, t_int_ptr));
  401. ssa_emit_store(proc, elem, memory);
  402. ssa_emit_store(proc, len, variable_count);
  403. ssa_emit_store(proc, cap, variable_count);
  404. } break;
  405. case Type_Proc: {
  406. tag = ssa_add_local_generated(proc, t_type_info_procedure);
  407. ssaValue *params = ssa_emit_struct_gep(proc, tag, v_zero32, t_type_info_ptr_ptr);
  408. ssaValue *results = ssa_emit_struct_gep(proc, tag, v_one32, t_type_info_ptr_ptr);
  409. ssaValue *variadic = ssa_emit_struct_gep(proc, tag, v_two32, t_bool_ptr);
  410. if (t->Proc.params) {
  411. ssa_emit_store(proc, params, get_type_info_ptr(proc, type_info_data, t->Proc.params));
  412. }
  413. if (t->Proc.results) {
  414. ssa_emit_store(proc, results, get_type_info_ptr(proc, type_info_data, t->Proc.results));
  415. }
  416. ssa_emit_store(proc, variadic, ssa_make_const_bool(a, t->Proc.variadic));
  417. // TODO(bill): Type_Info for procedures
  418. } break;
  419. }
  420. if (tag != NULL) {
  421. ssaValue *gep = ssa_emit_struct_gep(proc, type_info_data, entry_index, t_type_info_ptr);
  422. ssaValue *val = ssa_emit_conv(proc, ssa_emit_load(proc, tag), t_type_info);
  423. ssa_emit_store(proc, gep, val);
  424. }
  425. }
  426. }
  427. ssa_end_procedure_body(proc);
  428. }
  429. // 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");
  430. }
  431. void ssa_gen_ir(ssaGen *s) {
  432. ssaFileBuffer buf = {};
  433. ssa_file_buffer_init(&buf, &s->output_file);
  434. defer (ssa_file_buffer_destroy(&buf));
  435. ssa_print_llvm_ir(&buf, &s->module);
  436. }