| ... | @@ -494,6 +494,49 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { | ... | @@ -494,6 +494,49 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { |
| 494 | // use the ABI alignment, which is fine. | 494 | // use the ABI alignment, which is fine. |
| 495 | } | 495 | } |
| 496 | | 496 | |
| | 497 | if (!type_has_bits(fn_type->data.fn.fn_type_id.return_type)) { |
| | 498 | // nothing to do |
| | 499 | } else if (fn_type->data.fn.fn_type_id.return_type->id == TypeTableEntryIdPointer || |
| | 500 | fn_type->data.fn.fn_type_id.return_type->id == TypeTableEntryIdFn) |
| | 501 | { |
| | 502 | addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull"); |
| | 503 | } else if (handle_is_ptr(fn_type->data.fn.fn_type_id.return_type) && |
| | 504 | calling_convention_does_first_arg_return(fn_type->data.fn.fn_type_id.cc)) |
| | 505 | { |
| | 506 | addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret"); |
| | 507 | addLLVMArgAttr(fn_table_entry->llvm_value, 0, "nonnull"); |
| | 508 | } |
| | 509 | |
| | 510 | |
| | 511 | // set parameter attributes |
| | 512 | for (size_t param_i = 0; param_i < fn_type->data.fn.fn_type_id.param_count; param_i += 1) { |
| | 513 | FnGenParamInfo *gen_info = &fn_type->data.fn.gen_param_info[param_i]; |
| | 514 | size_t gen_index = gen_info->gen_index; |
| | 515 | bool is_byval = gen_info->is_byval; |
| | 516 | |
| | 517 | if (gen_index == SIZE_MAX) { |
| | 518 | continue; |
| | 519 | } |
| | 520 | |
| | 521 | FnTypeParamInfo *param_info = &fn_type->data.fn.fn_type_id.param_info[param_i]; |
| | 522 | |
| | 523 | TypeTableEntry *param_type = gen_info->type; |
| | 524 | if (param_info->is_noalias) { |
| | 525 | addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)gen_index, "noalias"); |
| | 526 | } |
| | 527 | if ((param_type->id == TypeTableEntryIdPointer && param_type->data.pointer.is_const) || is_byval) { |
| | 528 | addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)gen_index, "readonly"); |
| | 529 | } |
| | 530 | if (param_type->id == TypeTableEntryIdPointer) { |
| | 531 | addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)gen_index, "nonnull"); |
| | 532 | } |
| | 533 | // Note: byval is disabled on windows due to an LLVM bug: |
| | 534 | // https://github.com/zig-lang/zig/issues/536 |
| | 535 | if (is_byval && g->zig_target.os != ZigLLVM_Win32) { |
| | 536 | addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)gen_index, "byval"); |
| | 537 | } |
| | 538 | } |
| | 539 | |
| 497 | return fn_table_entry->llvm_value; | 540 | return fn_table_entry->llvm_value; |
| 498 | } | 541 | } |
| 499 | | 542 | |
| ... | @@ -4298,59 +4341,6 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -4298,59 +4341,6 @@ static void do_code_gen(CodeGen *g) { |
| 4298 | var->value_ref = global_value; | 4341 | var->value_ref = global_value; |
| 4299 | } | 4342 | } |
| 4300 | | 4343 | |
| 4301 | // Generate function prototypes | | |
| 4302 | for (size_t fn_proto_i = 0; fn_proto_i < g->fn_protos.length; fn_proto_i += 1) { | | |
| 4303 | FnTableEntry *fn_table_entry = g->fn_protos.at(fn_proto_i); | | |
| 4304 | | | |
| 4305 | TypeTableEntry *fn_type = fn_table_entry->type_entry; | | |
| 4306 | FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; | | |
| 4307 | | | |
| 4308 | LLVMValueRef fn_val = fn_llvm_value(g, fn_table_entry); | | |
| 4309 | | | |
| 4310 | if (!type_has_bits(fn_type->data.fn.fn_type_id.return_type)) { | | |
| 4311 | // nothing to do | | |
| 4312 | } else if (fn_type->data.fn.fn_type_id.return_type->id == TypeTableEntryIdPointer || | | |
| 4313 | fn_type->data.fn.fn_type_id.return_type->id == TypeTableEntryIdFn) | | |
| 4314 | { | | |
| 4315 | addLLVMAttr(fn_val, 0, "nonnull"); | | |
| 4316 | } else if (handle_is_ptr(fn_type->data.fn.fn_type_id.return_type) && | | |
| 4317 | calling_convention_does_first_arg_return(fn_type->data.fn.fn_type_id.cc)) | | |
| 4318 | { | | |
| 4319 | addLLVMArgAttr(fn_val, 0, "sret"); | | |
| 4320 | addLLVMArgAttr(fn_val, 0, "nonnull"); | | |
| 4321 | } | | |
| 4322 | | | |
| 4323 | | | |
| 4324 | // set parameter attributes | | |
| 4325 | for (size_t param_i = 0; param_i < fn_type_id->param_count; param_i += 1) { | | |
| 4326 | FnGenParamInfo *gen_info = &fn_type->data.fn.gen_param_info[param_i]; | | |
| 4327 | size_t gen_index = gen_info->gen_index; | | |
| 4328 | bool is_byval = gen_info->is_byval; | | |
| 4329 | | | |
| 4330 | if (gen_index == SIZE_MAX) { | | |
| 4331 | continue; | | |
| 4332 | } | | |
| 4333 | | | |
| 4334 | FnTypeParamInfo *param_info = &fn_type_id->param_info[param_i]; | | |
| 4335 | | | |
| 4336 | TypeTableEntry *param_type = gen_info->type; | | |
| 4337 | if (param_info->is_noalias) { | | |
| 4338 | addLLVMArgAttr(fn_val, (unsigned)gen_index, "noalias"); | | |
| 4339 | } | | |
| 4340 | if ((param_type->id == TypeTableEntryIdPointer && param_type->data.pointer.is_const) || is_byval) { | | |
| 4341 | addLLVMArgAttr(fn_val, (unsigned)gen_index, "readonly"); | | |
| 4342 | } | | |
| 4343 | if (param_type->id == TypeTableEntryIdPointer) { | | |
| 4344 | addLLVMArgAttr(fn_val, (unsigned)gen_index, "nonnull"); | | |
| 4345 | } | | |
| 4346 | // Note: byval is disabled on windows due to an LLVM bug: | | |
| 4347 | // https://github.com/zig-lang/zig/issues/536 | | |
| 4348 | if (is_byval && g->zig_target.os != ZigLLVM_Win32) { | | |
| 4349 | addLLVMArgAttr(fn_val, (unsigned)gen_index, "byval"); | | |
| 4350 | } | | |
| 4351 | } | | |
| 4352 | } | | |
| 4353 | | | |
| 4354 | // Generate function definitions. | 4344 | // Generate function definitions. |
| 4355 | for (size_t fn_i = 0; fn_i < g->fn_defs.length; fn_i += 1) { | 4345 | for (size_t fn_i = 0; fn_i < g->fn_defs.length; fn_i += 1) { |
| 4356 | FnTableEntry *fn_table_entry = g->fn_defs.at(fn_i); | 4346 | FnTableEntry *fn_table_entry = g->fn_defs.at(fn_i); |