| ... | @@ -588,6 +588,12 @@ pub const DeclGen = struct { | ... | @@ -588,6 +588,12 @@ pub const DeclGen = struct { |
| 588 | const info = t.intInfo(self.module.getTarget()); | 588 | const info = t.intInfo(self.module.getTarget()); |
| 589 | return self.context.intType(info.bits); | 589 | return self.context.intType(info.bits); |
| 590 | }, | 590 | }, |
| | 591 | .Enum => { |
| | 592 | var buffer: Type.Payload.Bits = undefined; |
| | 593 | const int_ty = t.enumTagType(&buffer); |
| | 594 | const bit_count = int_ty.intInfo(self.module.getTarget()).bits; |
| | 595 | return self.context.intType(bit_count); |
| | 596 | }, |
| 591 | .Float => switch (t.floatBits(self.module.getTarget())) { | 597 | .Float => switch (t.floatBits(self.module.getTarget())) { |
| 592 | 16 => return self.context.halfType(), | 598 | 16 => return self.context.halfType(), |
| 593 | 32 => return self.context.floatType(), | 599 | 32 => return self.context.floatType(), |
| ... | @@ -686,7 +692,6 @@ pub const DeclGen = struct { | ... | @@ -686,7 +692,6 @@ pub const DeclGen = struct { |
| 686 | | 692 | |
| 687 | .BoundFn => @panic("TODO remove BoundFn from the language"), | 693 | .BoundFn => @panic("TODO remove BoundFn from the language"), |
| 688 | | 694 | |
| 689 | .Enum, | | |
| 690 | .Union, | 695 | .Union, |
| 691 | .Opaque, | 696 | .Opaque, |
| 692 | .Frame, | 697 | .Frame, |
| ... | @@ -723,6 +728,17 @@ pub const DeclGen = struct { | ... | @@ -723,6 +728,17 @@ pub const DeclGen = struct { |
| 723 | } | 728 | } |
| 724 | return llvm_int; | 729 | return llvm_int; |
| 725 | }, | 730 | }, |
| | 731 | .Enum => { |
| | 732 | const llvm_type = try self.llvmType(tv.ty); |
| | 733 | const uint: u64 = uint: { |
| | 734 | if (tv.val.castTag(.enum_field_index)) |payload| { |
| | 735 | break :uint payload.data; |
| | 736 | } |
| | 737 | break :uint tv.val.toUnsignedInt(); |
| | 738 | }; |
| | 739 | const llvm_int = llvm_type.constInt(uint, .False); |
| | 740 | return llvm_int; |
| | 741 | }, |
| 726 | .Float => { | 742 | .Float => { |
| 727 | if (tv.ty.floatBits(self.module.getTarget()) <= 64) { | 743 | if (tv.ty.floatBits(self.module.getTarget()) <= 64) { |
| 728 | const llvm_ty = try self.llvmType(tv.ty); | 744 | const llvm_ty = try self.llvmType(tv.ty); |
| ... | @@ -907,7 +923,18 @@ pub const DeclGen = struct { | ... | @@ -907,7 +923,18 @@ pub const DeclGen = struct { |
| 907 | .ComptimeFloat => unreachable, | 923 | .ComptimeFloat => unreachable, |
| 908 | .Type => unreachable, | 924 | .Type => unreachable, |
| 909 | .EnumLiteral => unreachable, | 925 | .EnumLiteral => unreachable, |
| 910 | else => return self.todo("implement const of type '{}'", .{tv.ty}), | 926 | .Void => unreachable, |
| | 927 | .NoReturn => unreachable, |
| | 928 | .Undefined => unreachable, |
| | 929 | .Null => unreachable, |
| | 930 | .BoundFn => unreachable, |
| | 931 | .Opaque => unreachable, |
| | 932 | |
| | 933 | .Union, |
| | 934 | .Frame, |
| | 935 | .AnyFrame, |
| | 936 | .Vector, |
| | 937 | => return self.todo("implement const of type '{}'", .{tv.ty}), |
| 911 | } | 938 | } |
| 912 | } | 939 | } |
| 913 | | 940 | |
| ... | @@ -1195,21 +1222,15 @@ pub const FuncGen = struct { | ... | @@ -1195,21 +1222,15 @@ pub const FuncGen = struct { |
| 1195 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 1222 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 1196 | const lhs = try self.resolveInst(bin_op.lhs); | 1223 | const lhs = try self.resolveInst(bin_op.lhs); |
| 1197 | const rhs = try self.resolveInst(bin_op.rhs); | 1224 | const rhs = try self.resolveInst(bin_op.rhs); |
| 1198 | const inst_ty = self.air.typeOfIndex(inst); | 1225 | const operand_ty = self.air.typeOf(bin_op.lhs); |
| 1199 | | 1226 | |
| 1200 | switch (self.air.typeOf(bin_op.lhs).zigTypeTag()) { | 1227 | const int_ty = switch (operand_ty.zigTypeTag()) { |
| 1201 | .Int, .Bool, .Pointer, .ErrorSet => { | 1228 | .Enum => blk: { |
| 1202 | const is_signed = inst_ty.isSignedInt(); | 1229 | var buffer: Type.Payload.Bits = undefined; |
| 1203 | const operation = switch (op) { | 1230 | const int_ty = operand_ty.enumTagType(&buffer); |
| 1204 | .eq => .EQ, | 1231 | break :blk int_ty; |
| 1205 | .neq => .NE, | | |
| 1206 | .lt => @as(llvm.IntPredicate, if (is_signed) .SLT else .ULT), | | |
| 1207 | .lte => @as(llvm.IntPredicate, if (is_signed) .SLE else .ULE), | | |
| 1208 | .gt => @as(llvm.IntPredicate, if (is_signed) .SGT else .UGT), | | |
| 1209 | .gte => @as(llvm.IntPredicate, if (is_signed) .SGE else .UGE), | | |
| 1210 | }; | | |
| 1211 | return self.builder.buildICmp(operation, lhs, rhs, ""); | | |
| 1212 | }, | 1232 | }, |
| | 1233 | .Int, .Bool, .Pointer, .ErrorSet => operand_ty, |
| 1213 | .Float => { | 1234 | .Float => { |
| 1214 | const operation: llvm.RealPredicate = switch (op) { | 1235 | const operation: llvm.RealPredicate = switch (op) { |
| 1215 | .eq => .OEQ, | 1236 | .eq => .OEQ, |
| ... | @@ -1222,7 +1243,17 @@ pub const FuncGen = struct { | ... | @@ -1222,7 +1243,17 @@ pub const FuncGen = struct { |
| 1222 | return self.builder.buildFCmp(operation, lhs, rhs, ""); | 1243 | return self.builder.buildFCmp(operation, lhs, rhs, ""); |
| 1223 | }, | 1244 | }, |
| 1224 | else => unreachable, | 1245 | else => unreachable, |
| 1225 | } | 1246 | }; |
| | 1247 | const is_signed = int_ty.isSignedInt(); |
| | 1248 | const operation = switch (op) { |
| | 1249 | .eq => .EQ, |
| | 1250 | .neq => .NE, |
| | 1251 | .lt => @as(llvm.IntPredicate, if (is_signed) .SLT else .ULT), |
| | 1252 | .lte => @as(llvm.IntPredicate, if (is_signed) .SLE else .ULE), |
| | 1253 | .gt => @as(llvm.IntPredicate, if (is_signed) .SGT else .UGT), |
| | 1254 | .gte => @as(llvm.IntPredicate, if (is_signed) .SGE else .UGE), |
| | 1255 | }; |
| | 1256 | return self.builder.buildICmp(operation, lhs, rhs, ""); |
| 1226 | } | 1257 | } |
| 1227 | | 1258 | |
| 1228 | fn airBlock(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { | 1259 | fn airBlock(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { |