| ... | @@ -3960,10 +3960,11 @@ pub const FuncGen = struct { | ... | @@ -3960,10 +3960,11 @@ pub const FuncGen = struct { |
| 3960 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 3960 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 3961 | const operand = try self.resolveInst(ty_op.operand); | 3961 | const operand = try self.resolveInst(ty_op.operand); |
| 3962 | const operand_ty = self.air.typeOf(ty_op.operand); | 3962 | const operand_ty = self.air.typeOf(ty_op.operand); |
| | 3963 | const operand_scalar_ty = operand_ty.scalarType(); |
| 3963 | const dest_ty = self.air.typeOfIndex(inst); | 3964 | const dest_ty = self.air.typeOfIndex(inst); |
| 3964 | const dest_llvm_ty = try self.dg.llvmType(dest_ty); | 3965 | const dest_llvm_ty = try self.dg.llvmType(dest_ty); |
| 3965 | | 3966 | |
| 3966 | if (operand_ty.isSignedInt()) { | 3967 | if (operand_scalar_ty.isSignedInt()) { |
| 3967 | return self.builder.buildSIToFP(operand, dest_llvm_ty, ""); | 3968 | return self.builder.buildSIToFP(operand, dest_llvm_ty, ""); |
| 3968 | } else { | 3969 | } else { |
| 3969 | return self.builder.buildUIToFP(operand, dest_llvm_ty, ""); | 3970 | return self.builder.buildUIToFP(operand, dest_llvm_ty, ""); |
| ... | @@ -3977,11 +3978,12 @@ pub const FuncGen = struct { | ... | @@ -3977,11 +3978,12 @@ pub const FuncGen = struct { |
| 3977 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 3978 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 3978 | const operand = try self.resolveInst(ty_op.operand); | 3979 | const operand = try self.resolveInst(ty_op.operand); |
| 3979 | const dest_ty = self.air.typeOfIndex(inst); | 3980 | const dest_ty = self.air.typeOfIndex(inst); |
| | 3981 | const dest_scalar_ty = dest_ty.scalarType(); |
| 3980 | const dest_llvm_ty = try self.dg.llvmType(dest_ty); | 3982 | const dest_llvm_ty = try self.dg.llvmType(dest_ty); |
| 3981 | | 3983 | |
| 3982 | // TODO set fast math flag | 3984 | // TODO set fast math flag |
| 3983 | | 3985 | |
| 3984 | if (dest_ty.isSignedInt()) { | 3986 | if (dest_scalar_ty.isSignedInt()) { |
| 3985 | return self.builder.buildFPToSI(operand, dest_llvm_ty, ""); | 3987 | return self.builder.buildFPToSI(operand, dest_llvm_ty, ""); |
| 3986 | } else { | 3988 | } else { |
| 3987 | return self.builder.buildFPToUI(operand, dest_llvm_ty, ""); | 3989 | return self.builder.buildFPToUI(operand, dest_llvm_ty, ""); |
| ... | @@ -4912,9 +4914,10 @@ pub const FuncGen = struct { | ... | @@ -4912,9 +4914,10 @@ pub const FuncGen = struct { |
| 4912 | const lhs = try self.resolveInst(bin_op.lhs); | 4914 | const lhs = try self.resolveInst(bin_op.lhs); |
| 4913 | const rhs = try self.resolveInst(bin_op.rhs); | 4915 | const rhs = try self.resolveInst(bin_op.rhs); |
| 4914 | const inst_ty = self.air.typeOfIndex(inst); | 4916 | const inst_ty = self.air.typeOfIndex(inst); |
| | 4917 | const scalar_ty = inst_ty.scalarType(); |
| 4915 | | 4918 | |
| 4916 | if (inst_ty.isAnyFloat()) return self.builder.buildFAdd(lhs, rhs, ""); | 4919 | if (scalar_ty.isAnyFloat()) return self.builder.buildFAdd(lhs, rhs, ""); |
| 4917 | if (inst_ty.isSignedInt()) return self.builder.buildNSWAdd(lhs, rhs, ""); | 4920 | if (scalar_ty.isSignedInt()) return self.builder.buildNSWAdd(lhs, rhs, ""); |
| 4918 | return self.builder.buildNUWAdd(lhs, rhs, ""); | 4921 | return self.builder.buildNUWAdd(lhs, rhs, ""); |
| 4919 | } | 4922 | } |
| 4920 | | 4923 | |
| ... | @@ -4935,9 +4938,10 @@ pub const FuncGen = struct { | ... | @@ -4935,9 +4938,10 @@ pub const FuncGen = struct { |
| 4935 | const lhs = try self.resolveInst(bin_op.lhs); | 4938 | const lhs = try self.resolveInst(bin_op.lhs); |
| 4936 | const rhs = try self.resolveInst(bin_op.rhs); | 4939 | const rhs = try self.resolveInst(bin_op.rhs); |
| 4937 | const inst_ty = self.air.typeOfIndex(inst); | 4940 | const inst_ty = self.air.typeOfIndex(inst); |
| | 4941 | const scalar_ty = inst_ty.scalarType(); |
| 4938 | | 4942 | |
| 4939 | if (inst_ty.isAnyFloat()) return self.todo("saturating float add", .{}); | 4943 | if (scalar_ty.isAnyFloat()) return self.todo("saturating float add", .{}); |
| 4940 | if (inst_ty.isSignedInt()) return self.builder.buildSAddSat(lhs, rhs, ""); | 4944 | if (scalar_ty.isSignedInt()) return self.builder.buildSAddSat(lhs, rhs, ""); |
| 4941 | | 4945 | |
| 4942 | return self.builder.buildUAddSat(lhs, rhs, ""); | 4946 | return self.builder.buildUAddSat(lhs, rhs, ""); |
| 4943 | } | 4947 | } |
| ... | @@ -4949,9 +4953,10 @@ pub const FuncGen = struct { | ... | @@ -4949,9 +4953,10 @@ pub const FuncGen = struct { |
| 4949 | const lhs = try self.resolveInst(bin_op.lhs); | 4953 | const lhs = try self.resolveInst(bin_op.lhs); |
| 4950 | const rhs = try self.resolveInst(bin_op.rhs); | 4954 | const rhs = try self.resolveInst(bin_op.rhs); |
| 4951 | const inst_ty = self.air.typeOfIndex(inst); | 4955 | const inst_ty = self.air.typeOfIndex(inst); |
| | 4956 | const scalar_ty = inst_ty.scalarType(); |
| 4952 | | 4957 | |
| 4953 | if (inst_ty.isAnyFloat()) return self.builder.buildFSub(lhs, rhs, ""); | 4958 | if (scalar_ty.isAnyFloat()) return self.builder.buildFSub(lhs, rhs, ""); |
| 4954 | if (inst_ty.isSignedInt()) return self.builder.buildNSWSub(lhs, rhs, ""); | 4959 | if (scalar_ty.isSignedInt()) return self.builder.buildNSWSub(lhs, rhs, ""); |
| 4955 | return self.builder.buildNUWSub(lhs, rhs, ""); | 4960 | return self.builder.buildNUWSub(lhs, rhs, ""); |
| 4956 | } | 4961 | } |
| 4957 | | 4962 | |
| ... | @@ -4972,9 +4977,10 @@ pub const FuncGen = struct { | ... | @@ -4972,9 +4977,10 @@ pub const FuncGen = struct { |
| 4972 | const lhs = try self.resolveInst(bin_op.lhs); | 4977 | const lhs = try self.resolveInst(bin_op.lhs); |
| 4973 | const rhs = try self.resolveInst(bin_op.rhs); | 4978 | const rhs = try self.resolveInst(bin_op.rhs); |
| 4974 | const inst_ty = self.air.typeOfIndex(inst); | 4979 | const inst_ty = self.air.typeOfIndex(inst); |
| | 4980 | const scalar_ty = inst_ty.scalarType(); |
| 4975 | | 4981 | |
| 4976 | if (inst_ty.isAnyFloat()) return self.todo("saturating float sub", .{}); | 4982 | if (scalar_ty.isAnyFloat()) return self.todo("saturating float sub", .{}); |
| 4977 | if (inst_ty.isSignedInt()) return self.builder.buildSSubSat(lhs, rhs, ""); | 4983 | if (scalar_ty.isSignedInt()) return self.builder.buildSSubSat(lhs, rhs, ""); |
| 4978 | return self.builder.buildUSubSat(lhs, rhs, ""); | 4984 | return self.builder.buildUSubSat(lhs, rhs, ""); |
| 4979 | } | 4985 | } |
| 4980 | | 4986 | |
| ... | @@ -4985,9 +4991,10 @@ pub const FuncGen = struct { | ... | @@ -4985,9 +4991,10 @@ pub const FuncGen = struct { |
| 4985 | const lhs = try self.resolveInst(bin_op.lhs); | 4991 | const lhs = try self.resolveInst(bin_op.lhs); |
| 4986 | const rhs = try self.resolveInst(bin_op.rhs); | 4992 | const rhs = try self.resolveInst(bin_op.rhs); |
| 4987 | const inst_ty = self.air.typeOfIndex(inst); | 4993 | const inst_ty = self.air.typeOfIndex(inst); |
| | 4994 | const scalar_ty = inst_ty.scalarType(); |
| 4988 | | 4995 | |
| 4989 | if (inst_ty.isAnyFloat()) return self.builder.buildFMul(lhs, rhs, ""); | 4996 | if (scalar_ty.isAnyFloat()) return self.builder.buildFMul(lhs, rhs, ""); |
| 4990 | if (inst_ty.isSignedInt()) return self.builder.buildNSWMul(lhs, rhs, ""); | 4997 | if (scalar_ty.isSignedInt()) return self.builder.buildNSWMul(lhs, rhs, ""); |
| 4991 | return self.builder.buildNUWMul(lhs, rhs, ""); | 4998 | return self.builder.buildNUWMul(lhs, rhs, ""); |
| 4992 | } | 4999 | } |
| 4993 | | 5000 | |
| ... | @@ -5008,9 +5015,10 @@ pub const FuncGen = struct { | ... | @@ -5008,9 +5015,10 @@ pub const FuncGen = struct { |
| 5008 | const lhs = try self.resolveInst(bin_op.lhs); | 5015 | const lhs = try self.resolveInst(bin_op.lhs); |
| 5009 | const rhs = try self.resolveInst(bin_op.rhs); | 5016 | const rhs = try self.resolveInst(bin_op.rhs); |
| 5010 | const inst_ty = self.air.typeOfIndex(inst); | 5017 | const inst_ty = self.air.typeOfIndex(inst); |
| | 5018 | const scalar_ty = inst_ty.scalarType(); |
| 5011 | | 5019 | |
| 5012 | if (inst_ty.isAnyFloat()) return self.todo("saturating float mul", .{}); | 5020 | if (scalar_ty.isAnyFloat()) return self.todo("saturating float mul", .{}); |
| 5013 | if (inst_ty.isSignedInt()) return self.builder.buildSMulFixSat(lhs, rhs, ""); | 5021 | if (scalar_ty.isSignedInt()) return self.builder.buildSMulFixSat(lhs, rhs, ""); |
| 5014 | return self.builder.buildUMulFixSat(lhs, rhs, ""); | 5022 | return self.builder.buildUMulFixSat(lhs, rhs, ""); |
| 5015 | } | 5023 | } |
| 5016 | | 5024 | |
| ... | @@ -5031,12 +5039,13 @@ pub const FuncGen = struct { | ... | @@ -5031,12 +5039,13 @@ pub const FuncGen = struct { |
| 5031 | const lhs = try self.resolveInst(bin_op.lhs); | 5039 | const lhs = try self.resolveInst(bin_op.lhs); |
| 5032 | const rhs = try self.resolveInst(bin_op.rhs); | 5040 | const rhs = try self.resolveInst(bin_op.rhs); |
| 5033 | const inst_ty = self.air.typeOfIndex(inst); | 5041 | const inst_ty = self.air.typeOfIndex(inst); |
| | 5042 | const scalar_ty = inst_ty.scalarType(); |
| 5034 | | 5043 | |
| 5035 | if (inst_ty.isRuntimeFloat()) { | 5044 | if (scalar_ty.isRuntimeFloat()) { |
| 5036 | const result = self.builder.buildFDiv(lhs, rhs, ""); | 5045 | const result = self.builder.buildFDiv(lhs, rhs, ""); |
| 5037 | return self.callTrunc(result, inst_ty); | 5046 | return self.callTrunc(result, inst_ty); |
| 5038 | } | 5047 | } |
| 5039 | if (inst_ty.isSignedInt()) return self.builder.buildSDiv(lhs, rhs, ""); | 5048 | if (scalar_ty.isSignedInt()) return self.builder.buildSDiv(lhs, rhs, ""); |
| 5040 | return self.builder.buildUDiv(lhs, rhs, ""); | 5049 | return self.builder.buildUDiv(lhs, rhs, ""); |
| 5041 | } | 5050 | } |
| 5042 | | 5051 | |
| ... | @@ -5047,12 +5056,13 @@ pub const FuncGen = struct { | ... | @@ -5047,12 +5056,13 @@ pub const FuncGen = struct { |
| 5047 | const lhs = try self.resolveInst(bin_op.lhs); | 5056 | const lhs = try self.resolveInst(bin_op.lhs); |
| 5048 | const rhs = try self.resolveInst(bin_op.rhs); | 5057 | const rhs = try self.resolveInst(bin_op.rhs); |
| 5049 | const inst_ty = self.air.typeOfIndex(inst); | 5058 | const inst_ty = self.air.typeOfIndex(inst); |
| | 5059 | const scalar_ty = inst_ty.scalarType(); |
| 5050 | | 5060 | |
| 5051 | if (inst_ty.isRuntimeFloat()) { | 5061 | if (scalar_ty.isRuntimeFloat()) { |
| 5052 | const result = self.builder.buildFDiv(lhs, rhs, ""); | 5062 | const result = self.builder.buildFDiv(lhs, rhs, ""); |
| 5053 | return try self.callFloor(result, inst_ty); | 5063 | return try self.callFloor(result, inst_ty); |
| 5054 | } | 5064 | } |
| 5055 | if (inst_ty.isSignedInt()) { | 5065 | if (scalar_ty.isSignedInt()) { |
| 5056 | // const d = @divTrunc(a, b); | 5066 | // const d = @divTrunc(a, b); |
| 5057 | // const r = @rem(a, b); | 5067 | // const r = @rem(a, b); |
| 5058 | // return if (r == 0) d else d - ((a < 0) ^ (b < 0)); | 5068 | // return if (r == 0) d else d - ((a < 0) ^ (b < 0)); |
| ... | @@ -5078,9 +5088,10 @@ pub const FuncGen = struct { | ... | @@ -5078,9 +5088,10 @@ pub const FuncGen = struct { |
| 5078 | const lhs = try self.resolveInst(bin_op.lhs); | 5088 | const lhs = try self.resolveInst(bin_op.lhs); |
| 5079 | const rhs = try self.resolveInst(bin_op.rhs); | 5089 | const rhs = try self.resolveInst(bin_op.rhs); |
| 5080 | const inst_ty = self.air.typeOfIndex(inst); | 5090 | const inst_ty = self.air.typeOfIndex(inst); |
| | 5091 | const scalar_ty = inst_ty.scalarType(); |
| 5081 | | 5092 | |
| 5082 | if (inst_ty.isRuntimeFloat()) return self.builder.buildFDiv(lhs, rhs, ""); | 5093 | if (scalar_ty.isRuntimeFloat()) return self.builder.buildFDiv(lhs, rhs, ""); |
| 5083 | if (inst_ty.isSignedInt()) return self.builder.buildExactSDiv(lhs, rhs, ""); | 5094 | if (scalar_ty.isSignedInt()) return self.builder.buildExactSDiv(lhs, rhs, ""); |
| 5084 | return self.builder.buildExactUDiv(lhs, rhs, ""); | 5095 | return self.builder.buildExactUDiv(lhs, rhs, ""); |
| 5085 | } | 5096 | } |
| 5086 | | 5097 | |
| ... | @@ -5091,9 +5102,10 @@ pub const FuncGen = struct { | ... | @@ -5091,9 +5102,10 @@ pub const FuncGen = struct { |
| 5091 | const lhs = try self.resolveInst(bin_op.lhs); | 5102 | const lhs = try self.resolveInst(bin_op.lhs); |
| 5092 | const rhs = try self.resolveInst(bin_op.rhs); | 5103 | const rhs = try self.resolveInst(bin_op.rhs); |
| 5093 | const inst_ty = self.air.typeOfIndex(inst); | 5104 | const inst_ty = self.air.typeOfIndex(inst); |
| | 5105 | const scalar_ty = inst_ty.scalarType(); |
| 5094 | | 5106 | |
| 5095 | if (inst_ty.isRuntimeFloat()) return self.builder.buildFRem(lhs, rhs, ""); | 5107 | if (scalar_ty.isRuntimeFloat()) return self.builder.buildFRem(lhs, rhs, ""); |
| 5096 | if (inst_ty.isSignedInt()) return self.builder.buildSRem(lhs, rhs, ""); | 5108 | if (scalar_ty.isSignedInt()) return self.builder.buildSRem(lhs, rhs, ""); |
| 5097 | return self.builder.buildURem(lhs, rhs, ""); | 5109 | return self.builder.buildURem(lhs, rhs, ""); |
| 5098 | } | 5110 | } |
| 5099 | | 5111 | |
| ... | @@ -5105,8 +5117,9 @@ pub const FuncGen = struct { | ... | @@ -5105,8 +5117,9 @@ pub const FuncGen = struct { |
| 5105 | const rhs = try self.resolveInst(bin_op.rhs); | 5117 | const rhs = try self.resolveInst(bin_op.rhs); |
| 5106 | const inst_ty = self.air.typeOfIndex(inst); | 5118 | const inst_ty = self.air.typeOfIndex(inst); |
| 5107 | const inst_llvm_ty = try self.dg.llvmType(inst_ty); | 5119 | const inst_llvm_ty = try self.dg.llvmType(inst_ty); |
| | 5120 | const scalar_ty = inst_ty.scalarType(); |
| 5108 | | 5121 | |
| 5109 | if (inst_ty.isRuntimeFloat()) { | 5122 | if (scalar_ty.isRuntimeFloat()) { |
| 5110 | const a = self.builder.buildFRem(lhs, rhs, ""); | 5123 | const a = self.builder.buildFRem(lhs, rhs, ""); |
| 5111 | const b = self.builder.buildFAdd(a, rhs, ""); | 5124 | const b = self.builder.buildFAdd(a, rhs, ""); |
| 5112 | const c = self.builder.buildFRem(b, rhs, ""); | 5125 | const c = self.builder.buildFRem(b, rhs, ""); |
| ... | @@ -5114,7 +5127,7 @@ pub const FuncGen = struct { | ... | @@ -5114,7 +5127,7 @@ pub const FuncGen = struct { |
| 5114 | const ltz = self.builder.buildFCmp(.OLT, lhs, zero, ""); | 5127 | const ltz = self.builder.buildFCmp(.OLT, lhs, zero, ""); |
| 5115 | return self.builder.buildSelect(ltz, c, a, ""); | 5128 | return self.builder.buildSelect(ltz, c, a, ""); |
| 5116 | } | 5129 | } |
| 5117 | if (inst_ty.isSignedInt()) { | 5130 | if (scalar_ty.isSignedInt()) { |
| 5118 | const a = self.builder.buildSRem(lhs, rhs, ""); | 5131 | const a = self.builder.buildSRem(lhs, rhs, ""); |
| 5119 | const b = self.builder.buildNSWAdd(a, rhs, ""); | 5132 | const b = self.builder.buildNSWAdd(a, rhs, ""); |
| 5120 | const c = self.builder.buildSRem(b, rhs, ""); | 5133 | const c = self.builder.buildSRem(b, rhs, ""); |
| ... | @@ -5339,15 +5352,22 @@ pub const FuncGen = struct { | ... | @@ -5339,15 +5352,22 @@ pub const FuncGen = struct { |
| 5339 | if (self.liveness.isUnused(inst)) return null; | 5352 | if (self.liveness.isUnused(inst)) return null; |
| 5340 | | 5353 | |
| 5341 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 5354 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| | 5355 | |
| 5342 | const lhs = try self.resolveInst(bin_op.lhs); | 5356 | const lhs = try self.resolveInst(bin_op.lhs); |
| 5343 | const rhs = try self.resolveInst(bin_op.rhs); | 5357 | const rhs = try self.resolveInst(bin_op.rhs); |
| 5344 | const lhs_type = self.air.typeOf(bin_op.lhs); | 5358 | |
| | 5359 | const lhs_ty = self.air.typeOf(bin_op.lhs); |
| | 5360 | const rhs_ty = self.air.typeOf(bin_op.rhs); |
| | 5361 | const lhs_scalar_ty = lhs_ty.scalarType(); |
| | 5362 | const rhs_scalar_ty = rhs_ty.scalarType(); |
| | 5363 | |
| 5345 | const tg = self.dg.module.getTarget(); | 5364 | const tg = self.dg.module.getTarget(); |
| 5346 | const casted_rhs = if (self.air.typeOf(bin_op.rhs).bitSize(tg) < lhs_type.bitSize(tg)) | 5365 | |
| 5347 | self.builder.buildZExt(rhs, try self.dg.llvmType(lhs_type), "") | 5366 | const casted_rhs = if (rhs_scalar_ty.bitSize(tg) < lhs_scalar_ty.bitSize(tg)) |
| | 5367 | self.builder.buildZExt(rhs, try self.dg.llvmType(lhs_ty), "") |
| 5348 | else | 5368 | else |
| 5349 | rhs; | 5369 | rhs; |
| 5350 | if (lhs_type.isSignedInt()) return self.builder.buildNSWShl(lhs, casted_rhs, ""); | 5370 | if (lhs_scalar_ty.isSignedInt()) return self.builder.buildNSWShl(lhs, casted_rhs, ""); |
| 5351 | return self.builder.buildNUWShl(lhs, casted_rhs, ""); | 5371 | return self.builder.buildNUWShl(lhs, casted_rhs, ""); |
| 5352 | } | 5372 | } |
| 5353 | | 5373 | |
| ... | @@ -5355,11 +5375,18 @@ pub const FuncGen = struct { | ... | @@ -5355,11 +5375,18 @@ pub const FuncGen = struct { |
| 5355 | if (self.liveness.isUnused(inst)) return null; | 5375 | if (self.liveness.isUnused(inst)) return null; |
| 5356 | | 5376 | |
| 5357 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 5377 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| | 5378 | |
| 5358 | const lhs = try self.resolveInst(bin_op.lhs); | 5379 | const lhs = try self.resolveInst(bin_op.lhs); |
| 5359 | const rhs = try self.resolveInst(bin_op.rhs); | 5380 | const rhs = try self.resolveInst(bin_op.rhs); |
| | 5381 | |
| 5360 | const lhs_type = self.air.typeOf(bin_op.lhs); | 5382 | const lhs_type = self.air.typeOf(bin_op.lhs); |
| | 5383 | const rhs_type = self.air.typeOf(bin_op.rhs); |
| | 5384 | const lhs_scalar_ty = lhs_type.scalarType(); |
| | 5385 | const rhs_scalar_ty = rhs_type.scalarType(); |
| | 5386 | |
| 5361 | const tg = self.dg.module.getTarget(); | 5387 | const tg = self.dg.module.getTarget(); |
| 5362 | const casted_rhs = if (self.air.typeOf(bin_op.rhs).bitSize(tg) < lhs_type.bitSize(tg)) | 5388 | |
| | 5389 | const casted_rhs = if (rhs_scalar_ty.bitSize(tg) < lhs_scalar_ty.bitSize(tg)) |
| 5363 | self.builder.buildZExt(rhs, try self.dg.llvmType(lhs_type), "") | 5390 | self.builder.buildZExt(rhs, try self.dg.llvmType(lhs_type), "") |
| 5364 | else | 5391 | else |
| 5365 | rhs; | 5392 | rhs; |
| ... | @@ -5370,31 +5397,45 @@ pub const FuncGen = struct { | ... | @@ -5370,31 +5397,45 @@ pub const FuncGen = struct { |
| 5370 | if (self.liveness.isUnused(inst)) return null; | 5397 | if (self.liveness.isUnused(inst)) return null; |
| 5371 | | 5398 | |
| 5372 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 5399 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| | 5400 | |
| 5373 | const lhs = try self.resolveInst(bin_op.lhs); | 5401 | const lhs = try self.resolveInst(bin_op.lhs); |
| 5374 | const rhs = try self.resolveInst(bin_op.rhs); | 5402 | const rhs = try self.resolveInst(bin_op.rhs); |
| 5375 | const lhs_type = self.air.typeOf(bin_op.lhs); | 5403 | |
| | 5404 | const lhs_ty = self.air.typeOf(bin_op.lhs); |
| | 5405 | const rhs_ty = self.air.typeOf(bin_op.rhs); |
| | 5406 | const lhs_scalar_ty = lhs_ty.scalarType(); |
| | 5407 | const rhs_scalar_ty = rhs_ty.scalarType(); |
| | 5408 | |
| 5376 | const tg = self.dg.module.getTarget(); | 5409 | const tg = self.dg.module.getTarget(); |
| 5377 | const casted_rhs = if (self.air.typeOf(bin_op.rhs).bitSize(tg) < lhs_type.bitSize(tg)) | 5410 | |
| 5378 | self.builder.buildZExt(rhs, try self.dg.llvmType(lhs_type), "") | 5411 | const casted_rhs = if (rhs_scalar_ty.bitSize(tg) < lhs_scalar_ty.bitSize(tg)) |
| | 5412 | self.builder.buildZExt(rhs, try self.dg.llvmType(lhs_ty), "") |
| 5379 | else | 5413 | else |
| 5380 | rhs; | 5414 | rhs; |
| 5381 | if (lhs_type.isSignedInt()) return self.builder.buildSShlSat(lhs, casted_rhs, ""); | 5415 | if (lhs_scalar_ty.isSignedInt()) return self.builder.buildSShlSat(lhs, casted_rhs, ""); |
| 5382 | return self.builder.buildUShlSat(lhs, casted_rhs, ""); | 5416 | return self.builder.buildUShlSat(lhs, casted_rhs, ""); |
| 5383 | } | 5417 | } |
| 5384 | | 5418 | |
| 5385 | fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) !?*const llvm.Value { | 5419 | fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) !?*const llvm.Value { |
| 5386 | if (self.liveness.isUnused(inst)) | 5420 | if (self.liveness.isUnused(inst)) return null; |
| 5387 | return null; | 5421 | |
| 5388 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 5422 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| | 5423 | |
| 5389 | const lhs = try self.resolveInst(bin_op.lhs); | 5424 | const lhs = try self.resolveInst(bin_op.lhs); |
| 5390 | const rhs = try self.resolveInst(bin_op.rhs); | 5425 | const rhs = try self.resolveInst(bin_op.rhs); |
| 5391 | const lhs_type = self.air.typeOf(bin_op.lhs); | 5426 | |
| | 5427 | const lhs_ty = self.air.typeOf(bin_op.lhs); |
| | 5428 | const rhs_ty = self.air.typeOf(bin_op.rhs); |
| | 5429 | const lhs_scalar_ty = lhs_ty.scalarType(); |
| | 5430 | const rhs_scalar_ty = rhs_ty.scalarType(); |
| | 5431 | |
| 5392 | const tg = self.dg.module.getTarget(); | 5432 | const tg = self.dg.module.getTarget(); |
| 5393 | const casted_rhs = if (self.air.typeOf(bin_op.rhs).bitSize(tg) < lhs_type.bitSize(tg)) | 5433 | |
| 5394 | self.builder.buildZExt(rhs, try self.dg.llvmType(lhs_type), "") | 5434 | const casted_rhs = if (rhs_scalar_ty.bitSize(tg) < lhs_scalar_ty.bitSize(tg)) |
| | 5435 | self.builder.buildZExt(rhs, try self.dg.llvmType(lhs_ty), "") |
| 5395 | else | 5436 | else |
| 5396 | rhs; | 5437 | rhs; |
| 5397 | const is_signed_int = self.air.typeOfIndex(inst).isSignedInt(); | 5438 | const is_signed_int = lhs_scalar_ty.isSignedInt(); |
| 5398 | | 5439 | |
| 5399 | if (is_exact) { | 5440 | if (is_exact) { |
| 5400 | if (is_signed_int) { | 5441 | if (is_signed_int) { |