| ... | @@ -643,67 +643,21 @@ pub const DeclGen = struct { | ... | @@ -643,67 +643,21 @@ pub const DeclGen = struct { |
| 643 | llvm_fn.setUnnamedAddr(.True); | 643 | llvm_fn.setUnnamedAddr(.True); |
| 644 | } | 644 | } |
| 645 | | 645 | |
| | 646 | if (self.module.comp.bin_file.options.skip_linker_dependencies) { |
| | 647 | // The intent here is for compiler-rt and libc functions to not generate |
| | 648 | // infinite recursion. For example, if we are compiling the memcpy function, |
| | 649 | // and llvm detects that the body is equivalent to memcpy, it may replace the |
| | 650 | // body of memcpy with a call to memcpy, which would then cause a stack |
| | 651 | // overflow instead of performing memcpy. |
| | 652 | self.addFnAttr(llvm_fn, "nobuiltin"); |
| | 653 | } |
| | 654 | |
| 646 | // TODO: more attributes. see codegen.cpp `make_fn_llvm_value`. | 655 | // TODO: more attributes. see codegen.cpp `make_fn_llvm_value`. |
| 647 | const target = self.module.getTarget(); | 656 | const target = self.module.getTarget(); |
| 648 | switch (fn_info.cc) { | 657 | if (fn_info.cc == .Naked) { |
| 649 | .Unspecified, .Inline, .Async => { | 658 | self.addFnAttr(llvm_fn, "naked"); |
| 650 | llvm_fn.setFunctionCallConv(.Fast); | 659 | } else { |
| 651 | }, | 660 | llvm_fn.setFunctionCallConv(toLlvmCallConv(fn_info.cc, target)); |
| 652 | .C => { | | |
| 653 | llvm_fn.setFunctionCallConv(.C); | | |
| 654 | }, | | |
| 655 | .Naked => { | | |
| 656 | self.addFnAttr(llvm_fn, "naked"); | | |
| 657 | }, | | |
| 658 | .Stdcall => { | | |
| 659 | llvm_fn.setFunctionCallConv(.X86_StdCall); | | |
| 660 | }, | | |
| 661 | .Fastcall => { | | |
| 662 | llvm_fn.setFunctionCallConv(.X86_FastCall); | | |
| 663 | }, | | |
| 664 | .Vectorcall => { | | |
| 665 | switch (target.cpu.arch) { | | |
| 666 | .i386, .x86_64 => { | | |
| 667 | llvm_fn.setFunctionCallConv(.X86_VectorCall); | | |
| 668 | }, | | |
| 669 | .aarch64, .aarch64_be, .aarch64_32 => { | | |
| 670 | llvm_fn.setFunctionCallConv(.AArch64_VectorCall); | | |
| 671 | }, | | |
| 672 | else => unreachable, | | |
| 673 | } | | |
| 674 | }, | | |
| 675 | .Thiscall => { | | |
| 676 | llvm_fn.setFunctionCallConv(.X86_ThisCall); | | |
| 677 | }, | | |
| 678 | .APCS => { | | |
| 679 | llvm_fn.setFunctionCallConv(.ARM_APCS); | | |
| 680 | }, | | |
| 681 | .AAPCS => { | | |
| 682 | llvm_fn.setFunctionCallConv(.ARM_AAPCS); | | |
| 683 | }, | | |
| 684 | .AAPCSVFP => { | | |
| 685 | llvm_fn.setFunctionCallConv(.ARM_AAPCS_VFP); | | |
| 686 | }, | | |
| 687 | .Interrupt => { | | |
| 688 | switch (target.cpu.arch) { | | |
| 689 | .i386, .x86_64 => { | | |
| 690 | llvm_fn.setFunctionCallConv(.X86_INTR); | | |
| 691 | }, | | |
| 692 | .avr => { | | |
| 693 | llvm_fn.setFunctionCallConv(.AVR_INTR); | | |
| 694 | }, | | |
| 695 | .msp430 => { | | |
| 696 | llvm_fn.setFunctionCallConv(.MSP430_INTR); | | |
| 697 | }, | | |
| 698 | else => unreachable, | | |
| 699 | } | | |
| 700 | }, | | |
| 701 | .Signal => { | | |
| 702 | llvm_fn.setFunctionCallConv(.AVR_SIGNAL); | | |
| 703 | }, | | |
| 704 | .SysV => { | | |
| 705 | llvm_fn.setFunctionCallConv(.X86_64_SysV); | | |
| 706 | }, | | |
| 707 | } | 661 | } |
| 708 | | 662 | |
| 709 | // Function attributes that are independent of analysis results of the function body. | 663 | // Function attributes that are independent of analysis results of the function body. |
| ... | @@ -1445,6 +1399,7 @@ pub const FuncGen = struct { | ... | @@ -1445,6 +1399,7 @@ pub const FuncGen = struct { |
| 1445 | const zig_fn_type = self.air.typeOf(pl_op.operand); | 1399 | const zig_fn_type = self.air.typeOf(pl_op.operand); |
| 1446 | const return_type = zig_fn_type.fnReturnType(); | 1400 | const return_type = zig_fn_type.fnReturnType(); |
| 1447 | const llvm_fn = try self.resolveInst(pl_op.operand); | 1401 | const llvm_fn = try self.resolveInst(pl_op.operand); |
| | 1402 | const target = self.dg.module.getTarget(); |
| 1448 | | 1403 | |
| 1449 | const llvm_param_vals = try self.gpa.alloc(*const llvm.Value, args.len); | 1404 | const llvm_param_vals = try self.gpa.alloc(*const llvm.Value, args.len); |
| 1450 | defer self.gpa.free(llvm_param_vals); | 1405 | defer self.gpa.free(llvm_param_vals); |
| ... | @@ -1457,6 +1412,8 @@ pub const FuncGen = struct { | ... | @@ -1457,6 +1412,8 @@ pub const FuncGen = struct { |
| 1457 | llvm_fn, | 1412 | llvm_fn, |
| 1458 | llvm_param_vals.ptr, | 1413 | llvm_param_vals.ptr, |
| 1459 | @intCast(c_uint, args.len), | 1414 | @intCast(c_uint, args.len), |
| | 1415 | toLlvmCallConv(zig_fn_type.fnCallingConvention(), target), |
| | 1416 | .Auto, |
| 1460 | "", | 1417 | "", |
| 1461 | ); | 1418 | ); |
| 1462 | | 1419 | |
| ... | @@ -1489,13 +1446,10 @@ pub const FuncGen = struct { | ... | @@ -1489,13 +1446,10 @@ pub const FuncGen = struct { |
| 1489 | const lhs = try self.resolveInst(bin_op.lhs); | 1446 | const lhs = try self.resolveInst(bin_op.lhs); |
| 1490 | const rhs = try self.resolveInst(bin_op.rhs); | 1447 | const rhs = try self.resolveInst(bin_op.rhs); |
| 1491 | const operand_ty = self.air.typeOf(bin_op.lhs); | 1448 | const operand_ty = self.air.typeOf(bin_op.lhs); |
| | 1449 | var buffer: Type.Payload.Bits = undefined; |
| 1492 | | 1450 | |
| 1493 | const int_ty = switch (operand_ty.zigTypeTag()) { | 1451 | const int_ty = switch (operand_ty.zigTypeTag()) { |
| 1494 | .Enum => blk: { | 1452 | .Enum => operand_ty.intTagType(&buffer), |
| 1495 | var buffer: Type.Payload.Bits = undefined; | | |
| 1496 | const int_ty = operand_ty.intTagType(&buffer); | | |
| 1497 | break :blk int_ty; | | |
| 1498 | }, | | |
| 1499 | .Int, .Bool, .Pointer, .ErrorSet => operand_ty, | 1453 | .Int, .Bool, .Pointer, .ErrorSet => operand_ty, |
| 1500 | .Float => { | 1454 | .Float => { |
| 1501 | const operation: llvm.RealPredicate = switch (op) { | 1455 | const operation: llvm.RealPredicate = switch (op) { |
| ... | @@ -1511,13 +1465,13 @@ pub const FuncGen = struct { | ... | @@ -1511,13 +1465,13 @@ pub const FuncGen = struct { |
| 1511 | else => unreachable, | 1465 | else => unreachable, |
| 1512 | }; | 1466 | }; |
| 1513 | const is_signed = int_ty.isSignedInt(); | 1467 | const is_signed = int_ty.isSignedInt(); |
| 1514 | const operation = switch (op) { | 1468 | const operation: llvm.IntPredicate = switch (op) { |
| 1515 | .eq => .EQ, | 1469 | .eq => .EQ, |
| 1516 | .neq => .NE, | 1470 | .neq => .NE, |
| 1517 | .lt => @as(llvm.IntPredicate, if (is_signed) .SLT else .ULT), | 1471 | .lt => if (is_signed) llvm.IntPredicate.SLT else .ULT, |
| 1518 | .lte => @as(llvm.IntPredicate, if (is_signed) .SLE else .ULE), | 1472 | .lte => if (is_signed) llvm.IntPredicate.SLE else .ULE, |
| 1519 | .gt => @as(llvm.IntPredicate, if (is_signed) .SGT else .UGT), | 1473 | .gt => if (is_signed) llvm.IntPredicate.SGT else .UGT, |
| 1520 | .gte => @as(llvm.IntPredicate, if (is_signed) .SGE else .UGE), | 1474 | .gte => if (is_signed) llvm.IntPredicate.SGE else .UGE, |
| 1521 | }; | 1475 | }; |
| 1522 | return self.builder.buildICmp(operation, lhs, rhs, ""); | 1476 | return self.builder.buildICmp(operation, lhs, rhs, ""); |
| 1523 | } | 1477 | } |
| ... | @@ -1947,6 +1901,8 @@ pub const FuncGen = struct { | ... | @@ -1947,6 +1901,8 @@ pub const FuncGen = struct { |
| 1947 | asm_fn, | 1901 | asm_fn, |
| 1948 | llvm_param_values.ptr, | 1902 | llvm_param_values.ptr, |
| 1949 | @intCast(c_uint, llvm_param_values.len), | 1903 | @intCast(c_uint, llvm_param_values.len), |
| | 1904 | .C, |
| | 1905 | .Auto, |
| 1950 | "", | 1906 | "", |
| 1951 | ); | 1907 | ); |
| 1952 | } | 1908 | } |
| ... | @@ -2561,7 +2517,7 @@ pub const FuncGen = struct { | ... | @@ -2561,7 +2517,7 @@ pub const FuncGen = struct { |
| 2561 | fn airBreakpoint(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { | 2517 | fn airBreakpoint(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { |
| 2562 | _ = inst; | 2518 | _ = inst; |
| 2563 | const llvm_fn = self.getIntrinsic("llvm.debugtrap"); | 2519 | const llvm_fn = self.getIntrinsic("llvm.debugtrap"); |
| 2564 | _ = self.builder.buildCall(llvm_fn, undefined, 0, ""); | 2520 | _ = self.builder.buildCall(llvm_fn, undefined, 0, .C, .Auto, ""); |
| 2565 | return null; | 2521 | return null; |
| 2566 | } | 2522 | } |
| 2567 | | 2523 | |
| ... | @@ -2818,7 +2774,7 @@ pub const FuncGen = struct { | ... | @@ -2818,7 +2774,7 @@ pub const FuncGen = struct { |
| 2818 | }; | 2774 | }; |
| 2819 | | 2775 | |
| 2820 | const params = [_]*const llvm.Value{ operand, llvm_i1.constNull() }; | 2776 | const params = [_]*const llvm.Value{ operand, llvm_i1.constNull() }; |
| 2821 | const wrong_size_result = self.builder.buildCall(fn_val, &params, params.len, ""); | 2777 | const wrong_size_result = self.builder.buildCall(fn_val, &params, params.len, .C, .Auto, ""); |
| 2822 | const result_ty = self.air.typeOfIndex(inst); | 2778 | const result_ty = self.air.typeOfIndex(inst); |
| 2823 | const result_llvm_ty = try self.dg.llvmType(result_ty); | 2779 | const result_llvm_ty = try self.dg.llvmType(result_ty); |
| 2824 | const result_bits = result_ty.intInfo(target).bits; | 2780 | const result_bits = result_ty.intInfo(target).bits; |
| ... | @@ -3108,6 +3064,32 @@ fn toLlvmAtomicRmwBinOp( | ... | @@ -3108,6 +3064,32 @@ fn toLlvmAtomicRmwBinOp( |
| 3108 | }; | 3064 | }; |
| 3109 | } | 3065 | } |
| 3110 | | 3066 | |
| | 3067 | fn toLlvmCallConv(cc: std.builtin.CallingConvention, target: std.Target) llvm.CallConv { |
| | 3068 | return switch (cc) { |
| | 3069 | .Unspecified, .Inline, .Async => .Fast, |
| | 3070 | .C, .Naked => .C, |
| | 3071 | .Stdcall => .X86_StdCall, |
| | 3072 | .Fastcall => .X86_FastCall, |
| | 3073 | .Vectorcall => return switch (target.cpu.arch) { |
| | 3074 | .i386, .x86_64 => .X86_VectorCall, |
| | 3075 | .aarch64, .aarch64_be, .aarch64_32 => .AArch64_VectorCall, |
| | 3076 | else => unreachable, |
| | 3077 | }, |
| | 3078 | .Thiscall => .X86_ThisCall, |
| | 3079 | .APCS => .ARM_APCS, |
| | 3080 | .AAPCS => .ARM_AAPCS, |
| | 3081 | .AAPCSVFP => .ARM_AAPCS_VFP, |
| | 3082 | .Interrupt => return switch (target.cpu.arch) { |
| | 3083 | .i386, .x86_64 => .X86_INTR, |
| | 3084 | .avr => .AVR_INTR, |
| | 3085 | .msp430 => .MSP430_INTR, |
| | 3086 | else => unreachable, |
| | 3087 | }, |
| | 3088 | .Signal => .AVR_SIGNAL, |
| | 3089 | .SysV => .X86_64_SysV, |
| | 3090 | }; |
| | 3091 | } |
| | 3092 | |
| 3111 | /// Take into account 0 bit fields. | 3093 | /// Take into account 0 bit fields. |
| 3112 | fn llvmFieldIndex(ty: Type, index: u32) c_uint { | 3094 | fn llvmFieldIndex(ty: Type, index: u32) c_uint { |
| 3113 | const struct_obj = ty.castTag(.@"struct").?.data; | 3095 | const struct_obj = ty.castTag(.@"struct").?.data; |