zig

fork of https://codeberg.org/ziglang/zig
Log | Tree | Refs | README | LICENSE

blob c6863210 (156166B) - Raw


      1 /*
      2  * Copyright (c) 2015 Andrew Kelley
      3  *
      4  * This file is part of zig, which is MIT licensed.
      5  * See http://opensource.org/licenses/MIT
      6  */
      7 
      8 #include "codegen.hpp"
      9 #include "hash_map.hpp"
     10 #include "zig_llvm.hpp"
     11 #include "os.hpp"
     12 #include "config.h"
     13 #include "error.hpp"
     14 #include "analyze.hpp"
     15 #include "errmsg.hpp"
     16 #include "parseh.hpp"
     17 #include "ast_render.hpp"
     18 
     19 #include <stdio.h>
     20 #include <errno.h>
     21 
     22 
     23 CodeGen *codegen_create(Buf *root_source_dir) {
     24     CodeGen *g = allocate<CodeGen>(1);
     25     g->link_table.init(32);
     26     g->import_table.init(32);
     27     g->builtin_fn_table.init(32);
     28     g->primitive_type_table.init(32);
     29     g->unresolved_top_level_decls.init(32);
     30     g->fn_type_table.init(32);
     31     g->build_type = CodeGenBuildTypeDebug;
     32     g->root_source_dir = root_source_dir;
     33     g->next_error_index = 1;
     34     g->error_value_count = 1;
     35 
     36     g->libc_lib_dir = buf_create_from_str(ZIG_LIBC_LIB_DIR);
     37     g->libc_include_dir = buf_create_from_str(ZIG_LIBC_INCLUDE_DIR);
     38 
     39     return g;
     40 }
     41 
     42 void codegen_set_clang_argv(CodeGen *g, const char **args, int len) {
     43     g->clang_argv = args;
     44     g->clang_argv_len = len;
     45 }
     46 
     47 void codegen_set_build_type(CodeGen *g, CodeGenBuildType build_type) {
     48     g->build_type = build_type;
     49 }
     50 
     51 void codegen_set_is_static(CodeGen *g, bool is_static) {
     52     g->is_static = is_static;
     53 }
     54 
     55 void codegen_set_verbose(CodeGen *g, bool verbose) {
     56     g->verbose = verbose;
     57 }
     58 
     59 void codegen_set_errmsg_color(CodeGen *g, ErrColor err_color) {
     60     g->err_color = err_color;
     61 }
     62 
     63 void codegen_set_strip(CodeGen *g, bool strip) {
     64     g->strip_debug_symbols = strip;
     65 }
     66 
     67 void codegen_set_out_type(CodeGen *g, OutType out_type) {
     68     g->out_type = out_type;
     69 }
     70 
     71 void codegen_set_out_name(CodeGen *g, Buf *out_name) {
     72     g->root_out_name = out_name;
     73 }
     74 
     75 void codegen_set_libc_lib_dir(CodeGen *g, Buf *libc_lib_dir) {
     76     g->libc_lib_dir = libc_lib_dir;
     77 }
     78 
     79 void codegen_set_libc_include_dir(CodeGen *g, Buf *libc_include_dir) {
     80     g->libc_include_dir = libc_include_dir;
     81 }
     82 
     83 void codegen_add_lib_dir(CodeGen *g, const char *dir) {
     84     g->lib_dirs.append(dir);
     85 }
     86 
     87 static LLVMValueRef gen_expr(CodeGen *g, AstNode *expr_node);
     88 static LLVMValueRef gen_lvalue(CodeGen *g, AstNode *expr_node, AstNode *node, TypeTableEntry **out_type_entry);
     89 static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lvalue);
     90 static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVariableDeclaration *var_decl,
     91         bool unwrap_maybe, LLVMValueRef *init_val, TypeTableEntry **init_val_type);
     92 static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType bin_op,
     93         LLVMValueRef target_ref, LLVMValueRef value,
     94         TypeTableEntry *op1_type, TypeTableEntry *op2_type);
     95 static LLVMValueRef gen_unwrap_maybe(CodeGen *g, AstNode *node, LLVMValueRef maybe_struct_ref);
     96 
     97 static TypeTableEntry *get_type_for_type_node(AstNode *node) {
     98     Expr *expr = get_resolved_expr(node);
     99     assert(expr->type_entry->id == TypeTableEntryIdMetaType);
    100     ConstExprValue *const_val = &expr->const_val;
    101     assert(const_val->ok);
    102     return const_val->data.x_type;
    103 }
    104 
    105 static void add_debug_source_node(CodeGen *g, AstNode *node) {
    106     assert(node->block_context);
    107     LLVMZigSetCurrentDebugLocation(g->builder, node->line + 1, node->column + 1, node->block_context->di_scope);
    108 }
    109 
    110 static TypeTableEntry *get_expr_type(AstNode *node) {
    111     return get_resolved_expr(node)->type_entry;
    112 }
    113 
    114 static TypeTableEntry *fn_proto_type_from_type_node(CodeGen *g, AstNode *type_node) {
    115     TypeTableEntry *type_entry = get_type_for_type_node(type_node);
    116 
    117     if (handle_is_ptr(type_entry)) {
    118         return get_pointer_to_type(g, type_entry, true);
    119     } else {
    120         return type_entry;
    121     }
    122 }
    123 
    124 enum AddSubMul {
    125     AddSubMulAdd = 0,
    126     AddSubMulSub = 1,
    127     AddSubMulMul = 2,
    128 };
    129 
    130 static int bits_index(int size_in_bits) {
    131     switch (size_in_bits) {
    132         case 8:
    133             return 0;
    134         case 16:
    135             return 1;
    136         case 32:
    137             return 2;
    138         case 64:
    139             return 3;
    140         default:
    141             zig_unreachable();
    142     }
    143 }
    144 
    145 static LLVMValueRef get_arithmetic_overflow_fn(CodeGen *g, TypeTableEntry *type_entry,
    146         const char *signed_name, const char *unsigned_name)
    147 {
    148     const char *signed_str = type_entry->data.integral.is_signed ? signed_name : unsigned_name;
    149     Buf *llvm_name = buf_sprintf("llvm.%s.with.overflow.i%" PRIu64, signed_str, type_entry->size_in_bits);
    150 
    151     LLVMTypeRef return_elem_types[] = {
    152         type_entry->type_ref,
    153         LLVMInt1Type(),
    154     };
    155     LLVMTypeRef param_types[] = {
    156         type_entry->type_ref,
    157         type_entry->type_ref,
    158     };
    159     LLVMTypeRef return_struct_type = LLVMStructType(return_elem_types, 2, false);
    160     LLVMTypeRef fn_type = LLVMFunctionType(return_struct_type, param_types, 2, false);
    161     LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(llvm_name), fn_type);
    162     assert(LLVMGetIntrinsicID(fn_val));
    163     return fn_val;
    164 }
    165 
    166 static LLVMValueRef get_int_overflow_fn(CodeGen *g, TypeTableEntry *type_entry, AddSubMul add_sub_mul) {
    167     assert(type_entry->id == TypeTableEntryIdInt);
    168     // [0-signed,1-unsigned][0-add,1-sub,2-mul][0-8,1-16,2-32,3-64]
    169     int index0 = type_entry->data.integral.is_signed ? 0 : 1;
    170     int index1 = add_sub_mul;
    171     int index2 = bits_index(type_entry->size_in_bits);
    172     LLVMValueRef *fn = &g->int_overflow_fns[index0][index1][index2];
    173     if (*fn) {
    174         return *fn;
    175     }
    176     switch (add_sub_mul) {
    177         case AddSubMulAdd:
    178             *fn = get_arithmetic_overflow_fn(g, type_entry, "sadd", "uadd");
    179             break;
    180         case AddSubMulSub:
    181             *fn = get_arithmetic_overflow_fn(g, type_entry, "ssub", "usub");
    182             break;
    183         case AddSubMulMul:
    184             *fn = get_arithmetic_overflow_fn(g, type_entry, "smul", "umul");
    185             break;
    186 
    187     }
    188     return *fn;
    189 }
    190 
    191 
    192 static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
    193     assert(node->type == NodeTypeFnCallExpr);
    194     AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;
    195     assert(fn_ref_expr->type == NodeTypeSymbol);
    196     BuiltinFnEntry *builtin_fn = node->data.fn_call_expr.builtin_fn;
    197 
    198     switch (builtin_fn->id) {
    199         case BuiltinFnIdInvalid:
    200         case BuiltinFnIdTypeof:
    201         case BuiltinFnIdCInclude:
    202         case BuiltinFnIdCDefine:
    203         case BuiltinFnIdCUndef:
    204             zig_unreachable();
    205         case BuiltinFnIdAddWithOverflow:
    206         case BuiltinFnIdSubWithOverflow:
    207         case BuiltinFnIdMulWithOverflow:
    208             {
    209                 int fn_call_param_count = node->data.fn_call_expr.params.length;
    210                 assert(fn_call_param_count == 4);
    211 
    212                 TypeTableEntry *int_type = get_type_for_type_node(node->data.fn_call_expr.params.at(0));
    213                 AddSubMul add_sub_mul;
    214                 if (builtin_fn->id == BuiltinFnIdAddWithOverflow) {
    215                     add_sub_mul = AddSubMulAdd;
    216                 } else if (builtin_fn->id == BuiltinFnIdSubWithOverflow) {
    217                     add_sub_mul = AddSubMulSub;
    218                 } else if (builtin_fn->id == BuiltinFnIdMulWithOverflow) {
    219                     add_sub_mul = AddSubMulMul;
    220                 } else {
    221                     zig_unreachable();
    222                 }
    223                 LLVMValueRef fn_val = get_int_overflow_fn(g, int_type, add_sub_mul);
    224 
    225                 LLVMValueRef op1 = gen_expr(g, node->data.fn_call_expr.params.at(1));
    226                 LLVMValueRef op2 = gen_expr(g, node->data.fn_call_expr.params.at(2));
    227                 LLVMValueRef ptr_result = gen_expr(g, node->data.fn_call_expr.params.at(3));
    228 
    229                 LLVMValueRef params[] = {
    230                     op1,
    231                     op2,
    232                 };
    233 
    234                 add_debug_source_node(g, node);
    235                 LLVMValueRef result_struct = LLVMBuildCall(g->builder, fn_val, params, 2, "");
    236                 LLVMValueRef result = LLVMBuildExtractValue(g->builder, result_struct, 0, "");
    237                 LLVMValueRef overflow_bit = LLVMBuildExtractValue(g->builder, result_struct, 1, "");
    238                 LLVMBuildStore(g->builder, result, ptr_result);
    239 
    240                 return overflow_bit;
    241             }
    242         case BuiltinFnIdMemcpy:
    243             {
    244                 int fn_call_param_count = node->data.fn_call_expr.params.length;
    245                 assert(fn_call_param_count == 3);
    246 
    247                 AstNode *dest_node = node->data.fn_call_expr.params.at(0);
    248                 TypeTableEntry *dest_type = get_expr_type(dest_node);
    249 
    250                 LLVMValueRef dest_ptr = gen_expr(g, dest_node);
    251                 LLVMValueRef src_ptr = gen_expr(g, node->data.fn_call_expr.params.at(1));
    252                 LLVMValueRef len_val = gen_expr(g, node->data.fn_call_expr.params.at(2));
    253 
    254                 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
    255 
    256                 add_debug_source_node(g, node);
    257                 LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, dest_ptr, ptr_u8, "");
    258                 LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr, ptr_u8, "");
    259 
    260                 uint64_t align_in_bytes = dest_type->data.pointer.child_type->align_in_bits / 8;
    261 
    262                 LLVMValueRef params[] = {
    263                     dest_ptr_casted, // dest pointer
    264                     src_ptr_casted, // source pointer
    265                     len_val, // byte count
    266                     LLVMConstInt(LLVMInt32Type(), align_in_bytes, false), // align in bytes
    267                     LLVMConstNull(LLVMInt1Type()), // is volatile
    268                 };
    269 
    270                 LLVMBuildCall(g->builder, builtin_fn->fn_val, params, 5, "");
    271                 return nullptr;
    272             }
    273         case BuiltinFnIdMemset:
    274             {
    275                 int fn_call_param_count = node->data.fn_call_expr.params.length;
    276                 assert(fn_call_param_count == 3);
    277 
    278                 AstNode *dest_node = node->data.fn_call_expr.params.at(0);
    279                 TypeTableEntry *dest_type = get_expr_type(dest_node);
    280 
    281                 LLVMValueRef dest_ptr = gen_expr(g, dest_node);
    282                 LLVMValueRef char_val = gen_expr(g, node->data.fn_call_expr.params.at(1));
    283                 LLVMValueRef len_val = gen_expr(g, node->data.fn_call_expr.params.at(2));
    284 
    285                 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
    286 
    287                 add_debug_source_node(g, node);
    288                 LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, dest_ptr, ptr_u8, "");
    289 
    290                 uint64_t align_in_bytes = dest_type->data.pointer.child_type->align_in_bits / 8;
    291 
    292                 LLVMValueRef params[] = {
    293                     dest_ptr_casted, // dest pointer
    294                     char_val, // source pointer
    295                     len_val, // byte count
    296                     LLVMConstInt(LLVMInt32Type(), align_in_bytes, false), // align in bytes
    297                     LLVMConstNull(LLVMInt1Type()), // is volatile
    298                 };
    299 
    300                 LLVMBuildCall(g->builder, builtin_fn->fn_val, params, 5, "");
    301                 return nullptr;
    302             }
    303         case BuiltinFnIdSizeof:
    304         case BuiltinFnIdMinValue:
    305         case BuiltinFnIdMaxValue:
    306         case BuiltinFnIdMemberCount:
    307             // caught by constant expression eval codegen
    308             zig_unreachable();
    309     }
    310     zig_unreachable();
    311 }
    312 
    313 static LLVMValueRef gen_enum_value_expr(CodeGen *g, AstNode *node, TypeTableEntry *enum_type,
    314         AstNode *arg_node)
    315 {
    316     assert(node->type == NodeTypeFieldAccessExpr);
    317 
    318     uint64_t value = node->data.field_access_expr.type_enum_field->value;
    319     LLVMTypeRef tag_type_ref = enum_type->data.enumeration.tag_type->type_ref;
    320     LLVMValueRef tag_value = LLVMConstInt(tag_type_ref, value, false);
    321 
    322     if (enum_type->data.enumeration.gen_field_count == 0) {
    323         return tag_value;
    324     } else {
    325         TypeTableEntry *arg_node_type = nullptr;
    326         LLVMValueRef new_union_val = gen_expr(g, arg_node);
    327         if (arg_node) {
    328             arg_node_type = get_expr_type(arg_node);
    329             new_union_val = gen_expr(g, arg_node);
    330         } else {
    331             arg_node_type = g->builtin_types.entry_void;
    332         }
    333 
    334         LLVMValueRef tmp_struct_ptr = node->data.field_access_expr.resolved_struct_val_expr.ptr;
    335 
    336         // populate the new tag value
    337         add_debug_source_node(g, node);
    338         LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 0, "");
    339         LLVMBuildStore(g->builder, tag_value, tag_field_ptr);
    340 
    341         if (arg_node_type->id != TypeTableEntryIdVoid) {
    342             // populate the union value
    343             TypeTableEntry *union_val_type = get_expr_type(arg_node);
    344             LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 1, "");
    345             LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr,
    346                     LLVMPointerType(union_val_type->type_ref, 0), "");
    347 
    348             gen_assign_raw(g, arg_node, BinOpTypeAssign, bitcasted_union_field_ptr, new_union_val,
    349                     union_val_type, union_val_type);
    350 
    351         }
    352 
    353         return tmp_struct_ptr;
    354     }
    355 }
    356 
    357 static LLVMValueRef gen_widen_or_shorten(CodeGen *g, AstNode *source_node, TypeTableEntry *actual_type,
    358         TypeTableEntry *wanted_type, LLVMValueRef expr_val)
    359 {
    360     assert(actual_type->id == wanted_type->id);
    361     if (actual_type->size_in_bits == wanted_type->size_in_bits) {
    362         return expr_val;
    363     } else if (actual_type->size_in_bits < wanted_type->size_in_bits) {
    364         if (actual_type->id == TypeTableEntryIdFloat) {
    365             add_debug_source_node(g, source_node);
    366             return LLVMBuildFPExt(g->builder, expr_val, wanted_type->type_ref, "");
    367         } else if (actual_type->id == TypeTableEntryIdInt) {
    368             if (actual_type->data.integral.is_signed) {
    369                 add_debug_source_node(g, source_node);
    370                 return LLVMBuildSExt(g->builder, expr_val, wanted_type->type_ref, "");
    371             } else {
    372                 add_debug_source_node(g, source_node);
    373                 return LLVMBuildZExt(g->builder, expr_val, wanted_type->type_ref, "");
    374             }
    375         } else {
    376             zig_unreachable();
    377         }
    378     } else if (actual_type->size_in_bits > wanted_type->size_in_bits) {
    379         if (actual_type->id == TypeTableEntryIdFloat) {
    380             add_debug_source_node(g, source_node);
    381             return LLVMBuildFPTrunc(g->builder, expr_val, wanted_type->type_ref, "");
    382         } else if (actual_type->id == TypeTableEntryIdInt) {
    383             add_debug_source_node(g, source_node);
    384             return LLVMBuildTrunc(g->builder, expr_val, wanted_type->type_ref, "");
    385         } else {
    386             zig_unreachable();
    387         }
    388     } else {
    389         zig_unreachable();
    390     }
    391 }
    392 
    393 static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {
    394     assert(node->type == NodeTypeFnCallExpr);
    395 
    396     AstNode *expr_node = node->data.fn_call_expr.params.at(0);
    397 
    398     LLVMValueRef expr_val = gen_expr(g, expr_node);
    399 
    400     TypeTableEntry *actual_type = get_expr_type(expr_node);
    401     TypeTableEntry *wanted_type = get_expr_type(node);
    402 
    403     AstNodeFnCallExpr *cast_expr = &node->data.fn_call_expr;
    404 
    405     switch (cast_expr->cast_op) {
    406         case CastOpNoCast:
    407             zig_unreachable();
    408         case CastOpNoop:
    409             return expr_val;
    410         case CastOpErrToInt:
    411             assert(actual_type->id == TypeTableEntryIdErrorUnion);
    412             if (actual_type->data.error.child_type->size_in_bits == 0) {
    413                 return gen_widen_or_shorten(g, node, g->err_tag_type, wanted_type, expr_val);
    414             } else {
    415                 zig_panic("TODO");
    416             }
    417         case CastOpMaybeWrap:
    418             {
    419                 assert(cast_expr->tmp_ptr);
    420                 assert(wanted_type->id == TypeTableEntryIdMaybe);
    421                 assert(actual_type);
    422 
    423                 TypeTableEntry *child_type = wanted_type->data.maybe.child_type;
    424 
    425                 if (child_type->id == TypeTableEntryIdPointer ||
    426                     child_type->id == TypeTableEntryIdFn)
    427                 {
    428                     return expr_val;
    429                 } else {
    430                     add_debug_source_node(g, node);
    431                     LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, 0, "");
    432                     gen_assign_raw(g, node, BinOpTypeAssign,
    433                             val_ptr, expr_val, child_type, actual_type);
    434 
    435                     add_debug_source_node(g, node);
    436                     LLVMValueRef maybe_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, 1, "");
    437                     LLVMBuildStore(g->builder, LLVMConstAllOnes(LLVMInt1Type()), maybe_ptr);
    438                 }
    439 
    440                 return cast_expr->tmp_ptr;
    441             }
    442         case CastOpErrorWrap:
    443             {
    444                 assert(wanted_type->id == TypeTableEntryIdErrorUnion);
    445                 TypeTableEntry *child_type = wanted_type->data.error.child_type;
    446                 LLVMValueRef ok_err_val = LLVMConstNull(g->err_tag_type->type_ref);
    447 
    448                 if (child_type->size_in_bits == 0) {
    449                     return ok_err_val;
    450                 } else {
    451                     assert(cast_expr->tmp_ptr);
    452                     assert(wanted_type->id == TypeTableEntryIdErrorUnion);
    453                     assert(actual_type);
    454 
    455                     add_debug_source_node(g, node);
    456                     LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, 0, "");
    457                     LLVMBuildStore(g->builder, ok_err_val, err_tag_ptr);
    458 
    459                     LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, 1, "");
    460                     gen_assign_raw(g, node, BinOpTypeAssign,
    461                             payload_ptr, expr_val, child_type, actual_type);
    462 
    463                     return cast_expr->tmp_ptr;
    464                 }
    465             }
    466         case CastOpPureErrorWrap:
    467             assert(wanted_type->id == TypeTableEntryIdErrorUnion);
    468             if (wanted_type->data.error.child_type->size_in_bits == 0) {
    469                 return expr_val;
    470             } else {
    471                 zig_panic("TODO");
    472             }
    473         case CastOpPtrToInt:
    474             add_debug_source_node(g, node);
    475             return LLVMBuildPtrToInt(g->builder, expr_val, wanted_type->type_ref, "");
    476         case CastOpIntToPtr:
    477             add_debug_source_node(g, node);
    478             return LLVMBuildIntToPtr(g->builder, expr_val, wanted_type->type_ref, "");
    479         case CastOpPointerReinterpret:
    480             add_debug_source_node(g, node);
    481             return LLVMBuildBitCast(g->builder, expr_val, wanted_type->type_ref, "");
    482         case CastOpWidenOrShorten:
    483             return gen_widen_or_shorten(g, node, actual_type, wanted_type, expr_val);
    484         case CastOpToUnknownSizeArray:
    485             {
    486                 assert(cast_expr->tmp_ptr);
    487                 assert(wanted_type->id == TypeTableEntryIdStruct);
    488                 assert(wanted_type->data.structure.is_unknown_size_array);
    489 
    490                 TypeTableEntry *pointer_type = wanted_type->data.structure.fields[0].type_entry;
    491 
    492                 add_debug_source_node(g, node);
    493 
    494                 LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, 0, "");
    495                 LLVMValueRef expr_bitcast = LLVMBuildBitCast(g->builder, expr_val, pointer_type->type_ref, "");
    496                 LLVMBuildStore(g->builder, expr_bitcast, ptr_ptr);
    497 
    498                 LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, 1, "");
    499                 LLVMValueRef len_val = LLVMConstInt(g->builtin_types.entry_isize->type_ref,
    500                         actual_type->data.array.len, false);
    501                 LLVMBuildStore(g->builder, len_val, len_ptr);
    502 
    503                 return cast_expr->tmp_ptr;
    504             }
    505         case CastOpIntToFloat:
    506             assert(actual_type->id == TypeTableEntryIdInt);
    507             if (actual_type->data.integral.is_signed) {
    508                 add_debug_source_node(g, node);
    509                 return LLVMBuildSIToFP(g->builder, expr_val, wanted_type->type_ref, "");
    510             } else {
    511                 add_debug_source_node(g, node);
    512                 return LLVMBuildUIToFP(g->builder, expr_val, wanted_type->type_ref, "");
    513             }
    514         case CastOpFloatToInt:
    515             assert(wanted_type->id == TypeTableEntryIdInt);
    516             if (wanted_type->data.integral.is_signed) {
    517                 add_debug_source_node(g, node);
    518                 return LLVMBuildFPToSI(g->builder, expr_val, wanted_type->type_ref, "");
    519             } else {
    520                 add_debug_source_node(g, node);
    521                 return LLVMBuildFPToUI(g->builder, expr_val, wanted_type->type_ref, "");
    522             }
    523 
    524     }
    525     zig_unreachable();
    526 }
    527 
    528 
    529 static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {
    530     assert(node->type == NodeTypeFnCallExpr);
    531 
    532     if (node->data.fn_call_expr.is_builtin) {
    533         return gen_builtin_fn_call_expr(g, node);
    534     } else if (node->data.fn_call_expr.cast_op != CastOpNoCast) {
    535         return gen_cast_expr(g, node);
    536     }
    537 
    538     FnTableEntry *fn_table_entry = node->data.fn_call_expr.fn_entry;
    539     AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;
    540     TypeTableEntry *struct_type = nullptr;
    541     AstNode *first_param_expr = nullptr;
    542     if (fn_ref_expr->type == NodeTypeFieldAccessExpr) {
    543         first_param_expr = fn_ref_expr->data.field_access_expr.struct_expr;
    544         struct_type = get_expr_type(first_param_expr);
    545         if (struct_type->id == TypeTableEntryIdStruct) {
    546             fn_table_entry = node->data.fn_call_expr.fn_entry;
    547         } else if (struct_type->id == TypeTableEntryIdPointer) {
    548             assert(struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct);
    549             fn_table_entry = node->data.fn_call_expr.fn_entry;
    550         } else if (struct_type->id == TypeTableEntryIdMetaType) {
    551             TypeTableEntry *child_type = get_type_for_type_node(first_param_expr);
    552 
    553             if (child_type->id == TypeTableEntryIdEnum) {
    554                 int param_count = node->data.fn_call_expr.params.length;
    555                 AstNode *arg1_node;
    556                 if (param_count == 1) {
    557                     arg1_node = node->data.fn_call_expr.params.at(0);
    558                 } else {
    559                     assert(param_count == 0);
    560                     arg1_node = nullptr;
    561                 }
    562                 return gen_enum_value_expr(g, fn_ref_expr, child_type, arg1_node);
    563             } else if (child_type->id == TypeTableEntryIdStruct) {
    564                 struct_type = nullptr;
    565                 first_param_expr = nullptr;
    566                 fn_table_entry = node->data.fn_call_expr.fn_entry;
    567             } else {
    568                 zig_unreachable();
    569             }
    570         } else {
    571             zig_unreachable();
    572         }
    573     }
    574 
    575     TypeTableEntry *fn_type;
    576     LLVMValueRef fn_val;
    577     if (fn_table_entry) {
    578         fn_val = fn_table_entry->fn_value;
    579         fn_type = fn_table_entry->type_entry;
    580     } else {
    581         fn_val = gen_expr(g, fn_ref_expr);
    582         fn_type = get_expr_type(fn_ref_expr);
    583     }
    584 
    585     TypeTableEntry *src_return_type = fn_type->data.fn.fn_type_id.return_type;
    586 
    587     int fn_call_param_count = node->data.fn_call_expr.params.length;
    588     bool first_arg_ret = handle_is_ptr(src_return_type);
    589     int actual_param_count = fn_call_param_count + (struct_type ? 1 : 0) + (first_arg_ret ? 1 : 0);
    590     bool is_var_args = fn_type->data.fn.fn_type_id.is_var_args;
    591 
    592     // don't really include void values
    593     LLVMValueRef *gen_param_values = allocate<LLVMValueRef>(actual_param_count);
    594 
    595     int gen_param_index = 0;
    596     if (first_arg_ret) {
    597         gen_param_values[gen_param_index] = node->data.fn_call_expr.tmp_ptr;
    598         gen_param_index += 1;
    599     }
    600     if (struct_type) {
    601         gen_param_values[gen_param_index] = gen_expr(g, first_param_expr);
    602         gen_param_index += 1;
    603     }
    604 
    605     for (int i = 0; i < fn_call_param_count; i += 1) {
    606         AstNode *expr_node = node->data.fn_call_expr.params.at(i);
    607         LLVMValueRef param_value = gen_expr(g, expr_node);
    608         TypeTableEntry *param_type = get_expr_type(expr_node);
    609         if (is_var_args || param_type->size_in_bits > 0) {
    610             gen_param_values[gen_param_index] = param_value;
    611             gen_param_index += 1;
    612         }
    613     }
    614 
    615     add_debug_source_node(g, node);
    616     LLVMValueRef result = LLVMZigBuildCall(g->builder, fn_val,
    617             gen_param_values, gen_param_index, fn_type->data.fn.calling_convention, "");
    618 
    619     if (src_return_type->id == TypeTableEntryIdUnreachable) {
    620         return LLVMBuildUnreachable(g->builder);
    621     } else if (first_arg_ret) {
    622         return node->data.fn_call_expr.tmp_ptr;
    623     } else if (src_return_type->size_in_bits == 0) {
    624         return nullptr;
    625     } else {
    626         return result;
    627     }
    628 }
    629 
    630 static LLVMValueRef gen_array_base_ptr(CodeGen *g, AstNode *node) {
    631     TypeTableEntry *type_entry = get_expr_type(node);
    632 
    633     LLVMValueRef array_ptr;
    634     if (node->type == NodeTypeFieldAccessExpr) {
    635         array_ptr = gen_field_access_expr(g, node, true);
    636         if (type_entry->id == TypeTableEntryIdPointer) {
    637             // we have a double pointer so we must dereference it once
    638             add_debug_source_node(g, node);
    639             array_ptr = LLVMBuildLoad(g->builder, array_ptr, "");
    640         }
    641     } else {
    642         array_ptr = gen_expr(g, node);
    643     }
    644 
    645     assert(!array_ptr || LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
    646 
    647     return array_ptr;
    648 }
    649 
    650 static LLVMValueRef gen_array_elem_ptr(CodeGen *g, AstNode *source_node, LLVMValueRef array_ptr,
    651         TypeTableEntry *array_type, LLVMValueRef subscript_value)
    652 {
    653     assert(subscript_value);
    654 
    655     if (array_type->size_in_bits == 0) {
    656         return nullptr;
    657     }
    658 
    659     if (array_type->id == TypeTableEntryIdArray) {
    660         LLVMValueRef indices[] = {
    661             LLVMConstNull(g->builtin_types.entry_isize->type_ref),
    662             subscript_value
    663         };
    664         add_debug_source_node(g, source_node);
    665         return LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 2, "");
    666     } else if (array_type->id == TypeTableEntryIdPointer) {
    667         assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
    668         LLVMValueRef indices[] = {
    669             subscript_value
    670         };
    671         add_debug_source_node(g, source_node);
    672         return LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 1, "");
    673     } else if (array_type->id == TypeTableEntryIdStruct) {
    674         assert(array_type->data.structure.is_unknown_size_array);
    675         assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
    676         assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind);
    677 
    678         add_debug_source_node(g, source_node);
    679         LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, array_ptr, 0, "");
    680         LLVMValueRef ptr = LLVMBuildLoad(g->builder, ptr_ptr, "");
    681         return LLVMBuildInBoundsGEP(g->builder, ptr, &subscript_value, 1, "");
    682     } else {
    683         zig_unreachable();
    684     }
    685 }
    686 
    687 static LLVMValueRef gen_array_ptr(CodeGen *g, AstNode *node) {
    688     assert(node->type == NodeTypeArrayAccessExpr);
    689 
    690     AstNode *array_expr_node = node->data.array_access_expr.array_ref_expr;
    691     TypeTableEntry *array_type = get_expr_type(array_expr_node);
    692 
    693     LLVMValueRef array_ptr = gen_array_base_ptr(g, array_expr_node);
    694 
    695     LLVMValueRef subscript_value = gen_expr(g, node->data.array_access_expr.subscript);
    696 
    697     return gen_array_elem_ptr(g, node, array_ptr, array_type, subscript_value);
    698 }
    699 
    700 static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **out_type_entry) {
    701     assert(node->type == NodeTypeFieldAccessExpr);
    702 
    703     AstNode *struct_expr_node = node->data.field_access_expr.struct_expr;
    704 
    705     LLVMValueRef struct_ptr;
    706     if (struct_expr_node->type == NodeTypeSymbol) {
    707         VariableTableEntry *var = struct_expr_node->data.symbol_expr.variable;
    708         assert(var);
    709 
    710         if (var->is_ptr && var->type->id == TypeTableEntryIdPointer) {
    711             add_debug_source_node(g, node);
    712             struct_ptr = LLVMBuildLoad(g->builder, var->value_ref, "");
    713         } else {
    714             struct_ptr = var->value_ref;
    715         }
    716     } else if (struct_expr_node->type == NodeTypeFieldAccessExpr) {
    717         struct_ptr = gen_field_access_expr(g, struct_expr_node, true);
    718         TypeTableEntry *field_type = get_expr_type(struct_expr_node);
    719         if (field_type->id == TypeTableEntryIdPointer) {
    720             // we have a double pointer so we must dereference it once
    721             add_debug_source_node(g, node);
    722             struct_ptr = LLVMBuildLoad(g->builder, struct_ptr, "");
    723         }
    724     } else {
    725         struct_ptr = gen_expr(g, struct_expr_node);
    726     }
    727 
    728     assert(LLVMGetTypeKind(LLVMTypeOf(struct_ptr)) == LLVMPointerTypeKind);
    729     assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(struct_ptr))) == LLVMStructTypeKind);
    730 
    731     int gen_field_index = node->data.field_access_expr.type_struct_field->gen_index;
    732     assert(gen_field_index >= 0);
    733 
    734     *out_type_entry = node->data.field_access_expr.type_struct_field->type_entry;
    735 
    736     add_debug_source_node(g, node);
    737     return LLVMBuildStructGEP(g->builder, struct_ptr, gen_field_index, "");
    738 }
    739 
    740 static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {
    741     assert(node->type == NodeTypeSliceExpr);
    742 
    743     AstNode *array_ref_node = node->data.slice_expr.array_ref_expr;
    744     TypeTableEntry *array_type = get_expr_type(array_ref_node);
    745 
    746     LLVMValueRef tmp_struct_ptr = node->data.slice_expr.resolved_struct_val_expr.ptr;
    747     LLVMValueRef array_ptr = gen_array_base_ptr(g, array_ref_node);
    748 
    749     if (array_type->id == TypeTableEntryIdArray) {
    750         LLVMValueRef start_val = gen_expr(g, node->data.slice_expr.start);
    751         LLVMValueRef end_val;
    752         if (node->data.slice_expr.end) {
    753             end_val = gen_expr(g, node->data.slice_expr.end);
    754         } else {
    755             end_val = LLVMConstInt(g->builtin_types.entry_isize->type_ref, array_type->data.array.len, false);
    756         }
    757 
    758         add_debug_source_node(g, node);
    759         LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 0, "");
    760         LLVMValueRef indices[] = {
    761             LLVMConstNull(g->builtin_types.entry_isize->type_ref),
    762             start_val,
    763         };
    764         LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 2, "");
    765         LLVMBuildStore(g->builder, slice_start_ptr, ptr_field_ptr);
    766 
    767         LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 1, "");
    768         LLVMValueRef len_value = LLVMBuildSub(g->builder, end_val, start_val, "");
    769         LLVMBuildStore(g->builder, len_value, len_field_ptr);
    770 
    771         return tmp_struct_ptr;
    772     } else if (array_type->id == TypeTableEntryIdPointer) {
    773         LLVMValueRef start_val = gen_expr(g, node->data.slice_expr.start);
    774         LLVMValueRef end_val = gen_expr(g, node->data.slice_expr.end);
    775 
    776         add_debug_source_node(g, node);
    777         LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 0, "");
    778         LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, &start_val, 1, "");
    779         LLVMBuildStore(g->builder, slice_start_ptr, ptr_field_ptr);
    780 
    781         LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 1, "");
    782         LLVMValueRef len_value = LLVMBuildSub(g->builder, end_val, start_val, "");
    783         LLVMBuildStore(g->builder, len_value, len_field_ptr);
    784 
    785         return tmp_struct_ptr;
    786     } else if (array_type->id == TypeTableEntryIdStruct) {
    787         assert(array_type->data.structure.is_unknown_size_array);
    788         assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
    789         assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind);
    790 
    791         LLVMValueRef start_val = gen_expr(g, node->data.slice_expr.start);
    792         LLVMValueRef end_val;
    793         if (node->data.slice_expr.end) {
    794             end_val = gen_expr(g, node->data.slice_expr.end);
    795         } else {
    796             add_debug_source_node(g, node);
    797             LLVMValueRef src_len_ptr = LLVMBuildStructGEP(g->builder, array_ptr, 1, "");
    798             end_val = LLVMBuildLoad(g->builder, src_len_ptr, "");
    799         }
    800 
    801         add_debug_source_node(g, node);
    802         LLVMValueRef src_ptr_ptr = LLVMBuildStructGEP(g->builder, array_ptr, 0, "");
    803         LLVMValueRef src_ptr = LLVMBuildLoad(g->builder, src_ptr_ptr, "");
    804         LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 0, "");
    805         LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, src_ptr, &start_val, 1, "");
    806         LLVMBuildStore(g->builder, slice_start_ptr, ptr_field_ptr);
    807 
    808         LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 1, "");
    809         LLVMValueRef len_value = LLVMBuildSub(g->builder, end_val, start_val, "");
    810         LLVMBuildStore(g->builder, len_value, len_field_ptr);
    811 
    812         return tmp_struct_ptr;
    813     } else {
    814         zig_unreachable();
    815     }
    816 }
    817 
    818 
    819 static LLVMValueRef gen_array_access_expr(CodeGen *g, AstNode *node, bool is_lvalue) {
    820     assert(node->type == NodeTypeArrayAccessExpr);
    821 
    822     LLVMValueRef ptr = gen_array_ptr(g, node);
    823     TypeTableEntry *child_type;
    824     TypeTableEntry *array_type = get_expr_type(node->data.array_access_expr.array_ref_expr);
    825     if (array_type->id == TypeTableEntryIdPointer) {
    826         child_type = array_type->data.pointer.child_type;
    827     } else if (array_type->id == TypeTableEntryIdStruct) {
    828         assert(array_type->data.structure.is_unknown_size_array);
    829         TypeTableEntry *child_ptr_type = array_type->data.structure.fields[0].type_entry;
    830         assert(child_ptr_type->id == TypeTableEntryIdPointer);
    831         child_type = child_ptr_type->data.pointer.child_type;
    832     } else if (array_type->id == TypeTableEntryIdArray) {
    833         child_type = array_type->data.array.child_type;
    834     } else {
    835         zig_unreachable();
    836     }
    837 
    838     if (is_lvalue || !ptr || handle_is_ptr(child_type)) {
    839         return ptr;
    840     } else {
    841         add_debug_source_node(g, node);
    842         return LLVMBuildLoad(g->builder, ptr, "");
    843     }
    844 }
    845 
    846 static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lvalue) {
    847     assert(node->type == NodeTypeFieldAccessExpr);
    848 
    849     AstNode *struct_expr = node->data.field_access_expr.struct_expr;
    850     TypeTableEntry *struct_type = get_expr_type(struct_expr);
    851     Buf *name = &node->data.field_access_expr.field_name;
    852 
    853     if (struct_type->id == TypeTableEntryIdArray) {
    854         if (buf_eql_str(name, "len")) {
    855             return LLVMConstInt(g->builtin_types.entry_isize->type_ref,
    856                     struct_type->data.array.len, false);
    857         } else if (buf_eql_str(name, "ptr")) {
    858             LLVMValueRef array_val = gen_expr(g, node->data.field_access_expr.struct_expr);
    859             LLVMValueRef indices[] = {
    860                 LLVMConstNull(g->builtin_types.entry_isize->type_ref),
    861                 LLVMConstNull(g->builtin_types.entry_isize->type_ref),
    862             };
    863             add_debug_source_node(g, node);
    864             return LLVMBuildInBoundsGEP(g->builder, array_val, indices, 2, "");
    865         } else {
    866             zig_panic("gen_field_access_expr bad array field");
    867         }
    868     } else if (struct_type->id == TypeTableEntryIdStruct || (struct_type->id == TypeTableEntryIdPointer &&
    869                struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct))
    870     {
    871         TypeTableEntry *type_entry;
    872         LLVMValueRef ptr = gen_field_ptr(g, node, &type_entry);
    873         if (is_lvalue || handle_is_ptr(type_entry)) {
    874             return ptr;
    875         } else {
    876             add_debug_source_node(g, node);
    877             return LLVMBuildLoad(g->builder, ptr, "");
    878         }
    879     } else if (struct_type->id == TypeTableEntryIdMetaType) {
    880         assert(!is_lvalue);
    881         TypeTableEntry *child_type = get_type_for_type_node(struct_expr);
    882         if (child_type->id == TypeTableEntryIdEnum) {
    883             return gen_enum_value_expr(g, node, child_type, nullptr);
    884         } else {
    885             zig_unreachable();
    886         }
    887     } else {
    888         zig_unreachable();
    889     }
    890 }
    891 
    892 static LLVMValueRef gen_lvalue(CodeGen *g, AstNode *expr_node, AstNode *node,
    893         TypeTableEntry **out_type_entry)
    894 {
    895     LLVMValueRef target_ref;
    896 
    897     if (node->type == NodeTypeSymbol) {
    898         VariableTableEntry *var = node->data.symbol_expr.variable;
    899         assert(var);
    900 
    901         *out_type_entry = var->type;
    902         target_ref = var->value_ref;
    903     } else if (node->type == NodeTypeArrayAccessExpr) {
    904         TypeTableEntry *array_type = get_expr_type(node->data.array_access_expr.array_ref_expr);
    905         if (array_type->id == TypeTableEntryIdArray) {
    906             *out_type_entry = array_type->data.array.child_type;
    907             target_ref = gen_array_ptr(g, node);
    908         } else if (array_type->id == TypeTableEntryIdPointer) {
    909             *out_type_entry = array_type->data.pointer.child_type;
    910             target_ref = gen_array_ptr(g, node);
    911         } else if (array_type->id == TypeTableEntryIdStruct) {
    912             assert(array_type->data.structure.is_unknown_size_array);
    913             *out_type_entry = array_type->data.structure.fields[0].type_entry->data.pointer.child_type;
    914             target_ref = gen_array_ptr(g, node);
    915         } else {
    916             zig_unreachable();
    917         }
    918     } else if (node->type == NodeTypeFieldAccessExpr) {
    919         target_ref = gen_field_ptr(g, node, out_type_entry);
    920     } else if (node->type == NodeTypePrefixOpExpr) {
    921         assert(node->data.prefix_op_expr.prefix_op == PrefixOpDereference);
    922         AstNode *target_expr = node->data.prefix_op_expr.primary_expr;
    923         TypeTableEntry *type_entry = get_expr_type(target_expr);
    924         assert(type_entry->id == TypeTableEntryIdPointer);
    925         *out_type_entry = type_entry->data.pointer.child_type;
    926         return gen_expr(g, target_expr);
    927     } else {
    928         zig_panic("bad assign target");
    929     }
    930 
    931     return target_ref;
    932 }
    933 
    934 static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
    935     assert(node->type == NodeTypePrefixOpExpr);
    936     assert(node->data.prefix_op_expr.primary_expr);
    937 
    938     AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
    939     TypeTableEntry *expr_type = get_expr_type(expr_node);
    940 
    941     switch (node->data.prefix_op_expr.prefix_op) {
    942         case PrefixOpInvalid:
    943             zig_unreachable();
    944         case PrefixOpNegation:
    945             {
    946                 LLVMValueRef expr = gen_expr(g, expr_node);
    947                 if (expr_type->id == TypeTableEntryIdInt) {
    948                     add_debug_source_node(g, node);
    949                     return LLVMBuildNeg(g->builder, expr, "");
    950                 } else if (expr_type->id == TypeTableEntryIdFloat) {
    951                     add_debug_source_node(g, node);
    952                     return LLVMBuildFNeg(g->builder, expr, "");
    953                 } else {
    954                     zig_unreachable();
    955                 }
    956             }
    957         case PrefixOpBoolNot:
    958             {
    959                 LLVMValueRef expr = gen_expr(g, expr_node);
    960                 LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(expr));
    961                 add_debug_source_node(g, node);
    962                 return LLVMBuildICmp(g->builder, LLVMIntEQ, expr, zero, "");
    963             }
    964         case PrefixOpBinNot:
    965             {
    966                 LLVMValueRef expr = gen_expr(g, expr_node);
    967                 add_debug_source_node(g, node);
    968                 return LLVMBuildNot(g->builder, expr, "");
    969             }
    970         case PrefixOpAddressOf:
    971         case PrefixOpConstAddressOf:
    972             {
    973                 TypeTableEntry *lvalue_type;
    974                 return gen_lvalue(g, node, expr_node, &lvalue_type);
    975             }
    976 
    977         case PrefixOpDereference:
    978             {
    979                 LLVMValueRef expr = gen_expr(g, expr_node);
    980                 if (expr_type->size_in_bits == 0) {
    981                     return nullptr;
    982                 } else {
    983                     add_debug_source_node(g, node);
    984                     return LLVMBuildLoad(g->builder, expr, "");
    985                 }
    986             }
    987         case PrefixOpMaybe:
    988             {
    989                 zig_panic("TODO codegen PrefixOpMaybe");
    990             }
    991         case PrefixOpError:
    992             {
    993                 zig_panic("TODO codegen PrefixOpError");
    994             }
    995         case PrefixOpUnwrapError:
    996             {
    997                 LLVMValueRef expr_val = gen_expr(g, expr_node);
    998                 TypeTableEntry *expr_type = get_expr_type(expr_node);
    999                 assert(expr_type->id == TypeTableEntryIdErrorUnion);
   1000                 TypeTableEntry *child_type = expr_type->data.error.child_type;
   1001 
   1002                 if (g->build_type != CodeGenBuildTypeRelease) {
   1003                     LLVMValueRef err_val;
   1004                     if (child_type->size_in_bits > 0) {
   1005                         add_debug_source_node(g, node);
   1006                         LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 0, "");
   1007                         err_val = LLVMBuildLoad(g->builder, err_val_ptr, "");
   1008                     } else {
   1009                         err_val = expr_val;
   1010                     }
   1011                     LLVMValueRef zero = LLVMConstNull(g->err_tag_type->type_ref);
   1012                     LLVMValueRef cond_val = LLVMBuildICmp(g->builder, LLVMIntEQ, err_val, zero, "");
   1013                     LLVMBasicBlockRef err_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapErrError");
   1014                     LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapErrOk");
   1015                     LLVMBuildCondBr(g->builder, cond_val, ok_block, err_block);
   1016 
   1017                     LLVMPositionBuilderAtEnd(g->builder, err_block);
   1018                     LLVMBuildCall(g->builder, g->trap_fn_val, nullptr, 0, "");
   1019                     LLVMBuildUnreachable(g->builder);
   1020 
   1021                     LLVMPositionBuilderAtEnd(g->builder, ok_block);
   1022                 }
   1023 
   1024                 if (child_type->size_in_bits > 0) {
   1025                     LLVMValueRef child_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 1, "");
   1026                     if (handle_is_ptr(child_type)) {
   1027                         return child_val_ptr;
   1028                     } else {
   1029                         return LLVMBuildLoad(g->builder, child_val_ptr, "");
   1030                     }
   1031                 } else {
   1032                     return nullptr;
   1033                 }
   1034             }
   1035         case PrefixOpUnwrapMaybe:
   1036             {
   1037                 LLVMValueRef expr_val = gen_expr(g, expr_node);
   1038 
   1039                 TypeTableEntry *expr_type = get_expr_type(expr_node);
   1040                 assert(expr_type->id == TypeTableEntryIdMaybe);
   1041                 TypeTableEntry *child_type = expr_type->data.maybe.child_type;
   1042 
   1043                 if (g->build_type != CodeGenBuildTypeRelease) {
   1044                     add_debug_source_node(g, node);
   1045                     LLVMValueRef cond_val;
   1046                     if (child_type->id == TypeTableEntryIdPointer ||
   1047                         child_type->id == TypeTableEntryIdFn)
   1048                     {
   1049                         cond_val = LLVMBuildICmp(g->builder, LLVMIntNE, expr_val,
   1050                                 LLVMConstNull(child_type->type_ref), "");
   1051                     } else {
   1052                         LLVMValueRef maybe_null_ptr = LLVMBuildStructGEP(g->builder, expr_val, 1, "");
   1053                         cond_val = LLVMBuildLoad(g->builder, maybe_null_ptr, "");
   1054                     }
   1055 
   1056                     LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapMaybeOk");
   1057                     LLVMBasicBlockRef null_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapMaybeNull");
   1058                     LLVMBuildCondBr(g->builder, cond_val, ok_block, null_block);
   1059 
   1060                     LLVMPositionBuilderAtEnd(g->builder, null_block);
   1061                     LLVMBuildCall(g->builder, g->trap_fn_val, nullptr, 0, "");
   1062                     LLVMBuildUnreachable(g->builder);
   1063 
   1064                     LLVMPositionBuilderAtEnd(g->builder, ok_block);
   1065                 }
   1066 
   1067 
   1068                 if (child_type->id == TypeTableEntryIdPointer ||
   1069                     child_type->id == TypeTableEntryIdFn)
   1070                 {
   1071                     return expr_val;
   1072                 } else {
   1073                     add_debug_source_node(g, node);
   1074                     LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, expr_val, 0, "");
   1075                     if (handle_is_ptr(child_type)) {
   1076                         return maybe_field_ptr;
   1077                     } else {
   1078                         return LLVMBuildLoad(g->builder, maybe_field_ptr, "");
   1079                     }
   1080                 }
   1081             }
   1082     }
   1083     zig_unreachable();
   1084 }
   1085 
   1086 static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node,
   1087     LLVMValueRef val1, LLVMValueRef val2,
   1088     TypeTableEntry *op1_type, TypeTableEntry *op2_type,
   1089     BinOpType bin_op)
   1090 {
   1091     assert(op1_type == op2_type);
   1092 
   1093     switch (bin_op) {
   1094         case BinOpTypeBinOr:
   1095         case BinOpTypeAssignBitOr:
   1096             add_debug_source_node(g, source_node);
   1097             return LLVMBuildOr(g->builder, val1, val2, "");
   1098         case BinOpTypeBinXor:
   1099         case BinOpTypeAssignBitXor:
   1100             add_debug_source_node(g, source_node);
   1101             return LLVMBuildXor(g->builder, val1, val2, "");
   1102         case BinOpTypeBinAnd:
   1103         case BinOpTypeAssignBitAnd:
   1104             add_debug_source_node(g, source_node);
   1105             return LLVMBuildAnd(g->builder, val1, val2, "");
   1106         case BinOpTypeBitShiftLeft:
   1107         case BinOpTypeAssignBitShiftLeft:
   1108             add_debug_source_node(g, source_node);
   1109             return LLVMBuildShl(g->builder, val1, val2, "");
   1110         case BinOpTypeBitShiftRight:
   1111         case BinOpTypeAssignBitShiftRight:
   1112             assert(op1_type->id == TypeTableEntryIdInt);
   1113             assert(op2_type->id == TypeTableEntryIdInt);
   1114 
   1115             add_debug_source_node(g, source_node);
   1116             if (op1_type->data.integral.is_signed) {
   1117                 return LLVMBuildAShr(g->builder, val1, val2, "");
   1118             } else {
   1119                 return LLVMBuildLShr(g->builder, val1, val2, "");
   1120             }
   1121         case BinOpTypeAdd:
   1122         case BinOpTypeAssignPlus:
   1123             add_debug_source_node(g, source_node);
   1124             if (op1_type->id == TypeTableEntryIdFloat) {
   1125                 return LLVMBuildFAdd(g->builder, val1, val2, "");
   1126             } else {
   1127                 return LLVMBuildAdd(g->builder, val1, val2, "");
   1128             }
   1129         case BinOpTypeSub:
   1130         case BinOpTypeAssignMinus:
   1131             add_debug_source_node(g, source_node);
   1132             if (op1_type->id == TypeTableEntryIdFloat) {
   1133                 return LLVMBuildFSub(g->builder, val1, val2, "");
   1134             } else {
   1135                 return LLVMBuildSub(g->builder, val1, val2, "");
   1136             }
   1137         case BinOpTypeMult:
   1138         case BinOpTypeAssignTimes:
   1139             add_debug_source_node(g, source_node);
   1140             if (op1_type->id == TypeTableEntryIdFloat) {
   1141                 return LLVMBuildFMul(g->builder, val1, val2, "");
   1142             } else {
   1143                 return LLVMBuildMul(g->builder, val1, val2, "");
   1144             }
   1145         case BinOpTypeDiv:
   1146         case BinOpTypeAssignDiv:
   1147             add_debug_source_node(g, source_node);
   1148             if (op1_type->id == TypeTableEntryIdFloat) {
   1149                 return LLVMBuildFDiv(g->builder, val1, val2, "");
   1150             } else {
   1151                 assert(op1_type->id == TypeTableEntryIdInt);
   1152                 if (op1_type->data.integral.is_signed) {
   1153                     return LLVMBuildSDiv(g->builder, val1, val2, "");
   1154                 } else {
   1155                     return LLVMBuildUDiv(g->builder, val1, val2, "");
   1156                 }
   1157             }
   1158         case BinOpTypeMod:
   1159         case BinOpTypeAssignMod:
   1160             add_debug_source_node(g, source_node);
   1161             if (op1_type->id == TypeTableEntryIdFloat) {
   1162                 return LLVMBuildFRem(g->builder, val1, val2, "");
   1163             } else {
   1164                 assert(op1_type->id == TypeTableEntryIdInt);
   1165                 if (op1_type->data.integral.is_signed) {
   1166                     return LLVMBuildSRem(g->builder, val1, val2, "");
   1167                 } else {
   1168                     return LLVMBuildURem(g->builder, val1, val2, "");
   1169                 }
   1170             }
   1171         case BinOpTypeBoolOr:
   1172         case BinOpTypeBoolAnd:
   1173         case BinOpTypeCmpEq:
   1174         case BinOpTypeCmpNotEq:
   1175         case BinOpTypeCmpLessThan:
   1176         case BinOpTypeCmpGreaterThan:
   1177         case BinOpTypeCmpLessOrEq:
   1178         case BinOpTypeCmpGreaterOrEq:
   1179         case BinOpTypeInvalid:
   1180         case BinOpTypeAssign:
   1181         case BinOpTypeAssignBoolAnd:
   1182         case BinOpTypeAssignBoolOr:
   1183         case BinOpTypeUnwrapMaybe:
   1184         case BinOpTypeStrCat:
   1185             zig_unreachable();
   1186     }
   1187     zig_unreachable();
   1188 }
   1189 static LLVMValueRef gen_arithmetic_bin_op_expr(CodeGen *g, AstNode *node) {
   1190     assert(node->type == NodeTypeBinOpExpr);
   1191 
   1192     LLVMValueRef val1 = gen_expr(g, node->data.bin_op_expr.op1);
   1193     LLVMValueRef val2 = gen_expr(g, node->data.bin_op_expr.op2);
   1194 
   1195     TypeTableEntry *op1_type = get_expr_type(node->data.bin_op_expr.op1);
   1196     TypeTableEntry *op2_type = get_expr_type(node->data.bin_op_expr.op2);
   1197     return gen_arithmetic_bin_op(g, node, val1, val2, op1_type, op2_type, node->data.bin_op_expr.bin_op);
   1198 
   1199 }
   1200 
   1201 static LLVMIntPredicate cmp_op_to_int_predicate(BinOpType cmp_op, bool is_signed) {
   1202     switch (cmp_op) {
   1203         case BinOpTypeCmpEq:
   1204             return LLVMIntEQ;
   1205         case BinOpTypeCmpNotEq:
   1206             return LLVMIntNE;
   1207         case BinOpTypeCmpLessThan:
   1208             return is_signed ? LLVMIntSLT : LLVMIntULT;
   1209         case BinOpTypeCmpGreaterThan:
   1210             return is_signed ? LLVMIntSGT : LLVMIntUGT;
   1211         case BinOpTypeCmpLessOrEq:
   1212             return is_signed ? LLVMIntSLE : LLVMIntULE;
   1213         case BinOpTypeCmpGreaterOrEq:
   1214             return is_signed ? LLVMIntSGE : LLVMIntUGE;
   1215         default:
   1216             zig_unreachable();
   1217     }
   1218 }
   1219 
   1220 static LLVMRealPredicate cmp_op_to_real_predicate(BinOpType cmp_op) {
   1221     switch (cmp_op) {
   1222         case BinOpTypeCmpEq:
   1223             return LLVMRealOEQ;
   1224         case BinOpTypeCmpNotEq:
   1225             return LLVMRealONE;
   1226         case BinOpTypeCmpLessThan:
   1227             return LLVMRealOLT;
   1228         case BinOpTypeCmpGreaterThan:
   1229             return LLVMRealOGT;
   1230         case BinOpTypeCmpLessOrEq:
   1231             return LLVMRealOLE;
   1232         case BinOpTypeCmpGreaterOrEq:
   1233             return LLVMRealOGE;
   1234         default:
   1235             zig_unreachable();
   1236     }
   1237 }
   1238 
   1239 static LLVMValueRef gen_cmp_expr(CodeGen *g, AstNode *node) {
   1240     assert(node->type == NodeTypeBinOpExpr);
   1241 
   1242     LLVMValueRef val1 = gen_expr(g, node->data.bin_op_expr.op1);
   1243     LLVMValueRef val2 = gen_expr(g, node->data.bin_op_expr.op2);
   1244 
   1245     TypeTableEntry *op1_type = get_expr_type(node->data.bin_op_expr.op1);
   1246     TypeTableEntry *op2_type = get_expr_type(node->data.bin_op_expr.op2);
   1247     assert(op1_type == op2_type);
   1248 
   1249     add_debug_source_node(g, node);
   1250     if (op1_type->id == TypeTableEntryIdFloat) {
   1251         LLVMRealPredicate pred = cmp_op_to_real_predicate(node->data.bin_op_expr.bin_op);
   1252         return LLVMBuildFCmp(g->builder, pred, val1, val2, "");
   1253     } else if (op1_type->id == TypeTableEntryIdInt) {
   1254         LLVMIntPredicate pred = cmp_op_to_int_predicate(node->data.bin_op_expr.bin_op,
   1255                 op1_type->data.integral.is_signed);
   1256         return LLVMBuildICmp(g->builder, pred, val1, val2, "");
   1257     } else if (op1_type->id == TypeTableEntryIdEnum) {
   1258         LLVMIntPredicate pred = cmp_op_to_int_predicate(node->data.bin_op_expr.bin_op, false);
   1259         return LLVMBuildICmp(g->builder, pred, val1, val2, "");
   1260     } else {
   1261         zig_unreachable();
   1262     }
   1263 }
   1264 
   1265 static LLVMValueRef gen_bool_and_expr(CodeGen *g, AstNode *node) {
   1266     assert(node->type == NodeTypeBinOpExpr);
   1267 
   1268     LLVMValueRef val1 = gen_expr(g, node->data.bin_op_expr.op1);
   1269     LLVMBasicBlockRef post_val1_block = LLVMGetInsertBlock(g->builder);
   1270 
   1271     // block for when val1 == true
   1272     LLVMBasicBlockRef true_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoolAndTrue");
   1273     // block for when val1 == false (don't even evaluate the second part)
   1274     LLVMBasicBlockRef false_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoolAndFalse");
   1275 
   1276     add_debug_source_node(g, node);
   1277     LLVMBuildCondBr(g->builder, val1, true_block, false_block);
   1278 
   1279     LLVMPositionBuilderAtEnd(g->builder, true_block);
   1280     LLVMValueRef val2 = gen_expr(g, node->data.bin_op_expr.op2);
   1281     LLVMBasicBlockRef post_val2_block = LLVMGetInsertBlock(g->builder);
   1282 
   1283     add_debug_source_node(g, node);
   1284     LLVMBuildBr(g->builder, false_block);
   1285 
   1286     LLVMPositionBuilderAtEnd(g->builder, false_block);
   1287     add_debug_source_node(g, node);
   1288     LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMInt1Type(), "");
   1289     LLVMValueRef incoming_values[2] = {val1, val2};
   1290     LLVMBasicBlockRef incoming_blocks[2] = {post_val1_block, post_val2_block};
   1291     LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2);
   1292 
   1293     return phi;
   1294 }
   1295 
   1296 static LLVMValueRef gen_bool_or_expr(CodeGen *g, AstNode *expr_node) {
   1297     assert(expr_node->type == NodeTypeBinOpExpr);
   1298 
   1299     LLVMValueRef val1 = gen_expr(g, expr_node->data.bin_op_expr.op1);
   1300     LLVMBasicBlockRef post_val1_block = LLVMGetInsertBlock(g->builder);
   1301 
   1302     // block for when val1 == false
   1303     LLVMBasicBlockRef false_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoolOrFalse");
   1304     // block for when val1 == true (don't even evaluate the second part)
   1305     LLVMBasicBlockRef true_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoolOrTrue");
   1306 
   1307     add_debug_source_node(g, expr_node);
   1308     LLVMBuildCondBr(g->builder, val1, true_block, false_block);
   1309 
   1310     LLVMPositionBuilderAtEnd(g->builder, false_block);
   1311     LLVMValueRef val2 = gen_expr(g, expr_node->data.bin_op_expr.op2);
   1312 
   1313     LLVMBasicBlockRef post_val2_block = LLVMGetInsertBlock(g->builder);
   1314 
   1315     add_debug_source_node(g, expr_node);
   1316     LLVMBuildBr(g->builder, true_block);
   1317 
   1318     LLVMPositionBuilderAtEnd(g->builder, true_block);
   1319     add_debug_source_node(g, expr_node);
   1320     LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMInt1Type(), "");
   1321     LLVMValueRef incoming_values[2] = {val1, val2};
   1322     LLVMBasicBlockRef incoming_blocks[2] = {post_val1_block, post_val2_block};
   1323     LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2);
   1324 
   1325     return phi;
   1326 }
   1327 
   1328 static LLVMValueRef gen_struct_memcpy(CodeGen *g, AstNode *source_node, LLVMValueRef src, LLVMValueRef dest,
   1329         TypeTableEntry *type_entry)
   1330 {
   1331     assert(handle_is_ptr(type_entry));
   1332 
   1333     LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
   1334 
   1335     add_debug_source_node(g, source_node);
   1336     LLVMValueRef src_ptr = LLVMBuildBitCast(g->builder, src, ptr_u8, "");
   1337     LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, dest, ptr_u8, "");
   1338 
   1339     LLVMValueRef params[] = {
   1340         dest_ptr, // dest pointer
   1341         src_ptr, // source pointer
   1342         LLVMConstInt(LLVMIntType(g->pointer_size_bytes * 8), type_entry->size_in_bits / 8, false), // byte count
   1343         LLVMConstInt(LLVMInt32Type(), type_entry->align_in_bits / 8, false), // align in bytes
   1344         LLVMConstNull(LLVMInt1Type()), // is volatile
   1345     };
   1346 
   1347     return LLVMBuildCall(g->builder, g->memcpy_fn_val, params, 5, "");
   1348 }
   1349 
   1350 static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType bin_op,
   1351         LLVMValueRef target_ref, LLVMValueRef value,
   1352         TypeTableEntry *op1_type, TypeTableEntry *op2_type)
   1353 {
   1354     if (handle_is_ptr(op1_type)) {
   1355         assert(op1_type == op2_type);
   1356         assert(bin_op == BinOpTypeAssign);
   1357 
   1358         return gen_struct_memcpy(g, source_node, value, target_ref, op1_type);
   1359     }
   1360 
   1361     if (bin_op != BinOpTypeAssign) {
   1362         assert(source_node->type == NodeTypeBinOpExpr);
   1363         add_debug_source_node(g, source_node->data.bin_op_expr.op1);
   1364         LLVMValueRef left_value = LLVMBuildLoad(g->builder, target_ref, "");
   1365 
   1366         value = gen_arithmetic_bin_op(g, source_node, left_value, value, op1_type, op2_type, bin_op);
   1367     }
   1368 
   1369     add_debug_source_node(g, source_node);
   1370     return LLVMBuildStore(g->builder, value, target_ref);
   1371 }
   1372 
   1373 static LLVMValueRef gen_assign_expr(CodeGen *g, AstNode *node) {
   1374     assert(node->type == NodeTypeBinOpExpr);
   1375 
   1376     AstNode *lhs_node = node->data.bin_op_expr.op1;
   1377 
   1378     TypeTableEntry *op1_type;
   1379 
   1380     LLVMValueRef target_ref = gen_lvalue(g, node, lhs_node, &op1_type);
   1381 
   1382     TypeTableEntry *op2_type = get_expr_type(node->data.bin_op_expr.op2);
   1383 
   1384     LLVMValueRef value = gen_expr(g, node->data.bin_op_expr.op2);
   1385 
   1386     if (op1_type->size_in_bits == 0) {
   1387         return nullptr;
   1388     }
   1389 
   1390     return gen_assign_raw(g, node, node->data.bin_op_expr.bin_op, target_ref, value, op1_type, op2_type);
   1391 }
   1392 
   1393 static LLVMValueRef gen_unwrap_maybe(CodeGen *g, AstNode *node, LLVMValueRef maybe_struct_ref) {
   1394     TypeTableEntry *type_entry = get_expr_type(node);
   1395     assert(type_entry->id == TypeTableEntryIdMaybe);
   1396     TypeTableEntry *child_type = type_entry->data.maybe.child_type;
   1397     if (child_type->id == TypeTableEntryIdPointer ||
   1398         child_type->id == TypeTableEntryIdFn)
   1399     {
   1400         return maybe_struct_ref;
   1401     } else {
   1402         add_debug_source_node(g, node);
   1403         LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_struct_ref, 0, "");
   1404         if (handle_is_ptr(child_type)) {
   1405             return maybe_field_ptr;
   1406         } else {
   1407             return LLVMBuildLoad(g->builder, maybe_field_ptr, "");
   1408         }
   1409     }
   1410 }
   1411 
   1412 static LLVMValueRef gen_unwrap_maybe_expr(CodeGen *g, AstNode *node) {
   1413     assert(node->type == NodeTypeBinOpExpr);
   1414     assert(node->data.bin_op_expr.bin_op == BinOpTypeUnwrapMaybe);
   1415 
   1416     AstNode *op1_node = node->data.bin_op_expr.op1;
   1417     AstNode *op2_node = node->data.bin_op_expr.op2;
   1418 
   1419     LLVMValueRef maybe_struct_ref = gen_expr(g, op1_node);
   1420 
   1421     TypeTableEntry *maybe_type = get_expr_type(op1_node);
   1422     assert(maybe_type->id == TypeTableEntryIdMaybe);
   1423     TypeTableEntry *child_type = maybe_type->data.maybe.child_type;
   1424 
   1425     LLVMValueRef cond_value;
   1426     if (child_type->id == TypeTableEntryIdPointer ||
   1427         child_type->id == TypeTableEntryIdFn)
   1428     {
   1429         cond_value = LLVMBuildICmp(g->builder, LLVMIntNE, maybe_struct_ref,
   1430                 LLVMConstNull(child_type->type_ref), "");
   1431     } else {
   1432         add_debug_source_node(g, node);
   1433         LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_struct_ref, 1, "");
   1434         cond_value = LLVMBuildLoad(g->builder, maybe_field_ptr, "");
   1435     }
   1436 
   1437     LLVMBasicBlockRef non_null_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "MaybeNonNull");
   1438     LLVMBasicBlockRef null_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "MaybeNull");
   1439     LLVMBasicBlockRef end_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "MaybeEnd");
   1440 
   1441     bool null_reachable = get_expr_type(op2_node)->id != TypeTableEntryIdUnreachable;
   1442 
   1443     LLVMBuildCondBr(g->builder, cond_value, non_null_block, null_block);
   1444 
   1445     LLVMPositionBuilderAtEnd(g->builder, non_null_block);
   1446     LLVMValueRef non_null_result = gen_unwrap_maybe(g, op1_node, maybe_struct_ref);
   1447     add_debug_source_node(g, node);
   1448     LLVMBuildBr(g->builder, end_block);
   1449     LLVMBasicBlockRef post_non_null_result_block = LLVMGetInsertBlock(g->builder);
   1450 
   1451     LLVMPositionBuilderAtEnd(g->builder, null_block);
   1452     LLVMValueRef null_result = gen_expr(g, op2_node);
   1453     if (null_reachable) {
   1454         add_debug_source_node(g, node);
   1455         LLVMBuildBr(g->builder, end_block);
   1456     }
   1457     LLVMBasicBlockRef post_null_result_block = LLVMGetInsertBlock(g->builder);
   1458 
   1459     LLVMPositionBuilderAtEnd(g->builder, end_block);
   1460     if (null_reachable) {
   1461         add_debug_source_node(g, node);
   1462         LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMTypeOf(non_null_result), "");
   1463         LLVMValueRef incoming_values[2] = {non_null_result, null_result};
   1464         LLVMBasicBlockRef incoming_blocks[2] = {post_non_null_result_block, post_null_result_block};
   1465         LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2);
   1466         return phi;
   1467     } else {
   1468         return non_null_result;
   1469     }
   1470 
   1471     return nullptr;
   1472 }
   1473 
   1474 static LLVMValueRef gen_bin_op_expr(CodeGen *g, AstNode *node) {
   1475     switch (node->data.bin_op_expr.bin_op) {
   1476         case BinOpTypeInvalid:
   1477         case BinOpTypeStrCat:
   1478             zig_unreachable();
   1479         case BinOpTypeAssign:
   1480         case BinOpTypeAssignTimes:
   1481         case BinOpTypeAssignDiv:
   1482         case BinOpTypeAssignMod:
   1483         case BinOpTypeAssignPlus:
   1484         case BinOpTypeAssignMinus:
   1485         case BinOpTypeAssignBitShiftLeft:
   1486         case BinOpTypeAssignBitShiftRight:
   1487         case BinOpTypeAssignBitAnd:
   1488         case BinOpTypeAssignBitXor:
   1489         case BinOpTypeAssignBitOr:
   1490         case BinOpTypeAssignBoolAnd:
   1491         case BinOpTypeAssignBoolOr:
   1492             return gen_assign_expr(g, node);
   1493         case BinOpTypeBoolOr:
   1494             return gen_bool_or_expr(g, node);
   1495         case BinOpTypeBoolAnd:
   1496             return gen_bool_and_expr(g, node);
   1497         case BinOpTypeCmpEq:
   1498         case BinOpTypeCmpNotEq:
   1499         case BinOpTypeCmpLessThan:
   1500         case BinOpTypeCmpGreaterThan:
   1501         case BinOpTypeCmpLessOrEq:
   1502         case BinOpTypeCmpGreaterOrEq:
   1503             return gen_cmp_expr(g, node);
   1504         case BinOpTypeUnwrapMaybe:
   1505             return gen_unwrap_maybe_expr(g, node);
   1506         case BinOpTypeBinOr:
   1507         case BinOpTypeBinXor:
   1508         case BinOpTypeBinAnd:
   1509         case BinOpTypeBitShiftLeft:
   1510         case BinOpTypeBitShiftRight:
   1511         case BinOpTypeAdd:
   1512         case BinOpTypeSub:
   1513         case BinOpTypeMult:
   1514         case BinOpTypeDiv:
   1515         case BinOpTypeMod:
   1516             return gen_arithmetic_bin_op_expr(g, node);
   1517     }
   1518     zig_unreachable();
   1519 }
   1520 
   1521 static LLVMValueRef gen_unwrap_err_expr(CodeGen *g, AstNode *node) {
   1522     assert(node->type == NodeTypeUnwrapErrorExpr);
   1523 
   1524     AstNode *op1 = node->data.unwrap_err_expr.op1;
   1525     AstNode *op2 = node->data.unwrap_err_expr.op2;
   1526     VariableTableEntry *var = node->data.unwrap_err_expr.var;
   1527 
   1528     LLVMValueRef expr_val = gen_expr(g, op1);
   1529     TypeTableEntry *expr_type = get_expr_type(op1);
   1530     TypeTableEntry *op2_type = get_expr_type(op2);
   1531     assert(expr_type->id == TypeTableEntryIdErrorUnion);
   1532     TypeTableEntry *child_type = expr_type->data.error.child_type;
   1533     LLVMValueRef err_val;
   1534     add_debug_source_node(g, node);
   1535     if (handle_is_ptr(expr_type)) {
   1536         LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 0, "");
   1537         err_val = LLVMBuildLoad(g->builder, err_val_ptr, "");
   1538     } else {
   1539         err_val = expr_val;
   1540     }
   1541     LLVMValueRef zero = LLVMConstNull(g->err_tag_type->type_ref);
   1542     LLVMValueRef cond_val = LLVMBuildICmp(g->builder, LLVMIntEQ, err_val, zero, "");
   1543 
   1544     LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapErrOk");
   1545     LLVMBasicBlockRef err_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapErrError");
   1546     LLVMBasicBlockRef end_block;
   1547     bool err_reachable = op2_type->id != TypeTableEntryIdUnreachable;
   1548     bool have_end_block = err_reachable && (child_type->size_in_bits > 0);
   1549     if (have_end_block) {
   1550         end_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapErrEnd");
   1551     }
   1552 
   1553     LLVMBuildCondBr(g->builder, cond_val, ok_block, err_block);
   1554 
   1555     LLVMPositionBuilderAtEnd(g->builder, err_block);
   1556     if (var) {
   1557         LLVMBuildStore(g->builder, err_val, var->value_ref);
   1558     }
   1559     LLVMValueRef err_result = gen_expr(g, op2);
   1560     add_debug_source_node(g, node);
   1561     if (have_end_block) {
   1562         LLVMBuildBr(g->builder, end_block);
   1563     } else if (err_reachable) {
   1564         LLVMBuildBr(g->builder, ok_block);
   1565     }
   1566 
   1567     LLVMPositionBuilderAtEnd(g->builder, ok_block);
   1568     if (child_type->size_in_bits == 0) {
   1569         return nullptr;
   1570     }
   1571     LLVMValueRef child_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 1, "");
   1572     LLVMValueRef child_val;
   1573     if (handle_is_ptr(child_type)) {
   1574         child_val = child_val_ptr;
   1575     } else {
   1576         child_val = LLVMBuildLoad(g->builder, child_val_ptr, "");
   1577     }
   1578 
   1579     if (!have_end_block) {
   1580         return child_val;
   1581     }
   1582 
   1583     LLVMBuildBr(g->builder, end_block);
   1584 
   1585     LLVMPositionBuilderAtEnd(g->builder, end_block);
   1586     LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMTypeOf(err_result), "");
   1587     LLVMValueRef incoming_values[2] = {child_val, err_result};
   1588     LLVMBasicBlockRef incoming_blocks[2] = {ok_block, err_block};
   1589     LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2);
   1590     return phi;
   1591 }
   1592 
   1593 static LLVMValueRef gen_return(CodeGen *g, AstNode *source_node, LLVMValueRef value) {
   1594     TypeTableEntry *return_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;
   1595     if (handle_is_ptr(return_type)) {
   1596         assert(g->cur_ret_ptr);
   1597         gen_assign_raw(g, source_node, BinOpTypeAssign, g->cur_ret_ptr, value, return_type, return_type);
   1598         add_debug_source_node(g, source_node);
   1599         return LLVMBuildRetVoid(g->builder);
   1600     } else {
   1601         add_debug_source_node(g, source_node);
   1602         return LLVMBuildRet(g->builder, value);
   1603     }
   1604 }
   1605 
   1606 static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {
   1607     assert(node->type == NodeTypeReturnExpr);
   1608     AstNode *param_node = node->data.return_expr.expr;
   1609     assert(param_node);
   1610     LLVMValueRef value = gen_expr(g, param_node);
   1611     TypeTableEntry *value_type = get_expr_type(param_node);
   1612 
   1613     switch (node->data.return_expr.kind) {
   1614         case ReturnKindUnconditional:
   1615             return gen_return(g, node, value);
   1616         case ReturnKindError:
   1617             {
   1618                 assert(value_type->id == TypeTableEntryIdErrorUnion);
   1619                 TypeTableEntry *child_type = value_type->data.error.child_type;
   1620 
   1621                 LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ErrRetReturn");
   1622                 LLVMBasicBlockRef continue_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ErrRetContinue");
   1623 
   1624                 add_debug_source_node(g, node);
   1625                 LLVMValueRef err_val;
   1626                 if (child_type->size_in_bits > 0) {
   1627                     LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, value, 0, "");
   1628                     err_val = LLVMBuildLoad(g->builder, err_val_ptr, "");
   1629                 } else {
   1630                     err_val = value;
   1631                 }
   1632                 LLVMValueRef zero = LLVMConstNull(g->err_tag_type->type_ref);
   1633                 LLVMValueRef cond_val = LLVMBuildICmp(g->builder, LLVMIntEQ, err_val, zero, "");
   1634                 LLVMBuildCondBr(g->builder, cond_val, continue_block, return_block);
   1635 
   1636                 LLVMPositionBuilderAtEnd(g->builder, return_block);
   1637                 TypeTableEntry *return_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;
   1638                 if (return_type->id == TypeTableEntryIdPureError) {
   1639                     gen_return(g, node, err_val);
   1640                 } else if (return_type->id == TypeTableEntryIdErrorUnion) {
   1641                     if (return_type->data.error.child_type->size_in_bits > 0) {
   1642                         assert(g->cur_ret_ptr);
   1643 
   1644                         add_debug_source_node(g, node);
   1645                         LLVMValueRef tag_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, 0, "");
   1646                         LLVMBuildStore(g->builder, err_val, tag_ptr);
   1647                         LLVMBuildRetVoid(g->builder);
   1648                     } else {
   1649                         gen_return(g, node, err_val);
   1650                     }
   1651                 } else {
   1652                     zig_unreachable();
   1653                 }
   1654 
   1655                 LLVMPositionBuilderAtEnd(g->builder, continue_block);
   1656                 if (child_type->size_in_bits > 0) {
   1657                     add_debug_source_node(g, node);
   1658                     LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, value, 1, "");
   1659                     if (handle_is_ptr(child_type)) {
   1660                         return val_ptr;
   1661                     } else {
   1662                         return LLVMBuildLoad(g->builder, val_ptr, "");
   1663                     }
   1664                 } else {
   1665                     return nullptr;
   1666                 }
   1667             }
   1668         case ReturnKindMaybe:
   1669             zig_panic("TODO");
   1670     }
   1671 }
   1672 
   1673 static LLVMValueRef gen_if_bool_expr_raw(CodeGen *g, AstNode *source_node, LLVMValueRef cond_value,
   1674         AstNode *then_node, AstNode *else_node)
   1675 {
   1676     TypeTableEntry *then_type = get_expr_type(then_node);
   1677     bool use_expr_value = (then_type->id != TypeTableEntryIdUnreachable &&
   1678                            then_type->id != TypeTableEntryIdVoid);
   1679 
   1680     if (else_node) {
   1681         LLVMBasicBlockRef then_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "Then");
   1682         LLVMBasicBlockRef else_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "Else");
   1683 
   1684         LLVMBasicBlockRef endif_block;
   1685         bool then_endif_reachable = get_expr_type(then_node)->id != TypeTableEntryIdUnreachable;
   1686         bool else_endif_reachable = get_expr_type(else_node)->id != TypeTableEntryIdUnreachable;
   1687         if (then_endif_reachable || else_endif_reachable) {
   1688             endif_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "EndIf");
   1689         }
   1690 
   1691         LLVMBuildCondBr(g->builder, cond_value, then_block, else_block);
   1692 
   1693         LLVMPositionBuilderAtEnd(g->builder, then_block);
   1694         LLVMValueRef then_expr_result = gen_expr(g, then_node);
   1695         if (then_endif_reachable) {
   1696             LLVMBuildBr(g->builder, endif_block);
   1697         }
   1698         LLVMBasicBlockRef after_then_block = LLVMGetInsertBlock(g->builder);
   1699 
   1700         LLVMPositionBuilderAtEnd(g->builder, else_block);
   1701         LLVMValueRef else_expr_result = gen_expr(g, else_node);
   1702         if (else_endif_reachable) {
   1703             LLVMBuildBr(g->builder, endif_block);
   1704         }
   1705         LLVMBasicBlockRef after_else_block = LLVMGetInsertBlock(g->builder);
   1706 
   1707         if (then_endif_reachable || else_endif_reachable) {
   1708             LLVMPositionBuilderAtEnd(g->builder, endif_block);
   1709             if (use_expr_value) {
   1710                 LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMTypeOf(then_expr_result), "");
   1711                 LLVMValueRef incoming_values[2] = {then_expr_result, else_expr_result};
   1712                 LLVMBasicBlockRef incoming_blocks[2] = {after_then_block, after_else_block};
   1713                 LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2);
   1714 
   1715                 return phi;
   1716             }
   1717         }
   1718 
   1719         return nullptr;
   1720     }
   1721 
   1722     assert(!use_expr_value || then_type->id == TypeTableEntryIdErrorUnion);
   1723 
   1724     LLVMBasicBlockRef then_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "Then");
   1725     LLVMBasicBlockRef endif_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "EndIf");
   1726 
   1727     LLVMBuildCondBr(g->builder, cond_value, then_block, endif_block);
   1728 
   1729     LLVMPositionBuilderAtEnd(g->builder, then_block);
   1730     gen_expr(g, then_node);
   1731     if (get_expr_type(then_node)->id != TypeTableEntryIdUnreachable)
   1732         LLVMBuildBr(g->builder, endif_block);
   1733 
   1734     LLVMPositionBuilderAtEnd(g->builder, endif_block);
   1735 
   1736     if (use_expr_value) {
   1737         return LLVMConstNull(g->err_tag_type->type_ref);
   1738     } else {
   1739         return nullptr;
   1740     }
   1741 }
   1742 
   1743 static LLVMValueRef gen_if_bool_expr(CodeGen *g, AstNode *node) {
   1744     assert(node->type == NodeTypeIfBoolExpr);
   1745     assert(node->data.if_bool_expr.condition);
   1746     assert(node->data.if_bool_expr.then_block);
   1747 
   1748     ConstExprValue *const_val = &get_resolved_expr(node->data.if_bool_expr.condition)->const_val;
   1749     if (const_val->ok) {
   1750         if (const_val->data.x_bool) {
   1751             return gen_expr(g, node->data.if_bool_expr.then_block);
   1752         } else if (node->data.if_bool_expr.else_node) {
   1753             return gen_expr(g, node->data.if_bool_expr.else_node);
   1754         } else {
   1755             return nullptr;
   1756         }
   1757     } else {
   1758         LLVMValueRef cond_value = gen_expr(g, node->data.if_bool_expr.condition);
   1759 
   1760         return gen_if_bool_expr_raw(g, node, cond_value,
   1761                 node->data.if_bool_expr.then_block,
   1762                 node->data.if_bool_expr.else_node);
   1763     }
   1764 }
   1765 
   1766 static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) {
   1767     assert(node->type == NodeTypeIfVarExpr);
   1768     assert(node->data.if_var_expr.var_decl.expr);
   1769 
   1770     LLVMValueRef init_val;
   1771     TypeTableEntry *expr_type;
   1772     gen_var_decl_raw(g, node, &node->data.if_var_expr.var_decl, true, &init_val, &expr_type);
   1773 
   1774     // test if value is the maybe state
   1775     assert(expr_type->id == TypeTableEntryIdMaybe);
   1776     TypeTableEntry *child_type = expr_type->data.maybe.child_type;
   1777     LLVMValueRef cond_value;
   1778     if (child_type->id == TypeTableEntryIdPointer ||
   1779         child_type->id == TypeTableEntryIdFn)
   1780     {
   1781         cond_value = LLVMBuildICmp(g->builder, LLVMIntNE, init_val, LLVMConstNull(child_type->type_ref), "");
   1782     } else {
   1783         add_debug_source_node(g, node);
   1784         LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, init_val, 1, "");
   1785         cond_value = LLVMBuildLoad(g->builder, maybe_field_ptr, "");
   1786     }
   1787 
   1788     LLVMValueRef return_value = gen_if_bool_expr_raw(g, node, cond_value,
   1789             node->data.if_var_expr.then_block,
   1790             node->data.if_var_expr.else_node);
   1791 
   1792     return return_value;
   1793 }
   1794 
   1795 static LLVMValueRef gen_block(CodeGen *g, AstNode *block_node, TypeTableEntry *implicit_return_type) {
   1796     assert(block_node->type == NodeTypeBlock);
   1797 
   1798     LLVMValueRef return_value;
   1799     for (int i = 0; i < block_node->data.block.statements.length; i += 1) {
   1800         AstNode *statement_node = block_node->data.block.statements.at(i);
   1801         return_value = gen_expr(g, statement_node);
   1802     }
   1803 
   1804     if (implicit_return_type && implicit_return_type->id != TypeTableEntryIdUnreachable) {
   1805         return gen_return(g, block_node, return_value);
   1806     } else {
   1807         return return_value;
   1808     }
   1809 }
   1810 
   1811 static int find_asm_index(CodeGen *g, AstNode *node, AsmToken *tok) {
   1812     const char *ptr = buf_ptr(&node->data.asm_expr.asm_template) + tok->start + 2;
   1813     int len = tok->end - tok->start - 2;
   1814     int result = 0;
   1815     for (int i = 0; i < node->data.asm_expr.output_list.length; i += 1, result += 1) {
   1816         AsmOutput *asm_output = node->data.asm_expr.output_list.at(i);
   1817         if (buf_eql_mem(&asm_output->asm_symbolic_name, ptr, len)) {
   1818             return result;
   1819         }
   1820     }
   1821     for (int i = 0; i < node->data.asm_expr.input_list.length; i += 1, result += 1) {
   1822         AsmInput *asm_input = node->data.asm_expr.input_list.at(i);
   1823         if (buf_eql_mem(&asm_input->asm_symbolic_name, ptr, len)) {
   1824             return result;
   1825         }
   1826     }
   1827     return -1;
   1828 }
   1829 
   1830 static LLVMValueRef gen_asm_expr(CodeGen *g, AstNode *node) {
   1831     assert(node->type == NodeTypeAsmExpr);
   1832 
   1833     AstNodeAsmExpr *asm_expr = &node->data.asm_expr;
   1834 
   1835     Buf *src_template = &asm_expr->asm_template;
   1836 
   1837     Buf llvm_template = BUF_INIT;
   1838     buf_resize(&llvm_template, 0);
   1839 
   1840     for (int token_i = 0; token_i < asm_expr->token_list.length; token_i += 1) {
   1841         AsmToken *asm_token = &asm_expr->token_list.at(token_i);
   1842         switch (asm_token->id) {
   1843             case AsmTokenIdTemplate:
   1844                 for (int offset = asm_token->start; offset < asm_token->end; offset += 1) {
   1845                     uint8_t c = *((uint8_t*)(buf_ptr(src_template) + offset));
   1846                     if (c == '$') {
   1847                         buf_append_str(&llvm_template, "$$");
   1848                     } else {
   1849                         buf_append_char(&llvm_template, c);
   1850                     }
   1851                 }
   1852                 break;
   1853             case AsmTokenIdPercent:
   1854                 buf_append_char(&llvm_template, '%');
   1855                 break;
   1856             case AsmTokenIdVar:
   1857                 int index = find_asm_index(g, node, asm_token);
   1858                 assert(index >= 0);
   1859                 buf_appendf(&llvm_template, "$%d", index);
   1860                 break;
   1861         }
   1862     }
   1863 
   1864     Buf constraint_buf = BUF_INIT;
   1865     buf_resize(&constraint_buf, 0);
   1866 
   1867     assert(asm_expr->return_count == 0 || asm_expr->return_count == 1);
   1868 
   1869     int total_constraint_count = asm_expr->output_list.length +
   1870                                  asm_expr->input_list.length +
   1871                                  asm_expr->clobber_list.length;
   1872     int input_and_output_count = asm_expr->output_list.length +
   1873                                  asm_expr->input_list.length -
   1874                                  asm_expr->return_count;
   1875     int total_index = 0;
   1876     int param_index = 0;
   1877     LLVMTypeRef *param_types = allocate<LLVMTypeRef>(input_and_output_count);
   1878     LLVMValueRef *param_values = allocate<LLVMValueRef>(input_and_output_count);
   1879     for (int i = 0; i < asm_expr->output_list.length; i += 1, total_index += 1) {
   1880         AsmOutput *asm_output = asm_expr->output_list.at(i);
   1881         bool is_return = (asm_output->return_type != nullptr);
   1882         assert(*buf_ptr(&asm_output->constraint) == '=');
   1883         if (is_return) {
   1884             buf_appendf(&constraint_buf, "=%s", buf_ptr(&asm_output->constraint) + 1);
   1885         } else {
   1886             buf_appendf(&constraint_buf, "=*%s", buf_ptr(&asm_output->constraint) + 1);
   1887         }
   1888         if (total_index + 1 < total_constraint_count) {
   1889             buf_append_char(&constraint_buf, ',');
   1890         }
   1891 
   1892         if (!is_return) {
   1893             VariableTableEntry *variable = asm_output->variable;
   1894             assert(variable);
   1895             param_types[param_index] = LLVMTypeOf(variable->value_ref);
   1896             param_values[param_index] = variable->value_ref;
   1897             param_index += 1;
   1898         }
   1899     }
   1900     for (int i = 0; i < asm_expr->input_list.length; i += 1, total_index += 1, param_index += 1) {
   1901         AsmInput *asm_input = asm_expr->input_list.at(i);
   1902         buf_append_buf(&constraint_buf, &asm_input->constraint);
   1903         if (total_index + 1 < total_constraint_count) {
   1904             buf_append_char(&constraint_buf, ',');
   1905         }
   1906 
   1907         TypeTableEntry *expr_type = get_expr_type(asm_input->expr);
   1908         param_types[param_index] = expr_type->type_ref;
   1909         param_values[param_index] = gen_expr(g, asm_input->expr);
   1910     }
   1911     for (int i = 0; i < asm_expr->clobber_list.length; i += 1, total_index += 1) {
   1912         Buf *clobber_buf = asm_expr->clobber_list.at(i);
   1913         buf_appendf(&constraint_buf, "~{%s}", buf_ptr(clobber_buf));
   1914         if (total_index + 1 < total_constraint_count) {
   1915             buf_append_char(&constraint_buf, ',');
   1916         }
   1917     }
   1918 
   1919     LLVMTypeRef ret_type;
   1920     if (asm_expr->return_count == 0) {
   1921         ret_type = LLVMVoidType();
   1922     } else {
   1923         ret_type = get_expr_type(node)->type_ref;
   1924     }
   1925     LLVMTypeRef function_type = LLVMFunctionType(ret_type, param_types, input_and_output_count, false);
   1926 
   1927     bool is_volatile = asm_expr->is_volatile || (asm_expr->output_list.length == 0);
   1928     LLVMValueRef asm_fn = LLVMConstInlineAsm(function_type, buf_ptr(&llvm_template),
   1929             buf_ptr(&constraint_buf), is_volatile, false);
   1930 
   1931     add_debug_source_node(g, node);
   1932     return LLVMBuildCall(g->builder, asm_fn, param_values, input_and_output_count, "");
   1933 }
   1934 
   1935 static LLVMValueRef gen_container_init_expr(CodeGen *g, AstNode *node) {
   1936     assert(node->type == NodeTypeContainerInitExpr);
   1937 
   1938     TypeTableEntry *type_entry = get_expr_type(node);
   1939 
   1940     if (type_entry->id == TypeTableEntryIdStruct) {
   1941         assert(node->data.container_init_expr.kind == ContainerInitKindStruct);
   1942 
   1943         int src_field_count = type_entry->data.structure.src_field_count;
   1944         assert(src_field_count == node->data.container_init_expr.entries.length);
   1945 
   1946         StructValExprCodeGen *struct_val_expr_node = &node->data.container_init_expr.resolved_struct_val_expr;
   1947         LLVMValueRef tmp_struct_ptr = struct_val_expr_node->ptr;
   1948 
   1949         for (int i = 0; i < src_field_count; i += 1) {
   1950             AstNode *field_node = node->data.container_init_expr.entries.at(i);
   1951             assert(field_node->type == NodeTypeStructValueField);
   1952             TypeStructField *type_struct_field = field_node->data.struct_val_field.type_struct_field;
   1953             if (type_struct_field->type_entry->id == TypeTableEntryIdVoid) {
   1954                 continue;
   1955             }
   1956             assert(buf_eql_buf(type_struct_field->name, &field_node->data.struct_val_field.name));
   1957 
   1958             add_debug_source_node(g, field_node);
   1959             LLVMValueRef field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, type_struct_field->gen_index, "");
   1960             AstNode *expr_node = field_node->data.struct_val_field.expr;
   1961             LLVMValueRef value = gen_expr(g, expr_node);
   1962             gen_assign_raw(g, field_node, BinOpTypeAssign, field_ptr, value,
   1963                     type_struct_field->type_entry, get_expr_type(expr_node));
   1964         }
   1965 
   1966         return tmp_struct_ptr;
   1967     } else if (type_entry->id == TypeTableEntryIdUnreachable) {
   1968         assert(node->data.container_init_expr.entries.length == 0);
   1969         add_debug_source_node(g, node);
   1970         if (g->build_type != CodeGenBuildTypeRelease) {
   1971             LLVMBuildCall(g->builder, g->trap_fn_val, nullptr, 0, "");
   1972         }
   1973         return LLVMBuildUnreachable(g->builder);
   1974     } else if (type_entry->id == TypeTableEntryIdVoid) {
   1975         assert(node->data.container_init_expr.entries.length == 0);
   1976         return nullptr;
   1977     } else if (type_entry->id == TypeTableEntryIdArray) {
   1978         StructValExprCodeGen *struct_val_expr_node = &node->data.container_init_expr.resolved_struct_val_expr;
   1979         LLVMValueRef tmp_array_ptr = struct_val_expr_node->ptr;
   1980 
   1981         int field_count = type_entry->data.array.len;
   1982         assert(field_count == node->data.container_init_expr.entries.length);
   1983 
   1984         TypeTableEntry *child_type = type_entry->data.array.child_type;
   1985 
   1986         for (int i = 0; i < field_count; i += 1) {
   1987             AstNode *field_node = node->data.container_init_expr.entries.at(i);
   1988             LLVMValueRef elem_val = gen_expr(g, field_node);
   1989 
   1990             LLVMValueRef indices[] = {
   1991                 LLVMConstNull(g->builtin_types.entry_isize->type_ref),
   1992                 LLVMConstInt(g->builtin_types.entry_isize->type_ref, i, false),
   1993             };
   1994             add_debug_source_node(g, field_node);
   1995             LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP(g->builder, tmp_array_ptr, indices, 2, "");
   1996             gen_assign_raw(g, field_node, BinOpTypeAssign, elem_ptr, elem_val,
   1997                     child_type, get_expr_type(field_node));
   1998         }
   1999 
   2000         return tmp_array_ptr;
   2001     } else {
   2002         zig_unreachable();
   2003     }
   2004 }
   2005 
   2006 static LLVMValueRef gen_while_expr(CodeGen *g, AstNode *node) {
   2007     assert(node->type == NodeTypeWhileExpr);
   2008     assert(node->data.while_expr.condition);
   2009     assert(node->data.while_expr.body);
   2010 
   2011     bool condition_always_true = node->data.while_expr.condition_always_true;
   2012     bool contains_break = node->data.while_expr.contains_break;
   2013     if (condition_always_true) {
   2014         // generate a forever loop
   2015 
   2016         LLVMBasicBlockRef body_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileBody");
   2017         LLVMBasicBlockRef end_block = nullptr;
   2018         if (contains_break) {
   2019             end_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileEnd");
   2020         }
   2021 
   2022         add_debug_source_node(g, node);
   2023         LLVMBuildBr(g->builder, body_block);
   2024 
   2025         LLVMPositionBuilderAtEnd(g->builder, body_block);
   2026         g->break_block_stack.append(end_block);
   2027         g->continue_block_stack.append(body_block);
   2028         gen_expr(g, node->data.while_expr.body);
   2029         g->break_block_stack.pop();
   2030         g->continue_block_stack.pop();
   2031 
   2032         if (get_expr_type(node->data.while_expr.body)->id != TypeTableEntryIdUnreachable) {
   2033             add_debug_source_node(g, node);
   2034             LLVMBuildBr(g->builder, body_block);
   2035         }
   2036 
   2037         if (contains_break) {
   2038             LLVMPositionBuilderAtEnd(g->builder, end_block);
   2039         }
   2040     } else {
   2041         // generate a normal while loop
   2042 
   2043         LLVMBasicBlockRef cond_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileCond");
   2044         LLVMBasicBlockRef body_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileBody");
   2045         LLVMBasicBlockRef end_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileEnd");
   2046 
   2047         add_debug_source_node(g, node);
   2048         LLVMBuildBr(g->builder, cond_block);
   2049 
   2050         LLVMPositionBuilderAtEnd(g->builder, cond_block);
   2051         LLVMValueRef cond_val = gen_expr(g, node->data.while_expr.condition);
   2052         add_debug_source_node(g, node->data.while_expr.condition);
   2053         LLVMBuildCondBr(g->builder, cond_val, body_block, end_block);
   2054 
   2055         LLVMPositionBuilderAtEnd(g->builder, body_block);
   2056         g->break_block_stack.append(end_block);
   2057         g->continue_block_stack.append(cond_block);
   2058         gen_expr(g, node->data.while_expr.body);
   2059         g->break_block_stack.pop();
   2060         g->continue_block_stack.pop();
   2061         if (get_expr_type(node->data.while_expr.body)->id != TypeTableEntryIdUnreachable) {
   2062             add_debug_source_node(g, node);
   2063             LLVMBuildBr(g->builder, cond_block);
   2064         }
   2065 
   2066         LLVMPositionBuilderAtEnd(g->builder, end_block);
   2067     }
   2068 
   2069     return nullptr;
   2070 }
   2071 
   2072 static LLVMValueRef gen_for_expr(CodeGen *g, AstNode *node) {
   2073     assert(node->type == NodeTypeForExpr);
   2074     assert(node->data.for_expr.array_expr);
   2075     assert(node->data.for_expr.body);
   2076 
   2077     VariableTableEntry *elem_var = node->data.for_expr.elem_var;
   2078     assert(elem_var);
   2079 
   2080     TypeTableEntry *array_type = get_expr_type(node->data.for_expr.array_expr);
   2081 
   2082     VariableTableEntry *index_var = node->data.for_expr.index_var;
   2083     assert(index_var);
   2084     LLVMValueRef index_ptr = index_var->value_ref;
   2085     LLVMValueRef one_const = LLVMConstInt(g->builtin_types.entry_isize->type_ref, 1, false);
   2086 
   2087     LLVMBasicBlockRef cond_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ForCond");
   2088     LLVMBasicBlockRef body_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ForBody");
   2089     LLVMBasicBlockRef end_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ForEnd");
   2090 
   2091     LLVMValueRef array_val = gen_array_base_ptr(g, node->data.for_expr.array_expr);
   2092     add_debug_source_node(g, node);
   2093     LLVMBuildStore(g->builder, LLVMConstNull(index_var->type->type_ref), index_ptr);
   2094     LLVMValueRef len_val;
   2095     TypeTableEntry *child_type;
   2096     if (array_type->id == TypeTableEntryIdArray) {
   2097         len_val = LLVMConstInt(g->builtin_types.entry_isize->type_ref,
   2098                 array_type->data.array.len, false);
   2099         child_type = array_type->data.array.child_type;
   2100     } else if (array_type->id == TypeTableEntryIdStruct) {
   2101         assert(array_type->data.structure.is_unknown_size_array);
   2102         TypeTableEntry *child_ptr_type = array_type->data.structure.fields[0].type_entry;
   2103         assert(child_ptr_type->id == TypeTableEntryIdPointer);
   2104         child_type = child_ptr_type->data.pointer.child_type;
   2105         LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, array_val, 1, "");
   2106         len_val = LLVMBuildLoad(g->builder, len_field_ptr, "");
   2107     } else {
   2108         zig_unreachable();
   2109     }
   2110     LLVMBuildBr(g->builder, cond_block);
   2111 
   2112     LLVMPositionBuilderAtEnd(g->builder, cond_block);
   2113     LLVMValueRef index_val = LLVMBuildLoad(g->builder, index_ptr, "");
   2114     LLVMValueRef cond = LLVMBuildICmp(g->builder, LLVMIntSLT, index_val, len_val, "");
   2115     LLVMBuildCondBr(g->builder, cond, body_block, end_block);
   2116 
   2117     LLVMPositionBuilderAtEnd(g->builder, body_block);
   2118     LLVMValueRef elem_ptr = gen_array_elem_ptr(g, node, array_val, array_type, index_val);
   2119     LLVMValueRef elem_val = handle_is_ptr(child_type) ? elem_ptr : LLVMBuildLoad(g->builder, elem_ptr, "");
   2120     gen_assign_raw(g, node, BinOpTypeAssign, elem_var->value_ref, elem_val,
   2121             elem_var->type, child_type);
   2122     g->break_block_stack.append(end_block);
   2123     g->continue_block_stack.append(cond_block);
   2124     gen_expr(g, node->data.for_expr.body);
   2125     g->break_block_stack.pop();
   2126     g->continue_block_stack.pop();
   2127     if (get_expr_type(node->data.for_expr.body)->id != TypeTableEntryIdUnreachable) {
   2128         add_debug_source_node(g, node);
   2129         LLVMValueRef new_index_val = LLVMBuildAdd(g->builder, index_val, one_const, "");
   2130         LLVMBuildStore(g->builder, new_index_val, index_ptr);
   2131         LLVMBuildBr(g->builder, cond_block);
   2132     }
   2133 
   2134     LLVMPositionBuilderAtEnd(g->builder, end_block);
   2135     return nullptr;
   2136 }
   2137 
   2138 static LLVMValueRef gen_break(CodeGen *g, AstNode *node) {
   2139     assert(node->type == NodeTypeBreak);
   2140     LLVMBasicBlockRef dest_block = g->break_block_stack.last();
   2141 
   2142     add_debug_source_node(g, node);
   2143     return LLVMBuildBr(g->builder, dest_block);
   2144 }
   2145 
   2146 static LLVMValueRef gen_continue(CodeGen *g, AstNode *node) {
   2147     assert(node->type == NodeTypeContinue);
   2148     LLVMBasicBlockRef dest_block = g->continue_block_stack.last();
   2149 
   2150     add_debug_source_node(g, node);
   2151     return LLVMBuildBr(g->builder, dest_block);
   2152 }
   2153 
   2154 static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVariableDeclaration *var_decl,
   2155         bool unwrap_maybe, LLVMValueRef *init_value, TypeTableEntry **expr_type)
   2156 {
   2157     VariableTableEntry *variable = var_decl->variable;
   2158 
   2159     assert(variable);
   2160     assert(variable->is_ptr);
   2161 
   2162     if (var_decl->expr) {
   2163         *init_value = gen_expr(g, var_decl->expr);
   2164         *expr_type = get_expr_type(var_decl->expr);
   2165     }
   2166     if (variable->type->size_in_bits == 0) {
   2167         return nullptr;
   2168     }
   2169 
   2170     bool have_init_expr = false;
   2171     if (var_decl->expr) {
   2172         ConstExprValue *const_val = &get_resolved_expr(var_decl->expr)->const_val;
   2173         if (!const_val->ok || !const_val->undef) {
   2174             have_init_expr = true;
   2175         }
   2176     }
   2177     if (have_init_expr) {
   2178         TypeTableEntry *expr_type = get_expr_type(var_decl->expr);
   2179         LLVMValueRef value;
   2180         if (unwrap_maybe) {
   2181             assert(var_decl->expr);
   2182             assert(expr_type->id == TypeTableEntryIdMaybe);
   2183             value = gen_unwrap_maybe(g, var_decl->expr, *init_value);
   2184             expr_type = expr_type->data.maybe.child_type;
   2185         } else {
   2186             value = *init_value;
   2187         }
   2188         gen_assign_raw(g, var_decl->expr, BinOpTypeAssign, variable->value_ref,
   2189                 value, variable->type, expr_type);
   2190     } else {
   2191         bool ignore_uninit = false;
   2192         TypeTableEntry *var_type = get_type_for_type_node(var_decl->type);
   2193         if (var_type->id == TypeTableEntryIdStruct &&
   2194             var_type->data.structure.is_unknown_size_array)
   2195         {
   2196             assert(var_decl->type->type == NodeTypeArrayType);
   2197             AstNode *size_node = var_decl->type->data.array_type.size;
   2198             if (size_node) {
   2199                 ConstExprValue *const_val = &get_resolved_expr(size_node)->const_val;
   2200                 if (!const_val->ok) {
   2201                     TypeTableEntry *ptr_type = var_type->data.structure.fields[0].type_entry;
   2202                     assert(ptr_type->id == TypeTableEntryIdPointer);
   2203                     TypeTableEntry *child_type = ptr_type->data.pointer.child_type;
   2204 
   2205                     LLVMValueRef size_val = gen_expr(g, size_node);
   2206 
   2207                     add_debug_source_node(g, source_node);
   2208                     LLVMValueRef ptr_val = LLVMBuildArrayAlloca(g->builder, child_type->type_ref,
   2209                             size_val, "");
   2210 
   2211                     // store the freshly allocated pointer in the unknown size array struct
   2212                     LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder,
   2213                             variable->value_ref, 0, "");
   2214                     LLVMBuildStore(g->builder, ptr_val, ptr_field_ptr);
   2215 
   2216                     // store the size in the len field
   2217                     LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder,
   2218                             variable->value_ref, 1, "");
   2219                     LLVMBuildStore(g->builder, size_val, len_field_ptr);
   2220 
   2221                     // don't clobber what we just did with debug initialization
   2222                     ignore_uninit = true;
   2223                 }
   2224             }
   2225         }
   2226         if (!ignore_uninit && g->build_type != CodeGenBuildTypeRelease) {
   2227             // memset uninitialized memory to 0xa
   2228             add_debug_source_node(g, source_node);
   2229             LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
   2230             LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false);
   2231             LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, variable->value_ref, ptr_u8, "");
   2232             LLVMValueRef byte_count = LLVMConstInt(LLVMIntType(g->pointer_size_bytes * 8),
   2233                     variable->type->size_in_bits / 8, false);
   2234             LLVMValueRef align_in_bytes = LLVMConstInt(LLVMInt32Type(),
   2235                     variable->type->align_in_bits / 8, false);
   2236             LLVMValueRef params[] = {
   2237                 dest_ptr,
   2238                 fill_char,
   2239                 byte_count,
   2240                 align_in_bytes,
   2241                 LLVMConstNull(LLVMInt1Type()), // is volatile
   2242             };
   2243 
   2244             LLVMBuildCall(g->builder, g->memset_fn_val, params, 5, "");
   2245         }
   2246     }
   2247 
   2248     LLVMZigDILocation *debug_loc = LLVMZigGetDebugLoc(source_node->line + 1, source_node->column + 1,
   2249             source_node->block_context->di_scope);
   2250     LLVMZigInsertDeclareAtEnd(g->dbuilder, variable->value_ref, variable->di_loc_var, debug_loc,
   2251             LLVMGetInsertBlock(g->builder));
   2252     return nullptr;
   2253 }
   2254 
   2255 static LLVMValueRef gen_var_decl_expr(CodeGen *g, AstNode *node) {
   2256     AstNode *init_expr = node->data.variable_declaration.expr;
   2257     if (node->data.variable_declaration.is_const && init_expr) {
   2258         TypeTableEntry *init_expr_type = get_expr_type(init_expr);
   2259         if (init_expr_type->id == TypeTableEntryIdNumLitFloat ||
   2260             init_expr_type->id == TypeTableEntryIdNumLitInt)
   2261         {
   2262             return nullptr;
   2263         }
   2264     }
   2265 
   2266     LLVMValueRef init_val;
   2267     TypeTableEntry *init_val_type;
   2268     return gen_var_decl_raw(g, node, &node->data.variable_declaration, false, &init_val, &init_val_type);
   2269 }
   2270 
   2271 static LLVMValueRef gen_symbol(CodeGen *g, AstNode *node) {
   2272     assert(node->type == NodeTypeSymbol);
   2273     VariableTableEntry *variable = node->data.symbol_expr.variable;
   2274     if (variable) {
   2275         if (variable->type->size_in_bits == 0) {
   2276             return nullptr;
   2277         } else if (variable->is_ptr) {
   2278             assert(variable->value_ref);
   2279             if (handle_is_ptr(variable->type)) {
   2280                 return variable->value_ref;
   2281             } else {
   2282                 add_debug_source_node(g, node);
   2283                 return LLVMBuildLoad(g->builder, variable->value_ref, "");
   2284             }
   2285         } else {
   2286             return variable->value_ref;
   2287         }
   2288     }
   2289 
   2290     FnTableEntry *fn_entry = node->data.symbol_expr.fn_entry;
   2291     assert(fn_entry);
   2292     return fn_entry->fn_value;
   2293 }
   2294 
   2295 static LLVMValueRef gen_switch_expr(CodeGen *g, AstNode *node) {
   2296     assert(node->type == NodeTypeSwitchExpr);
   2297 
   2298     LLVMValueRef target_value = gen_expr(g, node->data.switch_expr.expr);
   2299 
   2300     bool end_unreachable = (get_expr_type(node)->id == TypeTableEntryIdUnreachable);
   2301 
   2302     LLVMBasicBlockRef end_block = end_unreachable ?
   2303         nullptr : LLVMAppendBasicBlock(g->cur_fn->fn_value, "SwitchEnd");
   2304     LLVMBasicBlockRef else_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "SwitchElse");
   2305     int prong_count = node->data.switch_expr.prongs.length;
   2306 
   2307     add_debug_source_node(g, node);
   2308     LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, target_value, else_block, prong_count);
   2309 
   2310     ZigList<LLVMValueRef> incoming_values = {0};
   2311     ZigList<LLVMBasicBlockRef> incoming_blocks = {0};
   2312 
   2313     AstNode *else_prong = nullptr;
   2314     for (int prong_i = 0; prong_i < prong_count; prong_i += 1) {
   2315         AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i);
   2316         LLVMBasicBlockRef prong_block;
   2317         if (prong_node->data.switch_prong.items.length == 0) {
   2318             assert(!else_prong);
   2319             else_prong = prong_node;
   2320             prong_block = else_block;
   2321         } else {
   2322             prong_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "SwitchProng");
   2323             for (int item_i = 0; item_i < prong_node->data.switch_prong.items.length; item_i += 1) {
   2324                 AstNode *item_node = prong_node->data.switch_prong.items.at(item_i);
   2325                 assert(item_node->type != NodeTypeSwitchRange);
   2326                 assert(get_resolved_expr(item_node)->const_val.ok);
   2327                 LLVMValueRef val = gen_expr(g, item_node);
   2328                 LLVMAddCase(switch_instr, val, prong_block);
   2329             }
   2330         }
   2331         assert(!prong_node->data.switch_prong.var_symbol);
   2332         LLVMPositionBuilderAtEnd(g->builder, prong_block);
   2333         AstNode *prong_expr = prong_node->data.switch_prong.expr;
   2334         LLVMValueRef prong_val = gen_expr(g, prong_expr);
   2335 
   2336         if (get_expr_type(prong_expr)->id != TypeTableEntryIdUnreachable) {
   2337             add_debug_source_node(g, prong_expr);
   2338             LLVMBuildBr(g->builder, end_block);
   2339             incoming_values.append(prong_val);
   2340             incoming_blocks.append(prong_block);
   2341         }
   2342     }
   2343 
   2344     if (!else_prong) {
   2345         LLVMPositionBuilderAtEnd(g->builder, else_block);
   2346         add_debug_source_node(g, node);
   2347         LLVMBuildUnreachable(g->builder);
   2348     }
   2349 
   2350     if (end_unreachable) {
   2351         return nullptr;
   2352     }
   2353 
   2354     LLVMPositionBuilderAtEnd(g->builder, end_block);
   2355 
   2356     add_debug_source_node(g, node);
   2357     LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMTypeOf(incoming_values.at(0)), "");
   2358     LLVMAddIncoming(phi, incoming_values.items, incoming_blocks.items, incoming_values.length);
   2359 
   2360     return phi;
   2361 }
   2362 
   2363 static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
   2364     Expr *expr = get_resolved_expr(node);
   2365     if (expr->const_val.ok) {
   2366         if (expr->type_entry->size_in_bits == 0) {
   2367             return nullptr;
   2368         } else {
   2369             assert(expr->const_llvm_val);
   2370             return expr->const_llvm_val;
   2371         }
   2372     }
   2373     switch (node->type) {
   2374         case NodeTypeBinOpExpr:
   2375             return gen_bin_op_expr(g, node);
   2376         case NodeTypeUnwrapErrorExpr:
   2377             return gen_unwrap_err_expr(g, node);
   2378         case NodeTypeReturnExpr:
   2379             return gen_return_expr(g, node);
   2380         case NodeTypeVariableDeclaration:
   2381             return gen_var_decl_expr(g, node);
   2382         case NodeTypePrefixOpExpr:
   2383             return gen_prefix_op_expr(g, node);
   2384         case NodeTypeFnCallExpr:
   2385             return gen_fn_call_expr(g, node);
   2386         case NodeTypeArrayAccessExpr:
   2387             return gen_array_access_expr(g, node, false);
   2388         case NodeTypeSliceExpr:
   2389             return gen_slice_expr(g, node);
   2390         case NodeTypeFieldAccessExpr:
   2391             return gen_field_access_expr(g, node, false);
   2392         case NodeTypeIfBoolExpr:
   2393             return gen_if_bool_expr(g, node);
   2394         case NodeTypeIfVarExpr:
   2395             return gen_if_var_expr(g, node);
   2396         case NodeTypeWhileExpr:
   2397             return gen_while_expr(g, node);
   2398         case NodeTypeForExpr:
   2399             return gen_for_expr(g, node);
   2400         case NodeTypeAsmExpr:
   2401             return gen_asm_expr(g, node);
   2402         case NodeTypeSymbol:
   2403             return gen_symbol(g, node);
   2404         case NodeTypeBlock:
   2405             return gen_block(g, node, nullptr);
   2406         case NodeTypeGoto:
   2407             add_debug_source_node(g, node);
   2408             return LLVMBuildBr(g->builder, node->data.goto_expr.label_entry->basic_block);
   2409         case NodeTypeBreak:
   2410             return gen_break(g, node);
   2411         case NodeTypeContinue:
   2412             return gen_continue(g, node);
   2413         case NodeTypeLabel:
   2414             {
   2415                 LabelTableEntry *label_entry = node->data.label.label_entry;
   2416                 assert(label_entry);
   2417                 LLVMBasicBlockRef basic_block = label_entry->basic_block;
   2418                 if (label_entry->entered_from_fallthrough) {
   2419                     add_debug_source_node(g, node);
   2420                     LLVMBuildBr(g->builder, basic_block);
   2421                 }
   2422                 LLVMPositionBuilderAtEnd(g->builder, basic_block);
   2423                 return nullptr;
   2424             }
   2425         case NodeTypeContainerInitExpr:
   2426             return gen_container_init_expr(g, node);
   2427         case NodeTypeSwitchExpr:
   2428             return gen_switch_expr(g, node);
   2429         case NodeTypeNumberLiteral:
   2430         case NodeTypeBoolLiteral:
   2431         case NodeTypeStringLiteral:
   2432         case NodeTypeCharLiteral:
   2433         case NodeTypeNullLiteral:
   2434         case NodeTypeUndefinedLiteral:
   2435         case NodeTypeErrorType:
   2436         case NodeTypeTypeLiteral:
   2437         case NodeTypeArrayType:
   2438             // caught by constant expression eval codegen
   2439             zig_unreachable();
   2440         case NodeTypeRoot:
   2441         case NodeTypeRootExportDecl:
   2442         case NodeTypeFnProto:
   2443         case NodeTypeFnDef:
   2444         case NodeTypeFnDecl:
   2445         case NodeTypeParamDecl:
   2446         case NodeTypeDirective:
   2447         case NodeTypeImport:
   2448         case NodeTypeCImport:
   2449         case NodeTypeStructDecl:
   2450         case NodeTypeStructField:
   2451         case NodeTypeStructValueField:
   2452         case NodeTypeSwitchProng:
   2453         case NodeTypeSwitchRange:
   2454         case NodeTypeErrorValueDecl:
   2455         case NodeTypeTypeDecl:
   2456             zig_unreachable();
   2457     }
   2458     zig_unreachable();
   2459 }
   2460 
   2461 static void build_label_blocks(CodeGen *g, AstNode *block_node) {
   2462     assert(block_node->type == NodeTypeBlock);
   2463     for (int i = 0; i < block_node->data.block.statements.length; i += 1) {
   2464         AstNode *label_node = block_node->data.block.statements.at(i);
   2465         if (label_node->type != NodeTypeLabel)
   2466             continue;
   2467 
   2468         Buf *name = &label_node->data.label.name;
   2469         label_node->data.label.label_entry->basic_block = LLVMAppendBasicBlock(
   2470                 g->cur_fn->fn_value, buf_ptr(name));
   2471     }
   2472 }
   2473 
   2474 static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val) {
   2475     assert(const_val->ok);
   2476 
   2477     if (const_val->undef) {
   2478         return LLVMGetUndef(type_entry->type_ref);
   2479     }
   2480 
   2481     switch (type_entry->id) {
   2482         case TypeTableEntryIdTypeDecl:
   2483             return gen_const_val(g, type_entry->data.type_decl.canonical_type, const_val);
   2484         case TypeTableEntryIdInt:
   2485             return LLVMConstInt(type_entry->type_ref, bignum_to_twos_complement(&const_val->data.x_bignum), false);
   2486         case TypeTableEntryIdPureError:
   2487             assert(const_val->data.x_err.err);
   2488             return LLVMConstInt(g->builtin_types.entry_pure_error->type_ref,
   2489                     const_val->data.x_err.err->value, false);
   2490         case TypeTableEntryIdFloat:
   2491             if (const_val->data.x_bignum.kind == BigNumKindFloat) {
   2492                 return LLVMConstReal(type_entry->type_ref, const_val->data.x_bignum.data.x_float);
   2493             } else {
   2494                 int64_t x = const_val->data.x_bignum.data.x_uint;
   2495                 if (const_val->data.x_bignum.is_negative) {
   2496                     x = -x;
   2497                 }
   2498                 return LLVMConstReal(type_entry->type_ref, x);
   2499             }
   2500         case TypeTableEntryIdBool:
   2501             if (const_val->data.x_bool) {
   2502                 return LLVMConstAllOnes(LLVMInt1Type());
   2503             } else {
   2504                 return LLVMConstNull(LLVMInt1Type());
   2505             }
   2506         case TypeTableEntryIdMaybe:
   2507             {
   2508                 TypeTableEntry *child_type = type_entry->data.maybe.child_type;
   2509                 if (child_type->id == TypeTableEntryIdPointer ||
   2510                     child_type->id == TypeTableEntryIdFn)
   2511                 {
   2512                     if (const_val->data.x_maybe) {
   2513                         return gen_const_val(g, child_type, const_val->data.x_maybe);
   2514                     } else {
   2515                         return LLVMConstNull(child_type->type_ref);
   2516                     }
   2517                 } else {
   2518                     LLVMValueRef child_val;
   2519                     LLVMValueRef maybe_val;
   2520                     if (const_val->data.x_maybe) {
   2521                         child_val = gen_const_val(g, child_type, const_val->data.x_maybe);
   2522                         maybe_val = LLVMConstAllOnes(LLVMInt1Type());
   2523                     } else {
   2524                         child_val = LLVMConstNull(child_type->type_ref);
   2525                         maybe_val = LLVMConstNull(LLVMInt1Type());
   2526                     }
   2527                     LLVMValueRef fields[] = {
   2528                         child_val,
   2529                         maybe_val,
   2530                     };
   2531                     return LLVMConstStruct(fields, 2, false);
   2532                 }
   2533             }
   2534         case TypeTableEntryIdStruct:
   2535             {
   2536                 LLVMValueRef *fields = allocate<LLVMValueRef>(type_entry->data.structure.gen_field_count);
   2537                 for (int i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
   2538                     TypeStructField *type_struct_field = &type_entry->data.structure.fields[i];
   2539                     if (type_struct_field->gen_index == -1) {
   2540                         continue;
   2541                     }
   2542                     fields[type_struct_field->gen_index] = gen_const_val(g, type_struct_field->type_entry,
   2543                             const_val->data.x_struct.fields[i]);
   2544                 }
   2545                 return LLVMConstNamedStruct(type_entry->type_ref, fields,
   2546                         type_entry->data.structure.gen_field_count);
   2547             }
   2548         case TypeTableEntryIdArray:
   2549             {
   2550                 TypeTableEntry *child_type = type_entry->data.array.child_type;
   2551                 uint64_t len = type_entry->data.array.len;
   2552                 LLVMValueRef *values = allocate<LLVMValueRef>(len);
   2553                 for (int i = 0; i < len; i += 1) {
   2554                     ConstExprValue *field_value = const_val->data.x_array.fields[i];
   2555                     values[i] = gen_const_val(g, child_type, field_value);
   2556                 }
   2557                 return LLVMConstArray(child_type->type_ref, values, len);
   2558             }
   2559         case TypeTableEntryIdEnum:
   2560             {
   2561                 LLVMTypeRef tag_type_ref = type_entry->data.enumeration.tag_type->type_ref;
   2562                 LLVMValueRef tag_value = LLVMConstInt(tag_type_ref, const_val->data.x_enum.tag, false);
   2563                 if (type_entry->data.enumeration.gen_field_count == 0) {
   2564                     return tag_value;
   2565                 } else {
   2566                     zig_panic("TODO");
   2567                 }
   2568             }
   2569         case TypeTableEntryIdFn:
   2570             return const_val->data.x_fn->fn_value;
   2571         case TypeTableEntryIdPointer:
   2572             {
   2573                 TypeTableEntry *child_type = type_entry->data.pointer.child_type;
   2574                 int len = const_val->data.x_ptr.len;
   2575                 LLVMValueRef target_val;
   2576                 if (len == 1) {
   2577                     target_val = gen_const_val(g, child_type, const_val->data.x_ptr.ptr[0]);
   2578                 } else if (len > 1) {
   2579                     LLVMValueRef *values = allocate<LLVMValueRef>(len);
   2580                     for (int i = 0; i < len; i += 1) {
   2581                         values[i] = gen_const_val(g, child_type, const_val->data.x_ptr.ptr[i]);
   2582                     }
   2583                     target_val = LLVMConstArray(child_type->type_ref, values, len);
   2584                 } else {
   2585                     zig_unreachable();
   2586                 }
   2587                 LLVMValueRef global_value = LLVMAddGlobal(g->module, LLVMTypeOf(target_val), "");
   2588                 LLVMSetInitializer(global_value, target_val);
   2589                 LLVMSetLinkage(global_value, LLVMPrivateLinkage);
   2590                 LLVMSetGlobalConstant(global_value, type_entry->data.pointer.is_const);
   2591                 LLVMSetUnnamedAddr(global_value, true);
   2592 
   2593                 if (len > 1) {
   2594                     return LLVMConstBitCast(global_value, type_entry->type_ref);
   2595                 } else {
   2596                     return global_value;
   2597                 }
   2598             }
   2599         case TypeTableEntryIdErrorUnion:
   2600             {
   2601                 TypeTableEntry *child_type = type_entry->data.error.child_type;
   2602                 if (child_type->size_in_bits == 0) {
   2603                     uint64_t value = const_val->data.x_err.err ? const_val->data.x_err.err->value : 0;
   2604                     return LLVMConstInt(g->err_tag_type->type_ref, value, false);
   2605                 } else {
   2606                     LLVMValueRef err_tag_value;
   2607                     LLVMValueRef err_payload_value;
   2608                     if (const_val->data.x_err.err) {
   2609                         err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, const_val->data.x_err.err->value, false);
   2610                         err_payload_value = LLVMConstNull(child_type->type_ref);
   2611                     } else {
   2612                         err_tag_value = LLVMConstNull(g->err_tag_type->type_ref);
   2613                         err_payload_value = gen_const_val(g, child_type, const_val->data.x_err.payload);
   2614                     }
   2615                     LLVMValueRef fields[] = {
   2616                         err_tag_value,
   2617                         err_payload_value,
   2618                     };
   2619                     return LLVMConstStruct(fields, 2, false);
   2620                 }
   2621             }
   2622         case TypeTableEntryIdInvalid:
   2623         case TypeTableEntryIdMetaType:
   2624         case TypeTableEntryIdUnreachable:
   2625         case TypeTableEntryIdNumLitFloat:
   2626         case TypeTableEntryIdNumLitInt:
   2627         case TypeTableEntryIdUndefLit:
   2628         case TypeTableEntryIdVoid:
   2629             zig_unreachable();
   2630 
   2631     }
   2632 }
   2633 
   2634 static void gen_const_globals(CodeGen *g) {
   2635     for (int i = 0; i < g->global_const_list.length; i += 1) {
   2636         Expr *expr = g->global_const_list.at(i);
   2637         ConstExprValue *const_val = &expr->const_val;
   2638         assert(const_val->ok);
   2639         TypeTableEntry *type_entry = expr->type_entry;
   2640 
   2641         if (handle_is_ptr(type_entry)) {
   2642             LLVMValueRef init_val = gen_const_val(g, type_entry, const_val);
   2643             LLVMValueRef global_value = LLVMAddGlobal(g->module, LLVMTypeOf(init_val), "");
   2644             LLVMSetInitializer(global_value, init_val);
   2645             LLVMSetLinkage(global_value, LLVMPrivateLinkage);
   2646             LLVMSetGlobalConstant(global_value, true);
   2647             LLVMSetUnnamedAddr(global_value, true);
   2648             expr->const_llvm_val = global_value;
   2649         } else {
   2650             expr->const_llvm_val = gen_const_val(g, type_entry, const_val);
   2651         }
   2652     }
   2653 }
   2654 
   2655 static void delete_unused_builtin_fns(CodeGen *g) {
   2656     auto it = g->builtin_fn_table.entry_iterator();
   2657     for (;;) {
   2658         auto *entry = it.next();
   2659         if (!entry)
   2660             break;
   2661 
   2662         BuiltinFnEntry *builtin_fn = entry->value;
   2663         if (builtin_fn->ref_count == 0 &&
   2664             builtin_fn->fn_val)
   2665         {
   2666             LLVMDeleteFunction(entry->value->fn_val);
   2667         }
   2668     }
   2669 }
   2670 
   2671 static void do_code_gen(CodeGen *g) {
   2672     assert(!g->errors.length);
   2673 
   2674     delete_unused_builtin_fns(g);
   2675 
   2676 
   2677     gen_const_globals(g);
   2678 
   2679     // Generate module level variables
   2680     for (int i = 0; i < g->global_vars.length; i += 1) {
   2681         VariableTableEntry *var = g->global_vars.at(i);
   2682 
   2683         if (var->type->id == TypeTableEntryIdNumLitFloat ||
   2684             var->type->id == TypeTableEntryIdNumLitInt ||
   2685             var->type->size_in_bits == 0)
   2686         {
   2687             continue;
   2688         }
   2689 
   2690         assert(var->decl_node);
   2691         assert(var->decl_node->type == NodeTypeVariableDeclaration);
   2692 
   2693         LLVMValueRef global_value;
   2694         if (var->decl_node->data.variable_declaration.is_extern) {
   2695             global_value = LLVMAddGlobal(g->module, var->type->type_ref, buf_ptr(&var->name));
   2696 
   2697             LLVMSetLinkage(global_value, LLVMExternalLinkage);
   2698         } else {
   2699             AstNode *expr_node = var->decl_node->data.variable_declaration.expr;
   2700             LLVMValueRef init_val;
   2701             if (expr_node) {
   2702                 Expr *expr = get_resolved_expr(expr_node);
   2703                 ConstExprValue *const_val = &expr->const_val;
   2704                 assert(const_val->ok);
   2705                 TypeTableEntry *type_entry = expr->type_entry;
   2706                 init_val = gen_const_val(g, type_entry, const_val);
   2707             } else {
   2708                 init_val = LLVMConstNull(var->type->type_ref);
   2709             }
   2710 
   2711             global_value = LLVMAddGlobal(g->module, LLVMTypeOf(init_val), buf_ptr(&var->name));
   2712             LLVMSetInitializer(global_value, init_val);
   2713             LLVMSetLinkage(global_value, LLVMInternalLinkage);
   2714             LLVMSetUnnamedAddr(global_value, true);
   2715         }
   2716 
   2717         LLVMSetGlobalConstant(global_value, var->is_const);
   2718 
   2719         var->value_ref = global_value;
   2720     }
   2721 
   2722     // Generate function prototypes
   2723     for (int fn_proto_i = 0; fn_proto_i < g->fn_protos.length; fn_proto_i += 1) {
   2724         FnTableEntry *fn_table_entry = g->fn_protos.at(fn_proto_i);
   2725         if (fn_table_entry->ref_count == 0) {
   2726             // huge time saver
   2727             LLVMDeleteFunction(fn_table_entry->fn_value);
   2728             continue;
   2729         }
   2730 
   2731         AstNode *proto_node = fn_table_entry->proto_node;
   2732         assert(proto_node->type == NodeTypeFnProto);
   2733         AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;
   2734 
   2735         TypeTableEntry *fn_type = fn_table_entry->type_entry;
   2736 
   2737         if (handle_is_ptr(fn_type->data.fn.fn_type_id.return_type)) {
   2738             LLVMValueRef first_arg = LLVMGetParam(fn_table_entry->fn_value, 0);
   2739             LLVMAddAttribute(first_arg, LLVMStructRetAttribute);
   2740         }
   2741 
   2742         // set parameter attributes
   2743         for (int param_decl_i = 0; param_decl_i < fn_proto->params.length; param_decl_i += 1) {
   2744             AstNode *param_node = fn_proto->params.at(param_decl_i);
   2745             assert(param_node->type == NodeTypeParamDecl);
   2746 
   2747             FnGenParamInfo *info = &fn_type->data.fn.gen_param_info[param_decl_i];
   2748             int gen_index = info->gen_index;
   2749             bool is_byval = info->is_byval;
   2750 
   2751             if (gen_index < 0) {
   2752                 continue;
   2753             }
   2754 
   2755             AstNode *type_node = param_node->data.param_decl.type;
   2756             TypeTableEntry *param_type = fn_proto_type_from_type_node(g, type_node);
   2757             LLVMValueRef argument_val = LLVMGetParam(fn_table_entry->fn_value, gen_index);
   2758             bool param_is_noalias = param_node->data.param_decl.is_noalias;
   2759             if (param_type->id == TypeTableEntryIdPointer && param_is_noalias) {
   2760                 LLVMAddAttribute(argument_val, LLVMNoAliasAttribute);
   2761             }
   2762             if (param_type->id == TypeTableEntryIdPointer && param_type->data.pointer.is_const) {
   2763                 LLVMAddAttribute(argument_val, LLVMReadOnlyAttribute);
   2764             }
   2765             if (param_type->id == TypeTableEntryIdPointer) {
   2766                 // when https://github.com/andrewrk/zig/issues/82 is fixed, add
   2767                 // non null attribute here
   2768             }
   2769             if (is_byval) {
   2770                 LLVMAddAttribute(argument_val, LLVMByValAttribute);
   2771             }
   2772         }
   2773 
   2774     }
   2775 
   2776     // Generate function definitions.
   2777     for (int fn_i = 0; fn_i < g->fn_defs.length; fn_i += 1) {
   2778         FnTableEntry *fn_table_entry = g->fn_defs.at(fn_i);
   2779         if (fn_table_entry->ref_count == 0) {
   2780             // huge time saver
   2781             continue;
   2782         }
   2783 
   2784         ImportTableEntry *import = fn_table_entry->import_entry;
   2785         AstNode *fn_def_node = fn_table_entry->fn_def_node;
   2786         LLVMValueRef fn = fn_table_entry->fn_value;
   2787         g->cur_fn = fn_table_entry;
   2788         if (handle_is_ptr(fn_table_entry->type_entry->data.fn.fn_type_id.return_type)) {
   2789             g->cur_ret_ptr = LLVMGetParam(fn, 0);
   2790         } else {
   2791             g->cur_ret_ptr = nullptr;
   2792         }
   2793 
   2794         AstNode *proto_node = fn_table_entry->proto_node;
   2795         assert(proto_node->type == NodeTypeFnProto);
   2796         AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;
   2797 
   2798         LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(fn, "entry");
   2799         LLVMPositionBuilderAtEnd(g->builder, entry_block);
   2800 
   2801 
   2802         AstNode *body_node = fn_def_node->data.fn_def.body;
   2803         build_label_blocks(g, body_node);
   2804 
   2805         // Set up debug info for blocks and variables and
   2806         // allocate all local variables
   2807         for (int bc_i = 0; bc_i < fn_table_entry->all_block_contexts.length; bc_i += 1) {
   2808             BlockContext *block_context = fn_table_entry->all_block_contexts.at(bc_i);
   2809 
   2810             if (!block_context->di_scope) {
   2811                 LLVMZigDILexicalBlock *di_block = LLVMZigCreateLexicalBlock(g->dbuilder,
   2812                     block_context->parent->di_scope,
   2813                     import->di_file,
   2814                     block_context->node->line + 1,
   2815                     block_context->node->column + 1);
   2816                 block_context->di_scope = LLVMZigLexicalBlockToScope(di_block);
   2817             }
   2818 
   2819             for (int var_i = 0; var_i < block_context->variable_list.length; var_i += 1) {
   2820                 VariableTableEntry *var = block_context->variable_list.at(var_i);
   2821 
   2822                 if (var->type->size_in_bits == 0) {
   2823                     continue;
   2824                 }
   2825 
   2826                 unsigned tag;
   2827                 unsigned arg_no;
   2828                 if (block_context->node->type == NodeTypeFnDef) {
   2829                     tag = LLVMZigTag_DW_arg_variable();
   2830                     arg_no = var->gen_arg_index + 1;
   2831 
   2832                     var->is_ptr = false;
   2833                     var->value_ref = LLVMGetParam(fn, var->gen_arg_index);
   2834                 } else {
   2835                     tag = LLVMZigTag_DW_auto_variable();
   2836                     arg_no = 0;
   2837 
   2838                     add_debug_source_node(g, var->decl_node);
   2839                     var->value_ref = LLVMBuildAlloca(g->builder, var->type->type_ref, buf_ptr(&var->name));
   2840                     LLVMSetAlignment(var->value_ref, var->type->align_in_bits / 8);
   2841                 }
   2842 
   2843                 var->di_loc_var = LLVMZigCreateLocalVariable(g->dbuilder, tag,
   2844                         block_context->di_scope, buf_ptr(&var->name),
   2845                         import->di_file, var->decl_node->line + 1,
   2846                         var->type->di_type, !g->strip_debug_symbols, 0, arg_no);
   2847             }
   2848 
   2849             // allocate structs which are the result of casts
   2850             for (int cea_i = 0; cea_i < block_context->cast_alloca_list.length; cea_i += 1) {
   2851                 AstNode *fn_call_node = block_context->cast_alloca_list.at(cea_i);
   2852                 add_debug_source_node(g, fn_call_node);
   2853                 Expr *expr = &fn_call_node->data.fn_call_expr.resolved_expr;
   2854                 fn_call_node->data.fn_call_expr.tmp_ptr = LLVMBuildAlloca(g->builder,
   2855                         expr->type_entry->type_ref, "");
   2856             }
   2857 
   2858             // allocate structs which are struct value expressions
   2859             for (int alloca_i = 0; alloca_i < block_context->struct_val_expr_alloca_list.length; alloca_i += 1) {
   2860                 StructValExprCodeGen *struct_val_expr_node = block_context->struct_val_expr_alloca_list.at(alloca_i);
   2861                 add_debug_source_node(g, struct_val_expr_node->source_node);
   2862                 struct_val_expr_node->ptr = LLVMBuildAlloca(g->builder,
   2863                         struct_val_expr_node->type_entry->type_ref, "");
   2864             }
   2865         }
   2866 
   2867         // create debug variable declarations for parameters
   2868         for (int param_i = 0; param_i < fn_proto->params.length; param_i += 1) {
   2869             AstNode *param_decl = fn_proto->params.at(param_i);
   2870             assert(param_decl->type == NodeTypeParamDecl);
   2871 
   2872             FnGenParamInfo *info = &fn_table_entry->type_entry->data.fn.gen_param_info[param_i];
   2873 
   2874             if (info->gen_index < 0) {
   2875                 continue;
   2876             }
   2877 
   2878             VariableTableEntry *variable = param_decl->data.param_decl.variable;
   2879             assert(variable);
   2880 
   2881             LLVMZigDILocation *debug_loc = LLVMZigGetDebugLoc(param_decl->line + 1, param_decl->column + 1,
   2882                     fn_def_node->data.fn_def.block_context->di_scope);
   2883             LLVMZigInsertDeclareAtEnd(g->dbuilder, variable->value_ref, variable->di_loc_var, debug_loc,
   2884                     entry_block);
   2885         }
   2886 
   2887         TypeTableEntry *implicit_return_type = fn_def_node->data.fn_def.implicit_return_type;
   2888         gen_block(g, fn_def_node->data.fn_def.body, implicit_return_type);
   2889 
   2890     }
   2891     assert(!g->errors.length);
   2892 
   2893     LLVMZigDIBuilderFinalize(g->dbuilder);
   2894 
   2895     if (g->verbose) {
   2896         LLVMDumpModule(g->module);
   2897     }
   2898 
   2899     // in release mode, we're sooooo confident that we've generated correct ir,
   2900     // that we skip the verify module step in order to get better performance.
   2901 #ifndef NDEBUG
   2902     char *error = nullptr;
   2903     LLVMVerifyModule(g->module, LLVMAbortProcessAction, &error);
   2904 #endif
   2905 }
   2906 
   2907 static const int int_sizes_in_bits[] = {
   2908     8,
   2909     16,
   2910     32,
   2911     64,
   2912 };
   2913 
   2914 struct CIntTypeInfo {
   2915     CIntType id;
   2916     const char *name;
   2917     bool is_signed;
   2918 };
   2919 
   2920 static const CIntTypeInfo c_int_type_infos[] = {
   2921     {CIntTypeShort, "c_short", true},
   2922     {CIntTypeUShort, "c_ushort", false},
   2923     {CIntTypeInt, "c_int", true},
   2924     {CIntTypeUInt, "c_uint", false},
   2925     {CIntTypeLong, "c_long", true},
   2926     {CIntTypeULong, "c_ulong", false},
   2927     {CIntTypeLongLong, "c_longlong", true},
   2928     {CIntTypeULongLong, "c_ulonglong", false},
   2929 };
   2930 
   2931 static int get_c_type_size_in_bits(CodeGen *g, CIntType id) {
   2932     // TODO other architectures besides x86_64
   2933     switch (id) {
   2934         case CIntTypeShort:
   2935         case CIntTypeUShort:
   2936             return 16;
   2937         case CIntTypeInt:
   2938         case CIntTypeUInt:
   2939             return 32;
   2940         case CIntTypeLong:
   2941         case CIntTypeULong:
   2942         case CIntTypeLongLong:
   2943         case CIntTypeULongLong:
   2944             return 64;
   2945     }
   2946     zig_unreachable();
   2947 }
   2948 
   2949 static void define_builtin_types(CodeGen *g) {
   2950     {
   2951         // if this type is anywhere in the AST, we should never hit codegen.
   2952         TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInvalid);
   2953         buf_init_from_str(&entry->name, "(invalid)");
   2954         g->builtin_types.entry_invalid = entry;
   2955     }
   2956     {
   2957         TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdNumLitFloat);
   2958         buf_init_from_str(&entry->name, "(float literal)");
   2959         g->builtin_types.entry_num_lit_float = entry;
   2960     }
   2961     {
   2962         TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdNumLitInt);
   2963         buf_init_from_str(&entry->name, "(integer literal)");
   2964         g->builtin_types.entry_num_lit_int = entry;
   2965     }
   2966     {
   2967         TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdUndefLit);
   2968         buf_init_from_str(&entry->name, "(undefined)");
   2969         g->builtin_types.entry_undef = entry;
   2970     }
   2971 
   2972     for (int i = 0; i < array_length(int_sizes_in_bits); i += 1) {
   2973         int size_in_bits = int_sizes_in_bits[i];
   2974         bool is_signed = true;
   2975         for (;;) {
   2976             TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt);
   2977             entry->type_ref = LLVMIntType(size_in_bits);
   2978 
   2979             const char u_or_i = is_signed ? 'i' : 'u';
   2980             buf_resize(&entry->name, 0);
   2981             buf_appendf(&entry->name, "%c%d", u_or_i, size_in_bits);
   2982 
   2983             entry->size_in_bits = size_in_bits;
   2984             entry->align_in_bits = size_in_bits;
   2985             entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
   2986                     entry->size_in_bits, entry->align_in_bits,
   2987                     is_signed ? LLVMZigEncoding_DW_ATE_signed() : LLVMZigEncoding_DW_ATE_unsigned());
   2988             entry->data.integral.is_signed = is_signed;
   2989             g->primitive_type_table.put(&entry->name, entry);
   2990 
   2991             get_int_type_ptr(g, is_signed, size_in_bits)[0] = entry;
   2992 
   2993             if (!is_signed) {
   2994                 break;
   2995             } else {
   2996                 is_signed = false;
   2997             }
   2998         }
   2999     }
   3000 
   3001     for (int i = 0; i < array_length(c_int_type_infos); i += 1) {
   3002         const CIntTypeInfo *info = &c_int_type_infos[i];
   3003         uint64_t size_in_bits = get_c_type_size_in_bits(g, info->id);
   3004         bool is_signed = info->is_signed;
   3005 
   3006         TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt);
   3007         entry->type_ref = LLVMIntType(size_in_bits);
   3008 
   3009         buf_init_from_str(&entry->name, info->name);
   3010 
   3011         entry->size_in_bits = size_in_bits;
   3012         entry->align_in_bits = size_in_bits;
   3013 
   3014         entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
   3015                 entry->size_in_bits, entry->align_in_bits,
   3016                 is_signed ? LLVMZigEncoding_DW_ATE_signed() : LLVMZigEncoding_DW_ATE_unsigned());
   3017         entry->data.integral.is_signed = is_signed;
   3018         g->primitive_type_table.put(&entry->name, entry);
   3019 
   3020         get_c_int_type_ptr(g, info->id)[0] = entry;
   3021     }
   3022 
   3023     {
   3024         TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdBool);
   3025         entry->type_ref = LLVMInt1Type();
   3026         buf_init_from_str(&entry->name, "bool");
   3027         entry->size_in_bits = 8;
   3028         entry->align_in_bits = 8;
   3029         entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
   3030                 entry->size_in_bits, entry->align_in_bits,
   3031                 LLVMZigEncoding_DW_ATE_unsigned());
   3032         g->builtin_types.entry_bool = entry;
   3033         g->primitive_type_table.put(&entry->name, entry);
   3034     }
   3035     {
   3036         TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt);
   3037         entry->type_ref = LLVMIntType(g->pointer_size_bytes * 8);
   3038         buf_init_from_str(&entry->name, "isize");
   3039         entry->size_in_bits = g->pointer_size_bytes * 8;
   3040         entry->align_in_bits = g->pointer_size_bytes * 8;
   3041         entry->data.integral.is_signed = true;
   3042 
   3043         entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
   3044                 entry->size_in_bits, entry->align_in_bits,
   3045                 LLVMZigEncoding_DW_ATE_signed());
   3046         g->builtin_types.entry_isize = entry;
   3047         g->primitive_type_table.put(&entry->name, entry);
   3048     }
   3049     {
   3050         TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt);
   3051         entry->type_ref = LLVMIntType(g->pointer_size_bytes * 8);
   3052         buf_init_from_str(&entry->name, "usize");
   3053         entry->size_in_bits = g->pointer_size_bytes * 8;
   3054         entry->align_in_bits = g->pointer_size_bytes * 8;
   3055         entry->data.integral.is_signed = false;
   3056 
   3057         entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
   3058                 entry->size_in_bits, entry->align_in_bits,
   3059                 LLVMZigEncoding_DW_ATE_unsigned());
   3060         g->builtin_types.entry_usize = entry;
   3061         g->primitive_type_table.put(&entry->name, entry);
   3062     }
   3063     {
   3064         TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdFloat);
   3065         entry->type_ref = LLVMFloatType();
   3066         buf_init_from_str(&entry->name, "f32");
   3067         entry->size_in_bits = 32;
   3068         entry->align_in_bits = 32;
   3069         entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
   3070                 entry->size_in_bits, entry->align_in_bits,
   3071                 LLVMZigEncoding_DW_ATE_float());
   3072         g->builtin_types.entry_f32 = entry;
   3073         g->primitive_type_table.put(&entry->name, entry);
   3074     }
   3075     {
   3076         TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdFloat);
   3077         entry->type_ref = LLVMDoubleType();
   3078         buf_init_from_str(&entry->name, "f64");
   3079         entry->size_in_bits = 64;
   3080         entry->align_in_bits = 64;
   3081         entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
   3082                 entry->size_in_bits, entry->align_in_bits,
   3083                 LLVMZigEncoding_DW_ATE_float());
   3084         g->builtin_types.entry_f64 = entry;
   3085         g->primitive_type_table.put(&entry->name, entry);
   3086     }
   3087     {
   3088         TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdFloat);
   3089         entry->type_ref = LLVMX86FP80Type();
   3090         buf_init_from_str(&entry->name, "c_long_double");
   3091         entry->size_in_bits = 128;
   3092         entry->align_in_bits = 128;
   3093         entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
   3094                 80, entry->align_in_bits,
   3095                 LLVMZigEncoding_DW_ATE_float());
   3096         g->builtin_types.entry_c_long_double = entry;
   3097         g->primitive_type_table.put(&entry->name, entry);
   3098     }
   3099     {
   3100         TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdVoid);
   3101         entry->type_ref = LLVMVoidType();
   3102         buf_init_from_str(&entry->name, "void");
   3103         entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
   3104                 entry->size_in_bits, entry->align_in_bits,
   3105                 LLVMZigEncoding_DW_ATE_unsigned());
   3106         g->builtin_types.entry_void = entry;
   3107         g->primitive_type_table.put(&entry->name, entry);
   3108     }
   3109     {
   3110         TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdUnreachable);
   3111         entry->type_ref = LLVMVoidType();
   3112         buf_init_from_str(&entry->name, "unreachable");
   3113         entry->di_type = g->builtin_types.entry_void->di_type;
   3114         g->builtin_types.entry_unreachable = entry;
   3115         g->primitive_type_table.put(&entry->name, entry);
   3116     }
   3117     {
   3118         TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdMetaType);
   3119         buf_init_from_str(&entry->name, "type");
   3120         g->builtin_types.entry_type = entry;
   3121         g->primitive_type_table.put(&entry->name, entry);
   3122     }
   3123     {
   3124         // partially complete the error type. we complete it later after we know
   3125         // error_value_count.
   3126         TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdPureError);
   3127         buf_init_from_str(&entry->name, "error");
   3128         g->builtin_types.entry_pure_error = entry;
   3129         g->primitive_type_table.put(&entry->name, entry);
   3130     }
   3131 
   3132     g->builtin_types.entry_u8 = get_int_type(g, false, 8);
   3133     g->builtin_types.entry_u16 = get_int_type(g, false, 16);
   3134     g->builtin_types.entry_u32 = get_int_type(g, false, 32);
   3135     g->builtin_types.entry_u64 = get_int_type(g, false, 64);
   3136     g->builtin_types.entry_i8 = get_int_type(g, true, 8);
   3137     g->builtin_types.entry_i16 = get_int_type(g, true, 16);
   3138     g->builtin_types.entry_i32 = get_int_type(g, true, 32);
   3139     g->builtin_types.entry_i64 = get_int_type(g, true, 64);
   3140 }
   3141 
   3142 
   3143 static BuiltinFnEntry *create_builtin_fn(CodeGen *g, BuiltinFnId id, const char *name) {
   3144     BuiltinFnEntry *builtin_fn = allocate<BuiltinFnEntry>(1);
   3145     buf_init_from_str(&builtin_fn->name, name);
   3146     builtin_fn->id = id;
   3147     g->builtin_fn_table.put(&builtin_fn->name, builtin_fn);
   3148     return builtin_fn;
   3149 }
   3150 
   3151 static BuiltinFnEntry *create_builtin_fn_with_arg_count(CodeGen *g, BuiltinFnId id, const char *name, int count) {
   3152     BuiltinFnEntry *builtin_fn = create_builtin_fn(g, id, name);
   3153     builtin_fn->param_count = count;
   3154     builtin_fn->param_types = allocate<TypeTableEntry *>(count);
   3155     return builtin_fn;
   3156 }
   3157 
   3158 static void define_builtin_fns(CodeGen *g) {
   3159     {
   3160         LLVMTypeRef fn_type = LLVMFunctionType(LLVMVoidType(), nullptr, 0, false);
   3161         g->trap_fn_val = LLVMAddFunction(g->module, "llvm.debugtrap", fn_type);
   3162         assert(LLVMGetIntrinsicID(g->trap_fn_val));
   3163     }
   3164     {
   3165         BuiltinFnEntry *builtin_fn = create_builtin_fn(g, BuiltinFnIdMemcpy, "memcpy");
   3166         builtin_fn->return_type = g->builtin_types.entry_void;
   3167         builtin_fn->param_count = 3;
   3168         builtin_fn->param_types = allocate<TypeTableEntry *>(builtin_fn->param_count);
   3169         builtin_fn->param_types[0] = nullptr; // manually checked later
   3170         builtin_fn->param_types[1] = nullptr; // manually checked later
   3171         builtin_fn->param_types[2] = g->builtin_types.entry_isize;
   3172         builtin_fn->ref_count = 1;
   3173 
   3174         LLVMTypeRef param_types[] = {
   3175             LLVMPointerType(LLVMInt8Type(), 0),
   3176             LLVMPointerType(LLVMInt8Type(), 0),
   3177             LLVMIntType(g->pointer_size_bytes * 8),
   3178             LLVMInt32Type(),
   3179             LLVMInt1Type(),
   3180         };
   3181         LLVMTypeRef fn_type = LLVMFunctionType(LLVMVoidType(), param_types, 5, false);
   3182         Buf *name = buf_sprintf("llvm.memcpy.p0i8.p0i8.i%d", g->pointer_size_bytes * 8);
   3183         builtin_fn->fn_val = LLVMAddFunction(g->module, buf_ptr(name), fn_type);
   3184         assert(LLVMGetIntrinsicID(builtin_fn->fn_val));
   3185 
   3186         g->memcpy_fn_val = builtin_fn->fn_val;
   3187     }
   3188     {
   3189         BuiltinFnEntry *builtin_fn = create_builtin_fn(g, BuiltinFnIdMemset, "memset");
   3190         builtin_fn->return_type = g->builtin_types.entry_void;
   3191         builtin_fn->param_count = 3;
   3192         builtin_fn->param_types = allocate<TypeTableEntry *>(builtin_fn->param_count);
   3193         builtin_fn->param_types[0] = nullptr; // manually checked later
   3194         builtin_fn->param_types[1] = g->builtin_types.entry_u8;
   3195         builtin_fn->param_types[2] = g->builtin_types.entry_isize;
   3196         builtin_fn->ref_count = 1;
   3197 
   3198         LLVMTypeRef param_types[] = {
   3199             LLVMPointerType(LLVMInt8Type(), 0),
   3200             LLVMInt8Type(),
   3201             LLVMIntType(g->pointer_size_bytes * 8),
   3202             LLVMInt32Type(),
   3203             LLVMInt1Type(),
   3204         };
   3205         LLVMTypeRef fn_type = LLVMFunctionType(LLVMVoidType(), param_types, 5, false);
   3206         Buf *name = buf_sprintf("llvm.memset.p0i8.i%d", g->pointer_size_bytes * 8);
   3207         builtin_fn->fn_val = LLVMAddFunction(g->module, buf_ptr(name), fn_type);
   3208         assert(LLVMGetIntrinsicID(builtin_fn->fn_val));
   3209 
   3210         g->memset_fn_val = builtin_fn->fn_val;
   3211     }
   3212     create_builtin_fn_with_arg_count(g, BuiltinFnIdSizeof, "sizeof", 1);
   3213     create_builtin_fn_with_arg_count(g, BuiltinFnIdMaxValue, "max_value", 1);
   3214     create_builtin_fn_with_arg_count(g, BuiltinFnIdMinValue, "min_value", 1);
   3215     create_builtin_fn_with_arg_count(g, BuiltinFnIdMemberCount, "member_count", 1);
   3216     create_builtin_fn_with_arg_count(g, BuiltinFnIdTypeof, "typeof", 1);
   3217     create_builtin_fn_with_arg_count(g, BuiltinFnIdAddWithOverflow, "add_with_overflow", 4);
   3218     create_builtin_fn_with_arg_count(g, BuiltinFnIdSubWithOverflow, "sub_with_overflow", 4);
   3219     create_builtin_fn_with_arg_count(g, BuiltinFnIdMulWithOverflow, "mul_with_overflow", 4);
   3220     create_builtin_fn_with_arg_count(g, BuiltinFnIdCInclude, "c_include", 1);
   3221     create_builtin_fn_with_arg_count(g, BuiltinFnIdCDefine, "c_define", 2);
   3222     create_builtin_fn_with_arg_count(g, BuiltinFnIdCUndef, "c_undef", 1);
   3223 }
   3224 
   3225 
   3226 
   3227 static void init(CodeGen *g, Buf *source_path) {
   3228     g->lib_search_paths.append(g->root_source_dir);
   3229     g->lib_search_paths.append(buf_create_from_str(ZIG_STD_DIR));
   3230 
   3231     LLVMInitializeAllTargets();
   3232     LLVMInitializeAllTargetMCs();
   3233     LLVMInitializeAllAsmPrinters();
   3234     LLVMInitializeAllAsmParsers();
   3235     LLVMInitializeNativeTarget();
   3236 
   3237     g->is_native_target = true;
   3238     char *native_triple = LLVMGetDefaultTargetTriple();
   3239 
   3240     g->module = LLVMModuleCreateWithName(buf_ptr(source_path));
   3241 
   3242     LLVMSetTarget(g->module, native_triple);
   3243 
   3244     LLVMTargetRef target_ref;
   3245     char *err_msg = nullptr;
   3246     if (LLVMGetTargetFromTriple(native_triple, &target_ref, &err_msg)) {
   3247         zig_panic("unable to get target from triple: %s", err_msg);
   3248     }
   3249 
   3250 
   3251     char *native_cpu = LLVMZigGetHostCPUName();
   3252     char *native_features = LLVMZigGetNativeFeatures();
   3253 
   3254     LLVMCodeGenOptLevel opt_level = (g->build_type == CodeGenBuildTypeDebug) ?
   3255         LLVMCodeGenLevelNone : LLVMCodeGenLevelAggressive;
   3256 
   3257     LLVMRelocMode reloc_mode = g->is_static ? LLVMRelocStatic : LLVMRelocPIC;
   3258 
   3259     g->target_machine = LLVMCreateTargetMachine(target_ref, native_triple,
   3260             native_cpu, native_features, opt_level, reloc_mode, LLVMCodeModelDefault);
   3261 
   3262     g->target_data_ref = LLVMGetTargetMachineData(g->target_machine);
   3263 
   3264     char *layout_str = LLVMCopyStringRepOfTargetData(g->target_data_ref);
   3265     LLVMSetDataLayout(g->module, layout_str);
   3266 
   3267 
   3268     g->pointer_size_bytes = LLVMPointerSize(g->target_data_ref);
   3269 
   3270     g->builder = LLVMCreateBuilder();
   3271     g->dbuilder = LLVMZigCreateDIBuilder(g->module, true);
   3272 
   3273     LLVMZigSetFastMath(g->builder, true);
   3274 
   3275 
   3276     Buf *producer = buf_sprintf("zig %s", ZIG_VERSION_STRING);
   3277     bool is_optimized = g->build_type == CodeGenBuildTypeRelease;
   3278     const char *flags = "";
   3279     unsigned runtime_version = 0;
   3280     g->compile_unit = LLVMZigCreateCompileUnit(g->dbuilder, LLVMZigLang_DW_LANG_C99(),
   3281             buf_ptr(source_path), buf_ptr(g->root_source_dir),
   3282             buf_ptr(producer), is_optimized, flags, runtime_version,
   3283             "", 0, !g->strip_debug_symbols);
   3284 
   3285     // This is for debug stuff that doesn't have a real file.
   3286     g->dummy_di_file = nullptr;
   3287 
   3288     define_builtin_types(g);
   3289     define_builtin_fns(g);
   3290 
   3291 }
   3292 
   3293 void codegen_parseh(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source_code) {
   3294     find_libc_path(g);
   3295     Buf *full_path = buf_alloc();
   3296     os_path_join(src_dirname, src_basename, full_path);
   3297 
   3298     ImportTableEntry *import = allocate<ImportTableEntry>(1);
   3299     import->source_code = source_code;
   3300     import->path = full_path;
   3301     import->fn_table.init(32);
   3302     g->root_import = import;
   3303 
   3304     init(g, full_path);
   3305 
   3306     import->di_file = LLVMZigCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname));
   3307 
   3308     ZigList<ErrorMsg *> errors = {0};
   3309     int err = parse_h_buf(import, &errors, source_code, g, nullptr);
   3310     if (err) {
   3311         fprintf(stderr, "unable to parse .h file: %s\n", err_str(err));
   3312         exit(1);
   3313     }
   3314 
   3315     if (errors.length > 0) {
   3316         for (int i = 0; i < errors.length; i += 1) {
   3317             ErrorMsg *err_msg = errors.at(i);
   3318             print_err_msg(err_msg, g->err_color);
   3319         }
   3320         exit(1);
   3321     }
   3322 }
   3323 
   3324 void codegen_render_ast(CodeGen *g, FILE *f, int indent_size) {
   3325     ast_render(stdout, g->root_import->root, 4);
   3326 }
   3327 
   3328 
   3329 static int parse_version_string(Buf *buf, int *major, int *minor, int *patch) {
   3330     char *dot1 = strstr(buf_ptr(buf), ".");
   3331     if (!dot1)
   3332         return ErrorInvalidFormat;
   3333     char *dot2 = strstr(dot1 + 1, ".");
   3334     if (!dot2)
   3335         return ErrorInvalidFormat;
   3336 
   3337     *major = (int)strtol(buf_ptr(buf), nullptr, 10);
   3338     *minor = (int)strtol(dot1 + 1, nullptr, 10);
   3339     *patch = (int)strtol(dot2 + 1, nullptr, 10);
   3340 
   3341     return ErrorNone;
   3342 }
   3343 
   3344 static void set_root_export_version(CodeGen *g, Buf *version_buf, AstNode *node) {
   3345     int err;
   3346     if ((err = parse_version_string(version_buf, &g->version_major, &g->version_minor, &g->version_patch))) {
   3347         add_node_error(g, node,
   3348                 buf_sprintf("invalid version string"));
   3349     }
   3350 }
   3351 
   3352 
   3353 static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path,
   3354         Buf *src_dirname, Buf *src_basename, Buf *source_code)
   3355 {
   3356     int err;
   3357     Buf *full_path = buf_alloc();
   3358     os_path_join(src_dirname, src_basename, full_path);
   3359 
   3360     if (g->verbose) {
   3361         fprintf(stderr, "\nOriginal Source (%s):\n", buf_ptr(full_path));
   3362         fprintf(stderr, "----------------\n");
   3363         fprintf(stderr, "%s\n", buf_ptr(source_code));
   3364 
   3365         fprintf(stderr, "\nTokens:\n");
   3366         fprintf(stderr, "---------\n");
   3367     }
   3368 
   3369     Tokenization tokenization = {0};
   3370     tokenize(source_code, &tokenization);
   3371 
   3372     if (tokenization.err) {
   3373         ErrorMsg *err = err_msg_create_with_line(full_path, tokenization.err_line, tokenization.err_column,
   3374                 source_code, tokenization.line_offsets, tokenization.err);
   3375 
   3376         print_err_msg(err, g->err_color);
   3377         exit(1);
   3378     }
   3379 
   3380     if (g->verbose) {
   3381         print_tokens(source_code, tokenization.tokens);
   3382 
   3383         fprintf(stderr, "\nAST:\n");
   3384         fprintf(stderr, "------\n");
   3385     }
   3386 
   3387     ImportTableEntry *import_entry = allocate<ImportTableEntry>(1);
   3388     import_entry->source_code = source_code;
   3389     import_entry->line_offsets = tokenization.line_offsets;
   3390     import_entry->path = full_path;
   3391     import_entry->fn_table.init(32);
   3392 
   3393     import_entry->root = ast_parse(source_code, tokenization.tokens, import_entry, g->err_color,
   3394             &g->next_node_index);
   3395     assert(import_entry->root);
   3396     if (g->verbose) {
   3397         ast_print(stderr, import_entry->root, 0);
   3398     }
   3399 
   3400     import_entry->di_file = LLVMZigCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname));
   3401     g->import_table.put(abs_full_path, import_entry);
   3402 
   3403     import_entry->block_context = new_block_context(import_entry->root, nullptr);
   3404     import_entry->block_context->di_scope = LLVMZigFileToScope(import_entry->di_file);
   3405 
   3406 
   3407     assert(import_entry->root->type == NodeTypeRoot);
   3408     for (int decl_i = 0; decl_i < import_entry->root->data.root.top_level_decls.length; decl_i += 1) {
   3409         AstNode *top_level_decl = import_entry->root->data.root.top_level_decls.at(decl_i);
   3410 
   3411         if (top_level_decl->type == NodeTypeRootExportDecl) {
   3412             if (g->root_import) {
   3413                 add_node_error(g, top_level_decl,
   3414                         buf_sprintf("root export declaration only valid in root source file"));
   3415             } else {
   3416                 ZigList<AstNode *> *directives = top_level_decl->data.root_export_decl.directives;
   3417                 if (directives) {
   3418                     for (int i = 0; i < directives->length; i += 1) {
   3419                         AstNode *directive_node = directives->at(i);
   3420                         Buf *name = &directive_node->data.directive.name;
   3421                         Buf *param = &directive_node->data.directive.param;
   3422                         if (buf_eql_str(name, "version")) {
   3423                             set_root_export_version(g, param, directive_node);
   3424                         } else if (buf_eql_str(name, "link")) {
   3425                             g->link_table.put(param, true);
   3426                             if (buf_eql_str(param, "c")) {
   3427                                 g->link_libc = true;
   3428                             }
   3429                         } else {
   3430                             add_node_error(g, directive_node,
   3431                                     buf_sprintf("invalid directive: '%s'", buf_ptr(name)));
   3432                         }
   3433                     }
   3434                 }
   3435 
   3436                 if (g->root_export_decl) {
   3437                     add_node_error(g, top_level_decl,
   3438                             buf_sprintf("only one root export declaration allowed"));
   3439                 } else {
   3440                     g->root_export_decl = top_level_decl;
   3441 
   3442                     if (!g->root_out_name)
   3443                         g->root_out_name = &top_level_decl->data.root_export_decl.name;
   3444 
   3445                     Buf *out_type = &top_level_decl->data.root_export_decl.type;
   3446                     OutType export_out_type;
   3447                     if (buf_eql_str(out_type, "executable")) {
   3448                         export_out_type = OutTypeExe;
   3449                     } else if (buf_eql_str(out_type, "library")) {
   3450                         export_out_type = OutTypeLib;
   3451                     } else if (buf_eql_str(out_type, "object")) {
   3452                         export_out_type = OutTypeObj;
   3453                     } else {
   3454                         add_node_error(g, top_level_decl,
   3455                                 buf_sprintf("invalid export type: '%s'", buf_ptr(out_type)));
   3456                     }
   3457                     if (g->out_type == OutTypeUnknown) {
   3458                         g->out_type = export_out_type;
   3459                     }
   3460                 }
   3461             }
   3462         } else if (top_level_decl->type == NodeTypeImport) {
   3463             Buf *import_target_path = &top_level_decl->data.import.path;
   3464             Buf full_path = BUF_INIT;
   3465             Buf *import_code = buf_alloc();
   3466             bool found_it = false;
   3467 
   3468             for (int path_i = 0; path_i < g->lib_search_paths.length; path_i += 1) {
   3469                 Buf *search_path = g->lib_search_paths.at(path_i);
   3470                 os_path_join(search_path, import_target_path, &full_path);
   3471 
   3472                 Buf *abs_full_path = buf_alloc();
   3473                 if ((err = os_path_real(&full_path, abs_full_path))) {
   3474                     if (err == ErrorFileNotFound) {
   3475                         continue;
   3476                     } else {
   3477                         g->error_during_imports = true;
   3478                         add_node_error(g, top_level_decl,
   3479                                 buf_sprintf("unable to open '%s': %s", buf_ptr(&full_path), err_str(err)));
   3480                         goto done_looking_at_imports;
   3481                     }
   3482                 }
   3483 
   3484                 auto entry = g->import_table.maybe_get(abs_full_path);
   3485                 if (entry) {
   3486                     found_it = true;
   3487                     top_level_decl->data.import.import = entry->value;
   3488                 } else {
   3489                     if ((err = os_fetch_file_path(abs_full_path, import_code))) {
   3490                         if (err == ErrorFileNotFound) {
   3491                             continue;
   3492                         } else {
   3493                             g->error_during_imports = true;
   3494                             add_node_error(g, top_level_decl,
   3495                                     buf_sprintf("unable to open '%s': %s", buf_ptr(&full_path), err_str(err)));
   3496                             goto done_looking_at_imports;
   3497                         }
   3498                     }
   3499                     top_level_decl->data.import.import = codegen_add_code(g,
   3500                             abs_full_path, search_path, &top_level_decl->data.import.path, import_code);
   3501                     found_it = true;
   3502                 }
   3503                 break;
   3504             }
   3505             if (!found_it) {
   3506                 g->error_during_imports = true;
   3507                 add_node_error(g, top_level_decl,
   3508                         buf_sprintf("unable to find '%s'", buf_ptr(import_target_path)));
   3509             }
   3510         } else if (top_level_decl->type == NodeTypeFnDef) {
   3511             AstNode *proto_node = top_level_decl->data.fn_def.fn_proto;
   3512             assert(proto_node->type == NodeTypeFnProto);
   3513             Buf *proto_name = &proto_node->data.fn_proto.name;
   3514 
   3515             bool is_private = (proto_node->data.fn_proto.visib_mod == VisibModPrivate);
   3516 
   3517             if (buf_eql_str(proto_name, "main") && !is_private) {
   3518                 g->have_exported_main = true;
   3519             }
   3520         }
   3521     }
   3522 
   3523 done_looking_at_imports:
   3524 
   3525     return import_entry;
   3526 }
   3527 
   3528 static ImportTableEntry *add_special_code(CodeGen *g, const char *basename) {
   3529     Buf *std_dir = buf_create_from_str(ZIG_STD_DIR);
   3530     Buf *code_basename = buf_create_from_str(basename);
   3531     Buf path_to_code_src = BUF_INIT;
   3532     os_path_join(std_dir, code_basename, &path_to_code_src);
   3533     Buf *abs_full_path = buf_alloc();
   3534     int err;
   3535     if ((err = os_path_real(&path_to_code_src, abs_full_path))) {
   3536         zig_panic("unable to open '%s': %s", buf_ptr(&path_to_code_src), err_str(err));
   3537     }
   3538     Buf *import_code = buf_alloc();
   3539     if ((err = os_fetch_file_path(abs_full_path, import_code))) {
   3540         zig_panic("unable to open '%s': %s", buf_ptr(&path_to_code_src), err_str(err));
   3541     }
   3542 
   3543     return codegen_add_code(g, abs_full_path, std_dir, code_basename, import_code);
   3544 }
   3545 
   3546 void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *source_code) {
   3547     Buf source_path = BUF_INIT;
   3548     os_path_join(src_dir, src_basename, &source_path);
   3549     init(g, &source_path);
   3550 
   3551     Buf *abs_full_path = buf_alloc();
   3552     int err;
   3553     if ((err = os_path_real(&source_path, abs_full_path))) {
   3554         zig_panic("unable to open '%s': %s", buf_ptr(&source_path), err_str(err));
   3555     }
   3556 
   3557     g->root_import = codegen_add_code(g, abs_full_path, src_dir, src_basename, source_code);
   3558 
   3559     if (!g->root_out_name) {
   3560         add_node_error(g, g->root_import->root,
   3561                 buf_sprintf("missing export declaration and output name not provided"));
   3562     } else if (g->out_type == OutTypeUnknown) {
   3563         add_node_error(g, g->root_import->root,
   3564                 buf_sprintf("missing export declaration and export type not provided"));
   3565     }
   3566 
   3567     if (!g->link_libc) {
   3568         if (g->have_exported_main && (g->out_type == OutTypeObj || g->out_type == OutTypeExe)) {
   3569             g->bootstrap_import = add_special_code(g, "bootstrap.zig");
   3570         }
   3571 
   3572         if (g->out_type == OutTypeExe) {
   3573             add_special_code(g, "builtin.zig");
   3574         }
   3575     }
   3576 
   3577     if (g->verbose) {
   3578         fprintf(stderr, "\nSemantic Analysis:\n");
   3579         fprintf(stderr, "--------------------\n");
   3580     }
   3581     if (!g->error_during_imports) {
   3582         semantic_analyze(g);
   3583     }
   3584 
   3585     if (g->errors.length == 0) {
   3586         if (g->verbose) {
   3587             fprintf(stderr, "OK\n");
   3588         }
   3589     } else {
   3590         for (int i = 0; i < g->errors.length; i += 1) {
   3591             ErrorMsg *err = g->errors.at(i);
   3592             print_err_msg(err, g->err_color);
   3593         }
   3594         exit(1);
   3595     }
   3596 
   3597     if (g->verbose) {
   3598         fprintf(stderr, "\nCode Generation:\n");
   3599         fprintf(stderr, "------------------\n");
   3600     }
   3601 
   3602     do_code_gen(g);
   3603 }
   3604 
   3605 static void to_c_type(CodeGen *g, AstNode *type_node, Buf *out_buf) {
   3606     zig_panic("TODO this function needs some love");
   3607     TypeTableEntry *type_entry = get_resolved_expr(type_node)->type_entry;
   3608     assert(type_entry);
   3609 
   3610     if (type_entry == g->builtin_types.entry_u8) {
   3611         g->c_stdint_used = true;
   3612         buf_init_from_str(out_buf, "uint8_t");
   3613     } else if (type_entry == g->builtin_types.entry_i32) {
   3614         g->c_stdint_used = true;
   3615         buf_init_from_str(out_buf, "int32_t");
   3616     } else if (type_entry == g->builtin_types.entry_isize) {
   3617         g->c_stdint_used = true;
   3618         buf_init_from_str(out_buf, "intptr_t");
   3619     } else if (type_entry == g->builtin_types.entry_f32) {
   3620         buf_init_from_str(out_buf, "float");
   3621     } else if (type_entry == g->builtin_types.entry_unreachable) {
   3622         buf_init_from_str(out_buf, "__attribute__((__noreturn__)) void");
   3623     } else if (type_entry == g->builtin_types.entry_bool) {
   3624         buf_init_from_str(out_buf, "unsigned char");
   3625     } else if (type_entry == g->builtin_types.entry_void) {
   3626         buf_init_from_str(out_buf, "void");
   3627     } else {
   3628         zig_panic("TODO to_c_type");
   3629     }
   3630 }
   3631 
   3632 static void generate_h_file(CodeGen *g) {
   3633     Buf *h_file_out_path = buf_sprintf("%s.h", buf_ptr(g->root_out_name));
   3634     FILE *out_h = fopen(buf_ptr(h_file_out_path), "wb");
   3635     if (!out_h)
   3636         zig_panic("unable to open %s: %s", buf_ptr(h_file_out_path), strerror(errno));
   3637 
   3638     Buf *export_macro = buf_sprintf("%s_EXPORT", buf_ptr(g->root_out_name));
   3639     buf_upcase(export_macro);
   3640 
   3641     Buf *extern_c_macro = buf_sprintf("%s_EXTERN_C", buf_ptr(g->root_out_name));
   3642     buf_upcase(extern_c_macro);
   3643 
   3644     Buf h_buf = BUF_INIT;
   3645     buf_resize(&h_buf, 0);
   3646     for (int fn_def_i = 0; fn_def_i < g->fn_defs.length; fn_def_i += 1) {
   3647         FnTableEntry *fn_table_entry = g->fn_defs.at(fn_def_i);
   3648         AstNode *proto_node = fn_table_entry->proto_node;
   3649         assert(proto_node->type == NodeTypeFnProto);
   3650         AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;
   3651 
   3652         if (fn_proto->visib_mod != VisibModExport)
   3653             continue;
   3654 
   3655         Buf return_type_c = BUF_INIT;
   3656         to_c_type(g, fn_proto->return_type, &return_type_c);
   3657 
   3658         buf_appendf(&h_buf, "%s %s %s(",
   3659                 buf_ptr(export_macro),
   3660                 buf_ptr(&return_type_c),
   3661                 buf_ptr(&fn_proto->name));
   3662 
   3663         Buf param_type_c = BUF_INIT;
   3664         if (fn_proto->params.length) {
   3665             for (int param_i = 0; param_i < fn_proto->params.length; param_i += 1) {
   3666                 AstNode *param_decl_node = fn_proto->params.at(param_i);
   3667                 AstNode *param_type = param_decl_node->data.param_decl.type;
   3668                 to_c_type(g, param_type, &param_type_c);
   3669                 buf_appendf(&h_buf, "%s %s",
   3670                         buf_ptr(&param_type_c),
   3671                         buf_ptr(&param_decl_node->data.param_decl.name));
   3672                 if (param_i < fn_proto->params.length - 1)
   3673                     buf_appendf(&h_buf, ", ");
   3674             }
   3675             buf_appendf(&h_buf, ")");
   3676         } else {
   3677             buf_appendf(&h_buf, "void)");
   3678         }
   3679 
   3680         buf_appendf(&h_buf, ";\n");
   3681 
   3682     }
   3683 
   3684     Buf *ifdef_dance_name = buf_sprintf("%s_%s_H",
   3685             buf_ptr(g->root_out_name), buf_ptr(g->root_out_name));
   3686     buf_upcase(ifdef_dance_name);
   3687 
   3688     fprintf(out_h, "#ifndef %s\n", buf_ptr(ifdef_dance_name));
   3689     fprintf(out_h, "#define %s\n\n", buf_ptr(ifdef_dance_name));
   3690 
   3691     if (g->c_stdint_used)
   3692         fprintf(out_h, "#include <stdint.h>\n");
   3693 
   3694     fprintf(out_h, "\n");
   3695 
   3696     fprintf(out_h, "#ifdef __cplusplus\n");
   3697     fprintf(out_h, "#define %s extern \"C\"\n", buf_ptr(extern_c_macro));
   3698     fprintf(out_h, "#else\n");
   3699     fprintf(out_h, "#define %s\n", buf_ptr(extern_c_macro));
   3700     fprintf(out_h, "#endif\n");
   3701     fprintf(out_h, "\n");
   3702     fprintf(out_h, "#if defined(_WIN32)\n");
   3703     fprintf(out_h, "#define %s %s __declspec(dllimport)\n", buf_ptr(export_macro), buf_ptr(extern_c_macro));
   3704     fprintf(out_h, "#else\n");
   3705     fprintf(out_h, "#define %s %s __attribute__((visibility (\"default\")))\n",
   3706             buf_ptr(export_macro), buf_ptr(extern_c_macro));
   3707     fprintf(out_h, "#endif\n");
   3708     fprintf(out_h, "\n");
   3709 
   3710     fprintf(out_h, "%s", buf_ptr(&h_buf));
   3711 
   3712     fprintf(out_h, "\n#endif\n");
   3713 
   3714     if (fclose(out_h))
   3715         zig_panic("unable to close h file: %s", strerror(errno));
   3716 }
   3717 
   3718 static const char *get_libc_file(CodeGen *g, const char *file) {
   3719     Buf *out_buf = buf_alloc();
   3720     os_path_join(g->libc_lib_dir, buf_create_from_str(file), out_buf);
   3721     return buf_ptr(out_buf);
   3722 }
   3723 
   3724 void codegen_link(CodeGen *g, const char *out_file) {
   3725     bool is_optimized = (g->build_type == CodeGenBuildTypeRelease);
   3726     if (is_optimized) {
   3727         if (g->verbose) {
   3728             fprintf(stderr, "\nOptimization:\n");
   3729             fprintf(stderr, "---------------\n");
   3730         }
   3731 
   3732         LLVMZigOptimizeModule(g->target_machine, g->module);
   3733 
   3734         if (g->verbose) {
   3735             LLVMDumpModule(g->module);
   3736         }
   3737     }
   3738     if (g->verbose) {
   3739         fprintf(stderr, "\nLink:\n");
   3740         fprintf(stderr, "-------\n");
   3741     }
   3742 
   3743     if (!out_file) {
   3744         out_file = buf_ptr(g->root_out_name);
   3745     }
   3746 
   3747     Buf out_file_o = BUF_INIT;
   3748     buf_init_from_str(&out_file_o, out_file);
   3749 
   3750     if (g->out_type != OutTypeObj) {
   3751         buf_append_str(&out_file_o, ".o");
   3752     }
   3753 
   3754     char *err_msg = nullptr;
   3755     if (LLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(&out_file_o),
   3756                 LLVMObjectFile, &err_msg))
   3757     {
   3758         zig_panic("unable to write object file: %s", err_msg);
   3759     }
   3760 
   3761     if (g->out_type == OutTypeObj) {
   3762         if (g->verbose) {
   3763             fprintf(stderr, "OK\n");
   3764         }
   3765         return;
   3766     }
   3767 
   3768     if (g->out_type == OutTypeLib && g->is_static) {
   3769         // invoke `ar`
   3770         // example:
   3771         // # static link into libfoo.a
   3772         // ar rcs libfoo.a foo1.o foo2.o
   3773         zig_panic("TODO invoke ar");
   3774         return;
   3775     }
   3776 
   3777     // invoke `ld`
   3778     ZigList<const char *> args = {0};
   3779     const char *crt1o;
   3780     if (g->is_static) {
   3781         args.append("-static");
   3782         crt1o = "crt1.o";
   3783     } else {
   3784         crt1o = "Scrt1.o";
   3785     }
   3786 
   3787     // TODO don't pass this parameter unless linking with libc
   3788     char *ZIG_NATIVE_DYNAMIC_LINKER = getenv("ZIG_NATIVE_DYNAMIC_LINKER");
   3789     if (g->is_native_target && ZIG_NATIVE_DYNAMIC_LINKER) {
   3790         if (ZIG_NATIVE_DYNAMIC_LINKER[0] != 0) {
   3791             args.append("-dynamic-linker");
   3792             args.append(ZIG_NATIVE_DYNAMIC_LINKER);
   3793         }
   3794     } else {
   3795         args.append("-dynamic-linker");
   3796         args.append(buf_ptr(get_dynamic_linker(g->target_machine)));
   3797     }
   3798 
   3799     if (g->out_type == OutTypeLib) {
   3800         Buf *out_lib_so = buf_sprintf("lib%s.so.%d.%d.%d",
   3801                 buf_ptr(g->root_out_name), g->version_major, g->version_minor, g->version_patch);
   3802         Buf *soname = buf_sprintf("lib%s.so.%d", buf_ptr(g->root_out_name), g->version_major);
   3803         args.append("-shared");
   3804         args.append("-soname");
   3805         args.append(buf_ptr(soname));
   3806         out_file = buf_ptr(out_lib_so);
   3807     }
   3808 
   3809     args.append("-o");
   3810     args.append(out_file);
   3811 
   3812     bool link_in_crt = (g->link_libc && g->out_type == OutTypeExe);
   3813 
   3814     if (link_in_crt) {
   3815         find_libc_path(g);
   3816 
   3817         args.append(get_libc_file(g, crt1o));
   3818         args.append(get_libc_file(g, "crti.o"));
   3819     }
   3820 
   3821     args.append((const char *)buf_ptr(&out_file_o));
   3822 
   3823     if (link_in_crt) {
   3824         args.append(get_libc_file(g, "crtn.o"));
   3825     }
   3826 
   3827     for (int i = 0; i < g->lib_dirs.length; i += 1) {
   3828         const char *lib_dir = g->lib_dirs.at(i);
   3829         args.append("-L");
   3830         args.append(lib_dir);
   3831     }
   3832 
   3833     auto it = g->link_table.entry_iterator();
   3834     for (;;) {
   3835         auto *entry = it.next();
   3836         if (!entry)
   3837             break;
   3838 
   3839         Buf *arg = buf_sprintf("-l%s", buf_ptr(entry->key));
   3840         args.append(buf_ptr(arg));
   3841     }
   3842 
   3843     if (g->verbose) {
   3844         fprintf(stderr, "ld");
   3845         for (int i = 0; i < args.length; i += 1) {
   3846             fprintf(stderr, " %s", args.at(i));
   3847         }
   3848         fprintf(stderr, "\n");
   3849     }
   3850 
   3851     int return_code;
   3852     Buf ld_stderr = BUF_INIT;
   3853     Buf ld_stdout = BUF_INIT;
   3854     os_exec_process("ld", args, &return_code, &ld_stderr, &ld_stdout);
   3855 
   3856     if (return_code != 0) {
   3857         fprintf(stderr, "ld failed with return code %d\n", return_code);
   3858         fprintf(stderr, "ld ");
   3859         for (int i = 0; i < args.length; i += 1) {
   3860             fprintf(stderr, "%s ", args.at(i));
   3861         }
   3862         fprintf(stderr, "\n%s\n", buf_ptr(&ld_stderr));
   3863         exit(1);
   3864     } else if (buf_len(&ld_stderr)) {
   3865         fprintf(stderr, "%s\n", buf_ptr(&ld_stderr));
   3866     }
   3867 
   3868     if (g->out_type == OutTypeLib) {
   3869         generate_h_file(g);
   3870     }
   3871 
   3872     if (g->verbose) {
   3873         fprintf(stderr, "OK\n");
   3874     }
   3875 }