authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-04-28 13:13:40-04:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-09-01 18:30:31+01:00
log49ad51b2feacad394e05d7b5c87c5020c3bc0f5e
tree336508d1623e4c35e52cddd7f924996ff54d4962
parent28383d4d985cd04c897f6b6a63bd2107d8e2a8e9
signaturelock-open Commit is signed but in an unrecognized format.

Builder: add `indirectbr` llvm instruction


2 files changed, 96 insertions(+), 15 deletions(-)

src/codegen/llvm/Builder.zig+82-15
...@@ -4157,6 +4157,7 @@ pub const Function = struct {...@@ -4157,6 +4157,7 @@ pub const Function = struct {
4157 @"icmp ugt",4157 @"icmp ugt",
4158 @"icmp ule",4158 @"icmp ule",
4159 @"icmp ult",4159 @"icmp ult",
4160 indirectbr,
4160 insertelement,4161 insertelement,
4161 insertvalue,4162 insertvalue,
4162 inttoptr,4163 inttoptr,
...@@ -4367,6 +4368,7 @@ pub const Function = struct {...@@ -4367,6 +4368,7 @@ pub const Function = struct {
4367 return switch (wip.instructions.items(.tag)[@intFromEnum(self)]) {4368 return switch (wip.instructions.items(.tag)[@intFromEnum(self)]) {
4368 .br,4369 .br,
4369 .br_cond,4370 .br_cond,
4371 .indirectbr,
4370 .ret,4372 .ret,
4371 .@"ret void",4373 .@"ret void",
4372 .@"switch",4374 .@"switch",
...@@ -4381,6 +4383,7 @@ pub const Function = struct {...@@ -4381,6 +4383,7 @@ pub const Function = struct {
4381 .br,4383 .br,
4382 .br_cond,4384 .br_cond,
4383 .fence,4385 .fence,
4386 .indirectbr,
4384 .ret,4387 .ret,
4385 .@"ret void",4388 .@"ret void",
4386 .store,4389 .store,
...@@ -4471,6 +4474,7 @@ pub const Function = struct {...@@ -4471,6 +4474,7 @@ pub const Function = struct {
4471 .br,4474 .br,
4472 .br_cond,4475 .br_cond,
4473 .fence,4476 .fence,
4477 .indirectbr,
4474 .ret,4478 .ret,
4475 .@"ret void",4479 .@"ret void",
4476 .store,4480 .store,
...@@ -4657,6 +4661,7 @@ pub const Function = struct {...@@ -4657,6 +4661,7 @@ pub const Function = struct {
4657 .br,4661 .br,
4658 .br_cond,4662 .br_cond,
4659 .fence,4663 .fence,
4664 .indirectbr,
4660 .ret,4665 .ret,
4661 .@"ret void",4666 .@"ret void",
4662 .store,4667 .store,
...@@ -4837,6 +4842,12 @@ pub const Function = struct {...@@ -4837,6 +4842,12 @@ pub const Function = struct {
4837 //case_blocks: [cases_len]Block.Index,4842 //case_blocks: [cases_len]Block.Index,
4838 };4843 };
48394844
4845 pub const IndirectBr = struct {
4846 addr: Value,
4847 targets_len: u32,
4848 //targets: [targets_len]Block.Index,
4849 };
4850
4840 pub const Binary = struct {4851 pub const Binary = struct {
4841 lhs: Value,4852 lhs: Value,
4842 rhs: Value,4853 rhs: Value,
...@@ -5294,10 +5305,27 @@ pub const WipFunction = struct {...@@ -5294,10 +5305,27 @@ pub const WipFunction = struct {
5294 return .{ .index = 0, .instruction = instruction };5305 return .{ .index = 0, .instruction = instruction };
5295 }5306 }
52965307
5308 pub fn indirectbr(
5309 self: *WipFunction,
5310 addr: Value,
5311 targets: []const Block.Index,
5312 ) Allocator.Error!Instruction.Index {
5313 try self.ensureUnusedExtraCapacity(1, Instruction.IndirectBr, targets.len);
5314 const instruction = try self.addInst(null, .{
5315 .tag = .indirectbr,
5316 .data = self.addExtraAssumeCapacity(Instruction.IndirectBr{
5317 .addr = addr,
5318 .targets_len = @intCast(targets.len),
5319 }),
5320 });
5321 _ = self.extra.appendSliceAssumeCapacity(@ptrCast(targets));
5322 for (targets) |target| target.ptr(self).branches += 1;
5323 return instruction;
5324 }
5325
5297 pub fn @"unreachable"(self: *WipFunction) Allocator.Error!Instruction.Index {5326 pub fn @"unreachable"(self: *WipFunction) Allocator.Error!Instruction.Index {
5298 try self.ensureUnusedExtraCapacity(1, NoExtra, 0);5327 try self.ensureUnusedExtraCapacity(1, NoExtra, 0);
5299 const instruction = try self.addInst(null, .{ .tag = .@"unreachable", .data = undefined });5328 return try self.addInst(null, .{ .tag = .@"unreachable", .data = undefined });
5300 return instruction;
5301 }5329 }
53025330
5303 pub fn un(5331 pub fn un(
...@@ -6299,8 +6327,7 @@ pub const WipFunction = struct {...@@ -6299,8 +6327,7 @@ pub const WipFunction = struct {
6299 });6327 });
6300 names[@intFromEnum(new_block_index)] = try wip_name.map(current_block.name, "");6328 names[@intFromEnum(new_block_index)] = try wip_name.map(current_block.name, "");
6301 for (current_block.instructions.items) |old_instruction_index| {6329 for (current_block.instructions.items) |old_instruction_index| {
6302 const new_instruction_index: Instruction.Index =6330 const new_instruction_index: Instruction.Index = @enumFromInt(function.instructions.len);
6303 @enumFromInt(function.instructions.len);
6304 var instruction = self.instructions.get(@intFromEnum(old_instruction_index));6331 var instruction = self.instructions.get(@intFromEnum(old_instruction_index));
6305 switch (instruction.tag) {6332 switch (instruction.tag) {
6306 .add,6333 .add,
...@@ -6509,6 +6536,15 @@ pub const WipFunction = struct {...@@ -6509,6 +6536,15 @@ pub const WipFunction = struct {
6509 });6536 });
6510 wip_extra.appendMappedValues(indices, instructions);6537 wip_extra.appendMappedValues(indices, instructions);
6511 },6538 },
6539 .indirectbr => {
6540 var extra = self.extraDataTrail(Instruction.IndirectBr, instruction.data);
6541 const targets = extra.trail.next(extra.data.targets_len, Block.Index, self);
6542 instruction.data = wip_extra.addExtra(Instruction.IndirectBr{
6543 .addr = instructions.map(extra.data.addr),
6544 .targets_len = extra.data.targets_len,
6545 });
6546 wip_extra.appendSlice(targets);
6547 },
6512 .insertelement => {6548 .insertelement => {
6513 const extra = self.extraData(Instruction.InsertElement, instruction.data);6549 const extra = self.extraData(Instruction.InsertElement, instruction.data);
6514 instruction.data = wip_extra.addExtra(Instruction.InsertElement{6550 instruction.data = wip_extra.addExtra(Instruction.InsertElement{
...@@ -7555,10 +7591,10 @@ pub const Constant = enum(u32) {...@@ -7555,10 +7591,10 @@ pub const Constant = enum(u32) {
7555 .blockaddress => |tag| {7591 .blockaddress => |tag| {
7556 const extra = data.builder.constantExtraData(BlockAddress, item.data);7592 const extra = data.builder.constantExtraData(BlockAddress, item.data);
7557 const function = extra.function.ptrConst(data.builder);7593 const function = extra.function.ptrConst(data.builder);
7558 try writer.print("{s}({}, %{d})", .{7594 try writer.print("{s}({}, {})", .{
7559 @tagName(tag),7595 @tagName(tag),
7560 function.global.fmt(data.builder),7596 function.global.fmt(data.builder),
7561 @intFromEnum(extra.block), // TODO7597 extra.block.toInst(function).fmt(extra.function, data.builder),
7562 });7598 });
7563 },7599 },
7564 .dso_local_equivalent,7600 .dso_local_equivalent,
...@@ -9902,6 +9938,23 @@ pub fn printUnbuffered(...@@ -9902,6 +9938,23 @@ pub fn printUnbuffered(
9902 index.fmt(function_index, self),9938 index.fmt(function_index, self),
9903 });9939 });
9904 },9940 },
9941 .indirectbr => |tag| {
9942 var extra =
9943 function.extraDataTrail(Function.Instruction.IndirectBr, instruction.data);
9944 const targets =
9945 extra.trail.next(extra.data.targets_len, Function.Block.Index, &function);
9946 try writer.print(" {s} {%}, [", .{
9947 @tagName(tag),
9948 extra.data.addr.fmt(function_index, self),
9949 });
9950 for (0.., targets) |target_index, target| {
9951 if (target_index > 0) try writer.writeAll(", ");
9952 try writer.print("{%}", .{
9953 target.toInst(&function).fmt(function_index, self),
9954 });
9955 }
9956 try writer.writeByte(']');
9957 },
9905 .insertelement => |tag| {9958 .insertelement => |tag| {
9906 const extra =9959 const extra =
9907 function.extraData(Function.Instruction.InsertElement, instruction.data);9960 function.extraData(Function.Instruction.InsertElement, instruction.data);
...@@ -14777,15 +14830,6 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co...@@ -14777,15 +14830,6 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
14777 .indices = indices,14830 .indices = indices,
14778 });14831 });
14779 },14832 },
14780 .insertvalue => {
14781 var extra = func.extraDataTrail(Function.Instruction.InsertValue, data);
14782 const indices = extra.trail.next(extra.data.indices_len, u32, &func);
14783 try function_block.writeAbbrev(FunctionBlock.InsertValue{
14784 .val = adapter.getOffsetValueIndex(extra.data.val),
14785 .elem = adapter.getOffsetValueIndex(extra.data.elem),
14786 .indices = indices,
14787 });
14788 },
14789 .extractelement => {14833 .extractelement => {
14790 const extra = func.extraData(Function.Instruction.ExtractElement, data);14834 const extra = func.extraData(Function.Instruction.ExtractElement, data);
14791 try function_block.writeAbbrev(FunctionBlock.ExtractElement{14835 try function_block.writeAbbrev(FunctionBlock.ExtractElement{
...@@ -14793,6 +14837,20 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co...@@ -14793,6 +14837,20 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
14793 .index = adapter.getOffsetValueIndex(extra.index),14837 .index = adapter.getOffsetValueIndex(extra.index),
14794 });14838 });
14795 },14839 },
14840 .indirectbr => {
14841 var extra =
14842 func.extraDataTrail(Function.Instruction.IndirectBr, datas[instr_index]);
14843 const targets =
14844 extra.trail.next(extra.data.targets_len, Function.Block.Index, &func);
14845 try function_block.writeAbbrevAdapted(
14846 FunctionBlock.IndirectBr{
14847 .ty = extra.data.addr.typeOf(@enumFromInt(func_index), self),
14848 .addr = extra.data.addr,
14849 .targets = targets,
14850 },
14851 adapter,
14852 );
14853 },
14796 .insertelement => {14854 .insertelement => {
14797 const extra = func.extraData(Function.Instruction.InsertElement, data);14855 const extra = func.extraData(Function.Instruction.InsertElement, data);
14798 try function_block.writeAbbrev(FunctionBlock.InsertElement{14856 try function_block.writeAbbrev(FunctionBlock.InsertElement{
...@@ -14801,6 +14859,15 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co...@@ -14801,6 +14859,15 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
14801 .index = adapter.getOffsetValueIndex(extra.index),14859 .index = adapter.getOffsetValueIndex(extra.index),
14802 });14860 });
14803 },14861 },
14862 .insertvalue => {
14863 var extra = func.extraDataTrail(Function.Instruction.InsertValue, datas[instr_index]);
14864 const indices = extra.trail.next(extra.data.indices_len, u32, &func);
14865 try function_block.writeAbbrev(FunctionBlock.InsertValue{
14866 .val = adapter.getOffsetValueIndex(extra.data.val),
14867 .elem = adapter.getOffsetValueIndex(extra.data.elem),
14868 .indices = indices,
14869 });
14870 },
14804 .select => {14871 .select => {
14805 const extra = func.extraData(Function.Instruction.Select, data);14872 const extra = func.extraData(Function.Instruction.Select, data);
14806 try function_block.writeAbbrev(FunctionBlock.Select{14873 try function_block.writeAbbrev(FunctionBlock.Select{
src/codegen/llvm/ir.zig+14
...@@ -19,6 +19,7 @@ const LineAbbrev = AbbrevOp{ .vbr = 8 };...@@ -19,6 +19,7 @@ const LineAbbrev = AbbrevOp{ .vbr = 8 };
19const ColumnAbbrev = AbbrevOp{ .vbr = 8 };19const ColumnAbbrev = AbbrevOp{ .vbr = 8 };
2020
21const BlockAbbrev = AbbrevOp{ .vbr = 6 };21const BlockAbbrev = AbbrevOp{ .vbr = 6 };
22const BlockArrayAbbrev = AbbrevOp{ .array_vbr = 6 };
2223
23/// Unused tags are commented out so that they are omitted in the generated24/// Unused tags are commented out so that they are omitted in the generated
24/// bitcode, which scans over this enum using reflection.25/// bitcode, which scans over this enum using reflection.
...@@ -1294,6 +1295,7 @@ pub const FunctionBlock = struct {...@@ -1294,6 +1295,7 @@ pub const FunctionBlock = struct {
1294 DebugLoc,1295 DebugLoc,
1295 DebugLocAgain,1296 DebugLocAgain,
1296 ColdOperandBundle,1297 ColdOperandBundle,
1298 IndirectBr,
1297 };1299 };
12981300
1299 pub const DeclareBlocks = struct {1301 pub const DeclareBlocks = struct {
...@@ -1813,6 +1815,18 @@ pub const FunctionBlock = struct {...@@ -1813,6 +1815,18 @@ pub const FunctionBlock = struct {
1813 .{ .literal = 0 },1815 .{ .literal = 0 },
1814 };1816 };
1815 };1817 };
1818
1819 pub const IndirectBr = struct {
1820 pub const ops = [_]AbbrevOp{
1821 .{ .literal = 31 },
1822 .{ .fixed_runtime = Builder.Type },
1823 ValueAbbrev,
1824 BlockArrayAbbrev,
1825 };
1826 ty: Builder.Type,
1827 addr: Builder.Value,
1828 targets: []const Builder.Function.Block.Index,
1829 };
1816};1830};
18171831
1818pub const FunctionValueSymbolTable = struct {1832pub const FunctionValueSymbolTable = struct {