| ... | ... | @@ -602,6 +602,7 @@ pub const Object = struct { |
| 602 | 602 | var builder = try Builder.init(.{ |
| 603 | 603 | .allocator = gpa, |
| 604 | 604 | .use_lib_llvm = options.use_lib_llvm, |
| 605 | .strip = options.strip, |
| 605 | 606 | .name = options.root_name, |
| 606 | 607 | .target = options.target, |
| 607 | 608 | .triple = llvm_target_triple, |
| ... | ... | @@ -682,7 +683,7 @@ pub const Object = struct { |
| 682 | 683 | |
| 683 | 684 | target_machine = llvm.TargetMachine.create( |
| 684 | 685 | builder.llvm.target.?, |
| 685 | | builder.target_triple.toSlice(&builder).?.ptr, |
| 686 | builder.target_triple.toSlice(&builder).?, |
| 686 | 687 | if (options.target.cpu.model.llvm_name) |s| s.ptr else null, |
| 687 | 688 | options.llvm_cpu_features, |
| 688 | 689 | opt_level, |
| ... | ... | @@ -749,7 +750,6 @@ pub const Object = struct { |
| 749 | 750 | self.named_enum_map.deinit(gpa); |
| 750 | 751 | self.type_map.deinit(gpa); |
| 751 | 752 | self.extern_collisions.deinit(gpa); |
| 752 | | self.builder.deinit(); |
| 753 | 753 | self.* = undefined; |
| 754 | 754 | } |
| 755 | 755 | |
| ... | ... | @@ -850,22 +850,19 @@ pub const Object = struct { |
| 850 | 850 | error_name_table_ptr_global.toLlvm(&o.builder).setInitializer(error_name_table_ptr); |
| 851 | 851 | } |
| 852 | 852 | |
| 853 | | fn genCmpLtErrorsLenFunction(object: *Object) !void { |
| 853 | fn genCmpLtErrorsLenFunction(o: *Object) !void { |
| 854 | 854 | // If there is no such function in the module, it means the source code does not need it. |
| 855 | | const llvm_fn = object.llvm_module.getNamedFunction(lt_errors_fn_name) orelse return; |
| 856 | | const mod = object.module; |
| 855 | const name = o.builder.stringIfExists(lt_errors_fn_name) orelse return; |
| 856 | const llvm_fn = o.builder.getGlobal(name) orelse return; |
| 857 | const mod = o.module; |
| 857 | 858 | const errors_len = mod.global_error_set.count(); |
| 858 | 859 | |
| 859 | | // Delete previous implementation. We replace it with every flush() because the |
| 860 | | // total number of errors may have changed. |
| 861 | | while (llvm_fn.getFirstBasicBlock()) |bb| { |
| 862 | | bb.deleteBasicBlock(); |
| 863 | | } |
| 860 | var wip = Builder.WipFunction.init(&o.builder, llvm_fn.ptrConst(&o.builder).kind.function); |
| 861 | defer wip.deinit(); |
| 864 | 862 | |
| 865 | | const builder = object.context.createBuilder(); |
| 866 | | |
| 867 | | const entry_block = object.context.appendBasicBlock(llvm_fn, "Entry"); |
| 868 | | builder.positionBuilderAtEnd(entry_block); |
| 863 | const builder = wip.llvm.builder; |
| 864 | const entry_block = try wip.block("Entry"); |
| 865 | builder.positionBuilderAtEnd(entry_block.toLlvm(&wip)); |
| 869 | 866 | builder.clearCurrentDebugLocation(); |
| 870 | 867 | |
| 871 | 868 | // Example source of the following LLVM IR: |
| ... | ... | @@ -873,10 +870,12 @@ pub const Object = struct { |
| 873 | 870 | // return index < total_errors_len; |
| 874 | 871 | // } |
| 875 | 872 | |
| 876 | | const lhs = llvm_fn.getParam(0); |
| 877 | | const rhs = try object.builder.intConst(Builder.Type.err_int, errors_len); |
| 878 | | const is_lt = builder.buildICmp(.ULT, lhs, rhs.toLlvm(&object.builder), ""); |
| 873 | const lhs = llvm_fn.toLlvm(&o.builder).getParam(0); |
| 874 | const rhs = try o.builder.intConst(Builder.Type.err_int, errors_len); |
| 875 | const is_lt = builder.buildICmp(.ULT, lhs, rhs.toLlvm(&o.builder), ""); |
| 879 | 876 | _ = builder.buildRet(is_lt); |
| 877 | |
| 878 | try wip.finish(); |
| 880 | 879 | } |
| 881 | 880 | |
| 882 | 881 | fn genModuleLevelAssembly(object: *Object) !void { |
| ... | ... | @@ -1158,11 +1157,14 @@ pub const Object = struct { |
| 1158 | 1157 | bb.deleteBasicBlock(); |
| 1159 | 1158 | } |
| 1160 | 1159 | |
| 1161 | | const builder = o.context.createBuilder(); |
| 1160 | var deinit_wip = true; |
| 1161 | var wip = Builder.WipFunction.init(&o.builder, function); |
| 1162 | defer if (deinit_wip) wip.deinit(); |
| 1162 | 1163 | |
| 1163 | | function.ptr(&o.builder).body = {}; |
| 1164 | | const entry_block = o.context.appendBasicBlock(llvm_func, "Entry"); |
| 1165 | | builder.positionBuilderAtEnd(entry_block); |
| 1164 | const builder = wip.llvm.builder; |
| 1165 | const entry_block = try wip.block("Entry"); |
| 1166 | wip.cursor = .{ .block = entry_block }; |
| 1167 | builder.positionBuilderAtEnd(entry_block.toLlvm(&wip)); |
| 1166 | 1168 | |
| 1167 | 1169 | // This gets the LLVM values from the function and stores them in `dg.args`. |
| 1168 | 1170 | const fn_info = mod.typeToFunc(decl.ty).?; |
| ... | ... | @@ -1260,8 +1262,7 @@ pub const Object = struct { |
| 1260 | 1262 | llvm_arg_i += 1; |
| 1261 | 1263 | |
| 1262 | 1264 | const param_llvm_ty = (try o.lowerType(param_ty)).toLlvm(&o.builder); |
| 1263 | | const abi_size = @as(c_uint, @intCast(param_ty.abiSize(mod))); |
| 1264 | | const int_llvm_ty = (try o.builder.intType(@intCast(abi_size * 8))).toLlvm(&o.builder); |
| 1265 | const int_llvm_ty = (try o.builder.intType(@intCast(param_ty.abiSize(mod) * 8))).toLlvm(&o.builder); |
| 1265 | 1266 | const alignment = @max( |
| 1266 | 1267 | param_ty.abiAlignment(mod), |
| 1267 | 1268 | o.target_data.abiAlignmentOfType(int_llvm_ty), |
| ... | ... | @@ -1317,11 +1318,10 @@ pub const Object = struct { |
| 1317 | 1318 | const param_alignment = param_ty.abiAlignment(mod); |
| 1318 | 1319 | const arg_ptr = try o.buildAllocaInner(builder, llvm_func, false, param_llvm_ty, param_alignment, target); |
| 1319 | 1320 | const llvm_ty = (try o.builder.structType(.normal, field_types)).toLlvm(&o.builder); |
| 1320 | | for (0..field_types.len) |field_i_usize| { |
| 1321 | | const field_i = @as(c_uint, @intCast(field_i_usize)); |
| 1321 | for (0..field_types.len) |field_i| { |
| 1322 | 1322 | const param = llvm_func.getParam(llvm_arg_i); |
| 1323 | 1323 | llvm_arg_i += 1; |
| 1324 | | const field_ptr = builder.buildStructGEP(llvm_ty, arg_ptr, field_i, ""); |
| 1324 | const field_ptr = builder.buildStructGEP(llvm_ty, arg_ptr, @intCast(field_i), ""); |
| 1325 | 1325 | const store_inst = builder.buildStore(param, field_ptr); |
| 1326 | 1326 | store_inst.setAlignment(target.ptrBitWidth() / 8); |
| 1327 | 1327 | } |
| ... | ... | @@ -1422,6 +1422,7 @@ pub const Object = struct { |
| 1422 | 1422 | .liveness = liveness, |
| 1423 | 1423 | .context = o.context, |
| 1424 | 1424 | .dg = &dg, |
| 1425 | .wip = wip, |
| 1425 | 1426 | .builder = builder, |
| 1426 | 1427 | .ret_ptr = ret_ptr, |
| 1427 | 1428 | .args = args.items, |
| ... | ... | @@ -1438,6 +1439,7 @@ pub const Object = struct { |
| 1438 | 1439 | .err_ret_trace = err_ret_trace, |
| 1439 | 1440 | }; |
| 1440 | 1441 | defer fg.deinit(); |
| 1442 | deinit_wip = false; |
| 1441 | 1443 | |
| 1442 | 1444 | fg.genBody(air.getMainBody()) catch |err| switch (err) { |
| 1443 | 1445 | error.CodegenFail => { |
| ... | ... | @@ -1449,6 +1451,8 @@ pub const Object = struct { |
| 1449 | 1451 | else => |e| return e, |
| 1450 | 1452 | }; |
| 1451 | 1453 | |
| 1454 | try fg.wip.finish(); |
| 1455 | |
| 1452 | 1456 | try o.updateDeclExports(mod, decl_index, mod.getDeclExports(decl_index)); |
| 1453 | 1457 | } |
| 1454 | 1458 | |
| ... | ... | @@ -1517,11 +1521,11 @@ pub const Object = struct { |
| 1517 | 1521 | if (self.di_map.get(decl)) |di_node| { |
| 1518 | 1522 | const decl_name_slice = decl_name.toSlice(&self.builder).?; |
| 1519 | 1523 | if (try decl.isFunction(mod)) { |
| 1520 | | const di_func = @as(*llvm.DISubprogram, @ptrCast(di_node)); |
| 1524 | const di_func: *llvm.DISubprogram = @ptrCast(di_node); |
| 1521 | 1525 | const linkage_name = llvm.MDString.get(self.context, decl_name_slice.ptr, decl_name_slice.len); |
| 1522 | 1526 | di_func.replaceLinkageName(linkage_name); |
| 1523 | 1527 | } else { |
| 1524 | | const di_global = @as(*llvm.DIGlobalVariable, @ptrCast(di_node)); |
| 1528 | const di_global: *llvm.DIGlobalVariable = @ptrCast(di_node); |
| 1525 | 1529 | const linkage_name = llvm.MDString.get(self.context, decl_name_slice.ptr, decl_name_slice.len); |
| 1526 | 1530 | di_global.replaceLinkageName(linkage_name); |
| 1527 | 1531 | } |
| ... | ... | @@ -1554,11 +1558,11 @@ pub const Object = struct { |
| 1554 | 1558 | if (self.di_map.get(decl)) |di_node| { |
| 1555 | 1559 | const exp_name_slice = exp_name.toSlice(&self.builder).?; |
| 1556 | 1560 | if (try decl.isFunction(mod)) { |
| 1557 | | const di_func = @as(*llvm.DISubprogram, @ptrCast(di_node)); |
| 1561 | const di_func: *llvm.DISubprogram = @ptrCast(di_node); |
| 1558 | 1562 | const linkage_name = llvm.MDString.get(self.context, exp_name_slice.ptr, exp_name_slice.len); |
| 1559 | 1563 | di_func.replaceLinkageName(linkage_name); |
| 1560 | 1564 | } else { |
| 1561 | | const di_global = @as(*llvm.DIGlobalVariable, @ptrCast(di_node)); |
| 1565 | const di_global: *llvm.DIGlobalVariable = @ptrCast(di_node); |
| 1562 | 1566 | const linkage_name = llvm.MDString.get(self.context, exp_name_slice.ptr, exp_name_slice.len); |
| 1563 | 1567 | di_global.replaceLinkageName(linkage_name); |
| 1564 | 1568 | } |
| ... | ... | @@ -1661,7 +1665,7 @@ pub const Object = struct { |
| 1661 | 1665 | const gop = try o.di_map.getOrPut(gpa, file); |
| 1662 | 1666 | errdefer assert(o.di_map.remove(file)); |
| 1663 | 1667 | if (gop.found_existing) { |
| 1664 | | return @as(*llvm.DIFile, @ptrCast(gop.value_ptr.*)); |
| 1668 | return @ptrCast(gop.value_ptr.*); |
| 1665 | 1669 | } |
| 1666 | 1670 | const dir_path_z = d: { |
| 1667 | 1671 | var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined; |
| ... | ... | @@ -1809,7 +1813,7 @@ pub const Object = struct { |
| 1809 | 1813 | ty.abiSize(mod) * 8, |
| 1810 | 1814 | ty.abiAlignment(mod) * 8, |
| 1811 | 1815 | enumerators.ptr, |
| 1812 | | @as(c_int, @intCast(enumerators.len)), |
| 1816 | @intCast(enumerators.len), |
| 1813 | 1817 | try o.lowerDebugType(int_ty, .full), |
| 1814 | 1818 | "", |
| 1815 | 1819 | ); |
| ... | ... | @@ -1984,7 +1988,7 @@ pub const Object = struct { |
| 1984 | 1988 | ty.abiSize(mod) * 8, |
| 1985 | 1989 | ty.abiAlignment(mod) * 8, |
| 1986 | 1990 | try o.lowerDebugType(ty.childType(mod), .full), |
| 1987 | | @as(i64, @intCast(ty.arrayLen(mod))), |
| 1991 | @intCast(ty.arrayLen(mod)), |
| 1988 | 1992 | ); |
| 1989 | 1993 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 1990 | 1994 | try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(array_di_ty)); |
| ... | ... | @@ -2289,7 +2293,7 @@ pub const Object = struct { |
| 2289 | 2293 | 0, // flags |
| 2290 | 2294 | null, // derived from |
| 2291 | 2295 | di_fields.items.ptr, |
| 2292 | | @as(c_int, @intCast(di_fields.items.len)), |
| 2296 | @intCast(di_fields.items.len), |
| 2293 | 2297 | 0, // run time lang |
| 2294 | 2298 | null, // vtable holder |
| 2295 | 2299 | "", // unique id |
| ... | ... | @@ -2376,7 +2380,7 @@ pub const Object = struct { |
| 2376 | 2380 | 0, // flags |
| 2377 | 2381 | null, // derived from |
| 2378 | 2382 | di_fields.items.ptr, |
| 2379 | | @as(c_int, @intCast(di_fields.items.len)), |
| 2383 | @intCast(di_fields.items.len), |
| 2380 | 2384 | 0, // run time lang |
| 2381 | 2385 | null, // vtable holder |
| 2382 | 2386 | "", // unique id |
| ... | ... | @@ -2488,7 +2492,7 @@ pub const Object = struct { |
| 2488 | 2492 | ty.abiAlignment(mod) * 8, // align in bits |
| 2489 | 2493 | 0, // flags |
| 2490 | 2494 | di_fields.items.ptr, |
| 2491 | | @as(c_int, @intCast(di_fields.items.len)), |
| 2495 | @intCast(di_fields.items.len), |
| 2492 | 2496 | 0, // run time lang |
| 2493 | 2497 | "", // unique id |
| 2494 | 2498 | ); |
| ... | ... | @@ -2601,7 +2605,7 @@ pub const Object = struct { |
| 2601 | 2605 | |
| 2602 | 2606 | const fn_di_ty = dib.createSubroutineType( |
| 2603 | 2607 | param_di_types.items.ptr, |
| 2604 | | @as(c_int, @intCast(param_di_types.items.len)), |
| 2608 | @intCast(param_di_types.items.len), |
| 2605 | 2609 | 0, |
| 2606 | 2610 | ); |
| 2607 | 2611 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| ... | ... | @@ -4248,9 +4252,9 @@ pub const Object = struct { |
| 4248 | 4252 | ) void { |
| 4249 | 4253 | const llvm_attr = o.context.createStringAttribute( |
| 4250 | 4254 | name.ptr, |
| 4251 | | @as(c_uint, @intCast(name.len)), |
| 4255 | @intCast(name.len), |
| 4252 | 4256 | value.ptr, |
| 4253 | | @as(c_uint, @intCast(value.len)), |
| 4257 | @intCast(value.len), |
| 4254 | 4258 | ); |
| 4255 | 4259 | val.addAttributeAtIndex(index, llvm_attr); |
| 4256 | 4260 | } |
| ... | ... | @@ -4364,11 +4368,7 @@ pub const Object = struct { |
| 4364 | 4368 | } |
| 4365 | 4369 | |
| 4366 | 4370 | const entry_block = llvm_func.getFirstBasicBlock().?; |
| 4367 | | if (entry_block.getFirstInstruction()) |first_inst| { |
| 4368 | | builder.positionBuilder(entry_block, first_inst); |
| 4369 | | } else { |
| 4370 | | builder.positionBuilderAtEnd(entry_block); |
| 4371 | | } |
| 4371 | builder.positionBuilder(entry_block, entry_block.getFirstInstruction()); |
| 4372 | 4372 | builder.clearCurrentDebugLocation(); |
| 4373 | 4373 | |
| 4374 | 4374 | break :blk builder.buildAllocaInAddressSpace(llvm_ty, @intFromEnum(address_space), ""); |
| ... | ... | @@ -4502,6 +4502,7 @@ pub const FuncGen = struct { |
| 4502 | 4502 | dg: *DeclGen, |
| 4503 | 4503 | air: Air, |
| 4504 | 4504 | liveness: Liveness, |
| 4505 | wip: Builder.WipFunction, |
| 4505 | 4506 | context: *llvm.Context, |
| 4506 | 4507 | builder: *llvm.Builder, |
| 4507 | 4508 | di_scope: ?*llvm.DIScope, |
| ... | ... | @@ -4542,7 +4543,7 @@ pub const FuncGen = struct { |
| 4542 | 4543 | |
| 4543 | 4544 | /// This data structure is used to implement breaking to blocks. |
| 4544 | 4545 | blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, struct { |
| 4545 | | parent_bb: *llvm.BasicBlock, |
| 4546 | parent_bb: Builder.Function.Block.Index, |
| 4546 | 4547 | breaks: *BreakList, |
| 4547 | 4548 | }), |
| 4548 | 4549 | |
| ... | ... | @@ -4555,7 +4556,7 @@ pub const FuncGen = struct { |
| 4555 | 4556 | }); |
| 4556 | 4557 | |
| 4557 | 4558 | fn deinit(self: *FuncGen) void { |
| 4558 | | self.builder.dispose(); |
| 4559 | self.wip.deinit(); |
| 4559 | 4560 | self.dbg_inlined.deinit(self.gpa); |
| 4560 | 4561 | self.dbg_block_stack.deinit(self.gpa); |
| 4561 | 4562 | self.func_inst_table.deinit(self.gpa); |
| ... | ... | @@ -4898,7 +4899,7 @@ pub const FuncGen = struct { |
| 4898 | 4899 | fn airCall(self: *FuncGen, inst: Air.Inst.Index, attr: llvm.CallAttr) !?*llvm.Value { |
| 4899 | 4900 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 4900 | 4901 | const extra = self.air.extraData(Air.Call, pl_op.payload); |
| 4901 | | const args = @as([]const Air.Inst.Ref, @ptrCast(self.air.extra[extra.end..][0..extra.data.args_len])); |
| 4902 | const args: []const Air.Inst.Ref = @ptrCast(self.air.extra[extra.end..][0..extra.data.args_len]); |
| 4902 | 4903 | const o = self.dg.object; |
| 4903 | 4904 | const mod = o.module; |
| 4904 | 4905 | const ip = &mod.intern_pool; |
| ... | ... | @@ -4987,8 +4988,7 @@ pub const FuncGen = struct { |
| 4987 | 4988 | const arg = args[it.zig_index - 1]; |
| 4988 | 4989 | const param_ty = self.typeOf(arg); |
| 4989 | 4990 | const llvm_arg = try self.resolveInst(arg); |
| 4990 | | const abi_size = @as(c_uint, @intCast(param_ty.abiSize(mod))); |
| 4991 | | const int_llvm_ty = (try o.builder.intType(@intCast(abi_size * 8))).toLlvm(&o.builder); |
| 4991 | const int_llvm_ty = (try o.builder.intType(@intCast(param_ty.abiSize(mod) * 8))).toLlvm(&o.builder); |
| 4992 | 4992 | |
| 4993 | 4993 | if (isByRef(param_ty, mod)) { |
| 4994 | 4994 | const alignment = param_ty.abiAlignment(mod); |
| ... | ... | @@ -5034,9 +5034,8 @@ pub const FuncGen = struct { |
| 5034 | 5034 | |
| 5035 | 5035 | const llvm_ty = (try o.builder.structType(.normal, llvm_types)).toLlvm(&o.builder); |
| 5036 | 5036 | try llvm_args.ensureUnusedCapacity(it.types_len); |
| 5037 | | for (llvm_types, 0..) |field_ty, i_usize| { |
| 5038 | | const i = @as(c_uint, @intCast(i_usize)); |
| 5039 | | const field_ptr = self.builder.buildStructGEP(llvm_ty, arg_ptr, i, ""); |
| 5037 | for (llvm_types, 0..) |field_ty, i| { |
| 5038 | const field_ptr = self.builder.buildStructGEP(llvm_ty, arg_ptr, @intCast(i), ""); |
| 5040 | 5039 | const load_inst = self.builder.buildLoad(field_ty.toLlvm(&o.builder), field_ptr, ""); |
| 5041 | 5040 | load_inst.setAlignment(target.ptrBitWidth() / 8); |
| 5042 | 5041 | llvm_args.appendAssumeCapacity(load_inst); |
| ... | ... | @@ -5091,7 +5090,7 @@ pub const FuncGen = struct { |
| 5091 | 5090 | (try o.lowerType(zig_fn_ty)).toLlvm(&o.builder), |
| 5092 | 5091 | llvm_fn, |
| 5093 | 5092 | llvm_args.items.ptr, |
| 5094 | | @as(c_uint, @intCast(llvm_args.items.len)), |
| 5093 | @intCast(llvm_args.items.len), |
| 5095 | 5094 | toLlvmCallConv(fn_info.cc, target), |
| 5096 | 5095 | attr, |
| 5097 | 5096 | "", |
| ... | ... | @@ -5256,7 +5255,7 @@ pub const FuncGen = struct { |
| 5256 | 5255 | const operand = try self.resolveInst(un_op); |
| 5257 | 5256 | const ptr_ty = try mod.singleMutPtrType(ret_ty); |
| 5258 | 5257 | try self.store(ret_ptr, ptr_ty, operand, .NotAtomic); |
| 5259 | | _ = self.builder.buildRetVoid(); |
| 5258 | try self.wip.retVoid(); |
| 5260 | 5259 | return null; |
| 5261 | 5260 | } |
| 5262 | 5261 | const fn_info = mod.typeToFunc(self.dg.decl.ty).?; |
| ... | ... | @@ -5268,7 +5267,7 @@ pub const FuncGen = struct { |
| 5268 | 5267 | const int = try o.builder.intConst(Builder.Type.err_int, 0); |
| 5269 | 5268 | _ = self.builder.buildRet(int.toLlvm(&o.builder)); |
| 5270 | 5269 | } else { |
| 5271 | | _ = self.builder.buildRetVoid(); |
| 5270 | try self.wip.retVoid(); |
| 5272 | 5271 | } |
| 5273 | 5272 | return null; |
| 5274 | 5273 | } |
| ... | ... | @@ -5316,12 +5315,12 @@ pub const FuncGen = struct { |
| 5316 | 5315 | const int = try o.builder.intConst(Builder.Type.err_int, 0); |
| 5317 | 5316 | _ = self.builder.buildRet(int.toLlvm(&o.builder)); |
| 5318 | 5317 | } else { |
| 5319 | | _ = self.builder.buildRetVoid(); |
| 5318 | try self.wip.retVoid(); |
| 5320 | 5319 | } |
| 5321 | 5320 | return null; |
| 5322 | 5321 | } |
| 5323 | 5322 | if (self.ret_ptr != null) { |
| 5324 | | _ = self.builder.buildRetVoid(); |
| 5323 | try self.wip.retVoid(); |
| 5325 | 5324 | return null; |
| 5326 | 5325 | } |
| 5327 | 5326 | const ptr = try self.resolveInst(un_op); |
| ... | ... | @@ -5476,33 +5475,33 @@ pub const FuncGen = struct { |
| 5476 | 5475 | const rhs_non_null_i2 = self.builder.buildZExt(rhs_non_null, llvm_i2.toLlvm(&o.builder), ""); |
| 5477 | 5476 | const lhs_shifted = self.builder.buildShl(lhs_non_null_i2, (try o.builder.intConst(llvm_i2, 1)).toLlvm(&o.builder), ""); |
| 5478 | 5477 | const lhs_rhs_ored = self.builder.buildOr(lhs_shifted, rhs_non_null_i2, ""); |
| 5479 | | const both_null_block = self.context.appendBasicBlock(self.llvm_func, "BothNull"); |
| 5480 | | const mixed_block = self.context.appendBasicBlock(self.llvm_func, "Mixed"); |
| 5481 | | const both_pl_block = self.context.appendBasicBlock(self.llvm_func, "BothNonNull"); |
| 5482 | | const end_block = self.context.appendBasicBlock(self.llvm_func, "End"); |
| 5483 | | const llvm_switch = self.builder.buildSwitch(lhs_rhs_ored, mixed_block, 2); |
| 5478 | const both_null_block = try self.wip.block("BothNull"); |
| 5479 | const mixed_block = try self.wip.block("Mixed"); |
| 5480 | const both_pl_block = try self.wip.block("BothNonNull"); |
| 5481 | const end_block = try self.wip.block("End"); |
| 5482 | const llvm_switch = self.builder.buildSwitch(lhs_rhs_ored, mixed_block.toLlvm(&self.wip), 2); |
| 5484 | 5483 | const llvm_i2_00 = try o.builder.intConst(llvm_i2, 0b00); |
| 5485 | 5484 | const llvm_i2_11 = try o.builder.intConst(llvm_i2, 0b11); |
| 5486 | | llvm_switch.addCase(llvm_i2_00.toLlvm(&o.builder), both_null_block); |
| 5487 | | llvm_switch.addCase(llvm_i2_11.toLlvm(&o.builder), both_pl_block); |
| 5485 | llvm_switch.addCase(llvm_i2_00.toLlvm(&o.builder), both_null_block.toLlvm(&self.wip)); |
| 5486 | llvm_switch.addCase(llvm_i2_11.toLlvm(&o.builder), both_pl_block.toLlvm(&self.wip)); |
| 5488 | 5487 | |
| 5489 | | self.builder.positionBuilderAtEnd(both_null_block); |
| 5490 | | _ = self.builder.buildBr(end_block); |
| 5488 | self.builder.positionBuilderAtEnd(both_null_block.toLlvm(&self.wip)); |
| 5489 | _ = self.builder.buildBr(end_block.toLlvm(&self.wip)); |
| 5491 | 5490 | |
| 5492 | | self.builder.positionBuilderAtEnd(mixed_block); |
| 5493 | | _ = self.builder.buildBr(end_block); |
| 5491 | self.builder.positionBuilderAtEnd(mixed_block.toLlvm(&self.wip)); |
| 5492 | _ = self.builder.buildBr(end_block.toLlvm(&self.wip)); |
| 5494 | 5493 | |
| 5495 | | self.builder.positionBuilderAtEnd(both_pl_block); |
| 5494 | self.builder.positionBuilderAtEnd(both_pl_block.toLlvm(&self.wip)); |
| 5496 | 5495 | const lhs_payload = try self.optPayloadHandle(opt_llvm_ty, lhs, scalar_ty, true); |
| 5497 | 5496 | const rhs_payload = try self.optPayloadHandle(opt_llvm_ty, rhs, scalar_ty, true); |
| 5498 | 5497 | const payload_cmp = try self.cmp(lhs_payload, rhs_payload, payload_ty, op); |
| 5499 | | _ = self.builder.buildBr(end_block); |
| 5498 | _ = self.builder.buildBr(end_block.toLlvm(&self.wip)); |
| 5500 | 5499 | const both_pl_block_end = self.builder.getInsertBlock(); |
| 5501 | 5500 | |
| 5502 | | self.builder.positionBuilderAtEnd(end_block); |
| 5501 | self.builder.positionBuilderAtEnd(end_block.toLlvm(&self.wip)); |
| 5503 | 5502 | const incoming_blocks: [3]*llvm.BasicBlock = .{ |
| 5504 | | both_null_block, |
| 5505 | | mixed_block, |
| 5503 | both_null_block.toLlvm(&self.wip), |
| 5504 | mixed_block.toLlvm(&self.wip), |
| 5506 | 5505 | both_pl_block_end, |
| 5507 | 5506 | }; |
| 5508 | 5507 | const llvm_i1_0 = Builder.Constant.false.toLlvm(&o.builder); |
| ... | ... | @@ -5552,7 +5551,6 @@ pub const FuncGen = struct { |
| 5552 | 5551 | const extra = self.air.extraData(Air.Block, ty_pl.payload); |
| 5553 | 5552 | const body = self.air.extra[extra.end..][0..extra.data.body_len]; |
| 5554 | 5553 | const inst_ty = self.typeOfIndex(inst); |
| 5555 | | const parent_bb = self.context.createBasicBlock("Block"); |
| 5556 | 5554 | |
| 5557 | 5555 | if (inst_ty.isNoReturn(mod)) { |
| 5558 | 5556 | try self.genBody(body); |
| ... | ... | @@ -5562,6 +5560,7 @@ pub const FuncGen = struct { |
| 5562 | 5560 | var breaks: BreakList = .{}; |
| 5563 | 5561 | defer breaks.deinit(self.gpa); |
| 5564 | 5562 | |
| 5563 | const parent_bb = try self.wip.block("Block"); |
| 5565 | 5564 | try self.blocks.putNoClobber(self.gpa, inst, .{ |
| 5566 | 5565 | .parent_bb = parent_bb, |
| 5567 | 5566 | .breaks = &breaks, |
| ... | ... | @@ -5570,8 +5569,7 @@ pub const FuncGen = struct { |
| 5570 | 5569 | |
| 5571 | 5570 | try self.genBody(body); |
| 5572 | 5571 | |
| 5573 | | self.llvm_func.appendExistingBasicBlock(parent_bb); |
| 5574 | | self.builder.positionBuilderAtEnd(parent_bb); |
| 5572 | self.builder.positionBuilderAtEnd(parent_bb.toLlvm(&self.wip)); |
| 5575 | 5573 | |
| 5576 | 5574 | // Create a phi node only if the block returns a value. |
| 5577 | 5575 | const is_body = inst_ty.zigTypeTag(mod) == .Fn; |
| ... | ... | @@ -5585,7 +5583,7 @@ pub const FuncGen = struct { |
| 5585 | 5583 | // of function pointers, however the phi makes it a runtime value and therefore |
| 5586 | 5584 | // the LLVM type has to be wrapped in a pointer. |
| 5587 | 5585 | if (is_body or isByRef(inst_ty, mod)) { |
| 5588 | | break :ty self.context.pointerType(0); |
| 5586 | break :ty Builder.Type.ptr.toLlvm(&o.builder); |
| 5589 | 5587 | } |
| 5590 | 5588 | break :ty raw_llvm_ty; |
| 5591 | 5589 | }; |
| ... | ... | @@ -5594,7 +5592,7 @@ pub const FuncGen = struct { |
| 5594 | 5592 | phi_node.addIncoming( |
| 5595 | 5593 | breaks.items(.val).ptr, |
| 5596 | 5594 | breaks.items(.bb).ptr, |
| 5597 | | @as(c_uint, @intCast(breaks.len)), |
| 5595 | @intCast(breaks.len), |
| 5598 | 5596 | ); |
| 5599 | 5597 | return phi_node; |
| 5600 | 5598 | } |
| ... | ... | @@ -5617,7 +5615,7 @@ pub const FuncGen = struct { |
| 5617 | 5615 | .val = val, |
| 5618 | 5616 | }); |
| 5619 | 5617 | } |
| 5620 | | _ = self.builder.buildBr(block.parent_bb); |
| 5618 | _ = self.builder.buildBr(block.parent_bb.toLlvm(&self.wip)); |
| 5621 | 5619 | return null; |
| 5622 | 5620 | } |
| 5623 | 5621 | |
| ... | ... | @@ -5628,14 +5626,14 @@ pub const FuncGen = struct { |
| 5628 | 5626 | const then_body = self.air.extra[extra.end..][0..extra.data.then_body_len]; |
| 5629 | 5627 | const else_body = self.air.extra[extra.end + then_body.len ..][0..extra.data.else_body_len]; |
| 5630 | 5628 | |
| 5631 | | const then_block = self.context.appendBasicBlock(self.llvm_func, "Then"); |
| 5632 | | const else_block = self.context.appendBasicBlock(self.llvm_func, "Else"); |
| 5633 | | _ = self.builder.buildCondBr(cond, then_block, else_block); |
| 5629 | const then_block = try self.wip.block("Then"); |
| 5630 | const else_block = try self.wip.block("Else"); |
| 5631 | _ = self.builder.buildCondBr(cond, then_block.toLlvm(&self.wip), else_block.toLlvm(&self.wip)); |
| 5634 | 5632 | |
| 5635 | | self.builder.positionBuilderAtEnd(then_block); |
| 5633 | self.builder.positionBuilderAtEnd(then_block.toLlvm(&self.wip)); |
| 5636 | 5634 | try self.genBody(then_body); |
| 5637 | 5635 | |
| 5638 | | self.builder.positionBuilderAtEnd(else_block); |
| 5636 | self.builder.positionBuilderAtEnd(else_block.toLlvm(&self.wip)); |
| 5639 | 5637 | try self.genBody(else_body); |
| 5640 | 5638 | |
| 5641 | 5639 | // No need to reset the insert cursor since this instruction is noreturn. |
| ... | ... | @@ -5707,14 +5705,14 @@ pub const FuncGen = struct { |
| 5707 | 5705 | break :err fg.builder.buildICmp(.NE, loaded, zero, ""); |
| 5708 | 5706 | }; |
| 5709 | 5707 | |
| 5710 | | const return_block = fg.context.appendBasicBlock(fg.llvm_func, "TryRet"); |
| 5711 | | const continue_block = fg.context.appendBasicBlock(fg.llvm_func, "TryCont"); |
| 5712 | | _ = fg.builder.buildCondBr(is_err, return_block, continue_block); |
| 5708 | const return_block = try fg.wip.block("TryRet"); |
| 5709 | const continue_block = try fg.wip.block("TryCont"); |
| 5710 | _ = fg.builder.buildCondBr(is_err, return_block.toLlvm(&fg.wip), continue_block.toLlvm(&fg.wip)); |
| 5713 | 5711 | |
| 5714 | | fg.builder.positionBuilderAtEnd(return_block); |
| 5712 | fg.builder.positionBuilderAtEnd(return_block.toLlvm(&fg.wip)); |
| 5715 | 5713 | try fg.genBody(body); |
| 5716 | 5714 | |
| 5717 | | fg.builder.positionBuilderAtEnd(continue_block); |
| 5715 | fg.builder.positionBuilderAtEnd(continue_block.toLlvm(&fg.wip)); |
| 5718 | 5716 | } |
| 5719 | 5717 | if (is_unused) { |
| 5720 | 5718 | return null; |
| ... | ... | @@ -5745,24 +5743,24 @@ pub const FuncGen = struct { |
| 5745 | 5743 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 5746 | 5744 | const cond = try self.resolveInst(pl_op.operand); |
| 5747 | 5745 | const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload); |
| 5748 | | const else_block = self.context.appendBasicBlock(self.llvm_func, "Else"); |
| 5746 | const else_block = try self.wip.block("Else"); |
| 5749 | 5747 | const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 5750 | 5748 | const cond_int = if (cond.typeOf().getTypeKind() == .Pointer) |
| 5751 | 5749 | self.builder.buildPtrToInt(cond, llvm_usize, "") |
| 5752 | 5750 | else |
| 5753 | 5751 | cond; |
| 5754 | | const llvm_switch = self.builder.buildSwitch(cond_int, else_block, switch_br.data.cases_len); |
| 5752 | const llvm_switch = self.builder.buildSwitch(cond_int, else_block.toLlvm(&self.wip), switch_br.data.cases_len); |
| 5755 | 5753 | |
| 5756 | 5754 | var extra_index: usize = switch_br.end; |
| 5757 | 5755 | var case_i: u32 = 0; |
| 5758 | 5756 | |
| 5759 | 5757 | while (case_i < switch_br.data.cases_len) : (case_i += 1) { |
| 5760 | 5758 | const case = self.air.extraData(Air.SwitchBr.Case, extra_index); |
| 5761 | | const items = @as([]const Air.Inst.Ref, @ptrCast(self.air.extra[case.end..][0..case.data.items_len])); |
| 5759 | const items: []const Air.Inst.Ref = @ptrCast(self.air.extra[case.end..][0..case.data.items_len]); |
| 5762 | 5760 | const case_body = self.air.extra[case.end + items.len ..][0..case.data.body_len]; |
| 5763 | 5761 | extra_index = case.end + case.data.items_len + case_body.len; |
| 5764 | 5762 | |
| 5765 | | const case_block = self.context.appendBasicBlock(self.llvm_func, "Case"); |
| 5763 | const case_block = try self.wip.block("Case"); |
| 5766 | 5764 | |
| 5767 | 5765 | for (items) |item| { |
| 5768 | 5766 | const llvm_item = try self.resolveInst(item); |
| ... | ... | @@ -5770,14 +5768,14 @@ pub const FuncGen = struct { |
| 5770 | 5768 | llvm_item.constPtrToInt(llvm_usize) |
| 5771 | 5769 | else |
| 5772 | 5770 | llvm_item; |
| 5773 | | llvm_switch.addCase(llvm_int_item, case_block); |
| 5771 | llvm_switch.addCase(llvm_int_item, case_block.toLlvm(&self.wip)); |
| 5774 | 5772 | } |
| 5775 | 5773 | |
| 5776 | | self.builder.positionBuilderAtEnd(case_block); |
| 5774 | self.builder.positionBuilderAtEnd(case_block.toLlvm(&self.wip)); |
| 5777 | 5775 | try self.genBody(case_body); |
| 5778 | 5776 | } |
| 5779 | 5777 | |
| 5780 | | self.builder.positionBuilderAtEnd(else_block); |
| 5778 | self.builder.positionBuilderAtEnd(else_block.toLlvm(&self.wip)); |
| 5781 | 5779 | const else_body = self.air.extra[extra_index..][0..switch_br.data.else_body_len]; |
| 5782 | 5780 | if (else_body.len != 0) { |
| 5783 | 5781 | try self.genBody(else_body); |
| ... | ... | @@ -5795,10 +5793,10 @@ pub const FuncGen = struct { |
| 5795 | 5793 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 5796 | 5794 | const loop = self.air.extraData(Air.Block, ty_pl.payload); |
| 5797 | 5795 | const body = self.air.extra[loop.end..][0..loop.data.body_len]; |
| 5798 | | const loop_block = self.context.appendBasicBlock(self.llvm_func, "Loop"); |
| 5799 | | _ = self.builder.buildBr(loop_block); |
| 5796 | const loop_block = try self.wip.block("Loop"); |
| 5797 | _ = self.builder.buildBr(loop_block.toLlvm(&self.wip)); |
| 5800 | 5798 | |
| 5801 | | self.builder.positionBuilderAtEnd(loop_block); |
| 5799 | self.builder.positionBuilderAtEnd(loop_block.toLlvm(&self.wip)); |
| 5802 | 5800 | try self.genBody(body); |
| 5803 | 5801 | |
| 5804 | 5802 | // TODO instead of this logic, change AIR to have the property that |
| ... | ... | @@ -5808,7 +5806,7 @@ pub const FuncGen = struct { |
| 5808 | 5806 | // be while(true) instead of for(body), which will eliminate 1 branch on |
| 5809 | 5807 | // a hot path. |
| 5810 | 5808 | if (body.len == 0 or !self.typeOfIndex(body[body.len - 1]).isNoReturn(mod)) { |
| 5811 | | _ = self.builder.buildBr(loop_block); |
| 5809 | _ = self.builder.buildBr(loop_block.toLlvm(&self.wip)); |
| 5812 | 5810 | } |
| 5813 | 5811 | return null; |
| 5814 | 5812 | } |
| ... | ... | @@ -5858,8 +5856,7 @@ pub const FuncGen = struct { |
| 5858 | 5856 | } |
| 5859 | 5857 | } |
| 5860 | 5858 | |
| 5861 | | const operand_bits = @as(u16, @intCast(operand_scalar_ty.bitSize(mod))); |
| 5862 | | const rt_int_bits = compilerRtIntBits(operand_bits); |
| 5859 | const rt_int_bits = compilerRtIntBits(@intCast(operand_scalar_ty.bitSize(mod))); |
| 5863 | 5860 | const rt_int_ty = try o.builder.intType(rt_int_bits); |
| 5864 | 5861 | var extended = e: { |
| 5865 | 5862 | if (operand_scalar_ty.isSignedInt(mod)) { |
| ... | ... | @@ -6193,13 +6190,11 @@ pub const FuncGen = struct { |
| 6193 | 6190 | const shifted_value = self.builder.buildLShr(containing_int, shift_amt, ""); |
| 6194 | 6191 | const elem_llvm_ty = (try o.lowerType(field_ty)).toLlvm(&o.builder); |
| 6195 | 6192 | if (field_ty.zigTypeTag(mod) == .Float or field_ty.zigTypeTag(mod) == .Vector) { |
| 6196 | | const elem_bits = @as(c_uint, @intCast(field_ty.bitSize(mod))); |
| 6197 | | const same_size_int = (try o.builder.intType(@intCast(elem_bits))).toLlvm(&o.builder); |
| 6193 | const same_size_int = (try o.builder.intType(@intCast(field_ty.bitSize(mod)))).toLlvm(&o.builder); |
| 6198 | 6194 | const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); |
| 6199 | 6195 | return self.builder.buildBitCast(truncated_int, elem_llvm_ty, ""); |
| 6200 | 6196 | } else if (field_ty.isPtrAtRuntime(mod)) { |
| 6201 | | const elem_bits = @as(c_uint, @intCast(field_ty.bitSize(mod))); |
| 6202 | | const same_size_int = (try o.builder.intType(@intCast(elem_bits))).toLlvm(&o.builder); |
| 6197 | const same_size_int = (try o.builder.intType(@intCast(field_ty.bitSize(mod)))).toLlvm(&o.builder); |
| 6203 | 6198 | const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); |
| 6204 | 6199 | return self.builder.buildIntToPtr(truncated_int, elem_llvm_ty, ""); |
| 6205 | 6200 | } |
| ... | ... | @@ -6215,13 +6210,11 @@ pub const FuncGen = struct { |
| 6215 | 6210 | const containing_int = struct_llvm_val; |
| 6216 | 6211 | const elem_llvm_ty = (try o.lowerType(field_ty)).toLlvm(&o.builder); |
| 6217 | 6212 | if (field_ty.zigTypeTag(mod) == .Float or field_ty.zigTypeTag(mod) == .Vector) { |
| 6218 | | const elem_bits = @as(c_uint, @intCast(field_ty.bitSize(mod))); |
| 6219 | | const same_size_int = (try o.builder.intType(@intCast(elem_bits))).toLlvm(&o.builder); |
| 6213 | const same_size_int = (try o.builder.intType(@intCast(field_ty.bitSize(mod)))).toLlvm(&o.builder); |
| 6220 | 6214 | const truncated_int = self.builder.buildTrunc(containing_int, same_size_int, ""); |
| 6221 | 6215 | return self.builder.buildBitCast(truncated_int, elem_llvm_ty, ""); |
| 6222 | 6216 | } else if (field_ty.isPtrAtRuntime(mod)) { |
| 6223 | | const elem_bits = @as(c_uint, @intCast(field_ty.bitSize(mod))); |
| 6224 | | const same_size_int = (try o.builder.intType(@intCast(elem_bits))).toLlvm(&o.builder); |
| 6217 | const same_size_int = (try o.builder.intType(@intCast(field_ty.bitSize(mod)))).toLlvm(&o.builder); |
| 6225 | 6218 | const truncated_int = self.builder.buildTrunc(containing_int, same_size_int, ""); |
| 6226 | 6219 | return self.builder.buildIntToPtr(truncated_int, elem_llvm_ty, ""); |
| 6227 | 6220 | } |
| ... | ... | @@ -6310,8 +6303,8 @@ pub const FuncGen = struct { |
| 6310 | 6303 | fn airDbgStmt(self: *FuncGen, inst: Air.Inst.Index) ?*llvm.Value { |
| 6311 | 6304 | const di_scope = self.di_scope orelse return null; |
| 6312 | 6305 | const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt; |
| 6313 | | self.prev_dbg_line = @as(c_uint, @intCast(self.base_line + dbg_stmt.line + 1)); |
| 6314 | | self.prev_dbg_column = @as(c_uint, @intCast(dbg_stmt.column + 1)); |
| 6306 | self.prev_dbg_line = @intCast(self.base_line + dbg_stmt.line + 1); |
| 6307 | self.prev_dbg_column = @intCast(dbg_stmt.column + 1); |
| 6315 | 6308 | const inlined_at = if (self.dbg_inlined.items.len > 0) |
| 6316 | 6309 | self.dbg_inlined.items[self.dbg_inlined.items.len - 1].loc |
| 6317 | 6310 | else |
| ... | ... | @@ -6491,12 +6484,12 @@ pub const FuncGen = struct { |
| 6491 | 6484 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 6492 | 6485 | const extra = self.air.extraData(Air.Asm, ty_pl.payload); |
| 6493 | 6486 | const is_volatile = @as(u1, @truncate(extra.data.flags >> 31)) != 0; |
| 6494 | | const clobbers_len = @as(u31, @truncate(extra.data.flags)); |
| 6487 | const clobbers_len: u31 = @truncate(extra.data.flags); |
| 6495 | 6488 | var extra_i: usize = extra.end; |
| 6496 | 6489 | |
| 6497 | | const outputs = @as([]const Air.Inst.Ref, @ptrCast(self.air.extra[extra_i..][0..extra.data.outputs_len])); |
| 6490 | const outputs: []const Air.Inst.Ref = @ptrCast(self.air.extra[extra_i..][0..extra.data.outputs_len]); |
| 6498 | 6491 | extra_i += outputs.len; |
| 6499 | | const inputs = @as([]const Air.Inst.Ref, @ptrCast(self.air.extra[extra_i..][0..extra.data.inputs_len])); |
| 6492 | const inputs: []const Air.Inst.Ref = @ptrCast(self.air.extra[extra_i..][0..extra.data.inputs_len]); |
| 6500 | 6493 | extra_i += inputs.len; |
| 6501 | 6494 | |
| 6502 | 6495 | var llvm_constraints: std.ArrayListUnmanaged(u8) = .{}; |
| ... | ... | @@ -6779,7 +6772,7 @@ pub const FuncGen = struct { |
| 6779 | 6772 | const llvm_fn_ty = llvm.functionType( |
| 6780 | 6773 | ret_llvm_ty.toLlvm(&o.builder), |
| 6781 | 6774 | llvm_param_types.ptr, |
| 6782 | | @as(c_uint, @intCast(param_count)), |
| 6775 | @intCast(param_count), |
| 6783 | 6776 | .False, |
| 6784 | 6777 | ); |
| 6785 | 6778 | const asm_fn = llvm.getInlineAsm( |
| ... | ... | @@ -6797,7 +6790,7 @@ pub const FuncGen = struct { |
| 6797 | 6790 | llvm_fn_ty, |
| 6798 | 6791 | asm_fn, |
| 6799 | 6792 | llvm_param_values.ptr, |
| 6800 | | @as(c_uint, @intCast(param_count)), |
| 6793 | @intCast(param_count), |
| 6801 | 6794 | .C, |
| 6802 | 6795 | .Auto, |
| 6803 | 6796 | "", |
| ... | ... | @@ -6814,7 +6807,7 @@ pub const FuncGen = struct { |
| 6814 | 6807 | if (llvm_ret_indirect[i]) continue; |
| 6815 | 6808 | |
| 6816 | 6809 | const output_value = if (return_count > 1) b: { |
| 6817 | | break :b self.builder.buildExtractValue(call, @as(c_uint, @intCast(llvm_ret_i)), ""); |
| 6810 | break :b self.builder.buildExtractValue(call, @intCast(llvm_ret_i), ""); |
| 6818 | 6811 | } else call; |
| 6819 | 6812 | |
| 6820 | 6813 | if (output != .none) { |
| ... | ... | @@ -7364,14 +7357,14 @@ pub const FuncGen = struct { |
| 7364 | 7357 | false => fg.builder.buildOrReduce(overflow_bit), |
| 7365 | 7358 | }; |
| 7366 | 7359 | |
| 7367 | | const fail_block = fg.context.appendBasicBlock(fg.llvm_func, "OverflowFail"); |
| 7368 | | const ok_block = fg.context.appendBasicBlock(fg.llvm_func, "OverflowOk"); |
| 7369 | | _ = fg.builder.buildCondBr(scalar_overflow_bit, fail_block, ok_block); |
| 7360 | const fail_block = try fg.wip.block("OverflowFail"); |
| 7361 | const ok_block = try fg.wip.block("OverflowOk"); |
| 7362 | _ = fg.builder.buildCondBr(scalar_overflow_bit, fail_block.toLlvm(&fg.wip), ok_block.toLlvm(&fg.wip)); |
| 7370 | 7363 | |
| 7371 | | fg.builder.positionBuilderAtEnd(fail_block); |
| 7364 | fg.builder.positionBuilderAtEnd(fail_block.toLlvm(&fg.wip)); |
| 7372 | 7365 | try fg.buildSimplePanic(.integer_overflow); |
| 7373 | 7366 | |
| 7374 | | fg.builder.positionBuilderAtEnd(ok_block); |
| 7367 | fg.builder.positionBuilderAtEnd(ok_block.toLlvm(&fg.wip)); |
| 7375 | 7368 | return fg.builder.buildExtractValue(result_struct, 0, ""); |
| 7376 | 7369 | } |
| 7377 | 7370 | |
| ... | ... | @@ -7729,8 +7722,7 @@ pub const FuncGen = struct { |
| 7729 | 7722 | vector_len: usize, |
| 7730 | 7723 | ) !*llvm.Value { |
| 7731 | 7724 | const o = self.dg.object; |
| 7732 | | const args_len = @as(c_uint, @intCast(args_vectors.len)); |
| 7733 | | assert(args_len <= 3); |
| 7725 | assert(args_vectors.len <= 3); |
| 7734 | 7726 | |
| 7735 | 7727 | var i: usize = 0; |
| 7736 | 7728 | var result = result_vector; |
| ... | ... | @@ -7741,7 +7733,7 @@ pub const FuncGen = struct { |
| 7741 | 7733 | for (args_vectors, 0..) |arg_vector, k| { |
| 7742 | 7734 | args[k] = self.builder.buildExtractElement(arg_vector, index_i32, ""); |
| 7743 | 7735 | } |
| 7744 | | const result_elem = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args_len, .C, .Auto, ""); |
| 7736 | const result_elem = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, @intCast(args_vectors.len), .C, .Auto, ""); |
| 7745 | 7737 | result = self.builder.buildInsertElement(result, result_elem, index_i32, ""); |
| 7746 | 7738 | } |
| 7747 | 7739 | return result; |
| ... | ... | @@ -8744,8 +8736,8 @@ pub const FuncGen = struct { |
| 8744 | 8736 | return null; |
| 8745 | 8737 | const ordering = toLlvmAtomicOrdering(atomic_load.order); |
| 8746 | 8738 | const abi_ty = try o.getAtomicAbiType(elem_ty, false); |
| 8747 | | const ptr_alignment = @as(u32, @intCast(ptr_info.flags.alignment.toByteUnitsOptional() orelse |
| 8748 | | ptr_info.child.toType().abiAlignment(mod))); |
| 8739 | const ptr_alignment: u32 = @intCast(ptr_info.flags.alignment.toByteUnitsOptional() orelse |
| 8740 | ptr_info.child.toType().abiAlignment(mod)); |
| 8749 | 8741 | const ptr_volatile = llvm.Bool.fromBool(ptr_info.flags.is_volatile); |
| 8750 | 8742 | const elem_llvm_ty = (try o.lowerType(elem_ty)).toLlvm(&o.builder); |
| 8751 | 8743 | |
| ... | ... | @@ -8887,9 +8879,9 @@ pub const FuncGen = struct { |
| 8887 | 8879 | // end: |
| 8888 | 8880 | // ... |
| 8889 | 8881 | const entry_block = self.builder.getInsertBlock(); |
| 8890 | | const loop_block = self.context.appendBasicBlock(self.llvm_func, "InlineMemsetLoop"); |
| 8891 | | const body_block = self.context.appendBasicBlock(self.llvm_func, "InlineMemsetBody"); |
| 8892 | | const end_block = self.context.appendBasicBlock(self.llvm_func, "InlineMemsetEnd"); |
| 8882 | const loop_block = try self.wip.block("InlineMemsetLoop"); |
| 8883 | const body_block = try self.wip.block("InlineMemsetBody"); |
| 8884 | const end_block = try self.wip.block("InlineMemsetEnd"); |
| 8893 | 8885 | |
| 8894 | 8886 | const usize_ty = try o.lowerType(Type.usize); |
| 8895 | 8887 | const len = switch (ptr_ty.ptrSize(mod)) { |
| ... | ... | @@ -8900,14 +8892,14 @@ pub const FuncGen = struct { |
| 8900 | 8892 | const elem_llvm_ty = (try o.lowerType(elem_ty)).toLlvm(&o.builder); |
| 8901 | 8893 | const len_gep = [_]*llvm.Value{len}; |
| 8902 | 8894 | const end_ptr = self.builder.buildInBoundsGEP(elem_llvm_ty, dest_ptr, &len_gep, len_gep.len, ""); |
| 8903 | | _ = self.builder.buildBr(loop_block); |
| 8895 | _ = self.builder.buildBr(loop_block.toLlvm(&self.wip)); |
| 8904 | 8896 | |
| 8905 | | self.builder.positionBuilderAtEnd(loop_block); |
| 8906 | | const it_ptr = self.builder.buildPhi(self.context.pointerType(0), ""); |
| 8897 | self.builder.positionBuilderAtEnd(loop_block.toLlvm(&self.wip)); |
| 8898 | const it_ptr = self.builder.buildPhi(Builder.Type.ptr.toLlvm(&o.builder), ""); |
| 8907 | 8899 | const end = self.builder.buildICmp(.NE, it_ptr, end_ptr, ""); |
| 8908 | | _ = self.builder.buildCondBr(end, body_block, end_block); |
| 8900 | _ = self.builder.buildCondBr(end, body_block.toLlvm(&self.wip), end_block.toLlvm(&self.wip)); |
| 8909 | 8901 | |
| 8910 | | self.builder.positionBuilderAtEnd(body_block); |
| 8902 | self.builder.positionBuilderAtEnd(body_block.toLlvm(&self.wip)); |
| 8911 | 8903 | const elem_abi_alignment = elem_ty.abiAlignment(mod); |
| 8912 | 8904 | const it_ptr_alignment = @min(elem_abi_alignment, dest_ptr_align); |
| 8913 | 8905 | if (isByRef(elem_ty, mod)) { |
| ... | ... | @@ -8928,12 +8920,12 @@ pub const FuncGen = struct { |
| 8928 | 8920 | (try o.builder.intConst(usize_ty, 1)).toLlvm(&o.builder), |
| 8929 | 8921 | }; |
| 8930 | 8922 | const next_ptr = self.builder.buildInBoundsGEP(elem_llvm_ty, it_ptr, &one_gep, one_gep.len, ""); |
| 8931 | | _ = self.builder.buildBr(loop_block); |
| 8923 | _ = self.builder.buildBr(loop_block.toLlvm(&self.wip)); |
| 8932 | 8924 | |
| 8933 | | self.builder.positionBuilderAtEnd(end_block); |
| 8925 | self.builder.positionBuilderAtEnd(end_block.toLlvm(&self.wip)); |
| 8934 | 8926 | |
| 8935 | 8927 | const incoming_values: [2]*llvm.Value = .{ next_ptr, dest_ptr }; |
| 8936 | | const incoming_blocks: [2]*llvm.BasicBlock = .{ body_block, entry_block }; |
| 8928 | const incoming_blocks: [2]*llvm.BasicBlock = .{ body_block.toLlvm(&self.wip), entry_block }; |
| 8937 | 8929 | it_ptr.addIncoming(&incoming_values, &incoming_blocks, 2); |
| 8938 | 8930 | |
| 8939 | 8931 | return null; |
| ... | ... | @@ -8950,13 +8942,13 @@ pub const FuncGen = struct { |
| 8950 | 8942 | const o = self.dg.object; |
| 8951 | 8943 | const llvm_usize_ty = try o.lowerType(Type.usize); |
| 8952 | 8944 | const cond = try self.cmp(len, (try o.builder.intConst(llvm_usize_ty, 0)).toLlvm(&o.builder), Type.usize, .neq); |
| 8953 | | const memset_block = self.context.appendBasicBlock(self.llvm_func, "MemsetTrapSkip"); |
| 8954 | | const end_block = self.context.appendBasicBlock(self.llvm_func, "MemsetTrapEnd"); |
| 8955 | | _ = self.builder.buildCondBr(cond, memset_block, end_block); |
| 8956 | | self.builder.positionBuilderAtEnd(memset_block); |
| 8945 | const memset_block = try self.wip.block("MemsetTrapSkip"); |
| 8946 | const end_block = try self.wip.block("MemsetTrapEnd"); |
| 8947 | _ = self.builder.buildCondBr(cond, memset_block.toLlvm(&self.wip), end_block.toLlvm(&self.wip)); |
| 8948 | self.builder.positionBuilderAtEnd(memset_block.toLlvm(&self.wip)); |
| 8957 | 8949 | _ = self.builder.buildMemSet(dest_ptr, fill_byte, len, dest_ptr_align, is_volatile); |
| 8958 | | _ = self.builder.buildBr(end_block); |
| 8959 | | self.builder.positionBuilderAtEnd(end_block); |
| 8950 | _ = self.builder.buildBr(end_block.toLlvm(&self.wip)); |
| 8951 | self.builder.positionBuilderAtEnd(end_block.toLlvm(&self.wip)); |
| 8960 | 8952 | } |
| 8961 | 8953 | |
| 8962 | 8954 | fn airMemcpy(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| ... | ... | @@ -8983,10 +8975,10 @@ pub const FuncGen = struct { |
| 8983 | 8975 | { |
| 8984 | 8976 | const llvm_usize_ty = try o.lowerType(Type.usize); |
| 8985 | 8977 | const cond = try self.cmp(len, (try o.builder.intConst(llvm_usize_ty, 0)).toLlvm(&o.builder), Type.usize, .neq); |
| 8986 | | const memcpy_block = self.context.appendBasicBlock(self.llvm_func, "MemcpyTrapSkip"); |
| 8987 | | const end_block = self.context.appendBasicBlock(self.llvm_func, "MemcpyTrapEnd"); |
| 8988 | | _ = self.builder.buildCondBr(cond, memcpy_block, end_block); |
| 8989 | | self.builder.positionBuilderAtEnd(memcpy_block); |
| 8978 | const memcpy_block = try self.wip.block("MemcpyTrapSkip"); |
| 8979 | const end_block = try self.wip.block("MemcpyTrapEnd"); |
| 8980 | _ = self.builder.buildCondBr(cond, memcpy_block.toLlvm(&self.wip), end_block.toLlvm(&self.wip)); |
| 8981 | self.builder.positionBuilderAtEnd(memcpy_block.toLlvm(&self.wip)); |
| 8990 | 8982 | _ = self.builder.buildMemCpy( |
| 8991 | 8983 | dest_ptr, |
| 8992 | 8984 | dest_ptr_ty.ptrAlignment(mod), |
| ... | ... | @@ -8995,8 +8987,8 @@ pub const FuncGen = struct { |
| 8995 | 8987 | len, |
| 8996 | 8988 | is_volatile, |
| 8997 | 8989 | ); |
| 8998 | | _ = self.builder.buildBr(end_block); |
| 8999 | | self.builder.positionBuilderAtEnd(end_block); |
| 8990 | _ = self.builder.buildBr(end_block.toLlvm(&self.wip)); |
| 8991 | self.builder.positionBuilderAtEnd(end_block.toLlvm(&self.wip)); |
| 9000 | 8992 | return null; |
| 9001 | 8993 | } |
| 9002 | 8994 | |
| ... | ... | @@ -9179,31 +9171,31 @@ pub const FuncGen = struct { |
| 9179 | 9171 | const error_set_ty = self.air.getRefType(ty_op.ty); |
| 9180 | 9172 | |
| 9181 | 9173 | const names = error_set_ty.errorSetNames(mod); |
| 9182 | | const valid_block = self.context.appendBasicBlock(self.llvm_func, "Valid"); |
| 9183 | | const invalid_block = self.context.appendBasicBlock(self.llvm_func, "Invalid"); |
| 9184 | | const end_block = self.context.appendBasicBlock(self.llvm_func, "End"); |
| 9185 | | const switch_instr = self.builder.buildSwitch(operand, invalid_block, @as(c_uint, @intCast(names.len))); |
| 9174 | const valid_block = try self.wip.block("Valid"); |
| 9175 | const invalid_block = try self.wip.block("Invalid"); |
| 9176 | const end_block = try self.wip.block("End"); |
| 9177 | const switch_instr = self.builder.buildSwitch(operand, invalid_block.toLlvm(&self.wip), @intCast(names.len)); |
| 9186 | 9178 | |
| 9187 | 9179 | for (names) |name| { |
| 9188 | | const err_int = @as(Module.ErrorInt, @intCast(mod.global_error_set.getIndex(name).?)); |
| 9180 | const err_int = mod.global_error_set.getIndex(name).?; |
| 9189 | 9181 | const this_tag_int_value = |
| 9190 | 9182 | try o.lowerValue((try mod.intValue(Type.err_int, err_int)).toIntern()); |
| 9191 | | switch_instr.addCase(this_tag_int_value.toLlvm(&o.builder), valid_block); |
| 9183 | switch_instr.addCase(this_tag_int_value.toLlvm(&o.builder), valid_block.toLlvm(&self.wip)); |
| 9192 | 9184 | } |
| 9193 | | self.builder.positionBuilderAtEnd(valid_block); |
| 9194 | | _ = self.builder.buildBr(end_block); |
| 9185 | self.builder.positionBuilderAtEnd(valid_block.toLlvm(&self.wip)); |
| 9186 | _ = self.builder.buildBr(end_block.toLlvm(&self.wip)); |
| 9195 | 9187 | |
| 9196 | | self.builder.positionBuilderAtEnd(invalid_block); |
| 9197 | | _ = self.builder.buildBr(end_block); |
| 9188 | self.builder.positionBuilderAtEnd(invalid_block.toLlvm(&self.wip)); |
| 9189 | _ = self.builder.buildBr(end_block.toLlvm(&self.wip)); |
| 9198 | 9190 | |
| 9199 | | self.builder.positionBuilderAtEnd(end_block); |
| 9191 | self.builder.positionBuilderAtEnd(end_block.toLlvm(&self.wip)); |
| 9200 | 9192 | |
| 9201 | 9193 | const incoming_values: [2]*llvm.Value = .{ |
| 9202 | 9194 | Builder.Constant.true.toLlvm(&o.builder), |
| 9203 | 9195 | Builder.Constant.false.toLlvm(&o.builder), |
| 9204 | 9196 | }; |
| 9205 | 9197 | const incoming_blocks: [2]*llvm.BasicBlock = .{ |
| 9206 | | valid_block, invalid_block, |
| 9198 | valid_block.toLlvm(&self.wip), invalid_block.toLlvm(&self.wip), |
| 9207 | 9199 | }; |
| 9208 | 9200 | const phi_node = self.builder.buildPhi(Builder.Type.i1.toLlvm(&o.builder), ""); |
| 9209 | 9201 | phi_node.addIncoming(&incoming_values, &incoming_blocks, 2); |
| ... | ... | @@ -9250,8 +9242,11 @@ pub const FuncGen = struct { |
| 9250 | 9242 | }; |
| 9251 | 9243 | var function = Builder.Function{ |
| 9252 | 9244 | .global = @enumFromInt(o.builder.globals.count()), |
| 9253 | | .body = {}, |
| 9254 | 9245 | }; |
| 9246 | try o.builder.llvm.globals.append(self.gpa, fn_val); |
| 9247 | _ = try o.builder.addGlobal(llvm_fn_name, global); |
| 9248 | try o.builder.functions.append(self.gpa, function); |
| 9249 | gop.value_ptr.* = global.kind.function; |
| 9255 | 9250 | |
| 9256 | 9251 | const prev_block = self.builder.getInsertBlock(); |
| 9257 | 9252 | const prev_debug_location = self.builder.getCurrentDebugLocation2(); |
| ... | ... | @@ -9262,31 +9257,30 @@ pub const FuncGen = struct { |
| 9262 | 9257 | } |
| 9263 | 9258 | } |
| 9264 | 9259 | |
| 9265 | | const entry_block = self.context.appendBasicBlock(fn_val, "Entry"); |
| 9266 | | self.builder.positionBuilderAtEnd(entry_block); |
| 9260 | var wip = Builder.WipFunction.init(&o.builder, global.kind.function); |
| 9261 | defer wip.deinit(); |
| 9262 | |
| 9263 | const entry_block = try wip.block("Entry"); |
| 9264 | self.builder.positionBuilderAtEnd(entry_block.toLlvm(&wip)); |
| 9267 | 9265 | self.builder.clearCurrentDebugLocation(); |
| 9268 | 9266 | |
| 9269 | | const named_block = self.context.appendBasicBlock(fn_val, "Named"); |
| 9270 | | const unnamed_block = self.context.appendBasicBlock(fn_val, "Unnamed"); |
| 9267 | const named_block = try wip.block("Named"); |
| 9268 | const unnamed_block = try wip.block("Unnamed"); |
| 9271 | 9269 | const tag_int_value = fn_val.getParam(0); |
| 9272 | | const switch_instr = self.builder.buildSwitch(tag_int_value, unnamed_block, @as(c_uint, @intCast(enum_type.names.len))); |
| 9270 | const switch_instr = self.builder.buildSwitch(tag_int_value, unnamed_block.toLlvm(&wip), @intCast(enum_type.names.len)); |
| 9273 | 9271 | |
| 9274 | | for (enum_type.names, 0..) |_, field_index_usize| { |
| 9275 | | const field_index = @as(u32, @intCast(field_index_usize)); |
| 9272 | for (0..enum_type.names.len) |field_index| { |
| 9276 | 9273 | const this_tag_int_value = |
| 9277 | | try o.lowerValue((try mod.enumValueFieldIndex(enum_ty, field_index)).toIntern()); |
| 9278 | | switch_instr.addCase(this_tag_int_value.toLlvm(&o.builder), named_block); |
| 9274 | try o.lowerValue((try mod.enumValueFieldIndex(enum_ty, @intCast(field_index))).toIntern()); |
| 9275 | switch_instr.addCase(this_tag_int_value.toLlvm(&o.builder), named_block.toLlvm(&wip)); |
| 9279 | 9276 | } |
| 9280 | | self.builder.positionBuilderAtEnd(named_block); |
| 9277 | self.builder.positionBuilderAtEnd(named_block.toLlvm(&wip)); |
| 9281 | 9278 | _ = self.builder.buildRet(Builder.Constant.true.toLlvm(&o.builder)); |
| 9282 | 9279 | |
| 9283 | | self.builder.positionBuilderAtEnd(unnamed_block); |
| 9280 | self.builder.positionBuilderAtEnd(unnamed_block.toLlvm(&wip)); |
| 9284 | 9281 | _ = self.builder.buildRet(Builder.Constant.false.toLlvm(&o.builder)); |
| 9285 | 9282 | |
| 9286 | | try o.builder.llvm.globals.append(self.gpa, fn_val); |
| 9287 | | _ = try o.builder.addGlobal(llvm_fn_name, global); |
| 9288 | | try o.builder.functions.append(self.gpa, function); |
| 9289 | | gop.value_ptr.* = global.kind.function; |
| 9283 | try wip.finish(); |
| 9290 | 9284 | return fn_val; |
| 9291 | 9285 | } |
| 9292 | 9286 | |
| ... | ... | @@ -9331,8 +9325,10 @@ pub const FuncGen = struct { |
| 9331 | 9325 | }; |
| 9332 | 9326 | var function = Builder.Function{ |
| 9333 | 9327 | .global = @enumFromInt(o.builder.globals.count()), |
| 9334 | | .body = {}, |
| 9335 | 9328 | }; |
| 9329 | try o.builder.llvm.globals.append(self.gpa, fn_val); |
| 9330 | gop.value_ptr.* = try o.builder.addGlobal(llvm_fn_name, global); |
| 9331 | try o.builder.functions.append(self.gpa, function); |
| 9336 | 9332 | |
| 9337 | 9333 | const prev_block = self.builder.getInsertBlock(); |
| 9338 | 9334 | const prev_debug_location = self.builder.getCurrentDebugLocation2(); |
| ... | ... | @@ -9343,16 +9339,18 @@ pub const FuncGen = struct { |
| 9343 | 9339 | } |
| 9344 | 9340 | } |
| 9345 | 9341 | |
| 9346 | | const entry_block = self.context.appendBasicBlock(fn_val, "Entry"); |
| 9347 | | self.builder.positionBuilderAtEnd(entry_block); |
| 9342 | var wip = Builder.WipFunction.init(&o.builder, global.kind.function); |
| 9343 | defer wip.deinit(); |
| 9344 | |
| 9345 | const entry_block = try wip.block("Entry"); |
| 9346 | self.builder.positionBuilderAtEnd(entry_block.toLlvm(&wip)); |
| 9348 | 9347 | self.builder.clearCurrentDebugLocation(); |
| 9349 | 9348 | |
| 9350 | | const bad_value_block = self.context.appendBasicBlock(fn_val, "BadValue"); |
| 9349 | const bad_value_block = try wip.block("BadValue"); |
| 9351 | 9350 | const tag_int_value = fn_val.getParam(0); |
| 9352 | | const switch_instr = self.builder.buildSwitch(tag_int_value, bad_value_block, @as(c_uint, @intCast(enum_type.names.len))); |
| 9351 | const switch_instr = self.builder.buildSwitch(tag_int_value, bad_value_block.toLlvm(&wip), @intCast(enum_type.names.len)); |
| 9353 | 9352 | |
| 9354 | | for (enum_type.names, 0..) |name_ip, field_index_usize| { |
| 9355 | | const field_index = @as(u32, @intCast(field_index_usize)); |
| 9353 | for (enum_type.names, 0..) |name_ip, field_index| { |
| 9356 | 9354 | const name = try o.builder.string(mod.intern_pool.stringToSlice(name_ip)); |
| 9357 | 9355 | const str_init = try o.builder.stringNullConst(name); |
| 9358 | 9356 | const str_ty = str_init.typeOf(&o.builder); |
| ... | ... | @@ -9384,35 +9382,32 @@ pub const FuncGen = struct { |
| 9384 | 9382 | try o.builder.intConst(usize_ty, name.toSlice(&o.builder).?.len), |
| 9385 | 9383 | }); |
| 9386 | 9384 | |
| 9387 | | const return_block = self.context.appendBasicBlock(fn_val, "Name"); |
| 9385 | const return_block = try wip.block("Name"); |
| 9388 | 9386 | const this_tag_int_value = |
| 9389 | | try o.lowerValue((try mod.enumValueFieldIndex(enum_ty, field_index)).toIntern()); |
| 9390 | | switch_instr.addCase(this_tag_int_value.toLlvm(&o.builder), return_block); |
| 9387 | try o.lowerValue((try mod.enumValueFieldIndex(enum_ty, @intCast(field_index))).toIntern()); |
| 9388 | switch_instr.addCase(this_tag_int_value.toLlvm(&o.builder), return_block.toLlvm(&wip)); |
| 9391 | 9389 | |
| 9392 | | self.builder.positionBuilderAtEnd(return_block); |
| 9390 | self.builder.positionBuilderAtEnd(return_block.toLlvm(&wip)); |
| 9393 | 9391 | _ = self.builder.buildRet(slice_val.toLlvm(&o.builder)); |
| 9394 | 9392 | } |
| 9395 | 9393 | |
| 9396 | | self.builder.positionBuilderAtEnd(bad_value_block); |
| 9394 | self.builder.positionBuilderAtEnd(bad_value_block.toLlvm(&wip)); |
| 9397 | 9395 | _ = self.builder.buildUnreachable(); |
| 9398 | 9396 | |
| 9399 | | try o.builder.llvm.globals.append(self.gpa, fn_val); |
| 9400 | | gop.value_ptr.* = try o.builder.addGlobal(llvm_fn_name, global); |
| 9401 | | try o.builder.functions.append(self.gpa, function); |
| 9397 | try wip.finish(); |
| 9402 | 9398 | return fn_val; |
| 9403 | 9399 | } |
| 9404 | 9400 | |
| 9405 | 9401 | fn getCmpLtErrorsLenFunction(self: *FuncGen) !*llvm.Value { |
| 9406 | 9402 | const o = self.dg.object; |
| 9407 | 9403 | |
| 9408 | | if (o.llvm_module.getNamedFunction(lt_errors_fn_name)) |llvm_fn| { |
| 9409 | | return llvm_fn; |
| 9410 | | } |
| 9404 | const name = try o.builder.string(lt_errors_fn_name); |
| 9405 | if (o.builder.getGlobal(name)) |llvm_fn| return llvm_fn.toLlvm(&o.builder); |
| 9411 | 9406 | |
| 9412 | 9407 | // Function signature: fn (anyerror) bool |
| 9413 | 9408 | |
| 9414 | 9409 | const fn_type = try o.builder.fnType(.i1, &.{Builder.Type.err_int}, .normal); |
| 9415 | | const llvm_fn = o.llvm_module.addFunction(lt_errors_fn_name, fn_type.toLlvm(&o.builder)); |
| 9410 | const llvm_fn = o.llvm_module.addFunction(name.toSlice(&o.builder).?, fn_type.toLlvm(&o.builder)); |
| 9416 | 9411 | |
| 9417 | 9412 | llvm_fn.setLinkage(.Internal); |
| 9418 | 9413 | llvm_fn.setFunctionCallConv(.Fast); |
| ... | ... | @@ -9425,13 +9420,12 @@ pub const FuncGen = struct { |
| 9425 | 9420 | }; |
| 9426 | 9421 | var function = Builder.Function{ |
| 9427 | 9422 | .global = @enumFromInt(o.builder.globals.count()), |
| 9428 | | .body = {}, |
| 9429 | 9423 | }; |
| 9430 | 9424 | |
| 9431 | 9425 | try o.builder.llvm.globals.append(self.gpa, llvm_fn); |
| 9432 | | _ = try o.builder.addGlobal(try o.builder.string(lt_errors_fn_name), global); |
| 9426 | const global_index = try o.builder.addGlobal(name, global); |
| 9433 | 9427 | try o.builder.functions.append(self.gpa, function); |
| 9434 | | return llvm_fn; |
| 9428 | return global_index.toLlvm(&o.builder); |
| 9435 | 9429 | } |
| 9436 | 9430 | |
| 9437 | 9431 | fn airErrorName(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| ... | ... | @@ -9494,7 +9488,7 @@ pub const FuncGen = struct { |
| 9494 | 9488 | val.* = try o.builder.undefConst(.i32); |
| 9495 | 9489 | } else { |
| 9496 | 9490 | const int = elem.toSignedInt(mod); |
| 9497 | | const unsigned = if (int >= 0) @as(u32, @intCast(int)) else @as(u32, @intCast(~int + a_len)); |
| 9491 | const unsigned: u32 = @intCast(if (int >= 0) int else ~int + a_len); |
| 9498 | 9492 | val.* = try o.builder.intConst(.i32, unsigned); |
| 9499 | 9493 | } |
| 9500 | 9494 | } |
| ... | ... | @@ -9537,21 +9531,21 @@ pub const FuncGen = struct { |
| 9537 | 9531 | _ = self.builder.buildStore(accum_init, accum_ptr); |
| 9538 | 9532 | |
| 9539 | 9533 | // Setup the loop |
| 9540 | | const loop = self.context.appendBasicBlock(self.llvm_func, "ReduceLoop"); |
| 9541 | | const loop_exit = self.context.appendBasicBlock(self.llvm_func, "AfterReduce"); |
| 9542 | | _ = self.builder.buildBr(loop); |
| 9534 | const loop = try self.wip.block("ReduceLoop"); |
| 9535 | const loop_exit = try self.wip.block("AfterReduce"); |
| 9536 | _ = self.builder.buildBr(loop.toLlvm(&self.wip)); |
| 9543 | 9537 | { |
| 9544 | | self.builder.positionBuilderAtEnd(loop); |
| 9538 | self.builder.positionBuilderAtEnd(loop.toLlvm(&self.wip)); |
| 9545 | 9539 | |
| 9546 | 9540 | // while (i < vec.len) |
| 9547 | 9541 | const i = self.builder.buildLoad(usize_ty.toLlvm(&o.builder), i_ptr, ""); |
| 9548 | 9542 | const cond = self.builder.buildICmp(.ULT, i, llvm_vector_len.toLlvm(&o.builder), ""); |
| 9549 | | const loop_then = self.context.appendBasicBlock(self.llvm_func, "ReduceLoopThen"); |
| 9543 | const loop_then = try self.wip.block("ReduceLoopThen"); |
| 9550 | 9544 | |
| 9551 | | _ = self.builder.buildCondBr(cond, loop_then, loop_exit); |
| 9545 | _ = self.builder.buildCondBr(cond, loop_then.toLlvm(&self.wip), loop_exit.toLlvm(&self.wip)); |
| 9552 | 9546 | |
| 9553 | 9547 | { |
| 9554 | | self.builder.positionBuilderAtEnd(loop_then); |
| 9548 | self.builder.positionBuilderAtEnd(loop_then.toLlvm(&self.wip)); |
| 9555 | 9549 | |
| 9556 | 9550 | // accum = f(accum, vec[i]); |
| 9557 | 9551 | const accum = self.builder.buildLoad(llvm_result_ty, accum_ptr, ""); |
| ... | ... | @@ -9563,11 +9557,11 @@ pub const FuncGen = struct { |
| 9563 | 9557 | // i += 1 |
| 9564 | 9558 | const new_i = self.builder.buildAdd(i, (try o.builder.intConst(usize_ty, 1)).toLlvm(&o.builder), ""); |
| 9565 | 9559 | _ = self.builder.buildStore(new_i, i_ptr); |
| 9566 | | _ = self.builder.buildBr(loop); |
| 9560 | _ = self.builder.buildBr(loop.toLlvm(&self.wip)); |
| 9567 | 9561 | } |
| 9568 | 9562 | } |
| 9569 | 9563 | |
| 9570 | | self.builder.positionBuilderAtEnd(loop_exit); |
| 9564 | self.builder.positionBuilderAtEnd(loop_exit.toLlvm(&self.wip)); |
| 9571 | 9565 | return self.builder.buildLoad(llvm_result_ty, accum_ptr, ""); |
| 9572 | 9566 | } |
| 9573 | 9567 | |
| ... | ... | @@ -9656,8 +9650,8 @@ pub const FuncGen = struct { |
| 9656 | 9650 | const mod = o.module; |
| 9657 | 9651 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 9658 | 9652 | const result_ty = self.typeOfIndex(inst); |
| 9659 | | const len = @as(usize, @intCast(result_ty.arrayLen(mod))); |
| 9660 | | const elements = @as([]const Air.Inst.Ref, @ptrCast(self.air.extra[ty_pl.payload..][0..len])); |
| 9653 | const len: usize = @intCast(result_ty.arrayLen(mod)); |
| 9654 | const elements: []const Air.Inst.Ref = @ptrCast(self.air.extra[ty_pl.payload..][0..len]); |
| 9661 | 9655 | const llvm_result_ty = (try o.lowerType(result_ty)).toLlvm(&o.builder); |
| 9662 | 9656 | |
| 9663 | 9657 | switch (result_ty.zigTypeTag(mod)) { |
| ... | ... | @@ -9685,8 +9679,8 @@ pub const FuncGen = struct { |
| 9685 | 9679 | if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 9686 | 9680 | |
| 9687 | 9681 | const non_int_val = try self.resolveInst(elem); |
| 9688 | | const ty_bit_size = @as(u16, @intCast(field.ty.bitSize(mod))); |
| 9689 | | const small_int_ty = (try o.builder.intType(@intCast(ty_bit_size))).toLlvm(&o.builder); |
| 9682 | const ty_bit_size: u16 = @intCast(field.ty.bitSize(mod)); |
| 9683 | const small_int_ty = (try o.builder.intType(ty_bit_size)).toLlvm(&o.builder); |
| 9690 | 9684 | const small_int_val = if (field.ty.isPtrAtRuntime(mod)) |
| 9691 | 9685 | self.builder.buildPtrToInt(non_int_val, small_int_ty, "") |
| 9692 | 9686 | else |
| ... | ... | @@ -9798,8 +9792,7 @@ pub const FuncGen = struct { |
| 9798 | 9792 | const int_llvm_ty = (try o.builder.intType(@intCast(big_bits))).toLlvm(&o.builder); |
| 9799 | 9793 | const field = union_obj.fields.values()[extra.field_index]; |
| 9800 | 9794 | const non_int_val = try self.resolveInst(extra.init); |
| 9801 | | const ty_bit_size = @as(u16, @intCast(field.ty.bitSize(mod))); |
| 9802 | | const small_int_ty = (try o.builder.intType(@intCast(ty_bit_size))).toLlvm(&o.builder); |
| 9795 | const small_int_ty = (try o.builder.intType(@intCast(field.ty.bitSize(mod)))).toLlvm(&o.builder); |
| 9803 | 9796 | const small_int_val = if (field.ty.isPtrAtRuntime(mod)) |
| 9804 | 9797 | self.builder.buildPtrToInt(non_int_val, small_int_ty, "") |
| 9805 | 9798 | else |
| ... | ... | @@ -10273,8 +10266,8 @@ pub const FuncGen = struct { |
| 10273 | 10266 | const elem_ty = info.child.toType(); |
| 10274 | 10267 | if (!elem_ty.hasRuntimeBitsIgnoreComptime(mod)) return null; |
| 10275 | 10268 | |
| 10276 | | const ptr_alignment = @as(u32, @intCast(info.flags.alignment.toByteUnitsOptional() orelse |
| 10277 | | elem_ty.abiAlignment(mod))); |
| 10269 | const ptr_alignment: u32 = @intCast(info.flags.alignment.toByteUnitsOptional() orelse |
| 10270 | elem_ty.abiAlignment(mod)); |
| 10278 | 10271 | const ptr_volatile = llvm.Bool.fromBool(info.flags.is_volatile); |
| 10279 | 10272 | |
| 10280 | 10273 | assert(info.flags.vector_index != .runtime); |
| ... | ... | @@ -10306,7 +10299,7 @@ pub const FuncGen = struct { |
| 10306 | 10299 | containing_int.setAlignment(ptr_alignment); |
| 10307 | 10300 | containing_int.setVolatile(ptr_volatile); |
| 10308 | 10301 | |
| 10309 | | const elem_bits = @as(c_uint, @intCast(ptr_ty.childType(mod).bitSize(mod))); |
| 10302 | const elem_bits = ptr_ty.childType(mod).bitSize(mod); |
| 10310 | 10303 | const shift_amt = try o.builder.intConst(containing_int_ty, info.packed_offset.bit_offset); |
| 10311 | 10304 | const shifted_value = self.builder.buildLShr(containing_int, shift_amt.toLlvm(&o.builder), ""); |
| 10312 | 10305 | const elem_llvm_ty = (try o.lowerType(elem_ty)).toLlvm(&o.builder); |
| ... | ... | @@ -10379,7 +10372,7 @@ pub const FuncGen = struct { |
| 10379 | 10372 | assert(ordering == .NotAtomic); |
| 10380 | 10373 | containing_int.setAlignment(ptr_alignment); |
| 10381 | 10374 | containing_int.setVolatile(ptr_volatile); |
| 10382 | | const elem_bits = @as(c_uint, @intCast(ptr_ty.childType(mod).bitSize(mod))); |
| 10375 | const elem_bits = ptr_ty.childType(mod).bitSize(mod); |
| 10383 | 10376 | const shift_amt = try o.builder.intConst(containing_int_ty, info.packed_offset.bit_offset); |
| 10384 | 10377 | // Convert to equally-sized integer type in order to perform the bit |
| 10385 | 10378 | // operations on the value to store |
| ... | ... | @@ -10451,11 +10444,11 @@ pub const FuncGen = struct { |
| 10451 | 10444 | if (!target_util.hasValgrindSupport(target)) return default_value; |
| 10452 | 10445 | |
| 10453 | 10446 | const llvm_usize = try o.lowerType(Type.usize); |
| 10454 | | const usize_alignment = @as(c_uint, @intCast(Type.usize.abiSize(mod))); |
| 10447 | const usize_alignment = Type.usize.abiSize(mod); |
| 10455 | 10448 | |
| 10456 | 10449 | const array_llvm_ty = (try o.builder.arrayType(6, llvm_usize)).toLlvm(&o.builder); |
| 10457 | 10450 | const array_ptr = fg.valgrind_client_request_array orelse a: { |
| 10458 | | const array_ptr = try fg.buildAlloca(array_llvm_ty, usize_alignment); |
| 10451 | const array_ptr = try fg.buildAlloca(array_llvm_ty, @intCast(usize_alignment)); |
| 10459 | 10452 | fg.valgrind_client_request_array = array_ptr; |
| 10460 | 10453 | break :a array_ptr; |
| 10461 | 10454 | }; |
| ... | ... | @@ -10467,7 +10460,7 @@ pub const FuncGen = struct { |
| 10467 | 10460 | }; |
| 10468 | 10461 | const elem_ptr = fg.builder.buildInBoundsGEP(array_llvm_ty, array_ptr, &indexes, indexes.len, ""); |
| 10469 | 10462 | const store_inst = fg.builder.buildStore(elem, elem_ptr); |
| 10470 | | store_inst.setAlignment(usize_alignment); |
| 10463 | store_inst.setAlignment(@intCast(usize_alignment)); |
| 10471 | 10464 | } |
| 10472 | 10465 | |
| 10473 | 10466 | const arch_specific: struct { |
| ... | ... | @@ -11642,23 +11635,23 @@ const AnnotatedDITypePtr = enum(usize) { |
| 11642 | 11635 | fn initFwd(di_type: *llvm.DIType) AnnotatedDITypePtr { |
| 11643 | 11636 | const addr = @intFromPtr(di_type); |
| 11644 | 11637 | assert(@as(u1, @truncate(addr)) == 0); |
| 11645 | | return @as(AnnotatedDITypePtr, @enumFromInt(addr | 1)); |
| 11638 | return @enumFromInt(addr | 1); |
| 11646 | 11639 | } |
| 11647 | 11640 | |
| 11648 | 11641 | fn initFull(di_type: *llvm.DIType) AnnotatedDITypePtr { |
| 11649 | 11642 | const addr = @intFromPtr(di_type); |
| 11650 | | return @as(AnnotatedDITypePtr, @enumFromInt(addr)); |
| 11643 | return @enumFromInt(addr); |
| 11651 | 11644 | } |
| 11652 | 11645 | |
| 11653 | 11646 | fn init(di_type: *llvm.DIType, resolve: Object.DebugResolveStatus) AnnotatedDITypePtr { |
| 11654 | 11647 | const addr = @intFromPtr(di_type); |
| 11655 | 11648 | const bit = @intFromBool(resolve == .fwd); |
| 11656 | | return @as(AnnotatedDITypePtr, @enumFromInt(addr | bit)); |
| 11649 | return @enumFromInt(addr | bit); |
| 11657 | 11650 | } |
| 11658 | 11651 | |
| 11659 | 11652 | fn toDIType(self: AnnotatedDITypePtr) *llvm.DIType { |
| 11660 | 11653 | const fixed_addr = @intFromEnum(self) & ~@as(usize, 1); |
| 11661 | | return @as(*llvm.DIType, @ptrFromInt(fixed_addr)); |
| 11654 | return @ptrFromInt(fixed_addr); |
| 11662 | 11655 | } |
| 11663 | 11656 | |
| 11664 | 11657 | fn isFwdOnly(self: AnnotatedDITypePtr) bool { |