mirror of
https://github.com/ziglang/zig.git
synced 2025-12-15 18:53:07 +00:00
AstGen: encode negativity into float literals
rather than a separate negation instruction. closes #11545
This commit is contained in:
parent
18d6523888
commit
d8e99164d3
@ -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,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user