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, ¶m_type_c); 3669 buf_appendf(&h_buf, "%s %s", 3670 buf_ptr(¶m_type_c), 3671 buf_ptr(¶m_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 }