| ... | ... | @@ -35,6 +35,18 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont |
| 35 | 35 | LValPurpose lval); |
| 36 | 36 | static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction); |
| 37 | 37 | |
| 38 | ConstExprValue *const_ptr_pointee(ConstExprValue *const_val) { |
| 39 | ConstExprValue *base_ptr = const_val->data.x_ptr.base_ptr; |
| 40 | size_t index = const_val->data.x_ptr.index; |
| 41 | |
| 42 | if (index == SIZE_MAX) { |
| 43 | return base_ptr; |
| 44 | } else { |
| 45 | assert(index < base_ptr->data.x_array.size); |
| 46 | return &base_ptr->data.x_array.elements[index]; |
| 47 | } |
| 48 | } |
| 49 | |
| 38 | 50 | static void ir_instruction_append(IrBasicBlock *basic_block, IrInstruction *instruction) { |
| 39 | 51 | assert(basic_block); |
| 40 | 52 | assert(instruction); |
| ... | ... | @@ -237,7 +249,7 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, AstNode *source_node, IrI |
| 237 | 249 | { |
| 238 | 250 | IrInstructionCondBr *cond_br_instruction = ir_build_instruction<IrInstructionCondBr>(irb, source_node); |
| 239 | 251 | cond_br_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable; |
| 240 | | cond_br_instruction->base.static_value.ok = true; |
| 252 | cond_br_instruction->base.static_value.special = ConstValSpecialStatic; |
| 241 | 253 | cond_br_instruction->condition = condition; |
| 242 | 254 | cond_br_instruction->then_block = then_block; |
| 243 | 255 | cond_br_instruction->else_block = else_block; |
| ... | ... | @@ -262,7 +274,7 @@ static IrInstruction *ir_build_cond_br_from(IrBuilder *irb, IrInstruction *old_i |
| 262 | 274 | static IrInstruction *ir_build_return(IrBuilder *irb, AstNode *source_node, IrInstruction *return_value) { |
| 263 | 275 | IrInstructionReturn *return_instruction = ir_build_instruction<IrInstructionReturn>(irb, source_node); |
| 264 | 276 | return_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable; |
| 265 | | return_instruction->base.static_value.ok = true; |
| 277 | return_instruction->base.static_value.special = ConstValSpecialStatic; |
| 266 | 278 | return_instruction->value = return_value; |
| 267 | 279 | |
| 268 | 280 | ir_ref_instruction(return_value); |
| ... | ... | @@ -281,20 +293,19 @@ static IrInstruction *ir_build_return_from(IrBuilder *irb, IrInstruction *old_in |
| 281 | 293 | static IrInstruction *ir_create_const(IrBuilder *irb, AstNode *source_node, TypeTableEntry *type_entry) { |
| 282 | 294 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(irb->exec, source_node); |
| 283 | 295 | const_instruction->base.type_entry = type_entry; |
| 284 | | const_instruction->base.static_value.ok = true; |
| 296 | const_instruction->base.static_value.special = ConstValSpecialStatic; |
| 285 | 297 | return &const_instruction->base; |
| 286 | 298 | } |
| 287 | 299 | |
| 288 | 300 | static IrInstruction *ir_build_const_void(IrBuilder *irb, AstNode *source_node) { |
| 289 | 301 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node); |
| 290 | 302 | const_instruction->base.type_entry = irb->codegen->builtin_types.entry_void; |
| 291 | | const_instruction->base.static_value.ok = true; |
| 303 | const_instruction->base.static_value.special = ConstValSpecialStatic; |
| 292 | 304 | return &const_instruction->base; |
| 293 | 305 | } |
| 294 | 306 | |
| 295 | 307 | static IrInstruction *ir_build_const_undefined(IrBuilder *irb, AstNode *source_node) { |
| 296 | 308 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node); |
| 297 | | const_instruction->base.static_value.ok = true; |
| 298 | 309 | const_instruction->base.static_value.special = ConstValSpecialUndef; |
| 299 | 310 | const_instruction->base.type_entry = irb->codegen->builtin_types.entry_undef; |
| 300 | 311 | return &const_instruction->base; |
| ... | ... | @@ -304,7 +315,7 @@ static IrInstruction *ir_build_const_bignum(IrBuilder *irb, AstNode *source_node |
| 304 | 315 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node); |
| 305 | 316 | const_instruction->base.type_entry = (bignum->kind == BigNumKindInt) ? |
| 306 | 317 | irb->codegen->builtin_types.entry_num_lit_int : irb->codegen->builtin_types.entry_num_lit_float; |
| 307 | | const_instruction->base.static_value.ok = true; |
| 318 | const_instruction->base.static_value.special = ConstValSpecialStatic; |
| 308 | 319 | const_instruction->base.static_value.data.x_bignum = *bignum; |
| 309 | 320 | return &const_instruction->base; |
| 310 | 321 | } |
| ... | ... | @@ -312,7 +323,7 @@ static IrInstruction *ir_build_const_bignum(IrBuilder *irb, AstNode *source_node |
| 312 | 323 | static IrInstruction *ir_build_const_usize(IrBuilder *irb, AstNode *source_node, uint64_t value) { |
| 313 | 324 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node); |
| 314 | 325 | const_instruction->base.type_entry = irb->codegen->builtin_types.entry_usize; |
| 315 | | const_instruction->base.static_value.ok = true; |
| 326 | const_instruction->base.static_value.special = ConstValSpecialStatic; |
| 316 | 327 | bignum_init_unsigned(&const_instruction->base.static_value.data.x_bignum, value); |
| 317 | 328 | return &const_instruction->base; |
| 318 | 329 | } |
| ... | ... | @@ -320,7 +331,7 @@ static IrInstruction *ir_build_const_usize(IrBuilder *irb, AstNode *source_node, |
| 320 | 331 | static IrInstruction *ir_create_const_type(IrBuilder *irb, AstNode *source_node, TypeTableEntry *type_entry) { |
| 321 | 332 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(irb->exec, source_node); |
| 322 | 333 | const_instruction->base.type_entry = irb->codegen->builtin_types.entry_type; |
| 323 | | const_instruction->base.static_value.ok = true; |
| 334 | const_instruction->base.static_value.special = ConstValSpecialStatic; |
| 324 | 335 | const_instruction->base.static_value.data.x_type = type_entry; |
| 325 | 336 | return &const_instruction->base; |
| 326 | 337 | } |
| ... | ... | @@ -334,7 +345,7 @@ static IrInstruction *ir_build_const_type(IrBuilder *irb, AstNode *source_node, |
| 334 | 345 | static IrInstruction *ir_build_const_fn(IrBuilder *irb, AstNode *source_node, FnTableEntry *fn_entry) { |
| 335 | 346 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node); |
| 336 | 347 | const_instruction->base.type_entry = fn_entry->type_entry; |
| 337 | | const_instruction->base.static_value.ok = true; |
| 348 | const_instruction->base.static_value.special = ConstValSpecialStatic; |
| 338 | 349 | const_instruction->base.static_value.data.x_fn = fn_entry; |
| 339 | 350 | return &const_instruction->base; |
| 340 | 351 | } |
| ... | ... | @@ -342,7 +353,7 @@ static IrInstruction *ir_build_const_fn(IrBuilder *irb, AstNode *source_node, Fn |
| 342 | 353 | static IrInstruction *ir_build_const_generic_fn(IrBuilder *irb, AstNode *source_node, TypeTableEntry *fn_type) { |
| 343 | 354 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node); |
| 344 | 355 | const_instruction->base.type_entry = fn_type; |
| 345 | | const_instruction->base.static_value.ok = true; |
| 356 | const_instruction->base.static_value.special = ConstValSpecialStatic; |
| 346 | 357 | const_instruction->base.static_value.data.x_type = fn_type; |
| 347 | 358 | return &const_instruction->base; |
| 348 | 359 | } |
| ... | ... | @@ -350,7 +361,7 @@ static IrInstruction *ir_build_const_generic_fn(IrBuilder *irb, AstNode *source_ |
| 350 | 361 | static IrInstruction *ir_build_const_import(IrBuilder *irb, AstNode *source_node, ImportTableEntry *import) { |
| 351 | 362 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node); |
| 352 | 363 | const_instruction->base.type_entry = irb->codegen->builtin_types.entry_namespace; |
| 353 | | const_instruction->base.static_value.ok = true; |
| 364 | const_instruction->base.static_value.special = ConstValSpecialStatic; |
| 354 | 365 | const_instruction->base.static_value.data.x_import = import; |
| 355 | 366 | return &const_instruction->base; |
| 356 | 367 | } |
| ... | ... | @@ -358,7 +369,7 @@ static IrInstruction *ir_build_const_import(IrBuilder *irb, AstNode *source_node |
| 358 | 369 | static IrInstruction *ir_build_const_scope(IrBuilder *irb, AstNode *source_node, BlockContext *scope) { |
| 359 | 370 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node); |
| 360 | 371 | const_instruction->base.type_entry = irb->codegen->builtin_types.entry_block; |
| 361 | | const_instruction->base.static_value.ok = true; |
| 372 | const_instruction->base.static_value.special = ConstValSpecialStatic; |
| 362 | 373 | const_instruction->base.static_value.data.x_block = scope; |
| 363 | 374 | return &const_instruction->base; |
| 364 | 375 | } |
| ... | ... | @@ -366,7 +377,7 @@ static IrInstruction *ir_build_const_scope(IrBuilder *irb, AstNode *source_node, |
| 366 | 377 | static IrInstruction *ir_build_const_bool(IrBuilder *irb, AstNode *source_node, bool value) { |
| 367 | 378 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node); |
| 368 | 379 | const_instruction->base.type_entry = irb->codegen->builtin_types.entry_bool; |
| 369 | | const_instruction->base.static_value.ok = true; |
| 380 | const_instruction->base.static_value.special = ConstValSpecialStatic; |
| 370 | 381 | const_instruction->base.static_value.data.x_bool = value; |
| 371 | 382 | return &const_instruction->base; |
| 372 | 383 | } |
| ... | ... | @@ -377,45 +388,45 @@ static IrInstruction *ir_build_const_str_lit(IrBuilder *irb, AstNode *source_nod |
| 377 | 388 | TypeTableEntry *type_entry = get_array_type(irb->codegen, u8_type, buf_len(str)); |
| 378 | 389 | const_instruction->base.type_entry = type_entry; |
| 379 | 390 | ConstExprValue *const_val = &const_instruction->base.static_value; |
| 380 | | const_val->ok = true; |
| 381 | | const_val->data.x_array.fields = allocate<ConstExprValue*>(buf_len(str)); |
| 391 | const_val->special = ConstValSpecialStatic; |
| 392 | const_val->data.x_array.elements = allocate<ConstExprValue>(buf_len(str)); |
| 393 | const_val->data.x_array.size = buf_len(str); |
| 382 | 394 | |
| 383 | | ConstExprValue *all_chars = allocate<ConstExprValue>(buf_len(str)); |
| 384 | 395 | for (size_t i = 0; i < buf_len(str); i += 1) { |
| 385 | | ConstExprValue *this_char = &all_chars[i]; |
| 386 | | this_char->ok = true; |
| 396 | ConstExprValue *this_char = &const_val->data.x_array.elements[i]; |
| 397 | this_char->special = ConstValSpecialStatic; |
| 387 | 398 | bignum_init_unsigned(&this_char->data.x_bignum, buf_ptr(str)[i]); |
| 388 | | const_val->data.x_array.fields[i] = this_char; |
| 389 | 399 | } |
| 390 | 400 | |
| 391 | 401 | return &const_instruction->base; |
| 392 | 402 | } |
| 393 | 403 | |
| 394 | 404 | static IrInstruction *ir_build_const_c_str_lit(IrBuilder *irb, AstNode *source_node, Buf *str) { |
| 395 | | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node); |
| 396 | | TypeTableEntry *u8_type = irb->codegen->builtin_types.entry_u8; |
| 397 | | TypeTableEntry *type_entry = get_pointer_to_type(irb->codegen, u8_type, true); |
| 398 | | const_instruction->base.type_entry = type_entry; |
| 399 | | ConstExprValue *const_val = &const_instruction->base.static_value; |
| 400 | | const_val->ok = true; |
| 401 | | |
| 405 | // first we build the underlying array |
| 402 | 406 | size_t len_with_null = buf_len(str) + 1; |
| 403 | | const_val->data.x_ptr.ptr = allocate<ConstExprValue*>(len_with_null); |
| 404 | | const_val->data.x_ptr.len = len_with_null; |
| 405 | | const_val->data.x_ptr.is_c_str = true; |
| 406 | | |
| 407 | | ConstExprValue *all_chars = allocate<ConstExprValue>(len_with_null); |
| 407 | ConstExprValue *array_val = allocate<ConstExprValue>(1); |
| 408 | array_val->special = ConstValSpecialStatic; |
| 409 | array_val->data.x_array.elements = allocate<ConstExprValue>(len_with_null); |
| 410 | array_val->data.x_array.size = len_with_null; |
| 408 | 411 | for (size_t i = 0; i < buf_len(str); i += 1) { |
| 409 | | ConstExprValue *this_char = &all_chars[i]; |
| 410 | | this_char->ok = true; |
| 412 | ConstExprValue *this_char = &array_val->data.x_array.elements[i]; |
| 413 | this_char->special = ConstValSpecialStatic; |
| 411 | 414 | bignum_init_unsigned(&this_char->data.x_bignum, buf_ptr(str)[i]); |
| 412 | | const_val->data.x_ptr.ptr[i] = this_char; |
| 413 | 415 | } |
| 414 | | |
| 415 | | ConstExprValue *null_char = &all_chars[len_with_null - 1]; |
| 416 | | null_char->ok = true; |
| 416 | ConstExprValue *null_char = &array_val->data.x_array.elements[len_with_null - 1]; |
| 417 | null_char->special = ConstValSpecialStatic; |
| 417 | 418 | bignum_init_unsigned(&null_char->data.x_bignum, 0); |
| 418 | | const_val->data.x_ptr.ptr[len_with_null - 1] = null_char; |
| 419 | |
| 420 | // then make the pointer point to it |
| 421 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node); |
| 422 | TypeTableEntry *u8_type = irb->codegen->builtin_types.entry_u8; |
| 423 | TypeTableEntry *type_entry = get_pointer_to_type(irb->codegen, u8_type, true); |
| 424 | const_instruction->base.type_entry = type_entry; |
| 425 | ConstExprValue *ptr_val = &const_instruction->base.static_value; |
| 426 | ptr_val->special = ConstValSpecialStatic; |
| 427 | ptr_val->data.x_ptr.base_ptr = array_val; |
| 428 | ptr_val->data.x_ptr.index = 0; |
| 429 | ptr_val->data.x_ptr.is_c_str = true; |
| 419 | 430 | |
| 420 | 431 | return &const_instruction->base; |
| 421 | 432 | } |
| ... | ... | @@ -591,7 +602,7 @@ static IrInstruction *ir_build_phi_from(IrBuilder *irb, IrInstruction *old_instr |
| 591 | 602 | static IrInstruction *ir_build_br(IrBuilder *irb, AstNode *source_node, IrBasicBlock *dest_block, bool is_inline) { |
| 592 | 603 | IrInstructionBr *br_instruction = ir_build_instruction<IrInstructionBr>(irb, source_node); |
| 593 | 604 | br_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable; |
| 594 | | br_instruction->base.static_value.ok = true; |
| 605 | br_instruction->base.static_value.special = ConstValSpecialStatic; |
| 595 | 606 | br_instruction->dest_block = dest_block; |
| 596 | 607 | br_instruction->is_inline = is_inline; |
| 597 | 608 | |
| ... | ... | @@ -662,7 +673,7 @@ static IrInstruction *ir_build_container_init_fields(IrBuilder *irb, AstNode *so |
| 662 | 673 | static IrInstruction *ir_build_unreachable(IrBuilder *irb, AstNode *source_node) { |
| 663 | 674 | IrInstructionUnreachable *unreachable_instruction = |
| 664 | 675 | ir_build_instruction<IrInstructionUnreachable>(irb, source_node); |
| 665 | | unreachable_instruction->base.static_value.ok = true; |
| 676 | unreachable_instruction->base.static_value.special = ConstValSpecialStatic; |
| 666 | 677 | unreachable_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable; |
| 667 | 678 | return &unreachable_instruction->base; |
| 668 | 679 | } |
| ... | ... | @@ -677,7 +688,7 @@ static IrInstruction *ir_build_store_ptr(IrBuilder *irb, AstNode *source_node, |
| 677 | 688 | IrInstruction *ptr, IrInstruction *value) |
| 678 | 689 | { |
| 679 | 690 | IrInstructionStorePtr *instruction = ir_build_instruction<IrInstructionStorePtr>(irb, source_node); |
| 680 | | instruction->base.static_value.ok = true; |
| 691 | instruction->base.static_value.special = ConstValSpecialStatic; |
| 681 | 692 | instruction->base.type_entry = irb->codegen->builtin_types.entry_void; |
| 682 | 693 | instruction->ptr = ptr; |
| 683 | 694 | instruction->value = value; |
| ... | ... | @@ -700,7 +711,7 @@ static IrInstruction *ir_build_var_decl(IrBuilder *irb, AstNode *source_node, |
| 700 | 711 | VariableTableEntry *var, IrInstruction *var_type, IrInstruction *init_value) |
| 701 | 712 | { |
| 702 | 713 | IrInstructionDeclVar *decl_var_instruction = ir_build_instruction<IrInstructionDeclVar>(irb, source_node); |
| 703 | | decl_var_instruction->base.static_value.ok = true; |
| 714 | decl_var_instruction->base.static_value.special = ConstValSpecialStatic; |
| 704 | 715 | decl_var_instruction->base.type_entry = irb->codegen->builtin_types.entry_void; |
| 705 | 716 | decl_var_instruction->var = var; |
| 706 | 717 | decl_var_instruction->var_type = var_type; |
| ... | ... | @@ -1900,7 +1911,7 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc |
| 1900 | 1911 | } |
| 1901 | 1912 | |
| 1902 | 1913 | ConstExprValue *const_val = &instruction->static_value; |
| 1903 | | assert(const_val->ok); |
| 1914 | assert(const_val->special != ConstValSpecialRuntime); |
| 1904 | 1915 | if (other_type_underlying->id == TypeTableEntryIdFloat) { |
| 1905 | 1916 | return true; |
| 1906 | 1917 | } else if (other_type_underlying->id == TypeTableEntryIdInt && |
| ... | ... | @@ -2110,10 +2121,10 @@ static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 2110 | 2121 | IrInstruction *dest_type, CastOp cast_op, bool need_alloca) |
| 2111 | 2122 | { |
| 2112 | 2123 | assert(dest_type->type_entry->id == TypeTableEntryIdMetaType); |
| 2113 | | assert(dest_type->static_value.ok); |
| 2124 | assert(dest_type->static_value.special != ConstValSpecialRuntime); |
| 2114 | 2125 | TypeTableEntry *wanted_type = dest_type->static_value.data.x_type; |
| 2115 | 2126 | |
| 2116 | | if (value->static_value.ok) { |
| 2127 | if (value->static_value.special != ConstValSpecialRuntime) { |
| 2117 | 2128 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->source_node, wanted_type); |
| 2118 | 2129 | eval_const_expr_implicit_cast(cast_op, &value->static_value, value->type_entry, |
| 2119 | 2130 | &result->static_value, wanted_type); |
| ... | ... | @@ -2194,7 +2205,7 @@ static ConstExprValue *ir_build_const_from(IrAnalyze *ira, IrInstruction *old_in |
| 2194 | 2205 | } |
| 2195 | 2206 | ir_link_new_instruction(new_instruction, old_instruction); |
| 2196 | 2207 | ConstExprValue *const_val = &new_instruction->static_value; |
| 2197 | | const_val->ok = true; |
| 2208 | const_val->special = ConstValSpecialStatic; |
| 2198 | 2209 | const_val->depends_on_compile_var = depends_on_compile_var; |
| 2199 | 2210 | return const_val; |
| 2200 | 2211 | } |
| ... | ... | @@ -2226,7 +2237,7 @@ static TypeTableEntry *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value |
| 2226 | 2237 | } |
| 2227 | 2238 | |
| 2228 | 2239 | ConstExprValue *const_val = &type_value->static_value; |
| 2229 | | if (!const_val->ok) { |
| 2240 | if (const_val->special == ConstValSpecialRuntime) { |
| 2230 | 2241 | add_node_error(ira->codegen, type_value->source_node, |
| 2231 | 2242 | buf_sprintf("unable to evaluate constant expression")); |
| 2232 | 2243 | return ira->codegen->builtin_types.entry_invalid; |
| ... | ... | @@ -2249,7 +2260,7 @@ static bool ir_resolve_bool(IrAnalyze *ira, IrInstruction *bool_value, bool *out |
| 2249 | 2260 | } |
| 2250 | 2261 | |
| 2251 | 2262 | ConstExprValue *const_val = &bool_value->static_value; |
| 2252 | | if (!const_val->ok) { |
| 2263 | if (const_val->special == ConstValSpecialRuntime) { |
| 2253 | 2264 | add_node_error(ira->codegen, bool_value->source_node, |
| 2254 | 2265 | buf_sprintf("unable to evaluate constant expression")); |
| 2255 | 2266 | return false; |
| ... | ... | @@ -2273,7 +2284,7 @@ static FnTableEntry *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) { |
| 2273 | 2284 | } |
| 2274 | 2285 | |
| 2275 | 2286 | ConstExprValue *const_val = &fn_value->static_value; |
| 2276 | | if (!const_val->ok) { |
| 2287 | if (const_val->special == ConstValSpecialRuntime) { |
| 2277 | 2288 | add_node_error(ira->codegen, fn_value->source_node, |
| 2278 | 2289 | buf_sprintf("unable to evaluate constant expression")); |
| 2279 | 2290 | return nullptr; |
| ... | ... | @@ -2286,7 +2297,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 2286 | 2297 | IrInstruction *dest_type, IrInstruction *value) |
| 2287 | 2298 | { |
| 2288 | 2299 | assert(dest_type->type_entry->id == TypeTableEntryIdMetaType); |
| 2289 | | assert(dest_type->static_value.ok); |
| 2300 | assert(dest_type->static_value.special != ConstValSpecialRuntime); |
| 2290 | 2301 | |
| 2291 | 2302 | TypeTableEntry *wanted_type = dest_type->static_value.data.x_type; |
| 2292 | 2303 | TypeTableEntry *actual_type = value->type_entry; |
| ... | ... | @@ -2618,7 +2629,7 @@ static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp |
| 2618 | 2629 | |
| 2619 | 2630 | ConstExprValue *op1_val = &casted_op1->static_value; |
| 2620 | 2631 | ConstExprValue *op2_val = &casted_op2->static_value; |
| 2621 | | if (op1_val->ok && op2_val->ok) { |
| 2632 | if (op1_val->special != ConstValSpecialRuntime && op2_val->special != ConstValSpecialRuntime) { |
| 2622 | 2633 | bool depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var; |
| 2623 | 2634 | ConstExprValue *out_val = ir_build_const_from(ira, &bin_op_instruction->base, depends_on_compile_var); |
| 2624 | 2635 | |
| ... | ... | @@ -2710,7 +2721,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp |
| 2710 | 2721 | |
| 2711 | 2722 | ConstExprValue *op1_val = &casted_op1->static_value; |
| 2712 | 2723 | ConstExprValue *op2_val = &casted_op2->static_value; |
| 2713 | | if (op1_val->ok && op2_val->ok) { |
| 2724 | if (op1_val->special != ConstValSpecialRuntime && op2_val->special != ConstValSpecialRuntime) { |
| 2714 | 2725 | bool type_can_gt_lt_cmp = (resolved_type->id == TypeTableEntryIdNumLitFloat || |
| 2715 | 2726 | resolved_type->id == TypeTableEntryIdNumLitInt || |
| 2716 | 2727 | resolved_type->id == TypeTableEntryIdFloat || |
| ... | ... | @@ -2799,7 +2810,7 @@ static int ir_eval_bignum(ConstExprValue *op1_val, ConstExprValue *op2_val, |
| 2799 | 2810 | } |
| 2800 | 2811 | } |
| 2801 | 2812 | |
| 2802 | | out_val->ok = true; |
| 2813 | out_val->special = ConstValSpecialStatic; |
| 2803 | 2814 | out_val->depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var; |
| 2804 | 2815 | return 0; |
| 2805 | 2816 | } |
| ... | ... | @@ -2892,7 +2903,7 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp |
| 2892 | 2903 | return ira->codegen->builtin_types.entry_invalid; |
| 2893 | 2904 | |
| 2894 | 2905 | |
| 2895 | | if (casted_op1->static_value.ok && casted_op2->static_value.ok) { |
| 2906 | if (casted_op1->static_value.special != ConstValSpecialRuntime && casted_op2->static_value.special != ConstValSpecialRuntime) { |
| 2896 | 2907 | ConstExprValue *op1_val = &casted_op1->static_value; |
| 2897 | 2908 | ConstExprValue *op2_val = &casted_op2->static_value; |
| 2898 | 2909 | ConstExprValue *out_val = &bin_op_instruction->base.static_value; |
| ... | ... | @@ -2992,7 +3003,7 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc |
| 2992 | 3003 | break; |
| 2993 | 3004 | case TypeTableEntryIdNumLitFloat: |
| 2994 | 3005 | case TypeTableEntryIdNumLitInt: |
| 2995 | | if (is_export || is_extern || !casted_init_value->static_value.ok) { |
| 3006 | if (is_export || is_extern || casted_init_value->static_value.special == ConstValSpecialRuntime) { |
| 2996 | 3007 | add_node_error(ira->codegen, var_type->source_node, buf_sprintf("unable to infer variable type")); |
| 2997 | 3008 | result_type = ira->codegen->builtin_types.entry_invalid; |
| 2998 | 3009 | } |
| ... | ... | @@ -3006,7 +3017,7 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc |
| 3006 | 3017 | break; |
| 3007 | 3018 | case TypeTableEntryIdMetaType: |
| 3008 | 3019 | case TypeTableEntryIdNamespace: |
| 3009 | | if (!casted_init_value->static_value.ok) { |
| 3020 | if (casted_init_value->static_value.special == ConstValSpecialRuntime) { |
| 3010 | 3021 | add_node_error(ira->codegen, var_type->source_node, |
| 3011 | 3022 | buf_sprintf("variable of type '%s' must be constant", buf_ptr(&result_type->name))); |
| 3012 | 3023 | result_type = ira->codegen->builtin_types.entry_invalid; |
| ... | ... | @@ -3052,7 +3063,7 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction |
| 3052 | 3063 | if (fn_ref->type_entry->id == TypeTableEntryIdInvalid) |
| 3053 | 3064 | return ira->codegen->builtin_types.entry_invalid; |
| 3054 | 3065 | |
| 3055 | | if (fn_ref->static_value.ok) { |
| 3066 | if (fn_ref->static_value.special != ConstValSpecialRuntime) { |
| 3056 | 3067 | if (fn_ref->type_entry->id == TypeTableEntryIdMetaType) { |
| 3057 | 3068 | size_t actual_param_count = call_instruction->arg_count; |
| 3058 | 3069 | |
| ... | ... | @@ -3106,9 +3117,9 @@ static TypeTableEntry *ir_analyze_unary_bool_not(IrAnalyze *ira, IrInstructionUn |
| 3106 | 3117 | return ira->codegen->builtin_types.entry_invalid; |
| 3107 | 3118 | |
| 3108 | 3119 | ConstExprValue *operand_val = &casted_value->static_value; |
| 3109 | | if (operand_val->ok) { |
| 3120 | if (operand_val->special != ConstValSpecialRuntime) { |
| 3110 | 3121 | ConstExprValue *result_val = &un_op_instruction->base.static_value; |
| 3111 | | result_val->ok = true; |
| 3122 | result_val->special = ConstValSpecialStatic; |
| 3112 | 3123 | result_val->depends_on_compile_var = operand_val->depends_on_compile_var; |
| 3113 | 3124 | result_val->data.x_bool = !operand_val->data.x_bool; |
| 3114 | 3125 | return bool_type; |
| ... | ... | @@ -3204,7 +3215,7 @@ static TypeTableEntry *ir_analyze_unary_address_of(IrAnalyze *ira, IrInstruction |
| 3204 | 3215 | { |
| 3205 | 3216 | ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base, |
| 3206 | 3217 | value->static_value.depends_on_compile_var); |
| 3207 | | assert(value->static_value.ok); |
| 3218 | assert(value->static_value.special != ConstValSpecialRuntime); |
| 3208 | 3219 | TypeTableEntry *child_type = value->static_value.data.x_type; |
| 3209 | 3220 | out_val->data.x_type = get_pointer_to_type(ira->codegen, child_type, is_const); |
| 3210 | 3221 | return ira->codegen->builtin_types.entry_type; |
| ... | ... | @@ -3252,9 +3263,10 @@ static TypeTableEntry *ir_analyze_dereference(IrAnalyze *ira, IrInstructionUnOp |
| 3252 | 3263 | // this dereference is always an rvalue because in the IR gen we identify lvalue and emit |
| 3253 | 3264 | // one of the ptr instructions |
| 3254 | 3265 | |
| 3255 | | if (value->static_value.ok) { |
| 3266 | if (value->static_value.special != ConstValSpecialRuntime) { |
| 3256 | 3267 | ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base, false); |
| 3257 | | *out_val = *value->static_value.data.x_ptr.ptr[0]; |
| 3268 | ConstExprValue *pointee = const_ptr_pointee(&value->static_value); |
| 3269 | *out_val = *pointee; |
| 3258 | 3270 | return child_type; |
| 3259 | 3271 | } |
| 3260 | 3272 | |
| ... | ... | @@ -3428,7 +3440,7 @@ static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstruct |
| 3428 | 3440 | return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable); |
| 3429 | 3441 | |
| 3430 | 3442 | // TODO detect backward jumps |
| 3431 | | if (condition->static_value.ok) { |
| 3443 | if (condition->static_value.special != ConstValSpecialRuntime) { |
| 3432 | 3444 | IrBasicBlock *old_dest_block = condition->static_value.data.x_bool ? |
| 3433 | 3445 | cond_br_instruction->then_block : cond_br_instruction->else_block; |
| 3434 | 3446 | |
| ... | ... | @@ -3463,7 +3475,7 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP |
| 3463 | 3475 | continue; |
| 3464 | 3476 | IrInstruction *value = phi_instruction->incoming_values[i]->other; |
| 3465 | 3477 | assert(value->type_entry); |
| 3466 | | if (value->static_value.ok) { |
| 3478 | if (value->static_value.special != ConstValSpecialRuntime) { |
| 3467 | 3479 | ConstExprValue *out_val = ir_build_const_from(ira, &phi_instruction->base, |
| 3468 | 3480 | value->static_value.depends_on_compile_var); |
| 3469 | 3481 | *out_val = value->static_value; |
| ... | ... | @@ -3523,17 +3535,16 @@ static TypeTableEntry *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstruct |
| 3523 | 3535 | } else if (var->src_is_const) { |
| 3524 | 3536 | AstNode *var_decl_node = var->decl_node; |
| 3525 | 3537 | assert(var_decl_node->type == NodeTypeVariableDeclaration); |
| 3526 | | mem_slot = &get_resolved_expr(var_decl_node->data.variable_declaration.expr)->const_val; |
| 3527 | | assert(mem_slot->ok); |
| 3538 | mem_slot = &get_resolved_expr(var_decl_node->data.variable_declaration.expr)->instruction->static_value; |
| 3539 | assert(mem_slot->special != ConstValSpecialRuntime); |
| 3528 | 3540 | } |
| 3529 | 3541 | |
| 3530 | | if (mem_slot && mem_slot->ok) { |
| 3542 | if (mem_slot && mem_slot->special != ConstValSpecialRuntime) { |
| 3531 | 3543 | ConstExprValue *out_val = ir_build_const_from(ira, &var_ptr_instruction->base, |
| 3532 | 3544 | mem_slot->depends_on_compile_var); |
| 3533 | 3545 | |
| 3534 | | out_val->data.x_ptr.len = 1; |
| 3535 | | out_val->data.x_ptr.ptr = allocate<ConstExprValue *>(1); |
| 3536 | | out_val->data.x_ptr.ptr[0] = mem_slot; |
| 3546 | out_val->data.x_ptr.base_ptr = mem_slot; |
| 3547 | out_val->data.x_ptr.index = SIZE_MAX; |
| 3537 | 3548 | return ptr_type; |
| 3538 | 3549 | } else { |
| 3539 | 3550 | ir_build_var_ptr_from(&ira->new_irb, &var_ptr_instruction->base, var); |
| ... | ... | @@ -3577,7 +3588,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc |
| 3577 | 3588 | if (casted_elem_index == ira->codegen->invalid_instruction) |
| 3578 | 3589 | return ira->codegen->builtin_types.entry_invalid; |
| 3579 | 3590 | |
| 3580 | | if (casted_elem_index->static_value.ok) { |
| 3591 | if (casted_elem_index->static_value.special != ConstValSpecialRuntime) { |
| 3581 | 3592 | uint64_t index = casted_elem_index->static_value.data.x_bignum.data.x_uint; |
| 3582 | 3593 | if (array_type->id == TypeTableEntryIdArray) { |
| 3583 | 3594 | uint64_t array_len = array_type->data.array.len; |
| ... | ... | @@ -3589,24 +3600,34 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc |
| 3589 | 3600 | } |
| 3590 | 3601 | } |
| 3591 | 3602 | |
| 3592 | | if (array_ptr->static_value.ok) { |
| 3603 | if (array_ptr->static_value.special != ConstValSpecialRuntime) { |
| 3593 | 3604 | bool depends_on_compile_var = array_ptr->static_value.depends_on_compile_var || |
| 3594 | 3605 | casted_elem_index->static_value.depends_on_compile_var; |
| 3595 | 3606 | ConstExprValue *out_val = ir_build_const_from(ira, &elem_ptr_instruction->base, depends_on_compile_var); |
| 3596 | | out_val->data.x_ptr.len = 1; |
| 3597 | | out_val->data.x_ptr.ptr = allocate<ConstExprValue *>(1); |
| 3598 | 3607 | if (array_type->id == TypeTableEntryIdPointer) { |
| 3599 | | uint64_t pointer_len = array_ptr->static_value.data.x_ptr.len; |
| 3600 | | if (index >= pointer_len) { |
| 3608 | size_t offset = array_ptr->static_value.data.x_ptr.index; |
| 3609 | size_t new_index; |
| 3610 | size_t mem_size; |
| 3611 | size_t old_size; |
| 3612 | if (offset == SIZE_MAX) { |
| 3613 | new_index = SIZE_MAX; |
| 3614 | mem_size = 1; |
| 3615 | old_size = 1; |
| 3616 | } else { |
| 3617 | new_index = offset + index; |
| 3618 | mem_size = array_ptr->static_value.data.x_ptr.base_ptr->data.x_array.size; |
| 3619 | old_size = mem_size - offset; |
| 3620 | } |
| 3621 | if (new_index >= mem_size) { |
| 3601 | 3622 | add_node_error(ira->codegen, elem_ptr_instruction->base.source_node, |
| 3602 | | buf_sprintf("index %" PRIu64 " outside pointer of size %" PRIu64, |
| 3603 | | index, pointer_len)); |
| 3623 | buf_sprintf("index %" PRIu64 " outside pointer of size %" PRIu64, index, old_size)); |
| 3604 | 3624 | return ira->codegen->builtin_types.entry_invalid; |
| 3605 | 3625 | } |
| 3606 | | out_val->data.x_ptr.ptr[0] = array_ptr->static_value.data.x_ptr.ptr[index]; |
| 3626 | out_val->data.x_ptr.base_ptr = array_ptr->static_value.data.x_ptr.base_ptr; |
| 3627 | out_val->data.x_ptr.index = new_index; |
| 3607 | 3628 | } else if (is_slice(array_type)) { |
| 3608 | | ConstExprValue *ptr_field = array_ptr->static_value.data.x_struct.fields[0]; |
| 3609 | | ConstExprValue *len_field = array_ptr->static_value.data.x_struct.fields[1]; |
| 3629 | ConstExprValue *ptr_field = &array_ptr->static_value.data.x_struct.fields[slice_ptr_index]; |
| 3630 | ConstExprValue *len_field = &array_ptr->static_value.data.x_struct.fields[slice_len_index]; |
| 3610 | 3631 | uint64_t slice_len = len_field->data.x_bignum.data.x_uint; |
| 3611 | 3632 | if (index >= slice_len) { |
| 3612 | 3633 | add_node_error(ira->codegen, elem_ptr_instruction->base.source_node, |
| ... | ... | @@ -3614,10 +3635,18 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc |
| 3614 | 3635 | index, slice_len)); |
| 3615 | 3636 | return ira->codegen->builtin_types.entry_invalid; |
| 3616 | 3637 | } |
| 3617 | | assert(index < ptr_field->data.x_ptr.len); |
| 3618 | | out_val->data.x_ptr.ptr[0] = ptr_field->data.x_ptr.ptr[index]; |
| 3638 | out_val->data.x_ptr.base_ptr = ptr_field->data.x_ptr.base_ptr; |
| 3639 | size_t offset = ptr_field->data.x_ptr.index; |
| 3640 | if (offset == SIZE_MAX) { |
| 3641 | out_val->data.x_ptr.index = SIZE_MAX; |
| 3642 | } else { |
| 3643 | uint64_t new_index = offset + index; |
| 3644 | assert(new_index < ptr_field->data.x_ptr.base_ptr->data.x_array.size); |
| 3645 | out_val->data.x_ptr.index = new_index; |
| 3646 | } |
| 3619 | 3647 | } else if (array_type->id == TypeTableEntryIdArray) { |
| 3620 | | out_val->data.x_ptr.ptr[0] = array_ptr->static_value.data.x_array.fields[index]; |
| 3648 | out_val->data.x_ptr.base_ptr = &array_ptr->static_value; |
| 3649 | out_val->data.x_ptr.index = index; |
| 3621 | 3650 | } else { |
| 3622 | 3651 | zig_unreachable(); |
| 3623 | 3652 | } |
| ... | ... | @@ -3790,9 +3819,9 @@ static TypeTableEntry *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstruc |
| 3790 | 3819 | return type_entry; |
| 3791 | 3820 | } else if (type_entry->id == TypeTableEntryIdPointer) { |
| 3792 | 3821 | TypeTableEntry *child_type = type_entry->data.pointer.child_type; |
| 3793 | | if (ptr->static_value.ok) { |
| 3794 | | ConstExprValue *pointee = ptr->static_value.data.x_ptr.ptr[0]; |
| 3795 | | if (pointee->ok) { |
| 3822 | if (ptr->static_value.special != ConstValSpecialRuntime) { |
| 3823 | ConstExprValue *pointee = const_ptr_pointee(&ptr->static_value); |
| 3824 | if (pointee->special != ConstValSpecialRuntime) { |
| 3796 | 3825 | ConstExprValue *out_val = ir_build_const_from(ira, &load_ptr_instruction->base, |
| 3797 | 3826 | pointee->depends_on_compile_var); |
| 3798 | 3827 | *out_val = *pointee; |
| ... | ... | @@ -3823,18 +3852,20 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru |
| 3823 | 3852 | if (casted_value == ira->codegen->invalid_instruction) |
| 3824 | 3853 | return ira->codegen->builtin_types.entry_invalid; |
| 3825 | 3854 | |
| 3826 | | if (ptr->static_value.ok && casted_value->static_value.ok) { |
| 3827 | | ConstExprValue *dest_val = ptr->static_value.data.x_ptr.ptr[0]; |
| 3828 | | if (dest_val->ok) { |
| 3855 | if (ptr->static_value.special != ConstValSpecialRuntime && |
| 3856 | casted_value->static_value.special != ConstValSpecialRuntime) |
| 3857 | { |
| 3858 | ConstExprValue *dest_val = const_ptr_pointee(&ptr->static_value); |
| 3859 | if (dest_val->special != ConstValSpecialRuntime) { |
| 3829 | 3860 | *dest_val = casted_value->static_value; |
| 3830 | 3861 | return ir_analyze_void(ira, &store_ptr_instruction->base); |
| 3831 | 3862 | } |
| 3832 | 3863 | } |
| 3833 | 3864 | |
| 3834 | | if (ptr->static_value.ok) { |
| 3865 | if (ptr->static_value.special != ConstValSpecialRuntime) { |
| 3835 | 3866 | // This memory location is transforming from known at compile time to known at runtime. |
| 3836 | 3867 | // We must emit our own var ptr instruction. |
| 3837 | | ptr->static_value.ok = false; |
| 3868 | ptr->static_value.special = ConstValSpecialRuntime; |
| 3838 | 3869 | IrInstruction *new_ptr_inst; |
| 3839 | 3870 | if (ptr->id == IrInstructionIdVarPtr) { |
| 3840 | 3871 | IrInstructionVarPtr *var_ptr_inst = (IrInstructionVarPtr *)ptr; |
| ... | ... | @@ -3842,7 +3873,7 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru |
| 3842 | 3873 | new_ptr_inst = ir_build_var_ptr(&ira->new_irb, store_ptr_instruction->base.source_node, var); |
| 3843 | 3874 | assert(var->mem_slot_index != SIZE_MAX); |
| 3844 | 3875 | ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index]; |
| 3845 | | mem_slot->ok = false; |
| 3876 | mem_slot->special = ConstValSpecialRuntime; |
| 3846 | 3877 | } else if (ptr->id == IrInstructionIdFieldPtr) { |
| 3847 | 3878 | zig_panic("TODO"); |
| 3848 | 3879 | } else if (ptr->id == IrInstructionIdElemPtr) { |
| ... | ... | @@ -4236,7 +4267,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { |
| 4236 | 4267 | |
| 4237 | 4268 | IrInstructionReturn *ret_inst = (IrInstructionReturn *)only_inst; |
| 4238 | 4269 | IrInstruction *value = ret_inst->value; |
| 4239 | | assert(value->static_value.ok); |
| 4270 | assert(value->static_value.special != ConstValSpecialRuntime); |
| 4240 | 4271 | return value; |
| 4241 | 4272 | } |
| 4242 | 4273 | |