╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ codegen.zig ──────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭ find file ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ ╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │ │ │http│ ssh │ │ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
1061 1062 .comptime_int => unreachable, 1063 .comptime_float => unreachable, 1064 .type => unreachable, 1065 .enum_literal => unreachable, 1066 .noreturn => unreachable, 1067 .undefined => unreachable, 1068 .null => unreachable, 1069 .@"opaque" => unreachable, 1070 1071 else => {}, 1072 } 1073 1074 return .{ .load_uav = .{ 1075 .val = val.toIntern(), 1076 .orig_ty = (try pt.singleConstPtrType(ty)).toIntern(), 1077 } }; 1078 } 1079 1080 pub fn errUnionPayloadOffset(payload_ty: Type, zcu: *Zcu) u64 { 1081 if (!payload_ty.hasRuntimeBits(zcu)) return 0; 1082 const payload_align = payload_ty.abiAlignment(zcu); 1083 const error_align = Type.anyerror.abiAlignment(zcu); 1084 if (payload_align.compare(.gte, error_align) or !payload_ty.hasRuntimeBits(zcu)) { 1085 return 0; 1086 } else { 1087 return payload_align.forward(Type.anyerror.abiSize(zcu)); 1088 } 1089 } 1090 1091 pub fn errUnionErrorOffset(payload_ty: Type, zcu: *Zcu) u64 { 1092 if (!payload_ty.hasRuntimeBits(zcu)) return 0; 1093 const payload_align = payload_ty.abiAlignment(zcu); 1094 const error_align = Type.anyerror.abiAlignment(zcu); 1095 if (payload_align.compare(.gte, error_align) and payload_ty.hasRuntimeBits(zcu)) { 1096 return error_align.forward(payload_ty.abiSize(zcu)); 1097 } else { 1098 return 0; 1099 } 1100 } 1101 1102 pub fn fieldOffset(ptr_agg_ty: Type, ptr_field_ty: Type, field_index: u32, zcu: *Zcu) u64 { 1103 const agg_ty = ptr_agg_ty.childType(zcu); 1104 return switch (agg_ty.containerLayout(zcu)) { 1105 .auto, .@"extern" => agg_ty.structFieldOffset(field_index, zcu), 1106 .@"packed" => @divExact(@as(u64, ptr_agg_ty.ptrInfo(zcu).packed_offset.bit_offset) + 1107 (if (zcu.typeToPackedStruct(agg_ty)) |loaded_struct| zcu.structPackedFieldBitOffset(loaded_struct, field_index) else 0) - 1108 ptr_field_ty.ptrInfo(zcu).packed_offset.bit_offset, 8), 1109 }; 1110 } 1111 1112 pub const FlattenedItem = struct { offset: u64, type: ?Type }; 1113 pub fn flattenType(items_buf: []FlattenedItem, ty: Type, zcu: *Zcu, opts: struct { 1114 offset: u64 = 0, 1115 allow_arrays: bool = true, 1116 fn increaseOffset(opts: @This(), offset: u64) @This() { 1117 return .{ 1118 .offset = opts.offset + offset, 1119 .allow_arrays = opts.allow_arrays, 1120 }; 1121 } 1122 }) ?[]FlattenedItem { 1123 const ip = &zcu.intern_pool; 1124 switch (ip.indexToKey(ty.toIntern())) { 1125 .int_type => |int_type| { 1126 if (int_type.bits == 0) return items_buf[0..0]; 1127 if (items_buf.len < 1) return null; 1128 const items = items_buf[0..1]; 1129 items.* = .{.{ .offset = opts.offset, .type = ty }}; 1130 return items; 1131 }, 1132 .ptr_type => |ptr_type| switch (ptr_type.flags.size) { 1133 .one, .many, .c => { 1134 if (items_buf.len < 1) return null; 1135 const items = items_buf[0..1]; 1136 items.* = .{.{ .offset = opts.offset, .type = ty }}; 1137 return items; 1138 }, 1139 .slice => { 1140 if (items_buf.len < 2) return null; 1141 const items = items_buf[0..2]; 1142 const ptr_field_ty = ty.slicePtrFieldType(zcu); 1143 items.* = .{ 1144 .{ .offset = opts.offset, .type = ptr_field_ty }, 1145 .{ .offset = opts.offset + ptr_field_ty.abiSize(zcu), .type = .usize }, 1146 }; 1147 return items; 1148 }, 1149 }, 1150 .array_type => |array_type| { 1151 const len = array_type.lenIncludingSentinel(); 1152 if (len == 0) return items_buf[0..0]; 1153 const elem_ty: Type = .fromInterned(array_type.child); 1154 const elem_items = flattenType(items_buf, elem_ty, zcu, opts) orelse return null; 1155 if (elem_items.len == 0) return items_buf[0..0]; 1156 if (!opts.allow_arrays) return null; 1157 const items_len, const items_overflow = @mulWithOverflow(elem_items.len, len); 1158 if (items_overflow != 0 or items_buf.len < items_len) return null; 1159 var items_index = elem_items.len; 1160 const elem_size = elem_ty.abiSize(zcu); 1161 var elem_offset: u64 = elem_size; 1162 while (items_index != items_len) : ({ 1163 items_index += elem_items.len; 1164 elem_offset += elem_size; 1165 }) for (items_buf[items_index..][0..elem_items.len], elem_items) |*item, elem_item| { 1166 item.* = .{ .offset = elem_offset + elem_item.offset, .type = elem_item.type }; 1167 }; 1168 return items_buf[0..@intCast(items_len)]; 1169 }, 1170 .vector_type => |vector_type| { 1171 if (vector_type.len == 0) return items_buf[0..0]; 1172 if (items_buf.len < 1) return null; 1173 const items = items_buf[0..1]; 1174 items.* = .{.{ .offset = opts.offset, .type = ty }}; 1175 return items; 1176 }, 1177 .opt_type, .error_union_type => return null, 1178 .simple_type => |simple_type| switch (simple_type) { 1179 .f16, 1180 .f32, 1181 .f64, 1182 .f80, 1183 .f128, 1184 .usize, 1185 .isize, 1186 .c_char, 1187 .c_short, 1188 .c_ushort, 1189 .c_int, 1190 .c_uint, 1191 .c_long, 1192 .c_ulong, 1193 .c_longlong, 1194 .c_ulonglong, 1195 .c_longdouble, 1196 .bool, 1197 .anyerror, 1198 => { 1199 if (items_buf.len < 1) return null; 1200 const items = items_buf[0..1]; 1201 items.* = .{.{ .offset = opts.offset, .type = ty }}; 1202 return items; 1203 }, 1204 .anyopaque, .noreturn => return null, 1205 .void, 1206 .type, 1207 .comptime_int, 1208 .comptime_float, 1209 .null, 1210 .undefined, 1211 .enum_literal, 1212 => return items_buf[0..0], 1213 .adhoc_inferred_error_set, .generic_poison => unreachable, 1214 }, 1215 .struct_type => { 1216 const loaded_struct = ip.loadStructType(ty.toIntern()); 1217 switch (loaded_struct.layout) { 1218 .auto, .@"extern" => {}, 1219 .@"packed" => return flattenType(items_buf, .fromInterned( 1220 loaded_struct.packed_backing_int_type, 1221 ), zcu, opts), 1222 } 1223 var items_len: usize = 0; 1224 var offset: u64 = 0; 1225 var field_it = loaded_struct.iterateRuntimeOrder(ip); 1226 while (field_it.next()) |field_index| { 1227 const field_ty: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); 1228 const field_offset = loaded_struct.field_offsets.get(ip)[field_index]; 1229 if (field_offset - offset > 0 and 1230 (items_len == 0 or items_buf[items_len - 1].type != null)) 1231 { 1232 if (items_len == items_buf.len) return null; 1233 items_buf[items_len] = .{ .offset = offset, .type = null }; 1234 items_len += 1; 1235 } 1236 items_len += (flattenType(items_buf[items_len..], field_ty, zcu, opts.increaseOffset( 1237 field_offset, 1238 )) orelse return null).len; 1239 offset = field_offset + field_ty.abiSize(zcu); 1240 } 1241 if (ty.abiSize(zcu) - offset > 0 and 1242 (items_len == 0 or items_buf[items_len - 1].type != null)) 1243 { 1244 if (items_len == items_buf.len) return null; 1245 items_buf[items_len] = .{ .offset = offset, .type = null }; 1246 items_len += 1; 1247 } 1248 return items_buf[0..items_len]; 1249 }, 1250 .tuple_type => |tuple_type| { 1251 if (items_buf.len < tuple_type.types.len) return null; 1252 var items_len: usize = 0; 1253 var offset: u64 = 0; 1254 for (tuple_type.types.get(ip)) |field_ty_ip| { 1255 const field_ty: Type = .fromInterned(field_ty_ip); 1256 offset = field_ty.abiAlignment(zcu).forward(offset); 1257 items_len += (flattenType(items_buf[items_len..], field_ty, zcu, opts.increaseOffset( 1258 offset, 1259 )) orelse return null).len; 1260 offset += field_ty.abiSize(zcu); 1261 } 1262 return items_buf[0..items_len]; 1263 }, 1264 .union_type => { 1265 const loaded_union = ip.loadUnionType(ty.toIntern()); 1266 return switch (loaded_union.layout) { 1267 .auto, .@"extern" => return null, 1268 .@"packed" => return flattenType(items_buf, .fromInterned( 1269 loaded_union.packed_backing_int_type, 1270 ), zcu, opts), 1271 }; 1272 }, 1273 .opaque_type, .spirv_type, .func_type => return null, 1274 .enum_type => return flattenType(items_buf, .fromInterned( 1275 ip.loadEnumType(ty.toIntern()).int_tag_type, 1276 ), zcu, opts), 1277 .error_set_type, .inferred_error_set_type => { 1278 if (items_buf.len < 1) return null; 1279 const items = items_buf[0..1]; 1280 items.* = .{.{ .offset = opts.offset, .type = ty }}; 1281 return items; 1282 }, 1283 .anyframe_type, 1284 // values, not types 1285 .undef, 1286 .simple_value, 1287 .@"extern", 1288 .func, 1289 .int, 1290 .err, 1291 .error_union, 1292 .enum_literal, 1293 .enum_tag, 1294 .float, 1295 .ptr, 1296 .slice, 1297 .opt, 1298 .aggregate, 1299 .un, 1300 .bitpack, 1301 // memoization, not types 1302 .memoized_call, 1303 => unreachable, 1304 } 1305 } 1306 1307 test { 1308 _ = aarch64; 1309 _ = loongarch; 1310 } 1311