stage2: LLVM backend: implement @tagName for enums

Introduced a new AIR instruction: `tag_name`. Reasons to do this
instead of lowering it in Sema to a switch, function call, array
lookup, or if-else tower:
 * Sema is a bottleneck; do less work in Sema whenever possible.
 * If any optimization passes run, and the operand to becomes
   comptime-known, then it could change to have a comptime result
   value instead of lowering to a function or array or something which
   would then have to be garbage-collected.
 * Backends may want to choose to use a function and a switch branch,
   or they may want to use a different strategy.

Codegen for `@tagName` is implemented for the LLVM backend but not any
others yet.

Introduced some new `Type` tags:
 * `const_slice_u8_sentinel_0`
 * `manyptr_const_u8_sentinel_0`

The motivation for this was to make typeof() on the tag_name AIR
instruction non-allocating.

A bunch more enum tests are passing now.
This commit is contained in:
Andrew Kelley
2021-12-27 01:14:50 -07:00
parent f41b9cdb6d
commit c8fb36b36c
17 changed files with 1031 additions and 654 deletions

View File

@@ -1230,6 +1230,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
.clz => try airBuiltinCall(f, inst, "clz"),
.ctz => try airBuiltinCall(f, inst, "ctz"),
.popcount => try airBuiltinCall(f, inst, "popcount"),
.tag_name => try airTagName(f, inst),
.int_to_float,
.float_to_int,
@@ -2914,6 +2915,24 @@ fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
return local;
}
fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue {
if (f.liveness.isUnused(inst)) return CValue.none;
const un_op = f.air.instructions.items(.data)[inst].un_op;
const writer = f.object.writer();
const inst_ty = f.air.typeOfIndex(inst);
const operand = try f.resolveInst(un_op);
const local = try f.allocLocal(inst_ty, .Const);
try writer.writeAll(" = ");
_ = operand;
_ = local;
return f.fail("TODO: C backend: implement airTagName", .{});
//try writer.writeAll(";\n");
//return local;
}
fn toMemoryOrder(order: std.builtin.AtomicOrder) [:0]const u8 {
return switch (order) {
.Unordered => "memory_order_relaxed",