================ @@ -0,0 +1,344 @@ +//===-- CIRDialectBytecode.td - CIR bytecode defs ----------*- tablegen -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This is the CIR bytecode reader/writer definition file. +// +// Modelled on mlir/include/mlir/Dialect/LLVMIR/LLVMDialectBytecode.td. Every +// entry's parameters must appear in the same order as the attribute's get(), +// because the generated reader feeds them positionally, and each name must +// derive the C++ getter (`get` + the name in UpperCamel). +// +//===----------------------------------------------------------------------===// + +#ifndef CIR_DIALECT_BYTECODE +#define CIR_DIALECT_BYTECODE + +include "mlir/IR/BytecodeBase.td" + +//===----------------------------------------------------------------------===// +// Bytecode classes for attributes and types. +//===----------------------------------------------------------------------===// + +class Attr<string type> : WithType<type, Attribute>; + +// Read a generic type into a narrowed C++ handle. The reader's templated +// readType does the dyn_cast and fails cleanly on a mismatch, so this stays +// safe against a malformed or cross-version file. +class Ty<string type> : WithType<type, Type>; + +class OptionalAttribute<string type> : + WithParser <"succeeded($_reader.readOptionalAttribute($_var))", + WithPrinter<"$_writer.writeOptionalAttribute($_getter)", + WithType<type, Attribute>>>; + +// For a parameter declared OptionalParameter<"std::optional<...>">, where the +// C++ type is an optional rather than a nullable attribute, so "absent" needs +// a flag of its own. The helpers live in CIRDialectBytecode.cpp. +class OptionalInt<string type> : + WithParser <"succeeded(readOptionalInt($_reader, $_var))", + WithBuilder<"$_args", + WithPrinter<"writeOptionalInt($_writer, $_getter)", + WithType <"std::optional<" # type # ">">>>>; + +// Named for the C++ spelling, not the concept, because the difference from +// OptionalAttribute above is exactly the C++ spelling and nothing else: +// OptionalAttribute is for a parameter that is a nullable attribute, this is +// for one declared std::optional<...>. The two share the same wire format, so +// at a glance nothing but the name says which a given parameter needs. +class StdOptionalAttribute<string type> : + WithParser <"succeeded(readStdOptionalAttribute($_reader, $_var))", + WithBuilder<"$_args", + WithPrinter<"writeStdOptionalAttribute($_writer, $_getter)", + WithType <"std::optional<" # type # ">">>>>; + +// A scoped enum read from an untrusted varint. The value is validated with +// the enum's symbolizer; an out-of-range value fails the read with a +// diagnostic instead of casting into undefined behavior. +def CtorKindParam : + WithParser<"succeeded(readEnum($_reader, $_var, cir::symbolizeCtorKind, \"CtorKind\"))", + WithPrinter<"$_writer.writeVarInt(static_cast<uint64_t>($_getter))", + WithType<"cir::CtorKind">>>; + +def AssignKindParam : + WithParser<"succeeded(readEnum($_reader, $_var, cir::symbolizeAssignKind, \"AssignKind\"))", + WithPrinter<"$_writer.writeVarInt(static_cast<uint64_t>($_getter))", + WithType<"cir::AssignKind">>>; + +// A varint on the wire narrowed to a fixed-width integer. The bound is checked +// on read; a file carrying a value the parameter cannot hold fails instead of +// truncating into a plausible count or index. +def CheckedInt : + WithParser<"succeeded(readCheckedInt($_reader, $_var))", + WithPrinter<"$_writer.writeSignedVarInt($_getter)", + WithType<"int">>>; + +def CheckedInt32 : + WithParser<"succeeded(readCheckedInt($_reader, $_var))", + WithPrinter<"$_writer.writeSignedVarInt($_getter)", + WithType<"int32_t">>>; + +def CheckedUnsigned : + WithParser<"succeeded(readCheckedInt($_reader, $_var))", + WithPrinter<"$_writer.writeVarInt($_getter)", + WithType<"unsigned">>>; + +//===----------------------------------------------------------------------===// +// OptInfoAttr +//===----------------------------------------------------------------------===// + +def OptInfoAttr : DialectAttribute<(attr + CheckedUnsigned:$level, + CheckedUnsigned:$size +)>; + +//===----------------------------------------------------------------------===// +// AddressPointAttr +// +// index and offset are int32_t and an address point legitimately carries a +// negative offset, so these are signed. +//===----------------------------------------------------------------------===// + +def AddressPointAttr : DialectAttribute<(attr + CheckedInt32:$index, + CheckedInt32:$offset +)>; + +//===----------------------------------------------------------------------===// +// OpenCLVersionAttr +//===----------------------------------------------------------------------===// + +def OpenCLVersionAttr : DialectAttribute<(attr + CheckedInt32:$major, + CheckedInt32:$minor +)>; + +//===----------------------------------------------------------------------===// +// BlockAddrInfoAttr +//===----------------------------------------------------------------------===// + +def BlockAddrInfoAttr : DialectAttribute<(attr + Ty<"cir::PointerType">:$type, + Attr<"mlir::FlatSymbolRefAttr">:$func, + Attr<"mlir::StringAttr">:$label +)>; + +//===----------------------------------------------------------------------===// +// BitfieldInfoAttr +//===----------------------------------------------------------------------===// + +def BitfieldInfoAttr : DialectAttribute<(attr + Attr<"mlir::StringAttr">:$name, + Type:$storage_type, + VarInt:$size, + VarInt:$offset, + Bool:$is_signed +)>; + +//===----------------------------------------------------------------------===// +// Constants +//===----------------------------------------------------------------------===// +// +// These are the entries that pay for themselves. Every literal in a function +// body is an IntAttr, an FPAttr or a BoolAttr, so under the assembly fallback +// each one costs its full printed form ("#cir.int<42> : !s32i") while the +// native encoding costs a type reference plus the payload's own width. + +// The value's width is implied by the type, so it is not stored twice; the +// helpers below recover it. This mirrors builtin's IntegerAttr / FloatAttr. +def IntAttr : DialectAttribute<(attr + Type:$type, + KnownWidthAPInt<"type">:$value +)> { + let cBuilder = "get<$_resultType>(context, mlir::cast<cir::IntTypeInterface>(type), *value)"; +} + +def FPAttr : DialectAttribute<(attr + Type:$type, + KnownSemanticsAPFloat<"type">:$value +)> { + let cBuilder = "get<$_resultType>(context, mlir::cast<cir::FPTypeInterface>(type), *value)"; +} + +// cir::BoolType is a singleton, so the self type carries no information and is +// rebuilt on read rather than stored. +def BoolAttr : DialectAttribute<(attr + Bool:$value +)> { + let cBuilder = "get<$_resultType>(context, cir::BoolType::get(context), value)"; +} + +def ConstPtrAttr : DialectAttribute<(attr + Ty<"cir::PointerType">:$type, + Attr<"mlir::IntegerAttr">:$value +)>; + +//===----------------------------------------------------------------------===// +// Parameterless marker attributes +//===----------------------------------------------------------------------===// +// +// No payload at all: the entry exists so the attribute costs a kind index +// instead of its printed mnemonic. + +def CatchAllAttr : DialectAttribute<(attr)>; +def UnwindAttr : DialectAttribute<(attr)>; + +//===----------------------------------------------------------------------===// +// Constant initializers +//===----------------------------------------------------------------------===// +// +// These carry a self type, and under the fallback each *occurrence* embeds +// that type's whole printed form, so a zero-initialized aggregate costs the +// full type text at every use. Encoding them natively writes a reference +// into the bytecode type table instead. + +def ZeroAttr : DialectAttribute<(attr + Type:$type +)>; + +def UndefAttr : DialectAttribute<(attr + Type:$type +)>; + +def PoisonAttr : DialectAttribute<(attr + Type:$type +)>; + +def ConstArrayAttr : DialectAttribute<(attr + Type:$type, + Attribute:$elts, + CheckedInt:$trailingZerosNum +)> { + let cBuilder = "getChecked<$_resultType>([&]() { return reader.emitError(); }, context, type, elts, trailingZerosNum)"; ---------------- xlauko wrote:
this can be dropped `DialectAttribute` already defaults to the same `cBuilder`. https://github.com/llvm/llvm-project/pull/229586 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
