print_llvm.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705
  1. #define SSA_PRINT_TO_STDOUT 0
  2. void ssa_fprintf(gbFile *f, char *fmt, ...) {
  3. va_list va;
  4. va_start(va, fmt);
  5. gb_fprintf_va(f, fmt, va);
  6. #if SSA_PRINT_TO_STDOUT
  7. gb_printf_va(fmt, va);
  8. #endif
  9. va_end(va);
  10. }
  11. void ssa_file_write(gbFile *f, void *data, isize len) {
  12. gb_file_write(f, data, len);
  13. #if SSA_PRINT_TO_STDOUT
  14. gb_file_write(gb_file_get_standard(gbFileStandard_Output), data, len);
  15. #endif
  16. }
  17. b32 ssa_valid_char(u8 c) {
  18. if (c >= 0x80)
  19. return false;
  20. if (gb_char_is_alphanumeric(c))
  21. return true;
  22. switch (c) {
  23. case '$':
  24. case '-':
  25. case '.':
  26. case '_':
  27. return true;
  28. }
  29. return false;
  30. }
  31. void ssa_print_escape_string(gbFile *f, String name) {
  32. isize extra = 0;
  33. for (isize i = 0; i < name.len; i++) {
  34. u8 c = name.text[i];
  35. if (!ssa_valid_char(c))
  36. extra += 2;
  37. }
  38. if (extra == 0) {
  39. ssa_fprintf(f, "%.*s", LIT(name));
  40. return;
  41. }
  42. char hex_table[] = "0123456789ABCDEF";
  43. isize buf_len = name.len + extra;
  44. u8 *buf = gb_alloc_array(gb_heap_allocator(), u8, buf_len);
  45. defer (gb_free(gb_heap_allocator(), buf));
  46. isize j = 0;
  47. for (isize i = 0; i < name.len; i++) {
  48. u8 c = name.text[i];
  49. if (ssa_valid_char(c)) {
  50. buf[j++] = c;
  51. } else {
  52. buf[j] = '\\';
  53. buf[j+1] = hex_table[c >> 4];
  54. buf[j+2] = hex_table[c & 0x0f];
  55. j += 3;
  56. }
  57. }
  58. ssa_file_write(f, buf, buf_len);
  59. }
  60. void ssa_print_encoded_local(gbFile *f, String name) {
  61. ssa_fprintf(f, "%%");
  62. ssa_print_escape_string(f, name);
  63. }
  64. void ssa_print_encoded_global(gbFile *f, String name) {
  65. ssa_fprintf(f, "@");
  66. ssa_print_escape_string(f, name);
  67. }
  68. void ssa_print_type(gbFile *f, BaseTypeSizes s, Type *t) {
  69. i64 word_bits = 8*s.word_size;
  70. GB_ASSERT_NOT_NULL(t);
  71. t = default_type(t);
  72. switch (t->kind) {
  73. case Type_Basic:
  74. switch (t->basic.kind) {
  75. case Basic_bool: ssa_fprintf(f, "i1"); break;
  76. case Basic_i8: ssa_fprintf(f, "i8"); break;
  77. case Basic_i16: ssa_fprintf(f, "i16"); break;
  78. case Basic_i32: ssa_fprintf(f, "i32"); break;
  79. case Basic_i64: ssa_fprintf(f, "i64"); break;
  80. case Basic_i128: ssa_fprintf(f, "i128"); break;
  81. case Basic_u8: ssa_fprintf(f, "i8"); break;
  82. case Basic_u16: ssa_fprintf(f, "i16"); break;
  83. case Basic_u32: ssa_fprintf(f, "i32"); break;
  84. case Basic_u64: ssa_fprintf(f, "i64"); break;
  85. case Basic_u128: ssa_fprintf(f, "u128"); break;
  86. case Basic_f32: ssa_fprintf(f, "float"); break;
  87. case Basic_f64: ssa_fprintf(f, "double"); break;
  88. case Basic_rawptr: ssa_fprintf(f, "%%.rawptr"); break;
  89. case Basic_string: ssa_fprintf(f, "%%.string"); break;
  90. case Basic_uint: ssa_fprintf(f, "i%lld", word_bits); break;
  91. case Basic_int: ssa_fprintf(f, "i%lld", word_bits); break;
  92. }
  93. break;
  94. case Type_Array:
  95. ssa_fprintf(f, "[%lld x ", t->array.count);
  96. ssa_print_type(f, s, t->array.elem);
  97. ssa_fprintf(f, "]");
  98. break;
  99. case Type_Vector: {
  100. // TODO(bill): actually do correctly
  101. ssa_fprintf(f, "<%lld x ", t->vector.count);
  102. ssa_print_type(f, s, t->vector.elem);
  103. ssa_fprintf(f, ">");
  104. } break;
  105. case Type_Slice:
  106. ssa_fprintf(f, "{");
  107. ssa_print_type(f, s, t->slice.elem);
  108. ssa_fprintf(f, "*, i%lld, i%lld}", word_bits, word_bits);
  109. break;
  110. case Type_Structure:
  111. if (t->structure.is_packed) {
  112. ssa_fprintf(f, "<");
  113. }
  114. ssa_fprintf(f, "{");
  115. for (isize i = 0; i < t->structure.field_count; i++) {
  116. if (i > 0) {
  117. ssa_fprintf(f, ", ");
  118. }
  119. ssa_print_type(f, s, t->structure.fields[i]->type);
  120. }
  121. ssa_fprintf(f, "}");
  122. if (t->structure.is_packed) {
  123. ssa_fprintf(f, ">");
  124. }
  125. break;
  126. case Type_Pointer:
  127. ssa_print_type(f, s, t->pointer.elem);
  128. ssa_fprintf(f, "*");
  129. break;
  130. case Type_Named:
  131. ssa_print_encoded_local(f, t->named.name);
  132. break;
  133. case Type_Alias:
  134. ssa_print_type(f, s, t->alias.base);
  135. break;
  136. case Type_Tuple:
  137. if (t->tuple.variable_count == 1) {
  138. ssa_print_type(f, s, t->tuple.variables[0]->type);
  139. } else {
  140. ssa_fprintf(f, "{");
  141. for (isize i = 0; i < t->tuple.variable_count; i++) {
  142. if (i > 0) ssa_fprintf(f, ", ");
  143. ssa_print_type(f, s, t->tuple.variables[i]->type);
  144. }
  145. ssa_fprintf(f, "}");
  146. }
  147. break;
  148. case Type_Proc:
  149. if (t->proc.result_count == 0) {
  150. ssa_fprintf(f, "void");
  151. } else {
  152. ssa_print_type(f, s, t->proc.results);
  153. }
  154. ssa_fprintf(f, " (");
  155. for (isize i = 0; i < t->proc.param_count; i++) {
  156. if (i > 0) {
  157. ssa_fprintf(f, ", ");
  158. }
  159. ssa_print_type(f, s, &t->proc.params[i]);
  160. }
  161. ssa_fprintf(f, ")*");
  162. break;
  163. }
  164. }
  165. void ssa_print_exact_value(gbFile *f, ssaModule *m, ExactValue value, Type *type) {
  166. if (is_type_float(type)) {
  167. value = exact_value_to_float(value);
  168. } else if (is_type_integer(type)) {
  169. value = exact_value_to_integer(value);
  170. }
  171. switch (value.kind) {
  172. case ExactValue_Bool:
  173. ssa_fprintf(f, (value.value_bool ? "true" : "false"));
  174. break;
  175. case ExactValue_String: {
  176. ssa_fprintf(f, "c\"");
  177. ssa_print_escape_string(f, value.value_string);
  178. ssa_fprintf(f, "\"");
  179. } break;
  180. case ExactValue_Integer:
  181. ssa_fprintf(f, "%lld", value.value_integer);
  182. break;
  183. case ExactValue_Float: {
  184. u64 u = *cast(u64*)&value.value_float;
  185. if (is_type_float(type) && type->basic.kind == Basic_f32) {
  186. // IMPORTANT NOTE(bill): LLVM requires all floating point constants to be
  187. // a 64 bit number if bits_of(float type) <= 64.
  188. // For some bizarre reason, you need to clear the bottom 28 bits
  189. // https://groups.google.com/forum/#!topic/llvm-dev/IlqV3TbSk6M
  190. u >>= 28;
  191. u <<= 28;
  192. }
  193. ssa_fprintf(f, "0x%016llx", u);
  194. } break;
  195. case ExactValue_Pointer:
  196. if (value.value_float == NULL) {
  197. ssa_fprintf(f, "null");
  198. } else {
  199. GB_PANIC("TODO(bill): ExactValue_Pointer");
  200. }
  201. break;
  202. default:
  203. GB_PANIC("Invalid ExactValue");
  204. break;
  205. }
  206. }
  207. void ssa_print_block_name(gbFile *f, ssaBlock *b) {
  208. ssa_print_escape_string(f, b->label);
  209. ssa_fprintf(f, ".-.%d", b->id);
  210. }
  211. void ssa_print_value(gbFile *f, ssaModule *m, ssaValue *value, Type *type_hint) {
  212. if (value == NULL) {
  213. ssa_fprintf(f, "!!!NULL_VALUE");
  214. return;
  215. }
  216. switch (value->kind) {
  217. case ssaValue_Constant:
  218. ssa_print_exact_value(f, m, value->constant.value, type_hint);
  219. break;
  220. case ssaValue_TypeName:
  221. ssa_print_encoded_local(f, value->type_name.name);
  222. break;
  223. case ssaValue_Global:
  224. ssa_print_encoded_global(f, value->global.entity->token.string);
  225. break;
  226. case ssaValue_Param:
  227. ssa_print_encoded_local(f, value->param.entity->token.string);
  228. break;
  229. case ssaValue_Proc:
  230. ssa_print_encoded_global(f, value->proc.name);
  231. break;
  232. case ssaValue_Instr:
  233. ssa_fprintf(f, "%%%d", value->id);
  234. break;
  235. }
  236. }
  237. void ssa_print_instr(gbFile *f, ssaModule *m, ssaValue *value) {
  238. GB_ASSERT(value->kind == ssaValue_Instr);
  239. ssaInstr *instr = &value->instr;
  240. ssa_fprintf(f, "\t");
  241. switch (instr->kind) {
  242. case ssaInstr_Local: {
  243. Type *type = instr->local.entity->type;
  244. ssa_fprintf(f, "%%%d = alloca ", value->id);
  245. ssa_print_type(f, m->sizes, type);
  246. ssa_fprintf(f, ", align %lld ", type_align_of(m->sizes, gb_heap_allocator(), type));
  247. {
  248. String str = instr->local.entity->token.string;
  249. if (str.len > 0)
  250. ssa_fprintf(f, "; %.*s", LIT(instr->local.entity->token.string));
  251. }
  252. ssa_fprintf(f, "\n");
  253. ssa_fprintf(f, "\tstore ");
  254. ssa_print_type(f, m->sizes, type);
  255. ssa_fprintf(f, " zeroinitializer, ");
  256. ssa_print_type(f, m->sizes, type);
  257. ssa_fprintf(f, "* %%%d\n", value->id);
  258. } break;
  259. case ssaInstr_Store: {
  260. Type *type = ssa_value_type(instr->store.address);
  261. ssa_fprintf(f, "store ");
  262. ssa_print_type(f, m->sizes, type);
  263. ssa_fprintf(f, " ");
  264. ssa_print_value(f, m, instr->store.value, type);
  265. ssa_fprintf(f, ", ");
  266. ssa_print_type(f, m->sizes, type);
  267. ssa_fprintf(f, "* ");
  268. ssa_print_value(f, m, instr->store.address, type);
  269. ssa_fprintf(f, "\n");
  270. } break;
  271. case ssaInstr_Load: {
  272. Type *type = instr->load.type;
  273. ssa_fprintf(f, "%%%d = load ", value->id);
  274. ssa_print_type(f, m->sizes, type);
  275. ssa_fprintf(f, ", ");
  276. ssa_print_type(f, m->sizes, type);
  277. ssa_fprintf(f, "* ");
  278. ssa_print_value(f, m, instr->load.address, type);
  279. ssa_fprintf(f, "\n");
  280. } break;
  281. case ssaInstr_GetElementPtr: {
  282. Type *et = instr->get_element_ptr.elem_type;
  283. ssa_fprintf(f, "%%%d = getelementptr ", value->id);
  284. if (instr->get_element_ptr.inbounds) {
  285. ssa_fprintf(f, "inbounds ");
  286. }
  287. ssa_print_type(f, m->sizes, et);
  288. ssa_fprintf(f, ", ");
  289. ssa_print_type(f, m->sizes, et);
  290. ssa_fprintf(f, "* ");
  291. ssa_print_value(f, m, instr->get_element_ptr.address, et);
  292. for (isize i = 0; i < instr->get_element_ptr.index_count; i++) {
  293. ssaValue *index = instr->get_element_ptr.indices[i];
  294. Type *t = ssa_value_type(index);
  295. ssa_fprintf(f, ", ");
  296. ssa_print_type(f, m->sizes, t);
  297. ssa_fprintf(f, " ");
  298. ssa_print_value(f, m, index, t);
  299. }
  300. ssa_fprintf(f, "\n");
  301. } break;
  302. case ssaInstr_ExtractValue: {
  303. Type *et = instr->extract_value.elem_type;
  304. ssa_fprintf(f, "%%%d = extractvalue ", value->id);
  305. ssa_print_type(f, m->sizes, et);
  306. ssa_fprintf(f, " ");
  307. ssa_print_value(f, m, instr->extract_value.address, et);
  308. ssa_fprintf(f, ", %d\n", instr->extract_value.index);
  309. } break;
  310. case ssaInstr_Br: {
  311. ssa_fprintf(f, "br ");
  312. if (instr->br.cond != NULL) {
  313. ssa_print_type(f, m->sizes, t_bool);
  314. ssa_fprintf(f, " ");
  315. ssa_print_value(f, m, instr->br.cond, t_bool);
  316. ssa_fprintf(f, ", ", instr->br.cond->id);
  317. }
  318. ssa_fprintf(f, "label ");
  319. ssa_fprintf(f, "%%"); ssa_print_block_name(f, instr->br.true_block);
  320. if (instr->br.false_block != NULL) {
  321. ssa_fprintf(f, ", label ");
  322. ssa_fprintf(f, "%%"); ssa_print_block_name(f, instr->br.false_block);
  323. }
  324. ssa_fprintf(f, "\n");
  325. } break;
  326. case ssaInstr_Ret: {
  327. auto *ret = &instr->ret;
  328. ssa_fprintf(f, "ret ");
  329. if (ret->value == NULL) {
  330. ssa_fprintf(f, "void");
  331. } else {
  332. Type *t = ssa_value_type(ret->value);
  333. ssa_print_type(f, m->sizes, t);
  334. ssa_fprintf(f, " ");
  335. ssa_print_value(f, m, ret->value, t);
  336. }
  337. ssa_fprintf(f, "\n");
  338. } break;
  339. case ssaInstr_Conv: {
  340. auto *c = &instr->conv;
  341. ssa_fprintf(f, "%%%d = %.*s ", value->id, LIT(ssa_conv_strings[c->kind]));
  342. ssa_print_type(f, m->sizes, c->from);
  343. ssa_fprintf(f, " ");
  344. ssa_print_value(f, m, c->value, c->from);
  345. ssa_fprintf(f, " to ");
  346. ssa_print_type(f, m->sizes, c->to);
  347. ssa_fprintf(f, "\n");
  348. } break;
  349. case ssaInstr_Unreachable: {
  350. ssa_fprintf(f, "unreachable\n");
  351. } break;
  352. case ssaInstr_BinaryOp: {
  353. auto *bo = &value->instr.binary_op;
  354. Type *type = get_base_type(ssa_value_type(bo->left));
  355. Type *elem_type = type;
  356. while (elem_type->kind == Type_Vector) {
  357. elem_type = get_base_type(elem_type->vector.elem);
  358. }
  359. ssa_fprintf(f, "%%%d = ", value->id);
  360. if (gb_is_between(bo->op.kind, Token__ComparisonBegin+1, Token__ComparisonEnd-1)) {
  361. if (is_type_float(elem_type)) {
  362. ssa_fprintf(f, "fcmp ");
  363. switch (bo->op.kind) {
  364. case Token_CmpEq: ssa_fprintf(f, "oeq"); break;
  365. case Token_NotEq: ssa_fprintf(f, "one"); break;
  366. case Token_Lt: ssa_fprintf(f, "olt"); break;
  367. case Token_Gt: ssa_fprintf(f, "ogt"); break;
  368. case Token_LtEq: ssa_fprintf(f, "ole"); break;
  369. case Token_GtEq: ssa_fprintf(f, "oge"); break;
  370. }
  371. } else {
  372. ssa_fprintf(f, "icmp ");
  373. if (bo->op.kind != Token_CmpEq &&
  374. bo->op.kind != Token_NotEq) {
  375. if (is_type_unsigned(elem_type)) {
  376. ssa_fprintf(f, "u");
  377. } else {
  378. ssa_fprintf(f, "s");
  379. }
  380. }
  381. switch (bo->op.kind) {
  382. case Token_CmpEq: ssa_fprintf(f, "eq"); break;
  383. case Token_NotEq: ssa_fprintf(f, "ne"); break;
  384. case Token_Lt: ssa_fprintf(f, "lt"); break;
  385. case Token_Gt: ssa_fprintf(f, "gt"); break;
  386. case Token_LtEq: ssa_fprintf(f, "le"); break;
  387. case Token_GtEq: ssa_fprintf(f, "ge"); break;
  388. }
  389. }
  390. } else {
  391. if (is_type_float(elem_type))
  392. ssa_fprintf(f, "f");
  393. switch (bo->op.kind) {
  394. case Token_Add: ssa_fprintf(f, "add"); break;
  395. case Token_Sub: ssa_fprintf(f, "sub"); break;
  396. case Token_And: ssa_fprintf(f, "and"); break;
  397. case Token_Or: ssa_fprintf(f, "or"); break;
  398. case Token_Xor: ssa_fprintf(f, "xor"); break;
  399. case Token_Shl: ssa_fprintf(f, "shl"); break;
  400. case Token_Shr: ssa_fprintf(f, "lshr"); break;
  401. case Token_Mul: ssa_fprintf(f, "mul"); break;
  402. case Token_AndNot: GB_PANIC("Token_AndNot Should never be called");
  403. default: {
  404. if (!is_type_float(elem_type)) {
  405. if (is_type_unsigned(elem_type)) ssa_fprintf(f, "u");
  406. else ssa_fprintf(f, "s");
  407. }
  408. switch (bo->op.kind) {
  409. case Token_Quo: ssa_fprintf(f, "div"); break;
  410. case Token_Mod: ssa_fprintf(f, "rem"); break;
  411. }
  412. } break;
  413. }
  414. }
  415. ssa_fprintf(f, " ");
  416. ssa_print_type(f, m->sizes, type);
  417. ssa_fprintf(f, " ");
  418. ssa_print_value(f, m, bo->left, type);
  419. ssa_fprintf(f, ", ");
  420. ssa_print_value(f, m, bo->right, type);
  421. ssa_fprintf(f, "\n");
  422. } break;
  423. case ssaInstr_Call: {
  424. auto *call = &instr->call;
  425. Type *result_type = call->type->proc.results;
  426. if (result_type) {
  427. ssa_fprintf(f, "%%%d = ", value->id);
  428. }
  429. ssa_fprintf(f, "call ");
  430. if (result_type) {
  431. ssa_print_type(f, m->sizes, result_type);
  432. } else {
  433. ssa_fprintf(f, "void");
  434. }
  435. ssa_fprintf(f, " ");
  436. ssa_print_value(f, m, call->value, call->type);
  437. ssa_fprintf(f, "(");
  438. auto *params = &call->type->proc.params->tuple;
  439. for (isize i = 0; i < call->arg_count; i++) {
  440. Entity *e = params->variables[i];
  441. GB_ASSERT(e != NULL);
  442. Type *t = e->type;
  443. if (i > 0) {
  444. ssa_fprintf(f, ", ");
  445. }
  446. ssa_print_type(f, m->sizes, t);
  447. ssa_fprintf(f, " ");
  448. ssaValue *arg = call->args[i];
  449. ssa_print_value(f, m, arg, t);
  450. }
  451. ssa_fprintf(f, ")\n");
  452. } break;
  453. case ssaInstr_Select: {
  454. ssa_fprintf(f, "%%%d = select i1 ", value->id);
  455. ssa_print_value(f, m, instr->select.cond, t_bool);
  456. ssa_fprintf(f, ", ");
  457. ssa_print_type(f, m->sizes, ssa_value_type(instr->select.true_value));
  458. ssa_fprintf(f, " ");
  459. ssa_print_value(f, m, instr->select.true_value, ssa_value_type(instr->select.true_value));
  460. ssa_fprintf(f, ", ");
  461. ssa_print_type(f, m->sizes, ssa_value_type(instr->select.false_value));
  462. ssa_fprintf(f, " ");
  463. ssa_print_value(f, m, instr->select.false_value, ssa_value_type(instr->select.false_value));
  464. ssa_fprintf(f, "\n");
  465. } break;
  466. case ssaInstr_CopyMemory: {
  467. ssa_fprintf(f, "call void @llvm.memmove.p0i8.p0i8.");
  468. ssa_print_type(f, m->sizes, t_int);
  469. ssa_fprintf(f, "(i8* ");
  470. ssa_print_value(f, m, instr->copy_memory.dst, t_rawptr);
  471. ssa_fprintf(f, ", i8* ");
  472. ssa_print_value(f, m, instr->copy_memory.src, t_rawptr);
  473. ssa_fprintf(f, ", ");
  474. ssa_print_type(f, m->sizes, t_int);
  475. ssa_fprintf(f, " ");
  476. ssa_print_value(f, m, instr->copy_memory.len, t_int);
  477. char *vol_str = "false";
  478. if (instr->copy_memory.is_volatile) {
  479. vol_str = "true";
  480. }
  481. ssa_fprintf(f, ", i32 %d, i1 %s)\n", instr->copy_memory.align, vol_str);
  482. } break;
  483. case ssaInstr_ExtractElement: {
  484. Type *vt = ssa_value_type(instr->extract_element.vector);
  485. ssa_fprintf(f, "%%%d = extractelement ", value->id);
  486. ssa_print_type(f, m->sizes, vt);
  487. ssa_fprintf(f, " ");
  488. ssa_print_value(f, m, instr->extract_element.vector, vt);
  489. ssa_fprintf(f, ", ");
  490. Type *it = ssa_value_type(instr->extract_element.index);
  491. ssa_print_type(f, m->sizes, it);
  492. ssa_fprintf(f, " ");
  493. ssa_print_value(f, m, instr->extract_element.index, it);
  494. ssa_fprintf(f, "\n");
  495. } break;
  496. case ssaInstr_InsertElement: {
  497. auto *ie = &instr->insert_element;
  498. Type *vt = ssa_value_type(ie->vector);
  499. ssa_fprintf(f, "%%%d = insertelement ", value->id);
  500. ssa_print_type(f, m->sizes, vt);
  501. ssa_fprintf(f, " ");
  502. ssa_print_value(f, m, ie->vector, vt);
  503. ssa_fprintf(f, ", ");
  504. ssa_print_type(f, m->sizes, ssa_value_type(ie->elem));
  505. ssa_fprintf(f, " ");
  506. ssa_print_value(f, m, ie->elem, ssa_value_type(ie->elem));
  507. ssa_fprintf(f, ", ");
  508. ssa_print_type(f, m->sizes, ssa_value_type(ie->index));
  509. ssa_fprintf(f, " ");
  510. ssa_print_value(f, m, ie->index, ssa_value_type(ie->index));
  511. ssa_fprintf(f, "\n");
  512. } break;
  513. default: {
  514. GB_PANIC("<unknown instr> %d\n", instr->kind);
  515. ssa_fprintf(f, "; <unknown instr> %d\n", instr->kind);
  516. } break;
  517. }
  518. }
  519. void ssa_print_proc(gbFile *f, ssaModule *m, ssaProcedure *proc) {
  520. if (proc->body == NULL) {
  521. ssa_fprintf(f, "declare ");
  522. } else {
  523. ssa_fprintf(f, "define ");
  524. }
  525. auto *proc_type = &proc->type->proc;
  526. if (proc_type->result_count == 0) {
  527. ssa_fprintf(f, "void");
  528. } else {
  529. ssa_print_type(f, m->sizes, proc_type->results);
  530. }
  531. ssa_fprintf(f, " ");
  532. ssa_print_encoded_global(f, proc->name);
  533. ssa_fprintf(f, "(");
  534. if (proc_type->param_count > 0) {
  535. auto *params = &proc_type->params->tuple;
  536. for (isize i = 0; i < params->variable_count; i++) {
  537. Entity *e = params->variables[i];
  538. if (i > 0)
  539. ssa_fprintf(f, ", ");
  540. ssa_print_type(f, m->sizes, e->type);
  541. ssa_fprintf(f, " %%%.*s", LIT(e->token.string));
  542. }
  543. }
  544. ssa_fprintf(f, ") ");
  545. if (proc->body == NULL) {
  546. ssa_fprintf(f, "\t; foreign procedure\n\n");
  547. } else {
  548. ssa_fprintf(f, "{\n");
  549. gb_for_array(i, proc->blocks) {
  550. ssaBlock *block = proc->blocks[i];
  551. if (i > 0) ssa_fprintf(f, "\n");
  552. ssa_print_block_name(f, block);
  553. ssa_fprintf(f, ":\n");
  554. gb_for_array(j, block->instrs) {
  555. ssaValue *value = block->instrs[j];
  556. ssa_print_instr(f, m, value);
  557. }
  558. }
  559. ssa_fprintf(f, "}\n\n");
  560. }
  561. gb_for_array(i, proc->children) {
  562. ssa_print_proc(f, m, proc->children[i]);
  563. }
  564. }
  565. void ssa_print_type_name(gbFile *f, ssaModule *m, ssaValue *v) {
  566. GB_ASSERT(v->kind == ssaValue_TypeName);
  567. ssa_print_encoded_local(f, v->type_name.name);
  568. ssa_fprintf(f, " = type ");
  569. ssa_print_type(f, m->sizes, get_base_type(v->type_name.type));
  570. ssa_fprintf(f, "\n");
  571. }
  572. void ssa_print_llvm_ir(gbFile *f, ssaModule *m) {
  573. if (m->layout.len > 0) {
  574. ssa_fprintf(f, "target datalayout = \"%.*s\"\n", LIT(m->layout));
  575. }
  576. ssa_print_encoded_local(f, make_string(".string"));
  577. ssa_fprintf(f, " = type {i8*, ");
  578. ssa_print_type(f, m->sizes, t_int);
  579. ssa_fprintf(f, "} ; Basic_string\n\n");
  580. ssa_print_encoded_local(f, make_string(".rawptr"));
  581. ssa_fprintf(f, " = type i8* ; Basic_rawptr\n\n");
  582. ssa_fprintf(f, "declare void @llvm.memmove.p0i8.p0i8.");
  583. ssa_print_type(f, m->sizes, t_int);
  584. ssa_fprintf(f, "(i8*, i8*, ");
  585. ssa_print_type(f, m->sizes, t_int);
  586. ssa_fprintf(f, ", i32, i1)\n\n");
  587. gb_for_array(i, m->nested_type_names) {
  588. ssaValue *v = m->nested_type_names[i];
  589. ssa_print_type_name(f, m, v);
  590. }
  591. gb_for_array(member_index, m->members.entries) {
  592. auto *entry = &m->members.entries[member_index];
  593. ssaValue *v = entry->value;
  594. switch (v->kind) {
  595. case ssaValue_TypeName: {
  596. ssa_print_encoded_local(f, v->type_name.name);
  597. ssa_fprintf(f, " = type ");
  598. ssa_print_type(f, m->sizes, get_base_type(v->type_name.type));
  599. ssa_fprintf(f, "\n");
  600. } break;
  601. case ssaValue_Global: {
  602. auto *g = &v->global;
  603. ssa_print_encoded_global(f, g->entity->token.string);
  604. ssa_fprintf(f, " = ");
  605. if (g->is_constant) {
  606. ssa_fprintf(f, "private constant ");
  607. } else {
  608. ssa_fprintf(f, "global ");
  609. }
  610. ssa_print_type(f, m->sizes, get_base_type(g->entity->type));
  611. ssa_fprintf(f, " ");
  612. ssa_print_value(f, m, g->value, g->entity->type);
  613. ssa_fprintf(f, "\n");
  614. } break;
  615. case ssaValue_Proc: {
  616. ssa_print_proc(f, m, &v->proc);
  617. } break;
  618. }
  619. }
  620. }