mirror of
https://github.com/ziglang/zig.git
synced 2025-12-16 11:13:08 +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_and => return boolBinOp(gz, scope, rl, node, .bool_br_and),
|
||||||
.bool_or => return boolBinOp(gz, scope, rl, node, .bool_br_or),
|
.bool_or => return boolBinOp(gz, scope, rl, node, .bool_br_or),
|
||||||
|
|
||||||
.bool_not => return boolNot(gz, scope, rl, node),
|
.bool_not => return simpleUnOp(gz, scope, rl, node, bool_rl, node_datas[node].lhs, .bool_not),
|
||||||
.bit_not => return bitNot(gz, scope, rl, node),
|
.bit_not => return simpleUnOp(gz, scope, rl, node, .none, node_datas[node].lhs, .bit_not),
|
||||||
|
|
||||||
.negation => return negation(gz, scope, rl, node, .negate),
|
.negation => return negation(gz, scope, rl, node),
|
||||||
.negation_wrap => return negation(gz, scope, rl, node, .negate_wrap),
|
.negation_wrap => return simpleUnOp(gz, scope, rl, node, .none, node_datas[node].lhs, .negate_wrap),
|
||||||
|
|
||||||
.identifier => return identifier(gz, scope, rl, node),
|
.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),
|
.@"return" => return ret(gz, scope, node),
|
||||||
.field_access => return fieldAccess(gz, scope, rl, 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_simple => return ifExpr(gz, scope, rl.br(), node, tree.ifSimple(node)),
|
||||||
.@"if" => return ifExpr(gz, scope, rl.br(), node, tree.ifFull(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);
|
_ = 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(
|
fn ptrType(
|
||||||
gz: *GenZir,
|
gz: *GenZir,
|
||||||
scope: *Scope,
|
scope: *Scope,
|
||||||
@ -6728,14 +6692,16 @@ fn integerLiteral(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Z
|
|||||||
return rvalue(gz, rl, result, node);
|
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 astgen = gz.astgen;
|
||||||
const tree = astgen.tree;
|
const tree = astgen.tree;
|
||||||
const main_tokens = tree.nodes.items(.main_token);
|
const main_tokens = tree.nodes.items(.main_token);
|
||||||
|
|
||||||
const main_token = main_tokens[node];
|
const main_token = main_tokens[node];
|
||||||
const bytes = tree.tokenSlice(main_token);
|
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
|
assert(bytes[0] == '0'); // validated by tokenizer
|
||||||
break :hex std.fmt.parseHexFloat(f128, bytes) catch |err| switch (err) {
|
break :hex std.fmt.parseHexFloat(f128, bytes) catch |err| switch (err) {
|
||||||
error.InvalidCharacter => unreachable, // validated by tokenizer
|
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) {
|
} else std.fmt.parseFloat(f128, bytes) catch |err| switch (err) {
|
||||||
error.InvalidCharacter => unreachable, // validated by tokenizer
|
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.
|
// If the value fits into a f64 without losing any precision, store it that way.
|
||||||
@setFloatMode(.Strict);
|
@setFloatMode(.Strict);
|
||||||
const smaller_float = @floatCast(f64, float_number);
|
const smaller_float = @floatCast(f64, float_number);
|
||||||
@ -7651,6 +7621,29 @@ fn simpleUnOp(
|
|||||||
return rvalue(gz, rl, result, node);
|
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(
|
fn cmpxchg(
|
||||||
gz: *GenZir,
|
gz: *GenZir,
|
||||||
scope: *Scope,
|
scope: *Scope,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user