authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2020-12-20 14:50:48+01:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2020-12-21 19:24:21+01:00
log82236a502959d39b97c783dc409a9a5b720e6e8b
treea6f741bab53ea91bafe9403afc815cc33c1ad92c
parent286077fec8f381c7b4d4d5bf351d963564a1dd69
signaturelock-open Commit is signed but in an unrecognized format.

stage2 ARM: implement basic binary bitwise operations


4 files changed, 106 insertions(+), 5 deletions(-)

src/codegen.zig+36-3
......@@ -764,6 +764,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
764764 .arg => return self.genArg(inst.castTag(.arg).?),
765765 .assembly => return self.genAsm(inst.castTag(.assembly).?),
766766 .bitcast => return self.genBitCast(inst.castTag(.bitcast).?),
767 .bitand => return self.genBitAnd(inst.castTag(.bitand).?),
768 .bitor => return self.genBitOr(inst.castTag(.bitor).?),
767769 .block => return self.genBlock(inst.castTag(.block).?),
768770 .br => return self.genBr(inst.castTag(.br).?),
769771 .breakpoint => return self.genBreakpoint(inst.src),
......@@ -799,6 +801,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
799801 .unwrap_optional => return self.genUnwrapOptional(inst.castTag(.unwrap_optional).?),
800802 .wrap_optional => return self.genWrapOptional(inst.castTag(.wrap_optional).?),
801803 .varptr => return self.genVarPtr(inst.castTag(.varptr).?),
804 .xor => return self.genXor(inst.castTag(.xor).?),
802805 }
803806 }
804807
......@@ -1009,6 +1012,36 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
10091012 }
10101013 }
10111014
1015 fn genBitAnd(self: *Self, inst: *ir.Inst.BinOp) !MCValue {
1016 // No side effects, so if it's unreferenced, do nothing.
1017 if (inst.base.isUnused())
1018 return MCValue.dead;
1019 switch (arch) {
1020 .arm, .armeb => return try self.genArmBinOp(&inst.base, inst.lhs, inst.rhs, .bitand),
1021 else => return self.fail(inst.base.src, "TODO implement bitwise and for {}", .{self.target.cpu.arch}),
1022 }
1023 }
1024
1025 fn genBitOr(self: *Self, inst: *ir.Inst.BinOp) !MCValue {
1026 // No side effects, so if it's unreferenced, do nothing.
1027 if (inst.base.isUnused())
1028 return MCValue.dead;
1029 switch (arch) {
1030 .arm, .armeb => return try self.genArmBinOp(&inst.base, inst.lhs, inst.rhs, .bitor),
1031 else => return self.fail(inst.base.src, "TODO implement bitwise or for {}", .{self.target.cpu.arch}),
1032 }
1033 }
1034
1035 fn genXor(self: *Self, inst: *ir.Inst.BinOp) !MCValue {
1036 // No side effects, so if it's unreferenced, do nothing.
1037 if (inst.base.isUnused())
1038 return MCValue.dead;
1039 switch (arch) {
1040 .arm, .armeb => return try self.genArmBinOp(&inst.base, inst.lhs, inst.rhs, .xor),
1041 else => return self.fail(inst.base.src, "TODO implement xor for {}", .{self.target.cpu.arch}),
1042 }
1043 }
1044
10121045 fn genUnwrapOptional(self: *Self, inst: *ir.Inst.UnOp) !MCValue {
10131046 // No side effects, so if it's unreferenced, do nothing.
10141047 if (inst.base.isUnused())
......@@ -1251,13 +1284,13 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
12511284 writeInt(u32, try self.code.addManyAsArray(4), Instruction.rsb(.al, dst_reg, dst_reg, operand).toU32());
12521285 }
12531286 },
1254 .booland => {
1287 .booland, .bitand => {
12551288 writeInt(u32, try self.code.addManyAsArray(4), Instruction.@"and"(.al, dst_reg, dst_reg, operand).toU32());
12561289 },
1257 .boolor => {
1290 .boolor, .bitor => {
12581291 writeInt(u32, try self.code.addManyAsArray(4), Instruction.orr(.al, dst_reg, dst_reg, operand).toU32());
12591292 },
1260 .not => {
1293 .not, .xor => {
12611294 writeInt(u32, try self.code.addManyAsArray(4), Instruction.eor(.al, dst_reg, dst_reg, operand).toU32());
12621295 },
12631296 else => unreachable, // not a binary instruction
src/ir.zig+6
......@@ -56,7 +56,9 @@ pub const Inst = struct {
5656 alloc,
5757 arg,
5858 assembly,
59 bitand,
5960 bitcast,
61 bitor,
6062 block,
6163 br,
6264 breakpoint,
......@@ -93,6 +95,7 @@ pub const Inst = struct {
9395 intcast,
9496 unwrap_optional,
9597 wrap_optional,
98 xor,
9699 switchbr,
97100
98101 pub fn Type(tag: Tag) type {
......@@ -130,6 +133,9 @@ pub const Inst = struct {
130133 .store,
131134 .booland,
132135 .boolor,
136 .bitand,
137 .bitor,
138 .xor,
133139 => BinOp,
134140
135141 .arg => Arg,
src/zir.zig+3
......@@ -2330,6 +2330,9 @@ const EmitZIR = struct {
23302330 .cmp_neq => try self.emitBinOp(inst.src, new_body, inst.castTag(.cmp_neq).?, .cmp_neq),
23312331 .booland => try self.emitBinOp(inst.src, new_body, inst.castTag(.booland).?, .booland),
23322332 .boolor => try self.emitBinOp(inst.src, new_body, inst.castTag(.boolor).?, .boolor),
2333 .bitand => try self.emitBinOp(inst.src, new_body, inst.castTag(.bitand).?, .bitand),
2334 .bitor => try self.emitBinOp(inst.src, new_body, inst.castTag(.bitor).?, .bitor),
2335 .xor => try self.emitBinOp(inst.src, new_body, inst.castTag(.xor).?, .xor),
23332336
23342337 .bitcast => try self.emitCast(inst.src, new_body, inst.castTag(.bitcast).?, .bitcast),
23352338 .intcast => try self.emitCast(inst.src, new_body, inst.castTag(.intcast).?, .intcast),
src/zir_sema.zig+61-2
......@@ -1458,7 +1458,66 @@ fn analyzeInstShr(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError
14581458}
14591459
14601460fn analyzeInstBitwise(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {
1461 return mod.fail(scope, inst.base.src, "TODO implement analyzeInstBitwise", .{});
1461 const tracy = trace(@src());
1462 defer tracy.end();
1463
1464 const lhs = try resolveInst(mod, scope, inst.positionals.lhs);
1465 const rhs = try resolveInst(mod, scope, inst.positionals.rhs);
1466
1467 const instructions = &[_]*Inst{ lhs, rhs };
1468 const resolved_type = try mod.resolvePeerTypes(scope, instructions);
1469 const casted_lhs = try mod.coerce(scope, resolved_type, lhs);
1470 const casted_rhs = try mod.coerce(scope, resolved_type, rhs);
1471
1472 const scalar_type = if (resolved_type.zigTypeTag() == .Vector)
1473 resolved_type.elemType()
1474 else
1475 resolved_type;
1476
1477 const scalar_tag = scalar_type.zigTypeTag();
1478
1479 if (lhs.ty.zigTypeTag() == .Vector and rhs.ty.zigTypeTag() == .Vector) {
1480 if (lhs.ty.arrayLen() != rhs.ty.arrayLen()) {
1481 return mod.fail(scope, inst.base.src, "vector length mismatch: {} and {}", .{
1482 lhs.ty.arrayLen(),
1483 rhs.ty.arrayLen(),
1484 });
1485 }
1486 return mod.fail(scope, inst.base.src, "TODO implement support for vectors in analyzeInstBitwise", .{});
1487 } else if (lhs.ty.zigTypeTag() == .Vector or rhs.ty.zigTypeTag() == .Vector) {
1488 return mod.fail(scope, inst.base.src, "mixed scalar and vector operands to binary expression: '{}' and '{}'", .{
1489 lhs.ty,
1490 rhs.ty,
1491 });
1492 }
1493
1494 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;
1495
1496 if (!is_int) {
1497 return mod.fail(scope, inst.base.src, "invalid operands to binary bitwise expression: '{}' and '{}'", .{ @tagName(lhs.ty.zigTypeTag()), @tagName(rhs.ty.zigTypeTag()) });
1498 }
1499
1500 if (casted_lhs.value()) |lhs_val| {
1501 if (casted_rhs.value()) |rhs_val| {
1502 if (lhs_val.isUndef() or rhs_val.isUndef()) {
1503 return mod.constInst(scope, inst.base.src, .{
1504 .ty = resolved_type,
1505 .val = Value.initTag(.undef),
1506 });
1507 }
1508 return mod.fail(scope, inst.base.src, "TODO implement comptime bitwise operations", .{});
1509 }
1510 }
1511
1512 const b = try mod.requireRuntimeBlock(scope, inst.base.src);
1513 const ir_tag = switch (inst.base.tag) {
1514 .bitand => Inst.Tag.bitand,
1515 .bitor => Inst.Tag.bitor,
1516 .xor => Inst.Tag.xor,
1517 else => unreachable,
1518 };
1519
1520 return mod.addBinOp(b, inst.base.src, scalar_type, ir_tag, casted_lhs, casted_rhs);
14621521}
14631522
14641523fn analyzeInstBitNot(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
......@@ -1501,7 +1560,7 @@ fn analyzeInstArithmetic(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) Inn
15011560 }
15021561 return mod.fail(scope, inst.base.src, "TODO implement support for vectors in analyzeInstBinOp", .{});
15031562 } else if (lhs.ty.zigTypeTag() == .Vector or rhs.ty.zigTypeTag() == .Vector) {
1504 return mod.fail(scope, inst.base.src, "mixed scalar and vector operands to comparison operator: '{}' and '{}'", .{
1563 return mod.fail(scope, inst.base.src, "mixed scalar and vector operands to binary expression: '{}' and '{}'", .{
15051564 lhs.ty,
15061565 rhs.ty,
15071566 });