| ... | @@ -274,6 +274,13 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { | ... | @@ -274,6 +274,13 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { |
| 274 | .storage_class = storage_class, | 274 | .storage_class = storage_class, |
| 275 | }); | 275 | }); |
| 276 | | 276 | |
| | 277 | if (nav.getAlignment() != ty.abiAlignment(zcu)) { |
| | 278 | if (target.os.tag != .opencl) return cg.fail("cannot apply alignment to variables", .{}); |
| | 279 | try cg.module.decorate(result_id, .{ |
| | 280 | .alignment = .{ .alignment = @intCast(nav.getAlignment().toByteUnits().?) }, |
| | 281 | }); |
| | 282 | } |
| | 283 | |
| 277 | switch (target.os.tag) { | 284 | switch (target.os.tag) { |
| 278 | .vulkan, .opengl => { | 285 | .vulkan, .opengl => { |
| 279 | if (ty.zigTypeTag(zcu) == .@"struct") { | 286 | if (ty.zigTypeTag(zcu) == .@"struct") { |
| ... | @@ -348,7 +355,7 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { | ... | @@ -348,7 +355,7 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { |
| 348 | .id_result_type = ptr_ty_id, | 355 | .id_result_type = ptr_ty_id, |
| 349 | .id_result = result_id, | 356 | .id_result = result_id, |
| 350 | .set = try cg.module.importInstructionSet(.zig), | 357 | .set = try cg.module.importInstructionSet(.zig), |
| 351 | .instruction = .{ .inst = 0 }, // TODO: Put this definition somewhere... | 358 | .instruction = .{ .inst = @intFromEnum(spec.Zig.InvocationGlobal) }, |
| 352 | .id_ref_4 = &.{initializer_id}, | 359 | .id_ref_4 = &.{initializer_id}, |
| 353 | }); | 360 | }); |
| 354 | } else { | 361 | } else { |
| ... | @@ -356,7 +363,7 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { | ... | @@ -356,7 +363,7 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { |
| 356 | .id_result_type = ptr_ty_id, | 363 | .id_result_type = ptr_ty_id, |
| 357 | .id_result = result_id, | 364 | .id_result = result_id, |
| 358 | .set = try cg.module.importInstructionSet(.zig), | 365 | .set = try cg.module.importInstructionSet(.zig), |
| 359 | .instruction = .{ .inst = 0 }, // TODO: Put this definition somewhere... | 366 | .instruction = .{ .inst = @intFromEnum(spec.Zig.InvocationGlobal) }, |
| 360 | .id_ref_4 = &.{}, | 367 | .id_ref_4 = &.{}, |
| 361 | }); | 368 | }); |
| 362 | } | 369 | } |
| ... | @@ -498,7 +505,7 @@ fn resolveUav(cg: *CodeGen, val: InternPool.Index) !Id { | ... | @@ -498,7 +505,7 @@ fn resolveUav(cg: *CodeGen, val: InternPool.Index) !Id { |
| 498 | .id_result_type = fn_decl_ptr_ty_id, | 505 | .id_result_type = fn_decl_ptr_ty_id, |
| 499 | .id_result = result_id, | 506 | .id_result = result_id, |
| 500 | .set = try cg.module.importInstructionSet(.zig), | 507 | .set = try cg.module.importInstructionSet(.zig), |
| 501 | .instruction = .{ .inst = 0 }, // TODO: Put this definition somewhere... | 508 | .instruction = .{ .inst = @intFromEnum(spec.Zig.InvocationGlobal) }, |
| 502 | .id_ref_4 = &.{initializer_id}, | 509 | .id_ref_4 = &.{initializer_id}, |
| 503 | }); | 510 | }); |
| 504 | } | 511 | } |
| ... | @@ -1037,9 +1044,18 @@ fn derivePtr(cg: *CodeGen, derivation: Value.PointerDeriveStep) !Id { | ... | @@ -1037,9 +1044,18 @@ fn derivePtr(cg: *CodeGen, derivation: Value.PointerDeriveStep) !Id { |
| 1037 | const gpa = cg.module.gpa; | 1044 | const gpa = cg.module.gpa; |
| 1038 | const pt = cg.pt; | 1045 | const pt = cg.pt; |
| 1039 | const zcu = cg.module.zcu; | 1046 | const zcu = cg.module.zcu; |
| | 1047 | const target = zcu.getTarget(); |
| 1040 | switch (derivation) { | 1048 | switch (derivation) { |
| 1041 | .comptime_alloc_ptr, .comptime_field_ptr => unreachable, | 1049 | .comptime_alloc_ptr, .comptime_field_ptr => unreachable, |
| 1042 | .int => |int| { | 1050 | .int => |int| { |
| | 1051 | if (target.os.tag != .opencl) { |
| | 1052 | if (int.ptr_ty.ptrAddressSpace(zcu) != .physical_storage_buffer) { |
| | 1053 | return cg.fail( |
| | 1054 | "cannot cast integer to pointer with address space '{s}'", |
| | 1055 | .{@tagName(int.ptr_ty.ptrAddressSpace(zcu))}, |
| | 1056 | ); |
| | 1057 | } |
| | 1058 | } |
| 1043 | const result_ty_id = try cg.resolveType(int.ptr_ty, .direct); | 1059 | const result_ty_id = try cg.resolveType(int.ptr_ty, .direct); |
| 1044 | // TODO: This can probably be an OpSpecConstantOp Bitcast, but | 1060 | // TODO: This can probably be an OpSpecConstantOp Bitcast, but |
| 1045 | // that is not implemented by Mesa yet. Therefore, just generate it | 1061 | // that is not implemented by Mesa yet. Therefore, just generate it |
| ... | @@ -1137,7 +1153,7 @@ fn constantUavRef( | ... | @@ -1137,7 +1153,7 @@ fn constantUavRef( |
| 1137 | // Uav refs are always generic. | 1153 | // Uav refs are always generic. |
| 1138 | assert(ty.ptrAddressSpace(zcu) == .generic); | 1154 | assert(ty.ptrAddressSpace(zcu) == .generic); |
| 1139 | const uav_ty_id = try cg.resolveType(uav_ty, .indirect); | 1155 | const uav_ty_id = try cg.resolveType(uav_ty, .indirect); |
| 1140 | const decl_ptr_ty_id = try cg.module.ptrType(uav_ty_id, .generic); | 1156 | const decl_ptr_ty_id = try cg.module.ptrType(uav_ty_id, .function); |
| 1141 | const ptr_id = try cg.resolveUav(uav.val); | 1157 | const ptr_id = try cg.resolveUav(uav.val); |
| 1142 | | 1158 | |
| 1143 | if (decl_ptr_ty_id != ty_id) { | 1159 | if (decl_ptr_ty_id != ty_id) { |
| ... | @@ -1327,7 +1343,10 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { | ... | @@ -1327,7 +1343,10 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { |
| 1327 | }, | 1343 | }, |
| 1328 | .void => switch (repr) { | 1344 | .void => switch (repr) { |
| 1329 | .direct => return try cg.module.voidType(), | 1345 | .direct => return try cg.module.voidType(), |
| 1330 | .indirect => return try cg.module.opaqueType("void"), | 1346 | .indirect => { |
| | 1347 | if (target.os.tag != .opencl) return cg.fail("cannot generate opaque type", .{}); |
| | 1348 | return try cg.module.opaqueType("void"); |
| | 1349 | }, |
| 1331 | }, | 1350 | }, |
| 1332 | .bool => switch (repr) { | 1351 | .bool => switch (repr) { |
| 1333 | .direct => return try cg.module.boolType(), | 1352 | .direct => return try cg.module.boolType(), |
| ... | @@ -1337,6 +1356,7 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { | ... | @@ -1337,6 +1356,7 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { |
| 1337 | const int_info = ty.intInfo(zcu); | 1356 | const int_info = ty.intInfo(zcu); |
| 1338 | if (int_info.bits == 0) { | 1357 | if (int_info.bits == 0) { |
| 1339 | assert(repr == .indirect); | 1358 | assert(repr == .indirect); |
| | 1359 | if (target.os.tag != .opencl) return cg.fail("cannot generate opaque type", .{}); |
| 1340 | return try cg.module.opaqueType("u0"); | 1360 | return try cg.module.opaqueType("u0"); |
| 1341 | } | 1361 | } |
| 1342 | return try cg.module.intType(int_info.signedness, int_info.bits); | 1362 | return try cg.module.intType(int_info.signedness, int_info.bits); |
| ... | @@ -1369,6 +1389,7 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { | ... | @@ -1369,6 +1389,7 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { |
| 1369 | | 1389 | |
| 1370 | if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | 1390 | if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) { |
| 1371 | assert(repr == .indirect); | 1391 | assert(repr == .indirect); |
| | 1392 | if (target.os.tag != .opencl) return cg.fail("cannot generate opaque type", .{}); |
| 1372 | return try cg.module.opaqueType("zero-sized-array"); | 1393 | return try cg.module.opaqueType("zero-sized-array"); |
| 1373 | } else if (total_len == 0) { | 1394 | } else if (total_len == 0) { |
| 1374 | // The size of the array would be 0, but that is not allowed in SPIR-V. | 1395 | // The size of the array would be 0, but that is not allowed in SPIR-V. |
| ... | @@ -1590,6 +1611,7 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { | ... | @@ -1590,6 +1611,7 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { |
| 1590 | return try cg.module.structType(&member_types, &member_names, null, .none); | 1611 | return try cg.module.structType(&member_types, &member_names, null, .none); |
| 1591 | }, | 1612 | }, |
| 1592 | .@"opaque" => { | 1613 | .@"opaque" => { |
| | 1614 | if (target.os.tag != .opencl) return cg.fail("cannot generate opaque type", .{}); |
| 1593 | const type_name = try cg.resolveTypeName(ty); | 1615 | const type_name = try cg.resolveTypeName(ty); |
| 1594 | defer gpa.free(type_name); | 1616 | defer gpa.free(type_name); |
| 1595 | return try cg.module.opaqueType(type_name); | 1617 | return try cg.module.opaqueType(type_name); |
| ... | @@ -2510,11 +2532,7 @@ fn generateTestEntryPoint( | ... | @@ -2510,11 +2532,7 @@ fn generateTestEntryPoint( |
| 2510 | try cg.module.declareEntryPoint(spv_decl_index, test_name, execution_mode, null); | 2532 | try cg.module.declareEntryPoint(spv_decl_index, test_name, execution_mode, null); |
| 2511 | } | 2533 | } |
| 2512 | | 2534 | |
| 2513 | fn intFromBool(cg: *CodeGen, value: Temporary) !Temporary { | 2535 | fn intFromBool(cg: *CodeGen, value: Temporary, result_ty: Type) !Temporary { |
| 2514 | return try cg.intFromBool2(value, Type.u1); | | |
| 2515 | } | | |
| 2516 | | | |
| 2517 | fn intFromBool2(cg: *CodeGen, value: Temporary, result_ty: Type) !Temporary { | | |
| 2518 | const zero_id = try cg.constInt(result_ty, 0); | 2536 | const zero_id = try cg.constInt(result_ty, 0); |
| 2519 | const one_id = try cg.constInt(result_ty, 1); | 2537 | const one_id = try cg.constInt(result_ty, 1); |
| 2520 | | 2538 | |
| ... | @@ -2558,7 +2576,7 @@ fn convertToIndirect(cg: *CodeGen, ty: Type, operand_id: Id) !Id { | ... | @@ -2558,7 +2576,7 @@ fn convertToIndirect(cg: *CodeGen, ty: Type, operand_id: Id) !Id { |
| 2558 | const zcu = cg.module.zcu; | 2576 | const zcu = cg.module.zcu; |
| 2559 | switch (ty.scalarType(zcu).zigTypeTag(zcu)) { | 2577 | switch (ty.scalarType(zcu).zigTypeTag(zcu)) { |
| 2560 | .bool => { | 2578 | .bool => { |
| 2561 | const result = try cg.intFromBool(Temporary.init(ty, operand_id)); | 2579 | const result = try cg.intFromBool(.init(ty, operand_id), .u1); |
| 2562 | return try result.materialize(cg); | 2580 | return try result.materialize(cg); |
| 2563 | }, | 2581 | }, |
| 2564 | else => return operand_id, | 2582 | else => return operand_id, |
| ... | @@ -2958,7 +2976,7 @@ fn normalize(cg: *CodeGen, value: Temporary, info: ArithmeticTypeInfo) !Temporar | ... | @@ -2958,7 +2976,7 @@ fn normalize(cg: *CodeGen, value: Temporary, info: ArithmeticTypeInfo) !Temporar |
| 2958 | .composite_integer, .integer, .bool, .float => return value, | 2976 | .composite_integer, .integer, .bool, .float => return value, |
| 2959 | .strange_integer => switch (info.signedness) { | 2977 | .strange_integer => switch (info.signedness) { |
| 2960 | .unsigned => { | 2978 | .unsigned => { |
| 2961 | const mask_value = if (info.bits == 64) 0xFFFF_FFFF_FFFF_FFFF else (@as(u64, 1) << @as(u6, @intCast(info.bits))) - 1; | 2979 | const mask_value = @as(u64, std.math.maxInt(u64)) >> @as(u6, @intCast(64 - info.bits)); |
| 2962 | const mask_id = try cg.constInt(ty.scalarType(zcu), mask_value); | 2980 | const mask_id = try cg.constInt(ty.scalarType(zcu), mask_value); |
| 2963 | return try cg.buildBinary(.OpBitwiseAnd, value, Temporary.init(ty.scalarType(zcu), mask_id)); | 2981 | return try cg.buildBinary(.OpBitwiseAnd, value, Temporary.init(ty.scalarType(zcu), mask_id)); |
| 2964 | }, | 2982 | }, |
| ... | @@ -2997,28 +3015,12 @@ fn airDivFloor(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -2997,28 +3015,12 @@ fn airDivFloor(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 2997 | | 3015 | |
| 2998 | const div = try cg.buildBinary(.OpSDiv, lhs, rhs); | 3016 | const div = try cg.buildBinary(.OpSDiv, lhs, rhs); |
| 2999 | const rem = try cg.buildBinary(.OpSRem, lhs, rhs); | 3017 | const rem = try cg.buildBinary(.OpSRem, lhs, rhs); |
| 3000 | | | |
| 3001 | const zero: Temporary = .init(lhs.ty, try cg.constInt(lhs.ty, 0)); | 3018 | const zero: Temporary = .init(lhs.ty, try cg.constInt(lhs.ty, 0)); |
| 3002 | | 3019 | const rem_non_zero = try cg.buildCmp(.OpINotEqual, rem, zero); |
| 3003 | const rem_is_not_zero = try cg.buildCmp(.OpINotEqual, rem, zero); | 3020 | const lhs_rhs_xor = try cg.buildBinary(.OpBitwiseXor, lhs, rhs); |
| 3004 | | 3021 | const signs_differ = try cg.buildCmp(.OpSLessThan, lhs_rhs_xor, zero); |
| 3005 | const result_negative = try cg.buildCmp( | 3022 | const adjust = try cg.buildBinary(.OpLogicalAnd, rem_non_zero, signs_differ); |
| 3006 | .OpLogicalNotEqual, | 3023 | const result = try cg.buildBinary(.OpISub, div, try cg.intFromBool(adjust, div.ty)); |
| 3007 | try cg.buildCmp(.OpSLessThan, lhs, zero), | | |
| 3008 | try cg.buildCmp(.OpSLessThan, rhs, zero), | | |
| 3009 | ); | | |
| 3010 | const rem_is_not_zero_and_result_is_negative = try cg.buildBinary( | | |
| 3011 | .OpLogicalAnd, | | |
| 3012 | rem_is_not_zero, | | |
| 3013 | result_negative, | | |
| 3014 | ); | | |
| 3015 | | | |
| 3016 | const result = try cg.buildBinary( | | |
| 3017 | .OpISub, | | |
| 3018 | div, | | |
| 3019 | try cg.intFromBool2(rem_is_not_zero_and_result_is_negative, div.ty), | | |
| 3020 | ); | | |
| 3021 | | | |
| 3022 | return try result.materialize(cg); | 3024 | return try result.materialize(cg); |
| 3023 | }, | 3025 | }, |
| 3024 | .float => { | 3026 | .float => { |
| ... | @@ -3032,10 +3034,8 @@ fn airDivFloor(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -3032,10 +3034,8 @@ fn airDivFloor(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 3032 | | 3034 | |
| 3033 | fn airDivTrunc(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | 3035 | fn airDivTrunc(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 3034 | const bin_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | 3036 | const bin_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 3035 | | | |
| 3036 | const lhs = try cg.temporary(bin_op.lhs); | 3037 | const lhs = try cg.temporary(bin_op.lhs); |
| 3037 | const rhs = try cg.temporary(bin_op.rhs); | 3038 | const rhs = try cg.temporary(bin_op.rhs); |
| 3038 | | | |
| 3039 | const info = cg.arithmeticTypeInfo(lhs.ty); | 3039 | const info = cg.arithmeticTypeInfo(lhs.ty); |
| 3040 | switch (info.class) { | 3040 | switch (info.class) { |
| 3041 | .composite_integer => unreachable, // TODO | 3041 | .composite_integer => unreachable, // TODO |
| ... | @@ -3073,12 +3073,9 @@ fn airArithOp( | ... | @@ -3073,12 +3073,9 @@ fn airArithOp( |
| 3073 | comptime uop: Opcode, | 3073 | comptime uop: Opcode, |
| 3074 | ) !?Id { | 3074 | ) !?Id { |
| 3075 | const bin_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | 3075 | const bin_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 3076 | | | |
| 3077 | const lhs = try cg.temporary(bin_op.lhs); | 3076 | const lhs = try cg.temporary(bin_op.lhs); |
| 3078 | const rhs = try cg.temporary(bin_op.rhs); | 3077 | const rhs = try cg.temporary(bin_op.rhs); |
| 3079 | | | |
| 3080 | const info = cg.arithmeticTypeInfo(lhs.ty); | 3078 | const info = cg.arithmeticTypeInfo(lhs.ty); |
| 3081 | | | |
| 3082 | const result = switch (info.class) { | 3079 | const result = switch (info.class) { |
| 3083 | .composite_integer => unreachable, // TODO | 3080 | .composite_integer => unreachable, // TODO |
| 3084 | .integer, .strange_integer => switch (info.signedness) { | 3081 | .integer, .strange_integer => switch (info.signedness) { |
| ... | @@ -3088,7 +3085,6 @@ fn airArithOp( | ... | @@ -3088,7 +3085,6 @@ fn airArithOp( |
| 3088 | .float => try cg.buildBinary(fop, lhs, rhs), | 3085 | .float => try cg.buildBinary(fop, lhs, rhs), |
| 3089 | .bool => unreachable, | 3086 | .bool => unreachable, |
| 3090 | }; | 3087 | }; |
| 3091 | | | |
| 3092 | return try result.materialize(cg); | 3088 | return try result.materialize(cg); |
| 3093 | } | 3089 | } |
| 3094 | | 3090 | |
| ... | @@ -3105,12 +3101,10 @@ fn abs(cg: *CodeGen, result_ty: Type, value: Temporary) !Temporary { | ... | @@ -3105,12 +3101,10 @@ fn abs(cg: *CodeGen, result_ty: Type, value: Temporary) !Temporary { |
| 3105 | const zcu = cg.module.zcu; | 3101 | const zcu = cg.module.zcu; |
| 3106 | const target = cg.module.zcu.getTarget(); | 3102 | const target = cg.module.zcu.getTarget(); |
| 3107 | const operand_info = cg.arithmeticTypeInfo(value.ty); | 3103 | const operand_info = cg.arithmeticTypeInfo(value.ty); |
| 3108 | | | |
| 3109 | switch (operand_info.class) { | 3104 | switch (operand_info.class) { |
| 3110 | .float => return try cg.buildUnary(.f_abs, value), | 3105 | .float => return try cg.buildUnary(.f_abs, value), |
| 3111 | .integer, .strange_integer => { | 3106 | .integer, .strange_integer => { |
| 3112 | const abs_value = try cg.buildUnary(.i_abs, value); | 3107 | const abs_value = try cg.buildUnary(.i_abs, value); |
| 3113 | | | |
| 3114 | switch (target.os.tag) { | 3108 | switch (target.os.tag) { |
| 3115 | .vulkan, .opengl => { | 3109 | .vulkan, .opengl => { |
| 3116 | if (value.ty.intInfo(zcu).signedness == .signed) { | 3110 | if (value.ty.intInfo(zcu).signedness == .signed) { |
| ... | @@ -3119,7 +3113,6 @@ fn abs(cg: *CodeGen, result_ty: Type, value: Temporary) !Temporary { | ... | @@ -3119,7 +3113,6 @@ fn abs(cg: *CodeGen, result_ty: Type, value: Temporary) !Temporary { |
| 3119 | }, | 3113 | }, |
| 3120 | else => {}, | 3114 | else => {}, |
| 3121 | } | 3115 | } |
| 3122 | | | |
| 3123 | return try cg.normalize(abs_value, cg.arithmeticTypeInfo(result_ty)); | 3116 | return try cg.normalize(abs_value, cg.arithmeticTypeInfo(result_ty)); |
| 3124 | }, | 3117 | }, |
| 3125 | .composite_integer => unreachable, // TODO | 3118 | .composite_integer => unreachable, // TODO |
| ... | @@ -3134,19 +3127,18 @@ fn airAddSubOverflow( | ... | @@ -3134,19 +3127,18 @@ fn airAddSubOverflow( |
| 3134 | u_opcode: Opcode, | 3127 | u_opcode: Opcode, |
| 3135 | s_opcode: Opcode, | 3128 | s_opcode: Opcode, |
| 3136 | ) !?Id { | 3129 | ) !?Id { |
| 3137 | _ = s_opcode; | | |
| 3138 | // Note: OpIAddCarry and OpISubBorrow are not really useful here: For unsigned numbers, | 3130 | // Note: OpIAddCarry and OpISubBorrow are not really useful here: For unsigned numbers, |
| 3139 | // there is in both cases only one extra operation required. For signed operations, | 3131 | // there is in both cases only one extra operation required. For signed operations, |
| 3140 | // the overflow bit is set then going from 0x80.. to 0x00.., but this doesn't actually | 3132 | // the overflow bit is set then going from 0x80.. to 0x00.., but this doesn't actually |
| 3141 | // normally set a carry bit. So the SPIR-V overflow operations are not particularly | 3133 | // normally set a carry bit. So the SPIR-V overflow operations are not particularly |
| 3142 | // useful here. | 3134 | // useful here. |
| 3143 | | 3135 | |
| | 3136 | _ = s_opcode; |
| | 3137 | |
| 3144 | const ty_pl = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | 3138 | const ty_pl = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 3145 | const extra = cg.air.extraData(Air.Bin, ty_pl.payload).data; | 3139 | const extra = cg.air.extraData(Air.Bin, ty_pl.payload).data; |
| 3146 | | | |
| 3147 | const lhs = try cg.temporary(extra.lhs); | 3140 | const lhs = try cg.temporary(extra.lhs); |
| 3148 | const rhs = try cg.temporary(extra.rhs); | 3141 | const rhs = try cg.temporary(extra.rhs); |
| 3149 | | | |
| 3150 | const result_ty = cg.typeOfIndex(inst); | 3142 | const result_ty = cg.typeOfIndex(inst); |
| 3151 | | 3143 | |
| 3152 | const info = cg.arithmeticTypeInfo(lhs.ty); | 3144 | const info = cg.arithmeticTypeInfo(lhs.ty); |
| ... | @@ -3158,7 +3150,6 @@ fn airAddSubOverflow( | ... | @@ -3158,7 +3150,6 @@ fn airAddSubOverflow( |
| 3158 | | 3150 | |
| 3159 | const sum = try cg.buildBinary(add, lhs, rhs); | 3151 | const sum = try cg.buildBinary(add, lhs, rhs); |
| 3160 | const result = try cg.normalize(sum, info); | 3152 | const result = try cg.normalize(sum, info); |
| 3161 | | | |
| 3162 | const overflowed = switch (info.signedness) { | 3153 | const overflowed = switch (info.signedness) { |
| 3163 | // Overflow happened if the result is smaller than either of the operands. It doesn't matter which. | 3154 | // Overflow happened if the result is smaller than either of the operands. It doesn't matter which. |
| 3164 | // For subtraction the conditions need to be swapped. | 3155 | // For subtraction the conditions need to be swapped. |
| ... | @@ -3173,38 +3164,31 @@ fn airAddSubOverflow( | ... | @@ -3173,38 +3164,31 @@ fn airAddSubOverflow( |
| 3173 | // and the result's sign is different from the minuend's (a's) sign. | 3164 | // and the result's sign is different from the minuend's (a's) sign. |
| 3174 | // (sign(a) != sign(b)) && (sign(a) != sign(result)) | 3165 | // (sign(a) != sign(b)) && (sign(a) != sign(result)) |
| 3175 | const zero: Temporary = .init(rhs.ty, try cg.constInt(rhs.ty, 0)); | 3166 | const zero: Temporary = .init(rhs.ty, try cg.constInt(rhs.ty, 0)); |
| 3176 | | | |
| 3177 | const lhs_is_neg = try cg.buildCmp(.OpSLessThan, lhs, zero); | 3167 | const lhs_is_neg = try cg.buildCmp(.OpSLessThan, lhs, zero); |
| 3178 | const rhs_is_neg = try cg.buildCmp(.OpSLessThan, rhs, zero); | 3168 | const rhs_is_neg = try cg.buildCmp(.OpSLessThan, rhs, zero); |
| 3179 | const result_is_neg = try cg.buildCmp(.OpSLessThan, result, zero); | 3169 | const result_is_neg = try cg.buildCmp(.OpSLessThan, result, zero); |
| 3180 | | | |
| 3181 | const signs_match = try cg.buildCmp(.OpLogicalEqual, lhs_is_neg, rhs_is_neg); | 3170 | const signs_match = try cg.buildCmp(.OpLogicalEqual, lhs_is_neg, rhs_is_neg); |
| 3182 | const result_sign_differs = try cg.buildCmp(.OpLogicalNotEqual, lhs_is_neg, result_is_neg); | 3171 | const result_sign_differs = try cg.buildCmp(.OpLogicalNotEqual, lhs_is_neg, result_is_neg); |
| 3183 | | 3172 | const overflow_condition = switch (add) { |
| 3184 | const overflow_condition = if (add == .OpIAdd) | 3173 | .OpIAdd => signs_match, |
| 3185 | signs_match | 3174 | .OpISub => try cg.buildUnary(.l_not, signs_match), |
| 3186 | else // .OpISub | 3175 | else => unreachable, |
| 3187 | try cg.buildUnary(.l_not, signs_match); | 3176 | }; |
| 3188 | | | |
| 3189 | break :blk try cg.buildCmp(.OpLogicalAnd, overflow_condition, result_sign_differs); | 3177 | break :blk try cg.buildCmp(.OpLogicalAnd, overflow_condition, result_sign_differs); |
| 3190 | }, | 3178 | }, |
| 3191 | }; | 3179 | }; |
| 3192 | | 3180 | |
| 3193 | const ov = try cg.intFromBool(overflowed); | 3181 | const ov = try cg.intFromBool(overflowed, .u1); |
| 3194 | | | |
| 3195 | const result_ty_id = try cg.resolveType(result_ty, .direct); | 3182 | const result_ty_id = try cg.resolveType(result_ty, .direct); |
| 3196 | return try cg.constructComposite(result_ty_id, &.{ try result.materialize(cg), try ov.materialize(cg) }); | 3183 | return try cg.constructComposite(result_ty_id, &.{ try result.materialize(cg), try ov.materialize(cg) }); |
| 3197 | } | 3184 | } |
| 3198 | | 3185 | |
| 3199 | fn airMulOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | 3186 | fn airMulOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 3200 | const pt = cg.pt; | 3187 | const pt = cg.pt; |
| 3201 | | | |
| 3202 | const ty_pl = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | 3188 | const ty_pl = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 3203 | const extra = cg.air.extraData(Air.Bin, ty_pl.payload).data; | 3189 | const extra = cg.air.extraData(Air.Bin, ty_pl.payload).data; |
| 3204 | | | |
| 3205 | const lhs = try cg.temporary(extra.lhs); | 3190 | const lhs = try cg.temporary(extra.lhs); |
| 3206 | const rhs = try cg.temporary(extra.rhs); | 3191 | const rhs = try cg.temporary(extra.rhs); |
| 3207 | | | |
| 3208 | const result_ty = cg.typeOfIndex(inst); | 3192 | const result_ty = cg.typeOfIndex(inst); |
| 3209 | | 3193 | |
| 3210 | const info = cg.arithmeticTypeInfo(lhs.ty); | 3194 | const info = cg.arithmeticTypeInfo(lhs.ty); |
| ... | @@ -3237,20 +3221,15 @@ fn airMulOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -3237,20 +3221,15 @@ fn airMulOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 3237 | const op_ty = try pt.intType(.unsigned, op_ty_bits); | 3221 | const op_ty = try pt.intType(.unsigned, op_ty_bits); |
| 3238 | const casted_lhs = try cg.buildConvert(op_ty, lhs); | 3222 | const casted_lhs = try cg.buildConvert(op_ty, lhs); |
| 3239 | const casted_rhs = try cg.buildConvert(op_ty, rhs); | 3223 | const casted_rhs = try cg.buildConvert(op_ty, rhs); |
| 3240 | | | |
| 3241 | const full_result = try cg.buildBinary(.OpIMul, casted_lhs, casted_rhs); | 3224 | const full_result = try cg.buildBinary(.OpIMul, casted_lhs, casted_rhs); |
| 3242 | | | |
| 3243 | const low_bits = try cg.buildConvert(lhs.ty, full_result); | 3225 | const low_bits = try cg.buildConvert(lhs.ty, full_result); |
| 3244 | const result = try cg.normalize(low_bits, info); | 3226 | const result = try cg.normalize(low_bits, info); |
| 3245 | | | |
| 3246 | // Shift the result bits away to get the overflow bits. | 3227 | // Shift the result bits away to get the overflow bits. |
| 3247 | const shift: Temporary = .init(full_result.ty, try cg.constInt(full_result.ty, info.bits)); | 3228 | const shift: Temporary = .init(full_result.ty, try cg.constInt(full_result.ty, info.bits)); |
| 3248 | const overflow = try cg.buildBinary(.OpShiftRightLogical, full_result, shift); | 3229 | const overflow = try cg.buildBinary(.OpShiftRightLogical, full_result, shift); |
| 3249 | | | |
| 3250 | // Directly check if its zero in the op_ty without converting first. | 3230 | // Directly check if its zero in the op_ty without converting first. |
| 3251 | const zero: Temporary = .init(full_result.ty, try cg.constInt(full_result.ty, 0)); | 3231 | const zero: Temporary = .init(full_result.ty, try cg.constInt(full_result.ty, 0)); |
| 3252 | const overflowed = try cg.buildCmp(.OpINotEqual, zero, overflow); | 3232 | const overflowed = try cg.buildCmp(.OpINotEqual, zero, overflow); |
| 3253 | | | |
| 3254 | break :blk .{ result, overflowed }; | 3233 | break :blk .{ result, overflowed }; |
| 3255 | } | 3234 | } |
| 3256 | | 3235 | |
| ... | @@ -3362,7 +3341,7 @@ fn airMulOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -3362,7 +3341,7 @@ fn airMulOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 3362 | }, | 3341 | }, |
| 3363 | }; | 3342 | }; |
| 3364 | | 3343 | |
| 3365 | const ov = try cg.intFromBool(overflowed); | 3344 | const ov = try cg.intFromBool(overflowed, .u1); |
| 3366 | | 3345 | |
| 3367 | const result_ty_id = try cg.resolveType(result_ty, .direct); | 3346 | const result_ty_id = try cg.resolveType(result_ty, .direct); |
| 3368 | return try cg.constructComposite(result_ty_id, &.{ try result.materialize(cg), try ov.materialize(cg) }); | 3347 | return try cg.constructComposite(result_ty_id, &.{ try result.materialize(cg), try ov.materialize(cg) }); |
| ... | @@ -3403,7 +3382,7 @@ fn airShlOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -3403,7 +3382,7 @@ fn airShlOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 3403 | }; | 3382 | }; |
| 3404 | | 3383 | |
| 3405 | const overflowed = try cg.buildCmp(.OpINotEqual, base, right); | 3384 | const overflowed = try cg.buildCmp(.OpINotEqual, base, right); |
| 3406 | const ov = try cg.intFromBool(overflowed); | 3385 | const ov = try cg.intFromBool(overflowed, .u1); |
| 3407 | | 3386 | |
| 3408 | const result_ty_id = try cg.resolveType(result_ty, .direct); | 3387 | const result_ty_id = try cg.resolveType(result_ty, .direct); |
| 3409 | return try cg.constructComposite(result_ty_id, &.{ try result.materialize(cg), try ov.materialize(cg) }); | 3388 | return try cg.constructComposite(result_ty_id, &.{ try result.materialize(cg), try ov.materialize(cg) }); |
| ... | @@ -3931,6 +3910,7 @@ fn bitCast( | ... | @@ -3931,6 +3910,7 @@ fn bitCast( |
| 3931 | ) !Id { | 3910 | ) !Id { |
| 3932 | const gpa = cg.module.gpa; | 3911 | const gpa = cg.module.gpa; |
| 3933 | const zcu = cg.module.zcu; | 3912 | const zcu = cg.module.zcu; |
| | 3913 | const target = zcu.getTarget(); |
| 3934 | const src_ty_id = try cg.resolveType(src_ty, .direct); | 3914 | const src_ty_id = try cg.resolveType(src_ty, .direct); |
| 3935 | const dst_ty_id = try cg.resolveType(dst_ty, .direct); | 3915 | const dst_ty_id = try cg.resolveType(dst_ty, .direct); |
| 3936 | | 3916 | |
| ... | @@ -3941,6 +3921,15 @@ fn bitCast( | ... | @@ -3941,6 +3921,15 @@ fn bitCast( |
| 3941 | // See fn bitCast in llvm.zig | 3921 | // See fn bitCast in llvm.zig |
| 3942 | | 3922 | |
| 3943 | if (src_ty.zigTypeTag(zcu) == .int and dst_ty.isPtrAtRuntime(zcu)) { | 3923 | if (src_ty.zigTypeTag(zcu) == .int and dst_ty.isPtrAtRuntime(zcu)) { |
| | 3924 | if (target.os.tag != .opencl) { |
| | 3925 | if (dst_ty.ptrAddressSpace(zcu) != .physical_storage_buffer) { |
| | 3926 | return cg.fail( |
| | 3927 | "cannot cast integer to pointer with address space '{s}'", |
| | 3928 | .{@tagName(dst_ty.ptrAddressSpace(zcu))}, |
| | 3929 | ); |
| | 3930 | } |
| | 3931 | } |
| | 3932 | |
| 3944 | const result_id = cg.module.allocId(); | 3933 | const result_id = cg.module.allocId(); |
| 3945 | try cg.body.emit(gpa, .OpConvertUToPtr, .{ | 3934 | try cg.body.emit(gpa, .OpConvertUToPtr, .{ |
| 3946 | .id_result_type = dst_ty_id, | 3935 | .id_result_type = dst_ty_id, |
| ... | @@ -3967,7 +3956,8 @@ fn bitCast( | ... | @@ -3967,7 +3956,8 @@ fn bitCast( |
| 3967 | | 3956 | |
| 3968 | const dst_ptr_ty_id = try cg.module.ptrType(dst_ty_id, .function); | 3957 | const dst_ptr_ty_id = try cg.module.ptrType(dst_ty_id, .function); |
| 3969 | | 3958 | |
| 3970 | const tmp_id = try cg.alloc(src_ty, .{ .storage_class = .function }); | 3959 | const src_ty_indirect_id = try cg.resolveType(src_ty, .indirect); |
| | 3960 | const tmp_id = try cg.alloc(src_ty_indirect_id, null); |
| 3971 | try cg.store(src_ty, tmp_id, src_id, .{}); | 3961 | try cg.store(src_ty, tmp_id, src_id, .{}); |
| 3972 | const casted_ptr_id = cg.module.allocId(); | 3962 | const casted_ptr_id = cg.module.allocId(); |
| 3973 | try cg.body.emit(gpa, .OpBitcast, .{ | 3963 | try cg.body.emit(gpa, .OpBitcast, .{ |
| ... | @@ -3997,7 +3987,7 @@ fn airBitCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -3997,7 +3987,7 @@ fn airBitCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 3997 | const result_ty = cg.typeOfIndex(inst); | 3987 | const result_ty = cg.typeOfIndex(inst); |
| 3998 | if (operand_ty.toIntern() == .bool_type) { | 3988 | if (operand_ty.toIntern() == .bool_type) { |
| 3999 | const operand = try cg.temporary(ty_op.operand); | 3989 | const operand = try cg.temporary(ty_op.operand); |
| 4000 | const result = try cg.intFromBool(operand); | 3990 | const result = try cg.intFromBool(operand, .u1); |
| 4001 | return try result.materialize(cg); | 3991 | return try result.materialize(cg); |
| 4002 | } | 3992 | } |
| 4003 | const operand_id = try cg.resolve(ty_op.operand); | 3993 | const operand_id = try cg.resolve(ty_op.operand); |
| ... | @@ -4420,7 +4410,6 @@ fn airArrayElemVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -4420,7 +4410,6 @@ fn airArrayElemVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 4420 | // TODO: This backend probably also should use isByRef from llvm... | 4410 | // TODO: This backend probably also should use isByRef from llvm... |
| 4421 | | 4411 | |
| 4422 | const is_vector = array_ty.isVector(zcu); | 4412 | const is_vector = array_ty.isVector(zcu); |
| 4423 | | | |
| 4424 | const elem_repr: Repr = if (is_vector) .direct else .indirect; | 4413 | const elem_repr: Repr = if (is_vector) .direct else .indirect; |
| 4425 | const array_ty_id = try cg.resolveType(array_ty, .direct); | 4414 | const array_ty_id = try cg.resolveType(array_ty, .direct); |
| 4426 | const elem_ty_id = try cg.resolveType(elem_ty, elem_repr); | 4415 | const elem_ty_id = try cg.resolveType(elem_ty, elem_repr); |
| ... | @@ -4588,7 +4577,8 @@ fn unionInit( | ... | @@ -4588,7 +4577,8 @@ fn unionInit( |
| 4588 | return try cg.constInt(tag_ty, tag_int); | 4577 | return try cg.constInt(tag_ty, tag_int); |
| 4589 | } | 4578 | } |
| 4590 | | 4579 | |
| 4591 | const tmp_id = try cg.alloc(ty, .{ .storage_class = .function }); | 4580 | const ty_id = try cg.resolveType(ty, .indirect); |
| | 4581 | const tmp_id = try cg.alloc(ty_id, null); |
| 4592 | | 4582 | |
| 4593 | if (layout.tag_size != 0) { | 4583 | if (layout.tag_size != 0) { |
| 4594 | const tag_ty_id = try cg.resolveType(tag_ty, .indirect); | 4584 | const tag_ty_id = try cg.resolveType(tag_ty, .indirect); |
| ... | @@ -4709,7 +4699,8 @@ fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -4709,7 +4699,8 @@ fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 4709 | const layout = cg.unionLayout(object_ty); | 4699 | const layout = cg.unionLayout(object_ty); |
| 4710 | assert(layout.has_payload); | 4700 | assert(layout.has_payload); |
| 4711 | | 4701 | |
| 4712 | const tmp_id = try cg.alloc(object_ty, .{ .storage_class = .function }); | 4702 | const object_ty_id = try cg.resolveType(object_ty, .indirect); |
| | 4703 | const tmp_id = try cg.alloc(object_ty_id, null); |
| 4713 | try cg.store(object_ty, tmp_id, object_id, .{}); | 4704 | try cg.store(object_ty, tmp_id, object_id, .{}); |
| 4714 | | 4705 | |
| 4715 | const layout_payload_ty_id = try cg.resolveType(layout.payload_ty, .indirect); | 4706 | const layout_payload_ty_id = try cg.resolveType(layout.payload_ty, .indirect); |
| ... | @@ -4733,13 +4724,16 @@ fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -4733,13 +4724,16 @@ fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 4733 | | 4724 | |
| 4734 | fn airFieldParentPtr(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | 4725 | fn airFieldParentPtr(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 4735 | const zcu = cg.module.zcu; | 4726 | const zcu = cg.module.zcu; |
| | 4727 | const target = zcu.getTarget(); |
| 4736 | const ty_pl = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | 4728 | const ty_pl = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 4737 | const extra = cg.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; | 4729 | const extra = cg.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; |
| 4738 | | 4730 | |
| 4739 | const parent_ty = ty_pl.ty.toType().childType(zcu); | 4731 | const parent_ptr_ty = ty_pl.ty.toType(); |
| 4740 | const result_ty_id = try cg.resolveType(ty_pl.ty.toType(), .indirect); | 4732 | const parent_ty = parent_ptr_ty.childType(zcu); |
| | 4733 | const result_ty_id = try cg.resolveType(parent_ptr_ty, .indirect); |
| 4741 | | 4734 | |
| 4742 | const field_ptr = try cg.resolve(extra.field_ptr); | 4735 | const field_ptr = try cg.resolve(extra.field_ptr); |
| | 4736 | const field_ptr_ty = cg.typeOf(extra.field_ptr); |
| 4743 | const field_ptr_int = try cg.intFromPtr(field_ptr); | 4737 | const field_ptr_int = try cg.intFromPtr(field_ptr); |
| 4744 | const field_offset = parent_ty.structFieldOffset(extra.field_index, zcu); | 4738 | const field_offset = parent_ty.structFieldOffset(extra.field_index, zcu); |
| 4745 | | 4739 | |
| ... | @@ -4753,6 +4747,15 @@ fn airFieldParentPtr(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -4753,6 +4747,15 @@ fn airFieldParentPtr(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 4753 | break :base_ptr_int try result.materialize(cg); | 4747 | break :base_ptr_int try result.materialize(cg); |
| 4754 | }; | 4748 | }; |
| 4755 | | 4749 | |
| | 4750 | if (target.os.tag != .opencl) { |
| | 4751 | if (field_ptr_ty.ptrAddressSpace(zcu) != .physical_storage_buffer) { |
| | 4752 | return cg.fail( |
| | 4753 | "cannot cast integer to pointer with address space '{s}'", |
| | 4754 | .{@tagName(field_ptr_ty.ptrAddressSpace(zcu))}, |
| | 4755 | ); |
| | 4756 | } |
| | 4757 | } |
| | 4758 | |
| 4756 | const base_ptr = cg.module.allocId(); | 4759 | const base_ptr = cg.module.allocId(); |
| 4757 | try cg.body.emit(cg.module.gpa, .OpConvertUToPtr, .{ | 4760 | try cg.body.emit(cg.module.gpa, .OpConvertUToPtr, .{ |
| 4758 | .id_result_type = result_ty_id, | 4761 | .id_result_type = result_ty_id, |
| ... | @@ -4821,46 +4824,33 @@ fn airStructFieldPtrIndex(cg: *CodeGen, inst: Air.Inst.Index, field_index: u32) | ... | @@ -4821,46 +4824,33 @@ fn airStructFieldPtrIndex(cg: *CodeGen, inst: Air.Inst.Index, field_index: u32) |
| 4821 | return try cg.structFieldPtr(result_ptr_ty, struct_ptr_ty, struct_ptr, field_index); | 4824 | return try cg.structFieldPtr(result_ptr_ty, struct_ptr_ty, struct_ptr, field_index); |
| 4822 | } | 4825 | } |
| 4823 | | 4826 | |
| 4824 | const AllocOptions = struct { | 4827 | fn alloc(cg: *CodeGen, ty_id: Id, initializer: ?Id) !Id { |
| 4825 | initializer: ?Id = null, | 4828 | const ptr_ty_id = try cg.module.ptrType(ty_id, .function); |
| 4826 | /// The final storage class of the pointer. This may be either `.Generic` or `.Function`. | 4829 | const result_id = cg.module.allocId(); |
| 4827 | /// In either case, the local is allocated in the `.Function` storage class, and optionally | | |
| 4828 | /// cast back to `.Generic`. | | |
| 4829 | storage_class: StorageClass, | | |
| 4830 | }; | | |
| 4831 | | | |
| 4832 | // Allocate a function-local variable, with possible initializer. | | |
| 4833 | // This function returns a pointer to a variable of type `ty`, | | |
| 4834 | // which is in the Generic address space. The variable is actually | | |
| 4835 | // placed in the Function address space. | | |
| 4836 | fn alloc( | | |
| 4837 | cg: *CodeGen, | | |
| 4838 | ty: Type, | | |
| 4839 | options: AllocOptions, | | |
| 4840 | ) !Id { | | |
| 4841 | const ty_id = try cg.resolveType(ty, .indirect); | | |
| 4842 | const ptr_fn_ty_id = try cg.module.ptrType(ty_id, .function); | | |
| 4843 | | | |
| 4844 | // SPIR-V requires that OpVariable declarations for locals go into the first block, so we are just going to | | |
| 4845 | // directly generate them into func.prologue instead of the body. | | |
| 4846 | const var_id = cg.module.allocId(); | | |
| 4847 | try cg.prologue.emit(cg.module.gpa, .OpVariable, .{ | 4830 | try cg.prologue.emit(cg.module.gpa, .OpVariable, .{ |
| 4848 | .id_result_type = ptr_fn_ty_id, | 4831 | .id_result_type = ptr_ty_id, |
| 4849 | .id_result = var_id, | 4832 | .id_result = result_id, |
| 4850 | .storage_class = .function, | 4833 | .storage_class = .function, |
| 4851 | .initializer = options.initializer, | 4834 | .initializer = initializer, |
| 4852 | }); | 4835 | }); |
| 4853 | | 4836 | return result_id; |
| 4854 | return var_id; | | |
| 4855 | } | 4837 | } |
| 4856 | | 4838 | |
| 4857 | fn airAlloc(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | 4839 | fn airAlloc(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 4858 | const zcu = cg.module.zcu; | 4840 | const zcu = cg.module.zcu; |
| | 4841 | const target = zcu.getTarget(); |
| 4859 | const ptr_ty = cg.typeOfIndex(inst); | 4842 | const ptr_ty = cg.typeOfIndex(inst); |
| 4860 | const child_ty = ptr_ty.childType(zcu); | 4843 | const child_ty = ptr_ty.childType(zcu); |
| 4861 | return try cg.alloc(child_ty, .{ | 4844 | const child_ty_id = try cg.resolveType(child_ty, .indirect); |
| 4862 | .storage_class = cg.module.storageClass(ptr_ty.ptrAddressSpace(zcu)), | 4845 | const ptr_align = ptr_ty.ptrAlignment(zcu); |
| 4863 | }); | 4846 | const result_id = try cg.alloc(child_ty_id, null); |
| | 4847 | if (ptr_align != child_ty.abiAlignment(zcu)) { |
| | 4848 | if (target.os.tag != .opencl) return cg.fail("cannot apply alignment to variables", .{}); |
| | 4849 | try cg.module.decorate(result_id, .{ |
| | 4850 | .alignment = .{ .alignment = @intCast(ptr_align.toByteUnits().?) }, |
| | 4851 | }); |
| | 4852 | } |
| | 4853 | return result_id; |
| 4864 | } | 4854 | } |
| 4865 | | 4855 | |
| 4866 | fn airArg(cg: *CodeGen) Id { | 4856 | fn airArg(cg: *CodeGen) Id { |
| ... | @@ -5087,7 +5077,8 @@ fn lowerBlock(cg: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index) | ... | @@ -5087,7 +5077,8 @@ fn lowerBlock(cg: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index) |
| 5087 | }; | 5077 | }; |
| 5088 | | 5078 | |
| 5089 | const maybe_block_result_var_id = if (have_block_result) blk: { | 5079 | const maybe_block_result_var_id = if (have_block_result) blk: { |
| 5090 | const block_result_var_id = try cg.alloc(ty, .{ .storage_class = .function }); | 5080 | const ty_id = try cg.resolveType(ty, .indirect); |
| | 5081 | const block_result_var_id = try cg.alloc(ty_id, null); |
| 5091 | try cf.block_results.putNoClobber(gpa, inst, block_result_var_id); | 5082 | try cf.block_results.putNoClobber(gpa, inst, block_result_var_id); |
| 5092 | break :blk block_result_var_id; | 5083 | break :blk block_result_var_id; |
| 5093 | } else null; | 5084 | } else null; |