| ... | ... | @@ -494,6 +494,49 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { |
| 494 | 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 | 540 | return fn_table_entry->llvm_value; |
| 498 | 541 | } |
| 499 | 542 | |
| ... | ... | @@ -4298,59 +4341,6 @@ static void do_code_gen(CodeGen *g) { |
| 4298 | 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 | 4344 | // Generate function definitions. |
| 4355 | 4345 | for (size_t fn_i = 0; fn_i < g->fn_defs.length; fn_i += 1) { |
| 4356 | 4346 | FnTableEntry *fn_table_entry = g->fn_defs.at(fn_i); |