diff --git a/src/AstGen.zig b/src/AstGen.zig index 230b46a489..c9fd82bd5f 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -694,11 +694,11 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr .bool_and => return boolBinOp(gz, scope, rl, node, .bool_br_and), .bool_or => return boolBinOp(gz, scope, rl, node, .bool_br_or), - .bool_not => return boolNot(gz, scope, rl, node), - .bit_not => return bitNot(gz, scope, rl, node), + .bool_not => return simpleUnOp(gz, scope, rl, node, bool_rl, node_datas[node].lhs, .bool_not), + .bit_not => return simpleUnOp(gz, scope, rl, node, .none, node_datas[node].lhs, .bit_not), - .negation => return negation(gz, scope, rl, node, .negate), - .negation_wrap => return negation(gz, scope, rl, node, .negate_wrap), + .negation => return negation(gz, scope, rl, node), + .negation_wrap => return simpleUnOp(gz, scope, rl, node, .none, node_datas[node].lhs, .negate_wrap), .identifier => return identifier(gz, scope, rl, node), @@ -748,7 +748,7 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr }, .@"return" => return ret(gz, scope, node), .field_access => return fieldAccess(gz, scope, rl, node), - .float_literal => return floatLiteral(gz, rl, node), + .float_literal => return floatLiteral(gz, rl, node, .positive), .if_simple => return ifExpr(gz, scope, rl.br(), node, tree.ifSimple(node)), .@"if" => return ifExpr(gz, scope, rl.br(), node, tree.ifFull(node)), @@ -3029,42 +3029,6 @@ fn assignShiftSat(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerE _ = try gz.addBin(.store, lhs_ptr, result); } -fn boolNot(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir.Inst.Ref { - const astgen = gz.astgen; - const tree = astgen.tree; - const node_datas = tree.nodes.items(.data); - - const operand = try expr(gz, scope, bool_rl, node_datas[node].lhs); - const result = try gz.addUnNode(.bool_not, operand, node); - return rvalue(gz, rl, result, node); -} - -fn bitNot(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir.Inst.Ref { - const astgen = gz.astgen; - const tree = astgen.tree; - const node_datas = tree.nodes.items(.data); - - const operand = try expr(gz, scope, .none, node_datas[node].lhs); - const result = try gz.addUnNode(.bit_not, operand, node); - return rvalue(gz, rl, result, node); -} - -fn negation( - gz: *GenZir, - scope: *Scope, - rl: ResultLoc, - node: Ast.Node.Index, - tag: Zir.Inst.Tag, -) InnerError!Zir.Inst.Ref { - const astgen = gz.astgen; - const tree = astgen.tree; - const node_datas = tree.nodes.items(.data); - - const operand = try expr(gz, scope, .none, node_datas[node].lhs); - const result = try gz.addUnNode(tag, operand, node); - return rvalue(gz, rl, result, node); -} - fn ptrType( gz: *GenZir, scope: *Scope, @@ -6728,14 +6692,16 @@ fn integerLiteral(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Z return rvalue(gz, rl, result, node); } -fn floatLiteral(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir.Inst.Ref { +const Sign = enum { negative, positive }; + +fn floatLiteral(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index, sign: Sign) InnerError!Zir.Inst.Ref { const astgen = gz.astgen; const tree = astgen.tree; const main_tokens = tree.nodes.items(.main_token); const main_token = main_tokens[node]; const bytes = tree.tokenSlice(main_token); - const float_number: f128 = if (bytes.len > 2 and bytes[1] == 'x') hex: { + const unsigned_float_number: f128 = if (bytes.len > 2 and bytes[1] == 'x') hex: { assert(bytes[0] == '0'); // validated by tokenizer break :hex std.fmt.parseHexFloat(f128, bytes) catch |err| switch (err) { error.InvalidCharacter => unreachable, // validated by tokenizer @@ -6744,6 +6710,10 @@ fn floatLiteral(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir } else std.fmt.parseFloat(f128, bytes) catch |err| switch (err) { error.InvalidCharacter => unreachable, // validated by tokenizer }; + const float_number = switch (sign) { + .negative => -unsigned_float_number, + .positive => unsigned_float_number, + }; // If the value fits into a f64 without losing any precision, store it that way. @setFloatMode(.Strict); const smaller_float = @floatCast(f64, float_number); @@ -7651,6 +7621,29 @@ fn simpleUnOp( return rvalue(gz, rl, result, node); } +fn negation( + gz: *GenZir, + scope: *Scope, + rl: ResultLoc, + node: Ast.Node.Index, +) InnerError!Zir.Inst.Ref { + const astgen = gz.astgen; + const tree = astgen.tree; + const node_tags = tree.nodes.items(.tag); + const node_datas = tree.nodes.items(.data); + + // Check for float literal as the sub-expression because we want to preserve + // its negativity rather than having it go through comptime subtraction. + const operand_node = node_datas[node].lhs; + if (node_tags[operand_node] == .float_literal) { + return floatLiteral(gz, rl, operand_node, .negative); + } + + const operand = try expr(gz, scope, .none, operand_node); + const result = try gz.addUnNode(.negate, operand, node); + return rvalue(gz, rl, result, node); +} + fn cmpxchg( gz: *GenZir, scope: *Scope,