diff --git a/pkg/sql/ir/Makefile b/pkg/sql/ir/Makefile index 6cfa9d07e76b..5c5419abaae0 100644 --- a/pkg/sql/ir/Makefile +++ b/pkg/sql/ir/Makefile @@ -4,9 +4,12 @@ SHELL = /usr/bin/env bash TEMPLATES = base/base.tmpl.go base/sexpr.tmpl.go -DEFS = example -TARGETS = $(foreach E,$(DEFS),$(foreach T,$(TEMPLATES),$(E)/$(T:.tmpl.go=.ir.go))) -all: $(TARGETS) +DEFS = example prims +CONFIGS = defcfg nopack expanded expandedpack onlyextra smallslots +TARGETS = $(foreach C,$(CONFIGS),$(foreach E,$(DEFS),$(foreach T,$(TEMPLATES),tests/$(C)/$(E)/$(T:.tmpl.go=.ir.go)))) +TEST_TARGETS = $(foreach C,$(CONFIGS),tests/$(C)/$(C)_cfg_test.go) + +all: $(TARGETS) $(TEST_TARGETS) clean: rm -f $(TARGETS) @@ -17,11 +20,21 @@ irgen/irgen: $(shell find irgen -name \*.go) .SUFFIXES: .ir.go .tmpl.go -# example/base/base.ir.go -> example -ir_def_base = $(firstword $(subst /, ,$(1))) +%_cfg_test.go: tests/irgen_test.go Makefile + mkdir -p $(notdir $*) + (echo "// Code generated by make. DO NOT EDIT."; \ + echo "// GENERATED FILE DO NOT EDIT"; \ + sed -e "s,ir/tests/defcfg,ir/tests/$(notdir $*),g;s,package main,package $(notdir $*),g" < $<) > $@.tmp + mv -f $@.tmp $@ + +# tests/cfg/example/base/base.ir.go -> example +ir_def_base = $(word 3,$(subst /, ,$(1))) + +# tests/cfg/example/base/base.ir.go -> cfg +cfg_base = $(word 2,$(subst /, ,$(1))) -# example/base/base.ir.go -> base/base.go -template_path = $(subst .ir,.tmpl,$(subst $(call ir_def_base,$(1))/,,$(1))) +# tests/cfg/example/base/base.ir.go -> base/base.tmpl.go +template_path = $(subst .ir,.tmpl,$(subst tests/$(call cfg_base,$(1))/$(call ir_def_base,$(1))/,,$(1))) # The special phrase ".SECONDEXPANSION" allows one to express rule # dependencies as a function of the name of the target. @@ -29,11 +42,17 @@ template_path = $(subst .ir,.tmpl,$(subst $(call ir_def_base,$(1))/,,$(1))) # The dependencies in the following rules are exactly, in this order: # - the name of the generator program ./irgen, +# - the configuration file, # - the source template, # - the input definition file # Those three items are then taken together to construct # a valid command line with $^ -%.ir.go: irgen/irgen $$(call template_path,$$@) $$(call ir_def_base,$$@).def - $^ > $@.tmp +%.ir.go: irgen/irgen tests/configs/$$(call cfg_base,$$@) $$(call template_path,$$@) tests/$$(call ir_def_base,$$@).def + mkdir -p $(dir $@) + run() { \ + set -x; \ + $$1 `cat $$2|grep -v '^#'` $$3 $$4; \ + }; run $^ > $@.tmp mv -f $@.tmp $@ gofmt -s -w $@ + goimports -w $@ diff --git a/pkg/sql/ir/base/base.tmpl.go b/pkg/sql/ir/base/base.tmpl.go index 5a0e5fd45cf2..32764acbdc7f 100644 --- a/pkg/sql/ir/base/base.tmpl.go +++ b/pkg/sql/ir/base/base.tmpl.go @@ -14,18 +14,27 @@ package base -import "fmt" +import ( + "fmt" +) // node is a generic ADT node type, with slots for references to other nodes and // enumeration values. Values that don't fit and values of other types go in the // extra field. type node struct { - refs [ºnumRefsPerNode]*node - enums [ºnumEnumsPerNode]enum + refs [ºnumRefsPerNode]*node + nums [ºnumNumsPerNode]numvalslot + strs [ºnumStrsPerNode]string extra } -type enum int32 +// enum is the type to define the tag part for working copies of IR +// node with sum and enum types. +type enum uint32 + +// numvalslot is the type used to store integer values in persistent IR nodes. +// must be larger than or as large as enum. +type numvalslot ºnumValSlotType type extra interface { extraRefs() []*node @@ -95,6 +104,18 @@ func (x ºEnum) String() string { // ºStruct is the type of a reference to an immutable record. type ºStruct struct{ ref *node } +// @for slot + +const ºStruct_Slot_ºslotName_Type = ºslotType +const ºStruct_Slot_ºslotName_Num = ºslotNum +const ºStruct_Slot_ºslotName_BitSize = ºslotBitSize +const ºStruct_Slot_ºslotName_BitOffset = ºslotBitOffset +const ºStruct_Slot_ºslotName_ByteSize = ºslotByteSize +const ºStruct_Slot_ºslotName_ByteOffset = ºslotByteOffset +const ºStruct_Slot_ºslotName_ValueMask = ºslotValueMask + +// @done slot + // ºStructValue is the logical type of a record. Immutable records are stored in // nodes. type ºStructValue struct { @@ -140,7 +161,7 @@ func (x ºStruct) ºItem() ºtype { return ºgetField(x.ref) } func (x ºStruct) V() ºStructValue { return ºStructValue{ // @for item - ºgetField(x.ref), + ºItem: ºgetField(x.ref), // @done item } } diff --git a/pkg/sql/ir/base/scaffolding.go b/pkg/sql/ir/base/scaffolding.go index 9fb389e6704b..f54e14b3f7f9 100644 --- a/pkg/sql/ir/base/scaffolding.go +++ b/pkg/sql/ir/base/scaffolding.go @@ -23,7 +23,8 @@ import "bytes" // These constants are replaced in template code. const ( ºnumRefsPerNode = iota - ºnumEnumsPerNode + ºnumNumsPerNode + ºnumStrsPerNode ºtag ) @@ -39,3 +40,16 @@ func (t ºtype) FormatSExpr(buf *bytes.Buffer) {} // FormatSExprºType is a stub for Sexpr formatters for primitive types. func FormatSExprºType(buf *bytes.Buffer, x ºtype) {} + +// ºnumValSlotType is overridden during code generation. +type ºnumValSlotType uint64 + +const ( + ºslotType = 0 + ºslotNum = 0 + ºslotBitSize = 0 + ºslotBitOffset = 0 + ºslotByteSize = 0 + ºslotByteOffset = 0 + ºslotValueMask = 0 +) diff --git a/pkg/sql/ir/base/sexpr.tmpl.go b/pkg/sql/ir/base/sexpr.tmpl.go index a77efd132807..696d310ecba2 100644 --- a/pkg/sql/ir/base/sexpr.tmpl.go +++ b/pkg/sql/ir/base/sexpr.tmpl.go @@ -16,16 +16,25 @@ package base import ( "bytes" - "strconv" + "fmt" ) type SexprFormatter interface { FormatSExpr(buf *bytes.Buffer) } -func FormatSExprInt64(buf *bytes.Buffer, x int64) { - buf.WriteString(strconv.FormatInt(x, 10)) -} +func FormatSExprBool(buf *bytes.Buffer, x bool) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt64(buf *bytes.Buffer, x int64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt32(buf *bytes.Buffer, x int32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt16(buf *bytes.Buffer, x int16) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt8(buf *bytes.Buffer, x int8) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint64(buf *bytes.Buffer, x uint64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint32(buf *bytes.Buffer, x uint32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint16(buf *bytes.Buffer, x uint16) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint8(buf *bytes.Buffer, x uint8) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprFloat32(buf *bytes.Buffer, x float32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprFloat64(buf *bytes.Buffer, x float64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprString(buf *bytes.Buffer, x string) { fmt.Fprintf(buf, "%q", x) } // @for enum diff --git a/pkg/sql/ir/irgen/codegen/codegen.go b/pkg/sql/ir/irgen/codegen/codegen.go index b53ece251c43..e4fbaf334c9b 100644 --- a/pkg/sql/ir/irgen/codegen/codegen.go +++ b/pkg/sql/ir/irgen/codegen/codegen.go @@ -17,6 +17,8 @@ package codegen import ( "fmt" "io" + "math" + "sort" "strings" "github.com/cockroachdb/cockroach/pkg/sql/ir/irgen/ir" @@ -24,17 +26,70 @@ import ( "github.com/cockroachdb/cockroach/pkg/sql/ir/irgen/template" ) -// Generate generates code for the given types. -func Generate( - w io.Writer, tmpl *template.Template, numRefs, numEnums int, namedTypeses ...[]ir.NamedType, -) error { +// Config holds configuration parameters for code generation. +type Config struct { + // NumNumericSlots is the number of numeric slots. + NumNumericSlots int + // NumSlotSize is the size of a numeric slot in the in-memory + // representation, in bits. + NumericSlotSize int + + // NumRefSlots is the number of reference slots. + NumRefSlots int + + // NumStrSlots is the number of slots for "string" values. Set to zero + // to avoid using dedicated string slots. + NumStrSlots int + + // Pack, if true, attempts to reuse slots for multiple + // numeric values. + Pack bool +} + +// Pervasives are predefined types in every language. +var Pervasives = []parser.Def{ + {Kind: parser.PrimDef, Name: parser.TypeNameOccur{Name: "bool"}}, + {Kind: parser.PrimDef, Name: parser.TypeNameOccur{Name: "string"}}, + {Kind: parser.PrimDef, Name: parser.TypeNameOccur{Name: "int8"}}, + {Kind: parser.PrimDef, Name: parser.TypeNameOccur{Name: "uint8"}}, + {Kind: parser.PrimDef, Name: parser.TypeNameOccur{Name: "int16"}}, + {Kind: parser.PrimDef, Name: parser.TypeNameOccur{Name: "uint16"}}, + {Kind: parser.PrimDef, Name: parser.TypeNameOccur{Name: "int32"}}, + {Kind: parser.PrimDef, Name: parser.TypeNameOccur{Name: "uint32"}}, + {Kind: parser.PrimDef, Name: parser.TypeNameOccur{Name: "int64"}}, + {Kind: parser.PrimDef, Name: parser.TypeNameOccur{Name: "uint64"}}, + {Kind: parser.PrimDef, Name: parser.TypeNameOccur{Name: "float32"}}, + {Kind: parser.PrimDef, Name: parser.TypeNameOccur{Name: "float64"}}, +} + +// DefaultConfig is to be used as default configuration for code generation. +var DefaultConfig = Config{ + NumNumericSlots: 2, + NumericSlotSize: 64, + NumRefSlots: 2, + NumStrSlots: 1, + Pack: true, +} + +// LanguageDef is a list of ADT definitions. +type LanguageDef []ir.NamedType + +// Generate generates code for the given languages. +func (cfg *Config) Generate(w io.Writer, tmpl *template.Template, languages ...LanguageDef) error { root := template.NewRoot() - root.AddReplacementf("numRefsPerNode", "%d", numRefs) - root.AddReplacementf("numEnumsPerNode", "%d", numEnums) - for _, namedTypes := range namedTypeses { - for _, namedType := range namedTypes { + + // Common configuration parameters. + root.AddReplacementf("numRefsPerNode", "%d", cfg.NumRefSlots) + root.AddReplacementf("numNumsPerNode", "%d", cfg.NumNumericSlots) + root.AddReplacementf("numStrsPerNode", "%d", cfg.NumStrSlots) + root.AddReplacementf("numValSlotType", "uint%d", cfg.NumericSlotSize) + + for _, language := range languages { + for _, namedType := range language { switch t := namedType.Type.(type) { case nil: + // Primary type. Nothing to do. + case *ir.EnumType: node := root.NewChild("enum") node.AddReplacement("Enum", namedType.Name) @@ -43,12 +98,67 @@ func Generate( child.AddReplacement(paramName, i.Name) child.AddReplacement(paramTag, i.Tag) } + + case *ir.SumType: + node := root.NewChild("sum") + node.AddReplacement("Sum", namedType.Name) + for _, i := range t.Items { + child := node.NewChild("item") + child.AddReplacement(paramType, i.Type) + child.AddReplacement(paramTag, i.Tag) + } + case *ir.StructType: + // Structs (product types). node := root.NewChild("struct") node.AddReplacement("Struct", namedType.Name) - a := slotAllocator{numRefs: numRefs, numEnums: numEnums, structNode: node} + a := slotAllocator{ + Config: cfg, + structNode: node, + } + + // Allocate the slots - this decides which fields go where in the + // persistent in-memory representation of nodes. + if err := a.allocateSlots(namedType.Name, t.Items); err != nil { + return err + } + + // Allow the template to inspect the slot structure. + for _, sslotName := range a.slotNames { + slotName := parser.ItemName(sslotName) + slot := a.slots[slotName] + child := node.NewChild("slot") + child.AddReplacement(paramSlotName, slotName) + child.AddReplacement(paramSlotType, fmt.Sprintf("%d", slot.slotType)) + child.AddReplacement(paramSlotNum, fmt.Sprintf("%d", slot.slotNum)) + if slot.slotType == slotTypeNum { + child.AddReplacement(paramSlotBitSize, fmt.Sprintf("%d", slot.szBits)) + child.AddReplacement(paramSlotByteSize, fmt.Sprintf("%d", (slot.szBits+7)/8)) + child.AddReplacement(paramSlotBitOffset, fmt.Sprintf("%d", slot.bitOffset)) + child.AddReplacement(paramSlotByteOffset, fmt.Sprintf("%d", slot.bitOffset/8)) + child.AddReplacement(paramSlotValueMask, fmt.Sprintf("%#x", uint64((1<> BinExpr_Slot_Left__Tag_BitOffset) & BinExpr_Slot_Left__Tag_ValueMask), x.ref.refs[0]} +// } +// func (x BinExpr) Op() BinOp { +// return BinOp((x.ref.nums[0] >> BinExpr_Slot_Op_BitOffset) & BinExpr_Slot_Op_ValueMask) +// } +// func (x BinExpr) Right() Expr { +// return Expr{ExprTag((x.ref.nums[0] >> BinExpr_Slot_Right__Tag_BitOffset) & BinExpr_Slot_Right__Tag_ValueMask), x.ref.refs[1]} +// } +// +// +// In addition, in both packed and unpacked mode we have a special handling +// for floating point types, which can be enabled with the configuration flag "allow unsafe". +// +// In safe mode, float values are always sent to extra slots. +// In unsafe mode, float values are stored in numeric slots. The Go +// unsafe package is used to access them (since a numeric cast would +// lose the value). +// + +// slotAllocator contains the allocation variables for a single struct type. type slotAllocator struct { - numRefs, numExtraRefs, numEnums int - structNode *template.Node + *Config + curRefs, curNums, curStrs int + numExtraRefs int + structNode *template.Node + + slotNames []string + slots map[parser.ItemName]slot +} + +// tSizes are the sizes in bits of the predefined primitive types. +var tSizes = map[parser.TypeName]int{ + "bool": 1, + "int8": 8, "uint8": 8, + "int16": 16, "uint16": 16, + "int32": 32, "uint32": 32, "float32": 32, + "int64": 64, "uint64": 64, "float64": 64, } -func (a *slotAllocator) allocateSlots(i ir.StructItem) (getName, setName string) { - switch t := i.Type.Type.(type) { - case nil: - return a.allocatePrimSlot(i.Name, i.Type.Name) - case *ir.EnumType: - return a.allocateEnumSlot(i.Name, i.Type.Name) - case *ir.StructType: - getRef, setRef := a.allocateRefSlot() - return fmt.Sprintf("%s{%s}", i.Type, getRef), - setRef - case *ir.SumType: - getTag, setTag := a.allocateEnumSlot(i.Name, i.Type.Name+"Tag") - getRef, setRef := a.allocateRefSlot() - return fmt.Sprintf("%s{%s, %s}", i.Type, getTag, getRef), - fmt.Sprintf("%s\n\t%s", strings.Replace(setTag, "$3", "$3.tag", -1), setRef) - default: - panic(fmt.Sprintf("case %T is not handled", t)) +// slot describes one slot in a struct. +type slot struct { + // getName is the Go code to access the value in a node. + // The substring "$1" is replaced by a node reference expression + // during code generation (macroGetName). + getName string + + // setName is the Go code to write a value in a node. + // The substrings are replaced as follows during + // code generation (macroSetName): + // $1 - an expression evaluating to the node reference; + // $2 - the reference to extra slots, if one is needed; + // $3 - the value being written to the node, for a set. + setName string + + // slotType is the kind of node (numeric, string, reference, extra, extra ref). + slotType slotType + + // slotNum is the index of the slot in its own category. + // In packed mode, multiple slots can share the same slotNum, + // and when they do their offset (defined below) differs. + slotNum int + + // For numeric slots, we have a size in bits and an offset. In + // unpacked mode, the size is the size of a slot and the offset is + // zero. + szBits int + bitOffset int +} + +// slotType is used to annotate slot metadata. +type slotType int + +const ( + slotTypeRef slotType = iota + slotTypeNum + slotTypeStr + slotTypeExtra + slotTypeExtraRef +) + +// ilog2 returns the first value P so that 2^P is equal to or greater +// than n. For example ilog2(1) = 0, ilog2(4) = 2, ilog2(5) = 3. Note +// that this is different from "find position of leftmost bit". +func ilog2(n int) int { + return int(math.Ceil(math.Log2(float64(n)))) +} + +// allocateSlots implements the algorithm described above. +func (a *slotAllocator) allocateSlots(sName parser.TypeName, items []ir.StructItem) error { + // First phase: compute the desired sizes for every item of non-reference type that + // can be stored in numeric slots. + // This includes: + // - primitive types of integer type; + // - tags of sum references; + // - float values if unsafe mode is unabled. + + // allSizes contains one unique value per size actually used + // by fields in this struct. + allSizes := make([]int, 0, len(items)) + + // slotItem is a helper struct defining a pair (slot name, slot type) + // It mirrors the struct field name and type in all cases except + // for the tags of sum references, in which case the word "Tag" is + // concatenated to both parts. + type slotItem struct { + name parser.ItemName + typ parser.TypeName } + + // itemsInEachSize collects, for each field size, the items + // that have that size. + itemsInEachSize := make(map[int][]slotItem) + + // Analyze the struct. + for _, item := range items { + // isz is the bit size we'll use for the slot. + var isz int + // name and typ are the fields we'll store in the slotItem struct. + name := item.Name + typ := item.Type.Name + + if s, ok := item.Type.Type.(*ir.SumType); ok { + // Sum types need a space for the tag. + // We compute the size of that space to be just + // sufficient to store all possible tag values. + maxTag := parser.Tag(1) + for _, it := range s.Items { + if maxTag < it.Tag { + maxTag = it.Tag + } + } + isz = ilog2(int(maxTag + 1)) + name = name + "__Tag" + typ = typ + "Tag" + } else if e, ok := item.Type.Type.(*ir.EnumType); ok { + // Like for struct types, we compute a size + // that is just sufficient to store all possible + // enum values. + maxTag := parser.Tag(1) + for _, it := range e.Items { + if maxTag < it.Tag { + maxTag = it.Tag + } + } + isz = ilog2(int(maxTag + 1)) + } else if sz, ok := tSizes[item.Type.Name]; ok { + // For primitive types with a known size, use that. + isz = sz + } + if isz == 0 || isz > a.NumericSlotSize { + // The type was not handled: + // - primitive type of unknown size, + // - primitive type that cannot fit in a numeric slot because + // it's too large (e.g. -num-slot-size configured smaller than + // the largest primitive type used in the struct) + // - float type and unsafe mode is disabled, + // - a struct reference. + continue + } + if !a.Pack { + // If the user specifies unpacked mode, we pretend the value is + // as large as the slot. This enables simplified accessors. + isz = a.NumericSlotSize + } + + // Store the computed size for later. + if _, ok := itemsInEachSize[isz]; !ok { + allSizes = append(allSizes, isz) + } + itemsInEachSize[isz] = append(itemsInEachSize[isz], slotItem{name: name, typ: typ}) + } + + // We want to look at the fields from largest to smallest. So we + // need the sizes to be sorted. + sort.Ints(allSizes) + + // Second phase is to allocate all the numeric slots, in decreasing + // field size. + + a.slots = make(map[parser.ItemName]slot) + + // seen collects all the field/slot names that are handled in this + // phase. This will be later used to skip the slots already handled + // here, in the third phase below. + seen := make(map[parser.ItemName]struct{}) + + // curNums tracks the index of the current "active" numeric slot + // where we can put field data in. + a.curNums = 0 + // curOffsetInNumSlot is the offset of the next bit position + // available to put data in the current active numeric slot. + curOffsetInNumSlot := 0 + + // Allocate from largest to smallest. + for j := len(allSizes) - 1; j >= 0 && a.curNums < a.NumericSlotSize; j-- { + sz := allSizes[j] + itemsOfThisSize := itemsInEachSize[sz] + + for _, i := range itemsOfThisSize { + if curOffsetInNumSlot+sz > a.NumericSlotSize { + // Current slot is exhausted. Allocate a new slot. + a.curNums++ + curOffsetInNumSlot = 0 + } + if a.curNums >= a.NumNumericSlots { + // No more numeric slots available. Give up. + // We'll just use extra slots below. + break + } + + seen[i.name] = struct{}{} + a.slots[i.name] = a.makeNumSlot(sName, i.name, i.typ, a.curNums, curOffsetInNumSlot, sz) + curOffsetInNumSlot += sz + } + } + + // Third phase: allocate everything else. + // This includes numeric fields that have to go to extra slots, + // but also string fields that can go to dedicated string slots, + // and of course the reference fields. + + for _, i := range items { + if _, ok := seen[i.Name]; ok { + // Already allocated above, nothing to do. + continue + } + + switch t := i.Type.Type.(type) { + case nil, (*ir.EnumType): + if i.Type.Name == "string" { + a.slots[i.Name] = a.allocateStrSlot(i.Name, i.Type.Name) + } else { + // Primitive or enum type, but we already have exhausted all + // numeric slots above. So give up and allocate an extra slot + // instead. + a.slots[i.Name] = a.allocateExtraSlot(i.Name, i.Type.Name) + } + + case *ir.StructType: + s := a.allocateRefSlot() + s.getName = fmt.Sprintf("%s{%s}", i.Type, s.getName) + // s.setName is unchanged. + a.slots[i.Name] = s + + case *ir.SumType: + // Have we already allocated a tag slot for this sum reference? + // If so, reuse that. + es, ok := a.slots[i.Name+"__Tag"] + if !ok { + // The allocation of a slot for the tag may have failed because + // all the numeric slots were exhausted. In that case, + // take an extra slot. + es = a.allocateExtraSlot(i.Name+"__Tag", i.Type.Name+"Tag") + } + + s := a.allocateRefSlot() + s.getName = fmt.Sprintf("%s{%s, %s}", i.Type, es.getName, s.getName) + s.setName = fmt.Sprintf("%s\n\t%s", strings.Replace(es.setName, "$3", "$3.tag", -1), s.setName) + a.slots[i.Name] = s + + default: + panic(fmt.Sprintf("case %T is not handled", t)) + } + } + + // Allocated all slots, prepare the name array so that the consumer + // can access the slot data in deterministic order. + a.slotNames = make([]string, 0, len(a.slots)) + for k := range a.slots { + a.slotNames = append(a.slotNames, string(k)) + } + sort.Strings(a.slotNames) + + return nil } -func (a *slotAllocator) allocatePrimSlot( - name parser.ItemName, typ parser.TypeName, -) (getName, setName string) { +func (a *slotAllocator) allocateExtraSlot(name parser.ItemName, typ parser.TypeName) slot { extra := a.structNode.NewChild("extraField") extra.AddReplacement(paramName, name) extra.AddReplacement(paramType, typ) - return fmt.Sprintf("$1.extra.(*extraºStruct).%s", name), - fmt.Sprintf("$2.%s = $3", name) + return slot{ + getName: fmt.Sprintf("$1.extra.(*extraºStruct).%s", name), + setName: fmt.Sprintf("$2.%s = $3", name), + slotType: slotTypeExtra, + slotNum: -1, + } } -func (a *slotAllocator) allocateRefSlot() (getName, setName string) { - if a.numRefs > 0 { - a.numRefs-- - j := a.numRefs - return fmt.Sprintf("$1.refs[%d]", j), - fmt.Sprintf("$1.refs[%d] = $3.ref", j) +func (a *slotAllocator) allocateStrSlot(name parser.ItemName, typ parser.TypeName) slot { + if a.curStrs >= a.NumStrSlots { + return a.allocateExtraSlot(name, typ) + } + + j := a.curStrs + a.curStrs++ + return slot{ + getName: fmt.Sprintf("$1.strs[%d]", j), + setName: fmt.Sprintf("$1.strs[%d] = $3", j), + slotType: slotTypeStr, + slotNum: j, } - j := a.numExtraRefs - a.numExtraRefs++ - return fmt.Sprintf("$1.extra.(*extraºStruct).refs[%d]", j), - fmt.Sprintf("$2.refs[%d] = $3.ref", j) } -func (a *slotAllocator) allocateEnumSlot( - name parser.ItemName, typ parser.TypeName, -) (getName, setName string) { - if a.numEnums > 0 { - a.numEnums-- - return fmt.Sprintf("%s($1.enums[%d])", typ, a.numEnums), - fmt.Sprintf("$1.enums[%d] = enum($3)", a.numEnums) +func (a *slotAllocator) allocateRefSlot() slot { + if a.curRefs >= a.NumRefSlots { + j := a.numExtraRefs + a.numExtraRefs++ + return slot{ + getName: fmt.Sprintf("$1.extra.(*extraºStruct).refs[%d]", j), + setName: fmt.Sprintf("$2.refs[%d] = $3.ref", j), + slotType: slotTypeExtraRef, + slotNum: j, + } + } + + j := a.curRefs + a.curRefs++ + return slot{ + getName: fmt.Sprintf("$1.refs[%d]", j), + setName: fmt.Sprintf("$1.refs[%d] = $3.ref", j), + slotType: slotTypeRef, + slotNum: j, + } +} + +func (a *slotAllocator) makeNumSlot( + sName parser.TypeName, name parser.ItemName, typ parser.TypeName, slotNum, offset, sz int, +) slot { + s := slot{ + slotType: slotTypeNum, + slotNum: slotNum, + szBits: sz, + bitOffset: offset, + } + isFloat := strings.HasPrefix(typ.String(), "float") + floatSz := tSizes[typ] + + if typ == "bool" { + // Argh, all this special casing! All this is only needed because + // Go doesn't know how to convert between bool and integer types. + if sz < a.NumericSlotSize { + // Packed mode. + s.getName = fmt.Sprintf("!(0 == ($1.nums[%[1]d] >> %[2]s_Slot_%[3]s_BitOffset & %[2]s_Slot_%[3]s_ValueMask))", slotNum, sName, name) + s.setName = fmt.Sprintf( + "if $3 { $1.nums[%[1]d] |= (numvalslot(1) << %[2]s_Slot_%[3]s_BitOffset); } "+ + "else { $1.nums[%[1]d] &^= (numvalslot(1) << %[2]s_Slot_%[3]s_BitOffset); }", + slotNum, sName, name) + } else { + // Unpacked mode. + s.getName = fmt.Sprintf("!(0 == $1.nums[%d])", slotNum) + s.setName = fmt.Sprintf("if $3 { $1.nums[%[1]d] = 1 } else { $1.nums[%[1]d] = 0 }", slotNum) + } + } else { + // General case. + if sz < a.NumericSlotSize { + // Packed mode. + if isFloat { + s.getName = fmt.Sprintf("math.Float%[1]dfrombits(uint%[1]d(($1.nums[%[2]d] >> %[3]s_Slot_%[4]s_BitOffset) & %[3]s_Slot_%[4]s_ValueMask))", floatSz, slotNum, sName, name) + s.setName = fmt.Sprintf("$1.nums[%[1]d] = ($1.nums[%[1]d] &^ (%[2]s_Slot_%[3]s_ValueMask << %[2]s_Slot_%[3]s_BitOffset)) | (numvalslot(math.Float%[4]dbits($3)) << %[2]s_Slot_%[3]s_BitOffset)", slotNum, sName, name, floatSz) + } else { + s.getName = fmt.Sprintf("%[1]s(($1.nums[%[2]d] >> %[3]s_Slot_%[4]s_BitOffset) & %[3]s_Slot_%[4]s_ValueMask)", typ, slotNum, sName, name) + s.setName = fmt.Sprintf("$1.nums[%[1]d] = ($1.nums[%[1]d] &^ (%[2]s_Slot_%[3]s_ValueMask << %[2]s_Slot_%[3]s_BitOffset)) | (numvalslot($3) << %[2]s_Slot_%[3]s_BitOffset)", + slotNum, sName, name) + } + } else { + // Unpacked mode. + if isFloat { + s.getName = fmt.Sprintf("math.Float%[1]dfrombits(uint%[1]d($1.nums[%[2]d]))", floatSz, slotNum) + s.setName = fmt.Sprintf("$1.nums[%[1]d] = numvalslot(math.Float%[2]dbits($3))", slotNum, floatSz) + } else { + s.getName = fmt.Sprintf("%[1]s($1.nums[%[2]d])", typ, slotNum) + s.setName = fmt.Sprintf("$1.nums[%[1]d] = numvalslot($3)", slotNum) + } + } } - return a.allocatePrimSlot(name, typ) + return s } func (a *slotAllocator) finish() (getExtraRefs string) { diff --git a/pkg/sql/ir/irgen/main.go b/pkg/sql/ir/irgen/main.go index 102e7c5e3e0a..f044314aafda 100644 --- a/pkg/sql/ir/irgen/main.go +++ b/pkg/sql/ir/irgen/main.go @@ -15,6 +15,8 @@ package main import ( + "bytes" + "flag" "fmt" "os" "strings" @@ -23,49 +25,106 @@ import ( "github.com/cockroachdb/cockroach/pkg/sql/ir/irgen/analyzer" "github.com/cockroachdb/cockroach/pkg/sql/ir/irgen/codegen" - "github.com/cockroachdb/cockroach/pkg/sql/ir/irgen/ir" "github.com/cockroachdb/cockroach/pkg/sql/ir/irgen/parser" "github.com/cockroachdb/cockroach/pkg/sql/ir/irgen/template" ) +// irgen loads one or more language definitions and uses the specified +// template file to generate the corresponding code. The languages +// are instantiated together in the output file. func irgen() error { - if len(os.Args) < 2 { - return errors.Errorf("usage: %s template definitions...", os.Args[0]) + cfg, args := getParams() + if len(args) < 2 { + return errors.Errorf("usage: %s template definitions...", args[0]) } - var namedTypeses [][]ir.NamedType - for _, name := range os.Args[2:] { - f, err := os.Open(name) - if err != nil { - return err - } - defer f.Close() - defs, err := parser.Parse(name, f) - if err != nil { - return err - } - namedTypes, err := analyzer.Analyze(defs) - if err != nil { - return err - } - namedTypeses = append(namedTypeses, namedTypes) - } - f, err := os.Open(os.Args[1]) + + // Get the template. + tmpl, err := openTemplate(args[1]) if err != nil { return err } - defer f.Close() - tmpl, err := template.Parse(f) + + // Get the languages. + languages, err := loadLanguages(args[2:]) if err != nil { return err } + + // Generate the code. + // First comment for github/Go; second for reviewable. // https://github.com/golang/go/issues/13560#issuecomment-277804473 // https://github.com/Reviewable/Reviewable/wiki/FAQ#how-do-i-tell-reviewable-that-a-file-is-generated-and-should-not-be-reviewed - if _, err := fmt.Printf("// Code generated by %s. DO NOT EDIT.\n// GENERATED FILE DO NOT EDIT\n", - strings.Join(os.Args, " ")); err != nil { - return err + fmt.Printf("// Code generated by %s. DO NOT EDIT.\n// GENERATED FILE DO NOT EDIT\n", + strings.Join(args, " ")) + err = cfg.Generate(os.Stdout, tmpl, languages...) + var buf bytes.Buffer + fmt.Fprintf(&buf, "// Codegen parameters:\n%+v\n", cfg) + fmt.Print(strings.Replace(buf.String(), "\n", "\n// ", -1)) + return err +} + +// loadLanguages analyzes the input language definition files, controls the definitions +// and returns the language definitions for each of them. +func loadLanguages(files []string) ([]codegen.LanguageDef, error) { + var languages []codegen.LanguageDef + for _, name := range files { + // Parse the language definition input file into a language + // definition AST. + defs, err := func() ([]parser.Def, error) { + f, err := os.Open(name) + if err != nil { + return nil, err + } + defer f.Close() + return parser.Parse(name, f) + }() + if err != nil { + return nil, err + } + + // Every language starts with all primitive types. + defs = append(codegen.Pervasives, defs...) + + // Analyze the semantics. + namedTypes, err := analyzer.Analyze(defs) + if err != nil { + return nil, err + } + languages = append(languages, codegen.LanguageDef(namedTypes)) + } + return languages, nil +} + +// getParams analyzes the command line and retrieves the codegen parameters and +// files to analyze. +func getParams() (cfg codegen.Config, files []string) { + cfg = codegen.DefaultConfig + flag.BoolVar(&cfg.Pack, "pack", cfg.Pack, "pack multiple numeric values per numeric slot (less memory usage)") + flag.IntVar(&cfg.NumericSlotSize, "num-slot-size", cfg.NumericSlotSize, "number of bits per numeric slot (must be power of two)") + flag.IntVar(&cfg.NumNumericSlots, "nums", cfg.NumNumericSlots, "number of embedded numeric slots (set to 0 to disable)") + flag.IntVar(&cfg.NumRefSlots, "refs", cfg.NumRefSlots, "number of embedded reference slots (set to 0 to disable)") + flag.IntVar(&cfg.NumStrSlots, "strs", cfg.NumStrSlots, "number of embedded string slots (set to 0 to disable)") + + flag.Parse() + args := flag.Args() + + // The flag package forgets about argv[0], but we like it for error + // messages. Keep it. + args = append([]string{os.Args[0]}, args...) + + return cfg, args +} + +// openTemplate instantiates a template.Template object from the given +// file name. +func openTemplate(tmplName string) (*template.Template, error) { + f, err := os.Open(tmplName) + if err != nil { + return nil, err } - return codegen.Generate(os.Stdout, tmpl, 1 /*numRefs*/, 2 /*numEnums*/, namedTypeses...) + defer f.Close() + return template.Parse(f) } func main() { diff --git a/pkg/sql/ir/tests/configs/defcfg b/pkg/sql/ir/tests/configs/defcfg new file mode 100644 index 000000000000..d88c85ac9c18 --- /dev/null +++ b/pkg/sql/ir/tests/configs/defcfg @@ -0,0 +1 @@ +-pack=true -nums 2 -num-slot-size 64 -refs 2 -strs 1 diff --git a/pkg/sql/ir/tests/configs/expanded b/pkg/sql/ir/tests/configs/expanded new file mode 100644 index 000000000000..1df0d3dd3912 --- /dev/null +++ b/pkg/sql/ir/tests/configs/expanded @@ -0,0 +1,3 @@ +-pack=false -nums 20 -num-slot-size 64 -refs 20 -strs 20 + + diff --git a/pkg/sql/ir/tests/configs/expandedpack b/pkg/sql/ir/tests/configs/expandedpack new file mode 100644 index 000000000000..615f8d2f3986 --- /dev/null +++ b/pkg/sql/ir/tests/configs/expandedpack @@ -0,0 +1 @@ +-pack=true -nums 20 -num-slot-size 64 -refs 20 -strs 20 diff --git a/pkg/sql/ir/tests/configs/nopack b/pkg/sql/ir/tests/configs/nopack new file mode 100644 index 000000000000..d061746eab75 --- /dev/null +++ b/pkg/sql/ir/tests/configs/nopack @@ -0,0 +1,2 @@ +-pack=false -nums 2 -num-slot-size 64 -refs 2 -strs 1 + diff --git a/pkg/sql/ir/tests/configs/onlyextra b/pkg/sql/ir/tests/configs/onlyextra new file mode 100644 index 000000000000..8d98e2eb35ed --- /dev/null +++ b/pkg/sql/ir/tests/configs/onlyextra @@ -0,0 +1 @@ +-pack=false -nums 0 -num-slot-size 64 -refs 0 -strs 0 diff --git a/pkg/sql/ir/tests/configs/smallslots b/pkg/sql/ir/tests/configs/smallslots new file mode 100644 index 000000000000..e4c7932e478f --- /dev/null +++ b/pkg/sql/ir/tests/configs/smallslots @@ -0,0 +1 @@ +-pack=true -nums 20 -num-slot-size 16 -refs 2 -strs 1 diff --git a/pkg/sql/ir/tests/defcfg/defcfg_cfg_test.go b/pkg/sql/ir/tests/defcfg/defcfg_cfg_test.go new file mode 100644 index 000000000000..dfcea6761b98 --- /dev/null +++ b/pkg/sql/ir/tests/defcfg/defcfg_cfg_test.go @@ -0,0 +1,249 @@ +// Code generated by make. DO NOT EDIT. +// GENERATED FILE DO NOT EDIT +// Copyright 2017 The Cockroach Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. + +package defcfg + +import ( + "bytes" + "fmt" + "reflect" + "strconv" + "strings" + "testing" + + d "github.com/cockroachdb/cockroach/pkg/sql/ir/tests/defcfg/example/base" + p "github.com/cockroachdb/cockroach/pkg/sql/ir/tests/defcfg/prims/base" +) + +func makeSampleExpr(a *d.Allocator) d.Expr { + c1 := d.ConstExprValue{Datum: 1}.R(a).Expr() + c2 := d.ConstExprValue{Datum: 2}.R(a).Expr() + c3 := d.ConstExprValue{Datum: 3}.R(a).Expr() + b4 := d.BinExprValue{Left: c1, Op: d.BinOpAdd, Right: c2}.R(a).Expr() + b5 := d.BinExprValue{Left: c3, Op: d.BinOpMul, Right: b4}.R(a).Expr() + return b5 +} + +func assertEq(t *testing.T, n int, val interface{}, exp interface{}) { + if !reflect.DeepEqual(val, exp) { + t.Errorf("equal failed %d: expected %v, got %v", n, exp, val) + } +} + +func TestExprValues(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + b5 := e.MustBeBinExpr() + assertEq(t, 1, b5.Op(), d.BinOpMul) + assertEq(t, 2, b5.Left().MustBeConstExpr().Datum(), int64(3)) + b4 := b5.Right().MustBeBinExpr() + assertEq(t, 3, b4.Op(), d.BinOpAdd) + assertEq(t, 4, b4.Left().MustBeConstExpr().Datum(), int64(1)) + assertEq(t, 5, b4.Right().MustBeConstExpr().Datum(), int64(2)) +} + +func format(ref d.Expr) string { + switch ref.Tag() { + case d.ExprConstExpr: + c := ref.MustBeConstExpr() + return strconv.FormatInt(c.Datum(), 10) + case d.ExprBinExpr: + b := ref.MustBeBinExpr() + var op string + switch b.Op() { + case d.BinOpAdd: + op = "+" + case d.BinOpMul: + op = "*" + default: + panic("unknown BinOp") + } + return fmt.Sprintf("(%s %s %s)", format(b.Left()), op, format(b.Right())) + default: + panic("unknown Expr tag") + } +} + +func TestExprFormatSExpr(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + + var buf bytes.Buffer + e.FormatSExpr(&buf) + if buf.String() != "(BinExpr Left: (ConstExpr Datum: 3) Op: Mul Right: (BinExpr Left: (ConstExpr Datum: 1) Op: Add Right: (ConstExpr Datum: 2)))" { + t.Fatalf("unexpected: %q", buf.String()) + } +} + +func TestFormat(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + const expected = "(3 * (1 + 2))" + if got := format(e); got != expected { + t.Fatalf("expected %q but got %q", expected, got) + } +} + +func reverse(ref d.Expr, a *d.Allocator) d.Expr { + if ref.Tag() != d.ExprBinExpr { + return ref + } + b := ref.MustBeBinExpr() + revLeft := reverse(b.Left(), a) + revRight := reverse(b.Right(), a) + return b.V().WithLeft(revRight).WithRight(revLeft).R(a).Expr() +} + +func TestReverse(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + const expected = "((2 + 1) * 3)" + if got := format(reverse(e, a)); got != expected { + t.Fatalf("expected %q but got %q", expected, got) + } +} + +func TestDoubleReverse(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + if got0, got2 := format(e), format(reverse(reverse(e, a), a)); got0 != got2 { + t.Fatalf("reverse is not an involution: %q != %q", got0, got2) + } +} + +func deepEqual(ref1 d.Expr, ref2 d.Expr) bool { + if ref1.Tag() != ref2.Tag() { + return false + } + switch ref1.Tag() { + case d.ExprConstExpr: + return ref1.MustBeConstExpr().Datum() == ref2.MustBeConstExpr().Datum() + case d.ExprBinExpr: + b1 := ref1.MustBeBinExpr() + b2 := ref2.MustBeBinExpr() + return b1.Op() == b2.Op() && + deepEqual(b1.Left(), b2.Left()) && deepEqual(b1.Right(), b2.Right()) + default: + panic("unknown Expr tag") + } +} + +func TestDeepEqual(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + if deepEqual(e, reverse(e, a)) { + t.Fatalf("expected expression not to be deepEqual to its reverse") + } + if !deepEqual(e, reverse(reverse(e, a), a)) { + t.Fatalf("expected expression to be deepEqual to the reverse of its reverse") + } +} + +func TestPrimValues(t *testing.T) { + a := p.NewAllocator() + all := p.AllValue{ + B: true, + I8: 'b', + U8: 'c', + I16: 0x1234, + U16: 0x4321, + I32: 0x12345678, + U32: 0x87654321, + I64: 0x123456789abcdef0, + U64: 0x0fedcba987654321, + S: "k", + F32: 1.234, + F64: 5.678, + }.R(a) + assertEq(t, 1, all.B(), true) + assertEq(t, 2, all.I8(), int8('b')) + assertEq(t, 3, all.U8(), uint8('c')) + assertEq(t, 4, all.I16(), int16(0x1234)) + assertEq(t, 5, all.U16(), uint16(0x4321)) + assertEq(t, 6, all.I32(), int32(0x12345678)) + assertEq(t, 7, all.U32(), uint32(0x87654321)) + assertEq(t, 8, all.I64(), int64(0x123456789abcdef0)) + assertEq(t, 9, all.U64(), uint64(0x0fedcba987654321)) + assertEq(t, 10, all.S(), "k") + assertEq(t, 11, all.F32(), float32(1.234)) + assertEq(t, 12, all.F64(), float64(5.678)) + + var buf bytes.Buffer + all.FormatSExpr(&buf) + assertEq(t, 100, buf.String(), strings.TrimSpace(` +(All B: true I8: 98 U8: 99 I16: 4660 U16: 17185 I32: 305419896 U32: 2271560481 I64: 1311768467463790320 U64: 1147797409030816545 S: "k" F32: 1.234 F64: 5.678) +`)) +} + +func TestPrimValues2(t *testing.T) { + a := p.NewAllocator() + v := p.SmallBeforeValue{ + A: true, + B: false, + C: 'c', + D: 'd', + E: 'e', + F: 0x1234, + G: 0x4321, + H: 0x12345678, + I: 0x123456789abcdef0, + }.R(a) + assertEq(t, 1, v.A(), true) + assertEq(t, 2, v.B(), false) + assertEq(t, 3, v.C(), uint8('c')) + assertEq(t, 4, v.D(), uint8('d')) + assertEq(t, 5, v.E(), uint8('e')) + assertEq(t, 6, v.F(), uint16(0x1234)) + assertEq(t, 7, v.G(), uint16(0x4321)) + assertEq(t, 8, v.H(), uint32(0x12345678)) + assertEq(t, 9, v.I(), uint64(0x123456789abcdef0)) + + var buf bytes.Buffer + v.FormatSExpr(&buf) + assertEq(t, 100, buf.String(), strings.TrimSpace(` +(SmallBefore A: true B: false C: 99 D: 100 E: 101 F: 4660 G: 17185 H: 305419896 I: 1311768467463790320) +`)) +} + +func TestPrimValues3(t *testing.T) { + a := p.NewAllocator() + v := p.BigBeforeValue{ + A: 0x123456789abcdef0, + B: 0x12345678, + C: 0x1234, + D: 0x4321, + E: 'e', + F: 'f', + G: 'g', + H: false, + I: true, + }.R(a) + assertEq(t, 1, v.A(), uint64(0x123456789abcdef0)) + assertEq(t, 2, v.B(), uint32(0x12345678)) + assertEq(t, 3, v.C(), uint16(0x1234)) + assertEq(t, 4, v.D(), uint16(0x4321)) + assertEq(t, 5, v.E(), uint8('e')) + assertEq(t, 6, v.F(), uint8('f')) + assertEq(t, 7, v.G(), uint8('g')) + assertEq(t, 8, v.H(), false) + assertEq(t, 9, v.I(), true) + + var buf bytes.Buffer + v.FormatSExpr(&buf) + assertEq(t, 100, buf.String(), strings.TrimSpace(` +(BigBefore A: 1311768467463790320 B: 305419896 C: 4660 D: 17185 E: 101 F: 102 G: 103 H: false I: true) +`)) +} diff --git a/pkg/sql/ir/tests/defcfg/example/base/base.ir.go b/pkg/sql/ir/tests/defcfg/example/base/base.ir.go new file mode 100644 index 000000000000..27f68ae2d3ff --- /dev/null +++ b/pkg/sql/ir/tests/defcfg/example/base/base.ir.go @@ -0,0 +1,678 @@ +// Code generated by irgen/irgen base/base.tmpl.go tests/example.def. DO NOT EDIT. +// GENERATED FILE DO NOT EDIT +// Copyright 2017 The Cockroach Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. + +package base + +import ( + "fmt" +) + +// node is a generic ADT node type, with slots for references to other nodes and +// enumeration values. Values that don't fit and values of other types go in the +// extra field. +type node struct { + refs [2]*node + nums [2]numvalslot + strs [1]string + extra +} + +// enum is the type to define the tag part for working copies of IR +// node with sum and enum types. +type enum uint32 + +// numvalslot is the type used to store integer values in persistent IR nodes. +// must be larger than or as large as enum. +type numvalslot uint64 + +type extra interface { + extraRefs() []*node +} + +// Allocator allocates nodes in batches. Construct Allocators with NewAllocator +// and pass them by value. +type Allocator struct { + nodes []node +} + +// MakeAllocator constructs a new Allocator. +func MakeAllocator() Allocator { + nodes := make([]node, 16) + return Allocator{nodes} +} + +// NewAllocator allocates a new Allocator. +func NewAllocator() *Allocator { + a := MakeAllocator() + return &a +} + +// new allocates a new node. Users of this package should use the appropriate +// R() method, which is type safe. +func (a *Allocator) new() *node { + nodes := a.nodes + if len(nodes) == 0 { + nodes = make([]node, 256) + } + x := &nodes[0] + a.nodes = nodes[1:] + return x +} + +// ---- BinOp ---- // + +// BinOp is an enumeration type. +type BinOp enum + +// BinOp constants. +const ( + BinOpAdd BinOp = 1 + BinOpMul BinOp = 2 +) + +func (x BinOp) String() string { + switch x { + case BinOpAdd: + return "Add" + case BinOpMul: + return "Mul" + default: + return fmt.Sprintf("", x) + } +} + +// ---- ConstExpr ---- // + +// ConstExpr is the type of a reference to an immutable record. +type ConstExpr struct{ ref *node } + +const ConstExpr_Slot_Datum_Type = 1 +const ConstExpr_Slot_Datum_Num = 0 +const ConstExpr_Slot_Datum_BitSize = 64 +const ConstExpr_Slot_Datum_BitOffset = 0 +const ConstExpr_Slot_Datum_ByteSize = 8 +const ConstExpr_Slot_Datum_ByteOffset = 0 +const ConstExpr_Slot_Datum_ValueMask = 0xffffffffffffffff + +// ConstExprValue is the logical type of a record. Immutable records are stored in +// nodes. +type ConstExprValue struct { + Datum int64 // 1 +} + +// R constructs a reference to an immutable record. +func (x ConstExprValue) R(a *Allocator) ConstExpr { + ref := a.new() + + ref.nums[0] = numvalslot(x.Datum) + return ConstExpr{ref} +} + +// Datum returns the Datum field. +func (x ConstExpr) Datum() int64 { return int64(x.ref.nums[0]) } + +// V unpacks a reference into a value. +func (x ConstExpr) V() ConstExprValue { + return ConstExprValue{ + Datum: int64(x.ref.nums[0]), + } +} + +// WithDatum constructs a new value where the value of Datum has been replaced by +// the argument. +func (x ConstExprValue) WithDatum(y int64) ConstExprValue { + x.Datum = y + return x +} + +// ---- BinExpr ---- // + +// BinExpr is the type of a reference to an immutable record. +type BinExpr struct{ ref *node } + +const BinExpr_Slot_Left_Type = 0 +const BinExpr_Slot_Left_Num = 0 +const BinExpr_Slot_Left_BitSize = -1 +const BinExpr_Slot_Left_BitOffset = -1 +const BinExpr_Slot_Left_ByteSize = -1 +const BinExpr_Slot_Left_ByteOffset = -1 +const BinExpr_Slot_Left_ValueMask = -1 + +const BinExpr_Slot_Left__Tag_Type = 1 +const BinExpr_Slot_Left__Tag_Num = 0 +const BinExpr_Slot_Left__Tag_BitSize = 2 +const BinExpr_Slot_Left__Tag_BitOffset = 0 +const BinExpr_Slot_Left__Tag_ByteSize = 1 +const BinExpr_Slot_Left__Tag_ByteOffset = 0 +const BinExpr_Slot_Left__Tag_ValueMask = 0x3 + +const BinExpr_Slot_Op_Type = 1 +const BinExpr_Slot_Op_Num = 0 +const BinExpr_Slot_Op_BitSize = 2 +const BinExpr_Slot_Op_BitOffset = 2 +const BinExpr_Slot_Op_ByteSize = 1 +const BinExpr_Slot_Op_ByteOffset = 0 +const BinExpr_Slot_Op_ValueMask = 0x3 + +const BinExpr_Slot_Right_Type = 0 +const BinExpr_Slot_Right_Num = 1 +const BinExpr_Slot_Right_BitSize = -1 +const BinExpr_Slot_Right_BitOffset = -1 +const BinExpr_Slot_Right_ByteSize = -1 +const BinExpr_Slot_Right_ByteOffset = -1 +const BinExpr_Slot_Right_ValueMask = -1 + +const BinExpr_Slot_Right__Tag_Type = 1 +const BinExpr_Slot_Right__Tag_Num = 0 +const BinExpr_Slot_Right__Tag_BitSize = 2 +const BinExpr_Slot_Right__Tag_BitOffset = 4 +const BinExpr_Slot_Right__Tag_ByteSize = 1 +const BinExpr_Slot_Right__Tag_ByteOffset = 0 +const BinExpr_Slot_Right__Tag_ValueMask = 0x3 + +// BinExprValue is the logical type of a record. Immutable records are stored in +// nodes. +type BinExprValue struct { + Left Expr // 1 + Op BinOp // 2 + Right Expr // 3 +} + +// R constructs a reference to an immutable record. +func (x BinExprValue) R(a *Allocator) BinExpr { + ref := a.new() + + ref.nums[0] = (ref.nums[0] &^ (BinExpr_Slot_Left__Tag_ValueMask << BinExpr_Slot_Left__Tag_BitOffset)) | (numvalslot(x.Left.tag) << BinExpr_Slot_Left__Tag_BitOffset) + ref.refs[0] = x.Left.ref + ref.nums[0] = (ref.nums[0] &^ (BinExpr_Slot_Op_ValueMask << BinExpr_Slot_Op_BitOffset)) | (numvalslot(x.Op) << BinExpr_Slot_Op_BitOffset) + ref.nums[0] = (ref.nums[0] &^ (BinExpr_Slot_Right__Tag_ValueMask << BinExpr_Slot_Right__Tag_BitOffset)) | (numvalslot(x.Right.tag) << BinExpr_Slot_Right__Tag_BitOffset) + ref.refs[1] = x.Right.ref + return BinExpr{ref} +} + +// Left returns the Left field. +func (x BinExpr) Left() Expr { + return Expr{ExprTag((x.ref.nums[0] >> BinExpr_Slot_Left__Tag_BitOffset) & BinExpr_Slot_Left__Tag_ValueMask), x.ref.refs[0]} +} + +// Op returns the Op field. +func (x BinExpr) Op() BinOp { + return BinOp((x.ref.nums[0] >> BinExpr_Slot_Op_BitOffset) & BinExpr_Slot_Op_ValueMask) +} + +// Right returns the Right field. +func (x BinExpr) Right() Expr { + return Expr{ExprTag((x.ref.nums[0] >> BinExpr_Slot_Right__Tag_BitOffset) & BinExpr_Slot_Right__Tag_ValueMask), x.ref.refs[1]} +} + +// V unpacks a reference into a value. +func (x BinExpr) V() BinExprValue { + return BinExprValue{ + Left: Expr{ExprTag((x.ref.nums[0] >> BinExpr_Slot_Left__Tag_BitOffset) & BinExpr_Slot_Left__Tag_ValueMask), x.ref.refs[0]}, + Op: BinOp((x.ref.nums[0] >> BinExpr_Slot_Op_BitOffset) & BinExpr_Slot_Op_ValueMask), + Right: Expr{ExprTag((x.ref.nums[0] >> BinExpr_Slot_Right__Tag_BitOffset) & BinExpr_Slot_Right__Tag_ValueMask), x.ref.refs[1]}, + } +} + +// WithLeft constructs a new value where the value of Left has been replaced by +// the argument. +func (x BinExprValue) WithLeft(y Expr) BinExprValue { + x.Left = y + return x +} + +// WithOp constructs a new value where the value of Op has been replaced by +// the argument. +func (x BinExprValue) WithOp(y BinOp) BinExprValue { + x.Op = y + return x +} + +// WithRight constructs a new value where the value of Right has been replaced by +// the argument. +func (x BinExprValue) WithRight(y Expr) BinExprValue { + x.Right = y + return x +} + +// ---- TriExpr ---- // + +// TriExpr is the type of a reference to an immutable record. +type TriExpr struct{ ref *node } + +const TriExpr_Slot_One_Type = 0 +const TriExpr_Slot_One_Num = 0 +const TriExpr_Slot_One_BitSize = -1 +const TriExpr_Slot_One_BitOffset = -1 +const TriExpr_Slot_One_ByteSize = -1 +const TriExpr_Slot_One_ByteOffset = -1 +const TriExpr_Slot_One_ValueMask = -1 + +const TriExpr_Slot_One__Tag_Type = 1 +const TriExpr_Slot_One__Tag_Num = 0 +const TriExpr_Slot_One__Tag_BitSize = 2 +const TriExpr_Slot_One__Tag_BitOffset = 0 +const TriExpr_Slot_One__Tag_ByteSize = 1 +const TriExpr_Slot_One__Tag_ByteOffset = 0 +const TriExpr_Slot_One__Tag_ValueMask = 0x3 + +const TriExpr_Slot_Three_Type = 4 +const TriExpr_Slot_Three_Num = 0 +const TriExpr_Slot_Three_BitSize = -1 +const TriExpr_Slot_Three_BitOffset = -1 +const TriExpr_Slot_Three_ByteSize = -1 +const TriExpr_Slot_Three_ByteOffset = -1 +const TriExpr_Slot_Three_ValueMask = -1 + +const TriExpr_Slot_Three__Tag_Type = 1 +const TriExpr_Slot_Three__Tag_Num = 0 +const TriExpr_Slot_Three__Tag_BitSize = 2 +const TriExpr_Slot_Three__Tag_BitOffset = 4 +const TriExpr_Slot_Three__Tag_ByteSize = 1 +const TriExpr_Slot_Three__Tag_ByteOffset = 0 +const TriExpr_Slot_Three__Tag_ValueMask = 0x3 + +const TriExpr_Slot_Two_Type = 0 +const TriExpr_Slot_Two_Num = 1 +const TriExpr_Slot_Two_BitSize = -1 +const TriExpr_Slot_Two_BitOffset = -1 +const TriExpr_Slot_Two_ByteSize = -1 +const TriExpr_Slot_Two_ByteOffset = -1 +const TriExpr_Slot_Two_ValueMask = -1 + +const TriExpr_Slot_Two__Tag_Type = 1 +const TriExpr_Slot_Two__Tag_Num = 0 +const TriExpr_Slot_Two__Tag_BitSize = 2 +const TriExpr_Slot_Two__Tag_BitOffset = 2 +const TriExpr_Slot_Two__Tag_ByteSize = 1 +const TriExpr_Slot_Two__Tag_ByteOffset = 0 +const TriExpr_Slot_Two__Tag_ValueMask = 0x3 + +// TriExprValue is the logical type of a record. Immutable records are stored in +// nodes. +type TriExprValue struct { + One Expr // 1 + Two Expr // 2 + Three Expr // 4 +} + +type extraTriExpr struct { + refs [1]*node +} + +func (x extraTriExpr) extraRefs() []*node { return x.refs[:] } + +// R constructs a reference to an immutable record. +func (x TriExprValue) R(a *Allocator) TriExpr { + ref := a.new() + extra := &extraTriExpr{} + ref.extra = extra + + ref.nums[0] = (ref.nums[0] &^ (TriExpr_Slot_One__Tag_ValueMask << TriExpr_Slot_One__Tag_BitOffset)) | (numvalslot(x.One.tag) << TriExpr_Slot_One__Tag_BitOffset) + ref.refs[0] = x.One.ref + ref.nums[0] = (ref.nums[0] &^ (TriExpr_Slot_Two__Tag_ValueMask << TriExpr_Slot_Two__Tag_BitOffset)) | (numvalslot(x.Two.tag) << TriExpr_Slot_Two__Tag_BitOffset) + ref.refs[1] = x.Two.ref + ref.nums[0] = (ref.nums[0] &^ (TriExpr_Slot_Three__Tag_ValueMask << TriExpr_Slot_Three__Tag_BitOffset)) | (numvalslot(x.Three.tag) << TriExpr_Slot_Three__Tag_BitOffset) + extra.refs[0] = x.Three.ref + return TriExpr{ref} +} + +// One returns the One field. +func (x TriExpr) One() Expr { + return Expr{ExprTag((x.ref.nums[0] >> TriExpr_Slot_One__Tag_BitOffset) & TriExpr_Slot_One__Tag_ValueMask), x.ref.refs[0]} +} + +// Two returns the Two field. +func (x TriExpr) Two() Expr { + return Expr{ExprTag((x.ref.nums[0] >> TriExpr_Slot_Two__Tag_BitOffset) & TriExpr_Slot_Two__Tag_ValueMask), x.ref.refs[1]} +} + +// Three returns the Three field. +func (x TriExpr) Three() Expr { + return Expr{ExprTag((x.ref.nums[0] >> TriExpr_Slot_Three__Tag_BitOffset) & TriExpr_Slot_Three__Tag_ValueMask), x.ref.extra.(*extraTriExpr).refs[0]} +} + +// V unpacks a reference into a value. +func (x TriExpr) V() TriExprValue { + return TriExprValue{ + One: Expr{ExprTag((x.ref.nums[0] >> TriExpr_Slot_One__Tag_BitOffset) & TriExpr_Slot_One__Tag_ValueMask), x.ref.refs[0]}, + Two: Expr{ExprTag((x.ref.nums[0] >> TriExpr_Slot_Two__Tag_BitOffset) & TriExpr_Slot_Two__Tag_ValueMask), x.ref.refs[1]}, + Three: Expr{ExprTag((x.ref.nums[0] >> TriExpr_Slot_Three__Tag_BitOffset) & TriExpr_Slot_Three__Tag_ValueMask), x.ref.extra.(*extraTriExpr).refs[0]}, + } +} + +// WithOne constructs a new value where the value of One has been replaced by +// the argument. +func (x TriExprValue) WithOne(y Expr) TriExprValue { + x.One = y + return x +} + +// WithTwo constructs a new value where the value of Two has been replaced by +// the argument. +func (x TriExprValue) WithTwo(y Expr) TriExprValue { + x.Two = y + return x +} + +// WithThree constructs a new value where the value of Three has been replaced by +// the argument. +func (x TriExprValue) WithThree(y Expr) TriExprValue { + x.Three = y + return x +} + +// ---- All ---- // + +// All is the type of a reference to an immutable record. +type All struct{ ref *node } + +const All_Slot_A_Type = 4 +const All_Slot_A_Num = 1 +const All_Slot_A_BitSize = -1 +const All_Slot_A_BitOffset = -1 +const All_Slot_A_ByteSize = -1 +const All_Slot_A_ByteOffset = -1 +const All_Slot_A_ValueMask = -1 + +const All_Slot_A__Tag_Type = 1 +const All_Slot_A__Tag_Num = 0 +const All_Slot_A__Tag_BitSize = 2 +const All_Slot_A__Tag_BitOffset = 4 +const All_Slot_A__Tag_ByteSize = 1 +const All_Slot_A__Tag_ByteOffset = 0 +const All_Slot_A__Tag_ValueMask = 0x3 + +const All_Slot_BE_Type = 4 +const All_Slot_BE_Num = 0 +const All_Slot_BE_BitSize = -1 +const All_Slot_BE_BitOffset = -1 +const All_Slot_BE_ByteSize = -1 +const All_Slot_BE_ByteOffset = -1 +const All_Slot_BE_ValueMask = -1 + +const All_Slot_BO_Type = 1 +const All_Slot_BO_Num = 0 +const All_Slot_BO_BitSize = 2 +const All_Slot_BO_BitOffset = 2 +const All_Slot_BO_ByteSize = 1 +const All_Slot_BO_ByteOffset = 0 +const All_Slot_BO_ValueMask = 0x3 + +const All_Slot_CE_Type = 0 +const All_Slot_CE_Num = 1 +const All_Slot_CE_BitSize = -1 +const All_Slot_CE_BitOffset = -1 +const All_Slot_CE_ByteSize = -1 +const All_Slot_CE_ByteOffset = -1 +const All_Slot_CE_ValueMask = -1 + +const All_Slot_E_Type = 0 +const All_Slot_E_Num = 0 +const All_Slot_E_BitSize = -1 +const All_Slot_E_BitOffset = -1 +const All_Slot_E_ByteSize = -1 +const All_Slot_E_ByteOffset = -1 +const All_Slot_E_ValueMask = -1 + +const All_Slot_E__Tag_Type = 1 +const All_Slot_E__Tag_Num = 0 +const All_Slot_E__Tag_BitSize = 2 +const All_Slot_E__Tag_BitOffset = 0 +const All_Slot_E__Tag_ByteSize = 1 +const All_Slot_E__Tag_ByteOffset = 0 +const All_Slot_E__Tag_ValueMask = 0x3 + +// AllValue is the logical type of a record. Immutable records are stored in +// nodes. +type AllValue struct { + E Expr // 1 + CE ConstExpr // 2 + BE BinExpr // 3 + BO BinOp // 4 + A AllOrExpr // 5 +} + +type extraAll struct { + refs [2]*node +} + +func (x extraAll) extraRefs() []*node { return x.refs[:] } + +// R constructs a reference to an immutable record. +func (x AllValue) R(a *Allocator) All { + ref := a.new() + extra := &extraAll{} + ref.extra = extra + + ref.nums[0] = (ref.nums[0] &^ (All_Slot_E__Tag_ValueMask << All_Slot_E__Tag_BitOffset)) | (numvalslot(x.E.tag) << All_Slot_E__Tag_BitOffset) + ref.refs[0] = x.E.ref + ref.refs[1] = x.CE.ref + extra.refs[0] = x.BE.ref + ref.nums[0] = (ref.nums[0] &^ (All_Slot_BO_ValueMask << All_Slot_BO_BitOffset)) | (numvalslot(x.BO) << All_Slot_BO_BitOffset) + ref.nums[0] = (ref.nums[0] &^ (All_Slot_A__Tag_ValueMask << All_Slot_A__Tag_BitOffset)) | (numvalslot(x.A.tag) << All_Slot_A__Tag_BitOffset) + extra.refs[1] = x.A.ref + return All{ref} +} + +// E returns the E field. +func (x All) E() Expr { + return Expr{ExprTag((x.ref.nums[0] >> All_Slot_E__Tag_BitOffset) & All_Slot_E__Tag_ValueMask), x.ref.refs[0]} +} + +// CE returns the CE field. +func (x All) CE() ConstExpr { return ConstExpr{x.ref.refs[1]} } + +// BE returns the BE field. +func (x All) BE() BinExpr { return BinExpr{x.ref.extra.(*extraAll).refs[0]} } + +// BO returns the BO field. +func (x All) BO() BinOp { + return BinOp((x.ref.nums[0] >> All_Slot_BO_BitOffset) & All_Slot_BO_ValueMask) +} + +// A returns the A field. +func (x All) A() AllOrExpr { + return AllOrExpr{AllOrExprTag((x.ref.nums[0] >> All_Slot_A__Tag_BitOffset) & All_Slot_A__Tag_ValueMask), x.ref.extra.(*extraAll).refs[1]} +} + +// V unpacks a reference into a value. +func (x All) V() AllValue { + return AllValue{ + E: Expr{ExprTag((x.ref.nums[0] >> All_Slot_E__Tag_BitOffset) & All_Slot_E__Tag_ValueMask), x.ref.refs[0]}, + CE: ConstExpr{x.ref.refs[1]}, + BE: BinExpr{x.ref.extra.(*extraAll).refs[0]}, + BO: BinOp((x.ref.nums[0] >> All_Slot_BO_BitOffset) & All_Slot_BO_ValueMask), + A: AllOrExpr{AllOrExprTag((x.ref.nums[0] >> All_Slot_A__Tag_BitOffset) & All_Slot_A__Tag_ValueMask), x.ref.extra.(*extraAll).refs[1]}, + } +} + +// WithE constructs a new value where the value of E has been replaced by +// the argument. +func (x AllValue) WithE(y Expr) AllValue { + x.E = y + return x +} + +// WithCE constructs a new value where the value of CE has been replaced by +// the argument. +func (x AllValue) WithCE(y ConstExpr) AllValue { + x.CE = y + return x +} + +// WithBE constructs a new value where the value of BE has been replaced by +// the argument. +func (x AllValue) WithBE(y BinExpr) AllValue { + x.BE = y + return x +} + +// WithBO constructs a new value where the value of BO has been replaced by +// the argument. +func (x AllValue) WithBO(y BinOp) AllValue { + x.BO = y + return x +} + +// WithA constructs a new value where the value of A has been replaced by +// the argument. +func (x AllValue) WithA(y AllOrExpr) AllValue { + x.A = y + return x +} + +// ---- Expr ---- // + +// Expr is the type of a tagged union of records. +type Expr struct { + tag ExprTag + ref *node +} + +// ExprTag is the tag type. +type ExprTag enum + +// ExprTag constants. +const ( + ExprConstExpr ExprTag = 1 + ExprBinExpr ExprTag = 2 +) + +func (x ExprTag) String() string { + switch x { + case ExprConstExpr: + return "ConstExpr" + case ExprBinExpr: + return "BinExpr" + default: + return fmt.Sprintf("", x) + } +} + +// Tag returns the tag. +func (x Expr) Tag() ExprTag { return x.tag } + +// Expr performs an upcast. +func (x ConstExpr) Expr() Expr { return Expr{ExprConstExpr, x.ref} } + +// ConstExpr performs a downcast. If the downcast fails, return false. +func (x Expr) ConstExpr() (ConstExpr, bool) { + if x.tag != ExprConstExpr { + return ConstExpr{}, false + } + return ConstExpr{x.ref}, true +} + +// MustBeConstExpr performs a downcast. If the downcast fails, panic. +func (x Expr) MustBeConstExpr() ConstExpr { + if x.tag != ExprConstExpr { + panic(fmt.Sprintf("type assertion failed: expected ConstExpr but got %s", x.tag)) + } + return ConstExpr{x.ref} +} + +// Expr performs an upcast. +func (x BinExpr) Expr() Expr { return Expr{ExprBinExpr, x.ref} } + +// BinExpr performs a downcast. If the downcast fails, return false. +func (x Expr) BinExpr() (BinExpr, bool) { + if x.tag != ExprBinExpr { + return BinExpr{}, false + } + return BinExpr{x.ref}, true +} + +// MustBeBinExpr performs a downcast. If the downcast fails, panic. +func (x Expr) MustBeBinExpr() BinExpr { + if x.tag != ExprBinExpr { + panic(fmt.Sprintf("type assertion failed: expected BinExpr but got %s", x.tag)) + } + return BinExpr{x.ref} +} + +// ---- AllOrExpr ---- // + +// AllOrExpr is the type of a tagged union of records. +type AllOrExpr struct { + tag AllOrExprTag + ref *node +} + +// AllOrExprTag is the tag type. +type AllOrExprTag enum + +// AllOrExprTag constants. +const ( + AllOrExprAll AllOrExprTag = 1 + AllOrExprBinExpr AllOrExprTag = 2 +) + +func (x AllOrExprTag) String() string { + switch x { + case AllOrExprAll: + return "All" + case AllOrExprBinExpr: + return "BinExpr" + default: + return fmt.Sprintf("", x) + } +} + +// Tag returns the tag. +func (x AllOrExpr) Tag() AllOrExprTag { return x.tag } + +// AllOrExpr performs an upcast. +func (x All) AllOrExpr() AllOrExpr { return AllOrExpr{AllOrExprAll, x.ref} } + +// All performs a downcast. If the downcast fails, return false. +func (x AllOrExpr) All() (All, bool) { + if x.tag != AllOrExprAll { + return All{}, false + } + return All{x.ref}, true +} + +// MustBeAll performs a downcast. If the downcast fails, panic. +func (x AllOrExpr) MustBeAll() All { + if x.tag != AllOrExprAll { + panic(fmt.Sprintf("type assertion failed: expected All but got %s", x.tag)) + } + return All{x.ref} +} + +// AllOrExpr performs an upcast. +func (x BinExpr) AllOrExpr() AllOrExpr { return AllOrExpr{AllOrExprBinExpr, x.ref} } + +// BinExpr performs a downcast. If the downcast fails, return false. +func (x AllOrExpr) BinExpr() (BinExpr, bool) { + if x.tag != AllOrExprBinExpr { + return BinExpr{}, false + } + return BinExpr{x.ref}, true +} + +// MustBeBinExpr performs a downcast. If the downcast fails, panic. +func (x AllOrExpr) MustBeBinExpr() BinExpr { + if x.tag != AllOrExprBinExpr { + panic(fmt.Sprintf("type assertion failed: expected BinExpr but got %s", x.tag)) + } + return BinExpr{x.ref} +} + +// Codegen parameters: +// {NumNumericSlots:2 NumericSlotSize:64 NumRefSlots:2 NumStrSlots:1 Pack:true} +// diff --git a/pkg/sql/ir/example/base/sexpr.ir.go b/pkg/sql/ir/tests/defcfg/example/base/sexpr.ir.go similarity index 57% rename from pkg/sql/ir/example/base/sexpr.ir.go rename to pkg/sql/ir/tests/defcfg/example/base/sexpr.ir.go index 18fbb2dd8e5d..bdc5d366be1d 100644 --- a/pkg/sql/ir/example/base/sexpr.ir.go +++ b/pkg/sql/ir/tests/defcfg/example/base/sexpr.ir.go @@ -1,4 +1,4 @@ -// Code generated by irgen/irgen base/sexpr.tmpl.go example.def. DO NOT EDIT. +// Code generated by irgen/irgen base/sexpr.tmpl.go tests/example.def. DO NOT EDIT. // GENERATED FILE DO NOT EDIT // Copyright 2017 The Cockroach Authors. // @@ -18,16 +18,25 @@ package base import ( "bytes" - "strconv" + "fmt" ) type SexprFormatter interface { FormatSExpr(buf *bytes.Buffer) } -func FormatSExprInt64(buf *bytes.Buffer, x int64) { - buf.WriteString(strconv.FormatInt(x, 10)) -} +func FormatSExprBool(buf *bytes.Buffer, x bool) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt64(buf *bytes.Buffer, x int64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt32(buf *bytes.Buffer, x int32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt16(buf *bytes.Buffer, x int16) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt8(buf *bytes.Buffer, x int8) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint64(buf *bytes.Buffer, x uint64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint32(buf *bytes.Buffer, x uint32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint16(buf *bytes.Buffer, x uint16) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint8(buf *bytes.Buffer, x uint8) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprFloat32(buf *bytes.Buffer, x float32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprFloat64(buf *bytes.Buffer, x float64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprString(buf *bytes.Buffer, x string) { fmt.Fprintf(buf, "%q", x) } func (x BinOp) FormatSExpr(buf *bytes.Buffer) { buf.WriteString(x.String()) @@ -57,6 +66,21 @@ func (x BinExpr) FormatSExpr(buf *bytes.Buffer) { buf.WriteByte(')') } +func (x TriExpr) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(TriExpr") + + buf.WriteString(" One: ") + x.One().FormatSExpr(buf) + + buf.WriteString(" Two: ") + x.Two().FormatSExpr(buf) + + buf.WriteString(" Three: ") + x.Three().FormatSExpr(buf) + + buf.WriteByte(')') +} + func (x All) FormatSExpr(buf *bytes.Buffer) { buf.WriteString("(All") @@ -95,3 +119,7 @@ func (x AllOrExpr) FormatSExpr(buf *bytes.Buffer) { x.MustBeBinExpr().FormatSExpr(buf) } } + +// Codegen parameters: +// {NumNumericSlots:2 NumericSlotSize:64 NumRefSlots:2 NumStrSlots:1 Pack:true} +// diff --git a/pkg/sql/ir/tests/defcfg/prims/base/base.ir.go b/pkg/sql/ir/tests/defcfg/prims/base/base.ir.go new file mode 100644 index 000000000000..e21f289585de --- /dev/null +++ b/pkg/sql/ir/tests/defcfg/prims/base/base.ir.go @@ -0,0 +1,824 @@ +// Code generated by irgen/irgen base/base.tmpl.go tests/prims.def. DO NOT EDIT. +// GENERATED FILE DO NOT EDIT +// Copyright 2017 The Cockroach Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. + +package base + +// node is a generic ADT node type, with slots for references to other nodes and +// enumeration values. Values that don't fit and values of other types go in the +// extra field. +type node struct { + refs [2]*node + nums [2]numvalslot + strs [1]string + extra +} + +// enum is the type to define the tag part for working copies of IR +// node with sum and enum types. +type enum uint32 + +// numvalslot is the type used to store integer values in persistent IR nodes. +// must be larger than or as large as enum. +type numvalslot uint64 + +type extra interface { + extraRefs() []*node +} + +// Allocator allocates nodes in batches. Construct Allocators with NewAllocator +// and pass them by value. +type Allocator struct { + nodes []node +} + +// MakeAllocator constructs a new Allocator. +func MakeAllocator() Allocator { + nodes := make([]node, 16) + return Allocator{nodes} +} + +// NewAllocator allocates a new Allocator. +func NewAllocator() *Allocator { + a := MakeAllocator() + return &a +} + +// new allocates a new node. Users of this package should use the appropriate +// R() method, which is type safe. +func (a *Allocator) new() *node { + nodes := a.nodes + if len(nodes) == 0 { + nodes = make([]node, 256) + } + x := &nodes[0] + a.nodes = nodes[1:] + return x +} + +// ---- All ---- // + +// All is the type of a reference to an immutable record. +type All struct{ ref *node } + +const All_Slot_B_Type = 3 +const All_Slot_B_Num = -1 +const All_Slot_B_BitSize = -1 +const All_Slot_B_BitOffset = -1 +const All_Slot_B_ByteSize = -1 +const All_Slot_B_ByteOffset = -1 +const All_Slot_B_ValueMask = -1 + +const All_Slot_F32_Type = 3 +const All_Slot_F32_Num = -1 +const All_Slot_F32_BitSize = -1 +const All_Slot_F32_BitOffset = -1 +const All_Slot_F32_ByteSize = -1 +const All_Slot_F32_ByteOffset = -1 +const All_Slot_F32_ValueMask = -1 + +const All_Slot_F64_Type = 3 +const All_Slot_F64_Num = -1 +const All_Slot_F64_BitSize = -1 +const All_Slot_F64_BitOffset = -1 +const All_Slot_F64_ByteSize = -1 +const All_Slot_F64_ByteOffset = -1 +const All_Slot_F64_ValueMask = -1 + +const All_Slot_I16_Type = 3 +const All_Slot_I16_Num = -1 +const All_Slot_I16_BitSize = -1 +const All_Slot_I16_BitOffset = -1 +const All_Slot_I16_ByteSize = -1 +const All_Slot_I16_ByteOffset = -1 +const All_Slot_I16_ValueMask = -1 + +const All_Slot_I32_Type = 3 +const All_Slot_I32_Num = -1 +const All_Slot_I32_BitSize = -1 +const All_Slot_I32_BitOffset = -1 +const All_Slot_I32_ByteSize = -1 +const All_Slot_I32_ByteOffset = -1 +const All_Slot_I32_ValueMask = -1 + +const All_Slot_I64_Type = 1 +const All_Slot_I64_Num = 0 +const All_Slot_I64_BitSize = 64 +const All_Slot_I64_BitOffset = 0 +const All_Slot_I64_ByteSize = 8 +const All_Slot_I64_ByteOffset = 0 +const All_Slot_I64_ValueMask = 0xffffffffffffffff + +const All_Slot_I8_Type = 3 +const All_Slot_I8_Num = -1 +const All_Slot_I8_BitSize = -1 +const All_Slot_I8_BitOffset = -1 +const All_Slot_I8_ByteSize = -1 +const All_Slot_I8_ByteOffset = -1 +const All_Slot_I8_ValueMask = -1 + +const All_Slot_S_Type = 2 +const All_Slot_S_Num = 0 +const All_Slot_S_BitSize = -1 +const All_Slot_S_BitOffset = -1 +const All_Slot_S_ByteSize = -1 +const All_Slot_S_ByteOffset = -1 +const All_Slot_S_ValueMask = -1 + +const All_Slot_U16_Type = 3 +const All_Slot_U16_Num = -1 +const All_Slot_U16_BitSize = -1 +const All_Slot_U16_BitOffset = -1 +const All_Slot_U16_ByteSize = -1 +const All_Slot_U16_ByteOffset = -1 +const All_Slot_U16_ValueMask = -1 + +const All_Slot_U32_Type = 3 +const All_Slot_U32_Num = -1 +const All_Slot_U32_BitSize = -1 +const All_Slot_U32_BitOffset = -1 +const All_Slot_U32_ByteSize = -1 +const All_Slot_U32_ByteOffset = -1 +const All_Slot_U32_ValueMask = -1 + +const All_Slot_U64_Type = 1 +const All_Slot_U64_Num = 1 +const All_Slot_U64_BitSize = 64 +const All_Slot_U64_BitOffset = 0 +const All_Slot_U64_ByteSize = 8 +const All_Slot_U64_ByteOffset = 0 +const All_Slot_U64_ValueMask = 0xffffffffffffffff + +const All_Slot_U8_Type = 3 +const All_Slot_U8_Num = -1 +const All_Slot_U8_BitSize = -1 +const All_Slot_U8_BitOffset = -1 +const All_Slot_U8_ByteSize = -1 +const All_Slot_U8_ByteOffset = -1 +const All_Slot_U8_ValueMask = -1 + +// AllValue is the logical type of a record. Immutable records are stored in +// nodes. +type AllValue struct { + B bool // 1 + I8 int8 // 2 + U8 uint8 // 3 + I16 int16 // 4 + U16 uint16 // 5 + I32 int32 // 6 + U32 uint32 // 7 + I64 int64 // 8 + U64 uint64 // 9 + S string // 10 + F32 float32 // 11 + F64 float64 // 12 +} + +type extraAll struct { + B bool + I8 int8 + U8 uint8 + I16 int16 + U16 uint16 + I32 int32 + U32 uint32 + F32 float32 + F64 float64 +} + +func (x extraAll) extraRefs() []*node { return nil } + +// R constructs a reference to an immutable record. +func (x AllValue) R(a *Allocator) All { + ref := a.new() + extra := &extraAll{} + ref.extra = extra + + extra.B = x.B + extra.I8 = x.I8 + extra.U8 = x.U8 + extra.I16 = x.I16 + extra.U16 = x.U16 + extra.I32 = x.I32 + extra.U32 = x.U32 + ref.nums[0] = numvalslot(x.I64) + ref.nums[1] = numvalslot(x.U64) + ref.strs[0] = x.S + extra.F32 = x.F32 + extra.F64 = x.F64 + return All{ref} +} + +// B returns the B field. +func (x All) B() bool { return x.ref.extra.(*extraAll).B } + +// I8 returns the I8 field. +func (x All) I8() int8 { return x.ref.extra.(*extraAll).I8 } + +// U8 returns the U8 field. +func (x All) U8() uint8 { return x.ref.extra.(*extraAll).U8 } + +// I16 returns the I16 field. +func (x All) I16() int16 { return x.ref.extra.(*extraAll).I16 } + +// U16 returns the U16 field. +func (x All) U16() uint16 { return x.ref.extra.(*extraAll).U16 } + +// I32 returns the I32 field. +func (x All) I32() int32 { return x.ref.extra.(*extraAll).I32 } + +// U32 returns the U32 field. +func (x All) U32() uint32 { return x.ref.extra.(*extraAll).U32 } + +// I64 returns the I64 field. +func (x All) I64() int64 { return int64(x.ref.nums[0]) } + +// U64 returns the U64 field. +func (x All) U64() uint64 { return uint64(x.ref.nums[1]) } + +// S returns the S field. +func (x All) S() string { return x.ref.strs[0] } + +// F32 returns the F32 field. +func (x All) F32() float32 { return x.ref.extra.(*extraAll).F32 } + +// F64 returns the F64 field. +func (x All) F64() float64 { return x.ref.extra.(*extraAll).F64 } + +// V unpacks a reference into a value. +func (x All) V() AllValue { + return AllValue{ + B: x.ref.extra.(*extraAll).B, + I8: x.ref.extra.(*extraAll).I8, + U8: x.ref.extra.(*extraAll).U8, + I16: x.ref.extra.(*extraAll).I16, + U16: x.ref.extra.(*extraAll).U16, + I32: x.ref.extra.(*extraAll).I32, + U32: x.ref.extra.(*extraAll).U32, + I64: int64(x.ref.nums[0]), + U64: uint64(x.ref.nums[1]), + S: x.ref.strs[0], + F32: x.ref.extra.(*extraAll).F32, + F64: x.ref.extra.(*extraAll).F64, + } +} + +// WithB constructs a new value where the value of B has been replaced by +// the argument. +func (x AllValue) WithB(y bool) AllValue { + x.B = y + return x +} + +// WithI8 constructs a new value where the value of I8 has been replaced by +// the argument. +func (x AllValue) WithI8(y int8) AllValue { + x.I8 = y + return x +} + +// WithU8 constructs a new value where the value of U8 has been replaced by +// the argument. +func (x AllValue) WithU8(y uint8) AllValue { + x.U8 = y + return x +} + +// WithI16 constructs a new value where the value of I16 has been replaced by +// the argument. +func (x AllValue) WithI16(y int16) AllValue { + x.I16 = y + return x +} + +// WithU16 constructs a new value where the value of U16 has been replaced by +// the argument. +func (x AllValue) WithU16(y uint16) AllValue { + x.U16 = y + return x +} + +// WithI32 constructs a new value where the value of I32 has been replaced by +// the argument. +func (x AllValue) WithI32(y int32) AllValue { + x.I32 = y + return x +} + +// WithU32 constructs a new value where the value of U32 has been replaced by +// the argument. +func (x AllValue) WithU32(y uint32) AllValue { + x.U32 = y + return x +} + +// WithI64 constructs a new value where the value of I64 has been replaced by +// the argument. +func (x AllValue) WithI64(y int64) AllValue { + x.I64 = y + return x +} + +// WithU64 constructs a new value where the value of U64 has been replaced by +// the argument. +func (x AllValue) WithU64(y uint64) AllValue { + x.U64 = y + return x +} + +// WithS constructs a new value where the value of S has been replaced by +// the argument. +func (x AllValue) WithS(y string) AllValue { + x.S = y + return x +} + +// WithF32 constructs a new value where the value of F32 has been replaced by +// the argument. +func (x AllValue) WithF32(y float32) AllValue { + x.F32 = y + return x +} + +// WithF64 constructs a new value where the value of F64 has been replaced by +// the argument. +func (x AllValue) WithF64(y float64) AllValue { + x.F64 = y + return x +} + +// ---- SmallBefore ---- // + +// SmallBefore is the type of a reference to an immutable record. +type SmallBefore struct{ ref *node } + +const SmallBefore_Slot_A_Type = 3 +const SmallBefore_Slot_A_Num = -1 +const SmallBefore_Slot_A_BitSize = -1 +const SmallBefore_Slot_A_BitOffset = -1 +const SmallBefore_Slot_A_ByteSize = -1 +const SmallBefore_Slot_A_ByteOffset = -1 +const SmallBefore_Slot_A_ValueMask = -1 + +const SmallBefore_Slot_B_Type = 3 +const SmallBefore_Slot_B_Num = -1 +const SmallBefore_Slot_B_BitSize = -1 +const SmallBefore_Slot_B_BitOffset = -1 +const SmallBefore_Slot_B_ByteSize = -1 +const SmallBefore_Slot_B_ByteOffset = -1 +const SmallBefore_Slot_B_ValueMask = -1 + +const SmallBefore_Slot_C_Type = 3 +const SmallBefore_Slot_C_Num = -1 +const SmallBefore_Slot_C_BitSize = -1 +const SmallBefore_Slot_C_BitOffset = -1 +const SmallBefore_Slot_C_ByteSize = -1 +const SmallBefore_Slot_C_ByteOffset = -1 +const SmallBefore_Slot_C_ValueMask = -1 + +const SmallBefore_Slot_D_Type = 3 +const SmallBefore_Slot_D_Num = -1 +const SmallBefore_Slot_D_BitSize = -1 +const SmallBefore_Slot_D_BitOffset = -1 +const SmallBefore_Slot_D_ByteSize = -1 +const SmallBefore_Slot_D_ByteOffset = -1 +const SmallBefore_Slot_D_ValueMask = -1 + +const SmallBefore_Slot_E_Type = 3 +const SmallBefore_Slot_E_Num = -1 +const SmallBefore_Slot_E_BitSize = -1 +const SmallBefore_Slot_E_BitOffset = -1 +const SmallBefore_Slot_E_ByteSize = -1 +const SmallBefore_Slot_E_ByteOffset = -1 +const SmallBefore_Slot_E_ValueMask = -1 + +const SmallBefore_Slot_F_Type = 1 +const SmallBefore_Slot_F_Num = 1 +const SmallBefore_Slot_F_BitSize = 16 +const SmallBefore_Slot_F_BitOffset = 32 +const SmallBefore_Slot_F_ByteSize = 2 +const SmallBefore_Slot_F_ByteOffset = 4 +const SmallBefore_Slot_F_ValueMask = 0xffff + +const SmallBefore_Slot_G_Type = 1 +const SmallBefore_Slot_G_Num = 1 +const SmallBefore_Slot_G_BitSize = 16 +const SmallBefore_Slot_G_BitOffset = 48 +const SmallBefore_Slot_G_ByteSize = 2 +const SmallBefore_Slot_G_ByteOffset = 6 +const SmallBefore_Slot_G_ValueMask = 0xffff + +const SmallBefore_Slot_H_Type = 1 +const SmallBefore_Slot_H_Num = 1 +const SmallBefore_Slot_H_BitSize = 32 +const SmallBefore_Slot_H_BitOffset = 0 +const SmallBefore_Slot_H_ByteSize = 4 +const SmallBefore_Slot_H_ByteOffset = 0 +const SmallBefore_Slot_H_ValueMask = 0xffffffff + +const SmallBefore_Slot_I_Type = 1 +const SmallBefore_Slot_I_Num = 0 +const SmallBefore_Slot_I_BitSize = 64 +const SmallBefore_Slot_I_BitOffset = 0 +const SmallBefore_Slot_I_ByteSize = 8 +const SmallBefore_Slot_I_ByteOffset = 0 +const SmallBefore_Slot_I_ValueMask = 0xffffffffffffffff + +// SmallBeforeValue is the logical type of a record. Immutable records are stored in +// nodes. +type SmallBeforeValue struct { + A bool // 1 + B bool // 2 + C uint8 // 3 + D uint8 // 4 + E uint8 // 5 + F uint16 // 6 + G uint16 // 7 + H uint32 // 8 + I uint64 // 9 +} + +type extraSmallBefore struct { + A bool + B bool + C uint8 + D uint8 + E uint8 +} + +func (x extraSmallBefore) extraRefs() []*node { return nil } + +// R constructs a reference to an immutable record. +func (x SmallBeforeValue) R(a *Allocator) SmallBefore { + ref := a.new() + extra := &extraSmallBefore{} + ref.extra = extra + + extra.A = x.A + extra.B = x.B + extra.C = x.C + extra.D = x.D + extra.E = x.E + ref.nums[1] = (ref.nums[1] &^ (SmallBefore_Slot_F_ValueMask << SmallBefore_Slot_F_BitOffset)) | (numvalslot(x.F) << SmallBefore_Slot_F_BitOffset) + ref.nums[1] = (ref.nums[1] &^ (SmallBefore_Slot_G_ValueMask << SmallBefore_Slot_G_BitOffset)) | (numvalslot(x.G) << SmallBefore_Slot_G_BitOffset) + ref.nums[1] = (ref.nums[1] &^ (SmallBefore_Slot_H_ValueMask << SmallBefore_Slot_H_BitOffset)) | (numvalslot(x.H) << SmallBefore_Slot_H_BitOffset) + ref.nums[0] = numvalslot(x.I) + return SmallBefore{ref} +} + +// A returns the A field. +func (x SmallBefore) A() bool { return x.ref.extra.(*extraSmallBefore).A } + +// B returns the B field. +func (x SmallBefore) B() bool { return x.ref.extra.(*extraSmallBefore).B } + +// C returns the C field. +func (x SmallBefore) C() uint8 { return x.ref.extra.(*extraSmallBefore).C } + +// D returns the D field. +func (x SmallBefore) D() uint8 { return x.ref.extra.(*extraSmallBefore).D } + +// E returns the E field. +func (x SmallBefore) E() uint8 { return x.ref.extra.(*extraSmallBefore).E } + +// F returns the F field. +func (x SmallBefore) F() uint16 { + return uint16((x.ref.nums[1] >> SmallBefore_Slot_F_BitOffset) & SmallBefore_Slot_F_ValueMask) +} + +// G returns the G field. +func (x SmallBefore) G() uint16 { + return uint16((x.ref.nums[1] >> SmallBefore_Slot_G_BitOffset) & SmallBefore_Slot_G_ValueMask) +} + +// H returns the H field. +func (x SmallBefore) H() uint32 { + return uint32((x.ref.nums[1] >> SmallBefore_Slot_H_BitOffset) & SmallBefore_Slot_H_ValueMask) +} + +// I returns the I field. +func (x SmallBefore) I() uint64 { return uint64(x.ref.nums[0]) } + +// V unpacks a reference into a value. +func (x SmallBefore) V() SmallBeforeValue { + return SmallBeforeValue{ + A: x.ref.extra.(*extraSmallBefore).A, + B: x.ref.extra.(*extraSmallBefore).B, + C: x.ref.extra.(*extraSmallBefore).C, + D: x.ref.extra.(*extraSmallBefore).D, + E: x.ref.extra.(*extraSmallBefore).E, + F: uint16((x.ref.nums[1] >> SmallBefore_Slot_F_BitOffset) & SmallBefore_Slot_F_ValueMask), + G: uint16((x.ref.nums[1] >> SmallBefore_Slot_G_BitOffset) & SmallBefore_Slot_G_ValueMask), + H: uint32((x.ref.nums[1] >> SmallBefore_Slot_H_BitOffset) & SmallBefore_Slot_H_ValueMask), + I: uint64(x.ref.nums[0]), + } +} + +// WithA constructs a new value where the value of A has been replaced by +// the argument. +func (x SmallBeforeValue) WithA(y bool) SmallBeforeValue { + x.A = y + return x +} + +// WithB constructs a new value where the value of B has been replaced by +// the argument. +func (x SmallBeforeValue) WithB(y bool) SmallBeforeValue { + x.B = y + return x +} + +// WithC constructs a new value where the value of C has been replaced by +// the argument. +func (x SmallBeforeValue) WithC(y uint8) SmallBeforeValue { + x.C = y + return x +} + +// WithD constructs a new value where the value of D has been replaced by +// the argument. +func (x SmallBeforeValue) WithD(y uint8) SmallBeforeValue { + x.D = y + return x +} + +// WithE constructs a new value where the value of E has been replaced by +// the argument. +func (x SmallBeforeValue) WithE(y uint8) SmallBeforeValue { + x.E = y + return x +} + +// WithF constructs a new value where the value of F has been replaced by +// the argument. +func (x SmallBeforeValue) WithF(y uint16) SmallBeforeValue { + x.F = y + return x +} + +// WithG constructs a new value where the value of G has been replaced by +// the argument. +func (x SmallBeforeValue) WithG(y uint16) SmallBeforeValue { + x.G = y + return x +} + +// WithH constructs a new value where the value of H has been replaced by +// the argument. +func (x SmallBeforeValue) WithH(y uint32) SmallBeforeValue { + x.H = y + return x +} + +// WithI constructs a new value where the value of I has been replaced by +// the argument. +func (x SmallBeforeValue) WithI(y uint64) SmallBeforeValue { + x.I = y + return x +} + +// ---- BigBefore ---- // + +// BigBefore is the type of a reference to an immutable record. +type BigBefore struct{ ref *node } + +const BigBefore_Slot_A_Type = 1 +const BigBefore_Slot_A_Num = 0 +const BigBefore_Slot_A_BitSize = 64 +const BigBefore_Slot_A_BitOffset = 0 +const BigBefore_Slot_A_ByteSize = 8 +const BigBefore_Slot_A_ByteOffset = 0 +const BigBefore_Slot_A_ValueMask = 0xffffffffffffffff + +const BigBefore_Slot_B_Type = 1 +const BigBefore_Slot_B_Num = 1 +const BigBefore_Slot_B_BitSize = 32 +const BigBefore_Slot_B_BitOffset = 0 +const BigBefore_Slot_B_ByteSize = 4 +const BigBefore_Slot_B_ByteOffset = 0 +const BigBefore_Slot_B_ValueMask = 0xffffffff + +const BigBefore_Slot_C_Type = 1 +const BigBefore_Slot_C_Num = 1 +const BigBefore_Slot_C_BitSize = 16 +const BigBefore_Slot_C_BitOffset = 32 +const BigBefore_Slot_C_ByteSize = 2 +const BigBefore_Slot_C_ByteOffset = 4 +const BigBefore_Slot_C_ValueMask = 0xffff + +const BigBefore_Slot_D_Type = 1 +const BigBefore_Slot_D_Num = 1 +const BigBefore_Slot_D_BitSize = 16 +const BigBefore_Slot_D_BitOffset = 48 +const BigBefore_Slot_D_ByteSize = 2 +const BigBefore_Slot_D_ByteOffset = 6 +const BigBefore_Slot_D_ValueMask = 0xffff + +const BigBefore_Slot_E_Type = 3 +const BigBefore_Slot_E_Num = -1 +const BigBefore_Slot_E_BitSize = -1 +const BigBefore_Slot_E_BitOffset = -1 +const BigBefore_Slot_E_ByteSize = -1 +const BigBefore_Slot_E_ByteOffset = -1 +const BigBefore_Slot_E_ValueMask = -1 + +const BigBefore_Slot_F_Type = 3 +const BigBefore_Slot_F_Num = -1 +const BigBefore_Slot_F_BitSize = -1 +const BigBefore_Slot_F_BitOffset = -1 +const BigBefore_Slot_F_ByteSize = -1 +const BigBefore_Slot_F_ByteOffset = -1 +const BigBefore_Slot_F_ValueMask = -1 + +const BigBefore_Slot_G_Type = 3 +const BigBefore_Slot_G_Num = -1 +const BigBefore_Slot_G_BitSize = -1 +const BigBefore_Slot_G_BitOffset = -1 +const BigBefore_Slot_G_ByteSize = -1 +const BigBefore_Slot_G_ByteOffset = -1 +const BigBefore_Slot_G_ValueMask = -1 + +const BigBefore_Slot_H_Type = 3 +const BigBefore_Slot_H_Num = -1 +const BigBefore_Slot_H_BitSize = -1 +const BigBefore_Slot_H_BitOffset = -1 +const BigBefore_Slot_H_ByteSize = -1 +const BigBefore_Slot_H_ByteOffset = -1 +const BigBefore_Slot_H_ValueMask = -1 + +const BigBefore_Slot_I_Type = 3 +const BigBefore_Slot_I_Num = -1 +const BigBefore_Slot_I_BitSize = -1 +const BigBefore_Slot_I_BitOffset = -1 +const BigBefore_Slot_I_ByteSize = -1 +const BigBefore_Slot_I_ByteOffset = -1 +const BigBefore_Slot_I_ValueMask = -1 + +// BigBeforeValue is the logical type of a record. Immutable records are stored in +// nodes. +type BigBeforeValue struct { + A uint64 // 1 + B uint32 // 2 + C uint16 // 3 + D uint16 // 4 + E uint8 // 5 + F uint8 // 6 + G uint8 // 7 + H bool // 8 + I bool // 9 +} + +type extraBigBefore struct { + E uint8 + F uint8 + G uint8 + H bool + I bool +} + +func (x extraBigBefore) extraRefs() []*node { return nil } + +// R constructs a reference to an immutable record. +func (x BigBeforeValue) R(a *Allocator) BigBefore { + ref := a.new() + extra := &extraBigBefore{} + ref.extra = extra + + ref.nums[0] = numvalslot(x.A) + ref.nums[1] = (ref.nums[1] &^ (BigBefore_Slot_B_ValueMask << BigBefore_Slot_B_BitOffset)) | (numvalslot(x.B) << BigBefore_Slot_B_BitOffset) + ref.nums[1] = (ref.nums[1] &^ (BigBefore_Slot_C_ValueMask << BigBefore_Slot_C_BitOffset)) | (numvalslot(x.C) << BigBefore_Slot_C_BitOffset) + ref.nums[1] = (ref.nums[1] &^ (BigBefore_Slot_D_ValueMask << BigBefore_Slot_D_BitOffset)) | (numvalslot(x.D) << BigBefore_Slot_D_BitOffset) + extra.E = x.E + extra.F = x.F + extra.G = x.G + extra.H = x.H + extra.I = x.I + return BigBefore{ref} +} + +// A returns the A field. +func (x BigBefore) A() uint64 { return uint64(x.ref.nums[0]) } + +// B returns the B field. +func (x BigBefore) B() uint32 { + return uint32((x.ref.nums[1] >> BigBefore_Slot_B_BitOffset) & BigBefore_Slot_B_ValueMask) +} + +// C returns the C field. +func (x BigBefore) C() uint16 { + return uint16((x.ref.nums[1] >> BigBefore_Slot_C_BitOffset) & BigBefore_Slot_C_ValueMask) +} + +// D returns the D field. +func (x BigBefore) D() uint16 { + return uint16((x.ref.nums[1] >> BigBefore_Slot_D_BitOffset) & BigBefore_Slot_D_ValueMask) +} + +// E returns the E field. +func (x BigBefore) E() uint8 { return x.ref.extra.(*extraBigBefore).E } + +// F returns the F field. +func (x BigBefore) F() uint8 { return x.ref.extra.(*extraBigBefore).F } + +// G returns the G field. +func (x BigBefore) G() uint8 { return x.ref.extra.(*extraBigBefore).G } + +// H returns the H field. +func (x BigBefore) H() bool { return x.ref.extra.(*extraBigBefore).H } + +// I returns the I field. +func (x BigBefore) I() bool { return x.ref.extra.(*extraBigBefore).I } + +// V unpacks a reference into a value. +func (x BigBefore) V() BigBeforeValue { + return BigBeforeValue{ + A: uint64(x.ref.nums[0]), + B: uint32((x.ref.nums[1] >> BigBefore_Slot_B_BitOffset) & BigBefore_Slot_B_ValueMask), + C: uint16((x.ref.nums[1] >> BigBefore_Slot_C_BitOffset) & BigBefore_Slot_C_ValueMask), + D: uint16((x.ref.nums[1] >> BigBefore_Slot_D_BitOffset) & BigBefore_Slot_D_ValueMask), + E: x.ref.extra.(*extraBigBefore).E, + F: x.ref.extra.(*extraBigBefore).F, + G: x.ref.extra.(*extraBigBefore).G, + H: x.ref.extra.(*extraBigBefore).H, + I: x.ref.extra.(*extraBigBefore).I, + } +} + +// WithA constructs a new value where the value of A has been replaced by +// the argument. +func (x BigBeforeValue) WithA(y uint64) BigBeforeValue { + x.A = y + return x +} + +// WithB constructs a new value where the value of B has been replaced by +// the argument. +func (x BigBeforeValue) WithB(y uint32) BigBeforeValue { + x.B = y + return x +} + +// WithC constructs a new value where the value of C has been replaced by +// the argument. +func (x BigBeforeValue) WithC(y uint16) BigBeforeValue { + x.C = y + return x +} + +// WithD constructs a new value where the value of D has been replaced by +// the argument. +func (x BigBeforeValue) WithD(y uint16) BigBeforeValue { + x.D = y + return x +} + +// WithE constructs a new value where the value of E has been replaced by +// the argument. +func (x BigBeforeValue) WithE(y uint8) BigBeforeValue { + x.E = y + return x +} + +// WithF constructs a new value where the value of F has been replaced by +// the argument. +func (x BigBeforeValue) WithF(y uint8) BigBeforeValue { + x.F = y + return x +} + +// WithG constructs a new value where the value of G has been replaced by +// the argument. +func (x BigBeforeValue) WithG(y uint8) BigBeforeValue { + x.G = y + return x +} + +// WithH constructs a new value where the value of H has been replaced by +// the argument. +func (x BigBeforeValue) WithH(y bool) BigBeforeValue { + x.H = y + return x +} + +// WithI constructs a new value where the value of I has been replaced by +// the argument. +func (x BigBeforeValue) WithI(y bool) BigBeforeValue { + x.I = y + return x +} + +// Codegen parameters: +// {NumNumericSlots:2 NumericSlotSize:64 NumRefSlots:2 NumStrSlots:1 Pack:true} +// diff --git a/pkg/sql/ir/tests/defcfg/prims/base/sexpr.ir.go b/pkg/sql/ir/tests/defcfg/prims/base/sexpr.ir.go new file mode 100644 index 000000000000..7fd96bda9c9c --- /dev/null +++ b/pkg/sql/ir/tests/defcfg/prims/base/sexpr.ir.go @@ -0,0 +1,151 @@ +// Code generated by irgen/irgen base/sexpr.tmpl.go tests/prims.def. DO NOT EDIT. +// GENERATED FILE DO NOT EDIT +// Copyright 2017 The Cockroach Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. + +package base + +import ( + "bytes" + "fmt" +) + +type SexprFormatter interface { + FormatSExpr(buf *bytes.Buffer) +} + +func FormatSExprBool(buf *bytes.Buffer, x bool) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt64(buf *bytes.Buffer, x int64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt32(buf *bytes.Buffer, x int32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt16(buf *bytes.Buffer, x int16) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt8(buf *bytes.Buffer, x int8) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint64(buf *bytes.Buffer, x uint64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint32(buf *bytes.Buffer, x uint32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint16(buf *bytes.Buffer, x uint16) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint8(buf *bytes.Buffer, x uint8) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprFloat32(buf *bytes.Buffer, x float32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprFloat64(buf *bytes.Buffer, x float64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprString(buf *bytes.Buffer, x string) { fmt.Fprintf(buf, "%q", x) } + +func (x All) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(All") + + buf.WriteString(" B: ") + FormatSExprBool(buf, x.B()) + + buf.WriteString(" I8: ") + FormatSExprInt8(buf, x.I8()) + + buf.WriteString(" U8: ") + FormatSExprUint8(buf, x.U8()) + + buf.WriteString(" I16: ") + FormatSExprInt16(buf, x.I16()) + + buf.WriteString(" U16: ") + FormatSExprUint16(buf, x.U16()) + + buf.WriteString(" I32: ") + FormatSExprInt32(buf, x.I32()) + + buf.WriteString(" U32: ") + FormatSExprUint32(buf, x.U32()) + + buf.WriteString(" I64: ") + FormatSExprInt64(buf, x.I64()) + + buf.WriteString(" U64: ") + FormatSExprUint64(buf, x.U64()) + + buf.WriteString(" S: ") + FormatSExprString(buf, x.S()) + + buf.WriteString(" F32: ") + FormatSExprFloat32(buf, x.F32()) + + buf.WriteString(" F64: ") + FormatSExprFloat64(buf, x.F64()) + + buf.WriteByte(')') +} + +func (x SmallBefore) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(SmallBefore") + + buf.WriteString(" A: ") + FormatSExprBool(buf, x.A()) + + buf.WriteString(" B: ") + FormatSExprBool(buf, x.B()) + + buf.WriteString(" C: ") + FormatSExprUint8(buf, x.C()) + + buf.WriteString(" D: ") + FormatSExprUint8(buf, x.D()) + + buf.WriteString(" E: ") + FormatSExprUint8(buf, x.E()) + + buf.WriteString(" F: ") + FormatSExprUint16(buf, x.F()) + + buf.WriteString(" G: ") + FormatSExprUint16(buf, x.G()) + + buf.WriteString(" H: ") + FormatSExprUint32(buf, x.H()) + + buf.WriteString(" I: ") + FormatSExprUint64(buf, x.I()) + + buf.WriteByte(')') +} + +func (x BigBefore) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(BigBefore") + + buf.WriteString(" A: ") + FormatSExprUint64(buf, x.A()) + + buf.WriteString(" B: ") + FormatSExprUint32(buf, x.B()) + + buf.WriteString(" C: ") + FormatSExprUint16(buf, x.C()) + + buf.WriteString(" D: ") + FormatSExprUint16(buf, x.D()) + + buf.WriteString(" E: ") + FormatSExprUint8(buf, x.E()) + + buf.WriteString(" F: ") + FormatSExprUint8(buf, x.F()) + + buf.WriteString(" G: ") + FormatSExprUint8(buf, x.G()) + + buf.WriteString(" H: ") + FormatSExprBool(buf, x.H()) + + buf.WriteString(" I: ") + FormatSExprBool(buf, x.I()) + + buf.WriteByte(')') +} + +// Codegen parameters: +// {NumNumericSlots:2 NumericSlotSize:64 NumRefSlots:2 NumStrSlots:1 Pack:true} +// diff --git a/pkg/sql/ir/example.def b/pkg/sql/ir/tests/example.def similarity index 83% rename from pkg/sql/ir/example.def rename to pkg/sql/ir/tests/example.def index 67aa28ed7a2b..6b7f7d77563c 100644 --- a/pkg/sql/ir/example.def +++ b/pkg/sql/ir/tests/example.def @@ -13,6 +13,12 @@ struct BinExpr { Expr Right = 3 } +struct TriExpr { + Expr One = 1 + Expr Two = 2 + Expr Three = 4 +} + enum BinOp { Add = 1 Mul = 2 @@ -31,4 +37,3 @@ sum AllOrExpr { BinExpr = 2 } -prim int64 diff --git a/pkg/sql/ir/tests/expanded/example/base/base.ir.go b/pkg/sql/ir/tests/expanded/example/base/base.ir.go new file mode 100644 index 000000000000..b63fe65f1cac --- /dev/null +++ b/pkg/sql/ir/tests/expanded/example/base/base.ir.go @@ -0,0 +1,644 @@ +// Code generated by irgen/irgen base/base.tmpl.go tests/example.def. DO NOT EDIT. +// GENERATED FILE DO NOT EDIT +// Copyright 2017 The Cockroach Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. + +package base + +import ( + "fmt" +) + +// node is a generic ADT node type, with slots for references to other nodes and +// enumeration values. Values that don't fit and values of other types go in the +// extra field. +type node struct { + refs [20]*node + nums [20]numvalslot + strs [20]string + extra +} + +// enum is the type to define the tag part for working copies of IR +// node with sum and enum types. +type enum uint32 + +// numvalslot is the type used to store integer values in persistent IR nodes. +// must be larger than or as large as enum. +type numvalslot uint64 + +type extra interface { + extraRefs() []*node +} + +// Allocator allocates nodes in batches. Construct Allocators with NewAllocator +// and pass them by value. +type Allocator struct { + nodes []node +} + +// MakeAllocator constructs a new Allocator. +func MakeAllocator() Allocator { + nodes := make([]node, 16) + return Allocator{nodes} +} + +// NewAllocator allocates a new Allocator. +func NewAllocator() *Allocator { + a := MakeAllocator() + return &a +} + +// new allocates a new node. Users of this package should use the appropriate +// R() method, which is type safe. +func (a *Allocator) new() *node { + nodes := a.nodes + if len(nodes) == 0 { + nodes = make([]node, 256) + } + x := &nodes[0] + a.nodes = nodes[1:] + return x +} + +// ---- BinOp ---- // + +// BinOp is an enumeration type. +type BinOp enum + +// BinOp constants. +const ( + BinOpAdd BinOp = 1 + BinOpMul BinOp = 2 +) + +func (x BinOp) String() string { + switch x { + case BinOpAdd: + return "Add" + case BinOpMul: + return "Mul" + default: + return fmt.Sprintf("", x) + } +} + +// ---- ConstExpr ---- // + +// ConstExpr is the type of a reference to an immutable record. +type ConstExpr struct{ ref *node } + +const ConstExpr_Slot_Datum_Type = 1 +const ConstExpr_Slot_Datum_Num = 0 +const ConstExpr_Slot_Datum_BitSize = 64 +const ConstExpr_Slot_Datum_BitOffset = 0 +const ConstExpr_Slot_Datum_ByteSize = 8 +const ConstExpr_Slot_Datum_ByteOffset = 0 +const ConstExpr_Slot_Datum_ValueMask = 0xffffffffffffffff + +// ConstExprValue is the logical type of a record. Immutable records are stored in +// nodes. +type ConstExprValue struct { + Datum int64 // 1 +} + +// R constructs a reference to an immutable record. +func (x ConstExprValue) R(a *Allocator) ConstExpr { + ref := a.new() + + ref.nums[0] = numvalslot(x.Datum) + return ConstExpr{ref} +} + +// Datum returns the Datum field. +func (x ConstExpr) Datum() int64 { return int64(x.ref.nums[0]) } + +// V unpacks a reference into a value. +func (x ConstExpr) V() ConstExprValue { + return ConstExprValue{ + Datum: int64(x.ref.nums[0]), + } +} + +// WithDatum constructs a new value where the value of Datum has been replaced by +// the argument. +func (x ConstExprValue) WithDatum(y int64) ConstExprValue { + x.Datum = y + return x +} + +// ---- BinExpr ---- // + +// BinExpr is the type of a reference to an immutable record. +type BinExpr struct{ ref *node } + +const BinExpr_Slot_Left_Type = 0 +const BinExpr_Slot_Left_Num = 0 +const BinExpr_Slot_Left_BitSize = -1 +const BinExpr_Slot_Left_BitOffset = -1 +const BinExpr_Slot_Left_ByteSize = -1 +const BinExpr_Slot_Left_ByteOffset = -1 +const BinExpr_Slot_Left_ValueMask = -1 + +const BinExpr_Slot_Left__Tag_Type = 1 +const BinExpr_Slot_Left__Tag_Num = 0 +const BinExpr_Slot_Left__Tag_BitSize = 64 +const BinExpr_Slot_Left__Tag_BitOffset = 0 +const BinExpr_Slot_Left__Tag_ByteSize = 8 +const BinExpr_Slot_Left__Tag_ByteOffset = 0 +const BinExpr_Slot_Left__Tag_ValueMask = 0xffffffffffffffff + +const BinExpr_Slot_Op_Type = 1 +const BinExpr_Slot_Op_Num = 1 +const BinExpr_Slot_Op_BitSize = 64 +const BinExpr_Slot_Op_BitOffset = 0 +const BinExpr_Slot_Op_ByteSize = 8 +const BinExpr_Slot_Op_ByteOffset = 0 +const BinExpr_Slot_Op_ValueMask = 0xffffffffffffffff + +const BinExpr_Slot_Right_Type = 0 +const BinExpr_Slot_Right_Num = 1 +const BinExpr_Slot_Right_BitSize = -1 +const BinExpr_Slot_Right_BitOffset = -1 +const BinExpr_Slot_Right_ByteSize = -1 +const BinExpr_Slot_Right_ByteOffset = -1 +const BinExpr_Slot_Right_ValueMask = -1 + +const BinExpr_Slot_Right__Tag_Type = 1 +const BinExpr_Slot_Right__Tag_Num = 2 +const BinExpr_Slot_Right__Tag_BitSize = 64 +const BinExpr_Slot_Right__Tag_BitOffset = 0 +const BinExpr_Slot_Right__Tag_ByteSize = 8 +const BinExpr_Slot_Right__Tag_ByteOffset = 0 +const BinExpr_Slot_Right__Tag_ValueMask = 0xffffffffffffffff + +// BinExprValue is the logical type of a record. Immutable records are stored in +// nodes. +type BinExprValue struct { + Left Expr // 1 + Op BinOp // 2 + Right Expr // 3 +} + +// R constructs a reference to an immutable record. +func (x BinExprValue) R(a *Allocator) BinExpr { + ref := a.new() + + ref.nums[0] = numvalslot(x.Left.tag) + ref.refs[0] = x.Left.ref + ref.nums[1] = numvalslot(x.Op) + ref.nums[2] = numvalslot(x.Right.tag) + ref.refs[1] = x.Right.ref + return BinExpr{ref} +} + +// Left returns the Left field. +func (x BinExpr) Left() Expr { return Expr{ExprTag(x.ref.nums[0]), x.ref.refs[0]} } + +// Op returns the Op field. +func (x BinExpr) Op() BinOp { return BinOp(x.ref.nums[1]) } + +// Right returns the Right field. +func (x BinExpr) Right() Expr { return Expr{ExprTag(x.ref.nums[2]), x.ref.refs[1]} } + +// V unpacks a reference into a value. +func (x BinExpr) V() BinExprValue { + return BinExprValue{ + Left: Expr{ExprTag(x.ref.nums[0]), x.ref.refs[0]}, + Op: BinOp(x.ref.nums[1]), + Right: Expr{ExprTag(x.ref.nums[2]), x.ref.refs[1]}, + } +} + +// WithLeft constructs a new value where the value of Left has been replaced by +// the argument. +func (x BinExprValue) WithLeft(y Expr) BinExprValue { + x.Left = y + return x +} + +// WithOp constructs a new value where the value of Op has been replaced by +// the argument. +func (x BinExprValue) WithOp(y BinOp) BinExprValue { + x.Op = y + return x +} + +// WithRight constructs a new value where the value of Right has been replaced by +// the argument. +func (x BinExprValue) WithRight(y Expr) BinExprValue { + x.Right = y + return x +} + +// ---- TriExpr ---- // + +// TriExpr is the type of a reference to an immutable record. +type TriExpr struct{ ref *node } + +const TriExpr_Slot_One_Type = 0 +const TriExpr_Slot_One_Num = 0 +const TriExpr_Slot_One_BitSize = -1 +const TriExpr_Slot_One_BitOffset = -1 +const TriExpr_Slot_One_ByteSize = -1 +const TriExpr_Slot_One_ByteOffset = -1 +const TriExpr_Slot_One_ValueMask = -1 + +const TriExpr_Slot_One__Tag_Type = 1 +const TriExpr_Slot_One__Tag_Num = 0 +const TriExpr_Slot_One__Tag_BitSize = 64 +const TriExpr_Slot_One__Tag_BitOffset = 0 +const TriExpr_Slot_One__Tag_ByteSize = 8 +const TriExpr_Slot_One__Tag_ByteOffset = 0 +const TriExpr_Slot_One__Tag_ValueMask = 0xffffffffffffffff + +const TriExpr_Slot_Three_Type = 0 +const TriExpr_Slot_Three_Num = 2 +const TriExpr_Slot_Three_BitSize = -1 +const TriExpr_Slot_Three_BitOffset = -1 +const TriExpr_Slot_Three_ByteSize = -1 +const TriExpr_Slot_Three_ByteOffset = -1 +const TriExpr_Slot_Three_ValueMask = -1 + +const TriExpr_Slot_Three__Tag_Type = 1 +const TriExpr_Slot_Three__Tag_Num = 2 +const TriExpr_Slot_Three__Tag_BitSize = 64 +const TriExpr_Slot_Three__Tag_BitOffset = 0 +const TriExpr_Slot_Three__Tag_ByteSize = 8 +const TriExpr_Slot_Three__Tag_ByteOffset = 0 +const TriExpr_Slot_Three__Tag_ValueMask = 0xffffffffffffffff + +const TriExpr_Slot_Two_Type = 0 +const TriExpr_Slot_Two_Num = 1 +const TriExpr_Slot_Two_BitSize = -1 +const TriExpr_Slot_Two_BitOffset = -1 +const TriExpr_Slot_Two_ByteSize = -1 +const TriExpr_Slot_Two_ByteOffset = -1 +const TriExpr_Slot_Two_ValueMask = -1 + +const TriExpr_Slot_Two__Tag_Type = 1 +const TriExpr_Slot_Two__Tag_Num = 1 +const TriExpr_Slot_Two__Tag_BitSize = 64 +const TriExpr_Slot_Two__Tag_BitOffset = 0 +const TriExpr_Slot_Two__Tag_ByteSize = 8 +const TriExpr_Slot_Two__Tag_ByteOffset = 0 +const TriExpr_Slot_Two__Tag_ValueMask = 0xffffffffffffffff + +// TriExprValue is the logical type of a record. Immutable records are stored in +// nodes. +type TriExprValue struct { + One Expr // 1 + Two Expr // 2 + Three Expr // 4 +} + +// R constructs a reference to an immutable record. +func (x TriExprValue) R(a *Allocator) TriExpr { + ref := a.new() + + ref.nums[0] = numvalslot(x.One.tag) + ref.refs[0] = x.One.ref + ref.nums[1] = numvalslot(x.Two.tag) + ref.refs[1] = x.Two.ref + ref.nums[2] = numvalslot(x.Three.tag) + ref.refs[2] = x.Three.ref + return TriExpr{ref} +} + +// One returns the One field. +func (x TriExpr) One() Expr { return Expr{ExprTag(x.ref.nums[0]), x.ref.refs[0]} } + +// Two returns the Two field. +func (x TriExpr) Two() Expr { return Expr{ExprTag(x.ref.nums[1]), x.ref.refs[1]} } + +// Three returns the Three field. +func (x TriExpr) Three() Expr { return Expr{ExprTag(x.ref.nums[2]), x.ref.refs[2]} } + +// V unpacks a reference into a value. +func (x TriExpr) V() TriExprValue { + return TriExprValue{ + One: Expr{ExprTag(x.ref.nums[0]), x.ref.refs[0]}, + Two: Expr{ExprTag(x.ref.nums[1]), x.ref.refs[1]}, + Three: Expr{ExprTag(x.ref.nums[2]), x.ref.refs[2]}, + } +} + +// WithOne constructs a new value where the value of One has been replaced by +// the argument. +func (x TriExprValue) WithOne(y Expr) TriExprValue { + x.One = y + return x +} + +// WithTwo constructs a new value where the value of Two has been replaced by +// the argument. +func (x TriExprValue) WithTwo(y Expr) TriExprValue { + x.Two = y + return x +} + +// WithThree constructs a new value where the value of Three has been replaced by +// the argument. +func (x TriExprValue) WithThree(y Expr) TriExprValue { + x.Three = y + return x +} + +// ---- All ---- // + +// All is the type of a reference to an immutable record. +type All struct{ ref *node } + +const All_Slot_A_Type = 0 +const All_Slot_A_Num = 3 +const All_Slot_A_BitSize = -1 +const All_Slot_A_BitOffset = -1 +const All_Slot_A_ByteSize = -1 +const All_Slot_A_ByteOffset = -1 +const All_Slot_A_ValueMask = -1 + +const All_Slot_A__Tag_Type = 1 +const All_Slot_A__Tag_Num = 2 +const All_Slot_A__Tag_BitSize = 64 +const All_Slot_A__Tag_BitOffset = 0 +const All_Slot_A__Tag_ByteSize = 8 +const All_Slot_A__Tag_ByteOffset = 0 +const All_Slot_A__Tag_ValueMask = 0xffffffffffffffff + +const All_Slot_BE_Type = 0 +const All_Slot_BE_Num = 2 +const All_Slot_BE_BitSize = -1 +const All_Slot_BE_BitOffset = -1 +const All_Slot_BE_ByteSize = -1 +const All_Slot_BE_ByteOffset = -1 +const All_Slot_BE_ValueMask = -1 + +const All_Slot_BO_Type = 1 +const All_Slot_BO_Num = 1 +const All_Slot_BO_BitSize = 64 +const All_Slot_BO_BitOffset = 0 +const All_Slot_BO_ByteSize = 8 +const All_Slot_BO_ByteOffset = 0 +const All_Slot_BO_ValueMask = 0xffffffffffffffff + +const All_Slot_CE_Type = 0 +const All_Slot_CE_Num = 1 +const All_Slot_CE_BitSize = -1 +const All_Slot_CE_BitOffset = -1 +const All_Slot_CE_ByteSize = -1 +const All_Slot_CE_ByteOffset = -1 +const All_Slot_CE_ValueMask = -1 + +const All_Slot_E_Type = 0 +const All_Slot_E_Num = 0 +const All_Slot_E_BitSize = -1 +const All_Slot_E_BitOffset = -1 +const All_Slot_E_ByteSize = -1 +const All_Slot_E_ByteOffset = -1 +const All_Slot_E_ValueMask = -1 + +const All_Slot_E__Tag_Type = 1 +const All_Slot_E__Tag_Num = 0 +const All_Slot_E__Tag_BitSize = 64 +const All_Slot_E__Tag_BitOffset = 0 +const All_Slot_E__Tag_ByteSize = 8 +const All_Slot_E__Tag_ByteOffset = 0 +const All_Slot_E__Tag_ValueMask = 0xffffffffffffffff + +// AllValue is the logical type of a record. Immutable records are stored in +// nodes. +type AllValue struct { + E Expr // 1 + CE ConstExpr // 2 + BE BinExpr // 3 + BO BinOp // 4 + A AllOrExpr // 5 +} + +// R constructs a reference to an immutable record. +func (x AllValue) R(a *Allocator) All { + ref := a.new() + + ref.nums[0] = numvalslot(x.E.tag) + ref.refs[0] = x.E.ref + ref.refs[1] = x.CE.ref + ref.refs[2] = x.BE.ref + ref.nums[1] = numvalslot(x.BO) + ref.nums[2] = numvalslot(x.A.tag) + ref.refs[3] = x.A.ref + return All{ref} +} + +// E returns the E field. +func (x All) E() Expr { return Expr{ExprTag(x.ref.nums[0]), x.ref.refs[0]} } + +// CE returns the CE field. +func (x All) CE() ConstExpr { return ConstExpr{x.ref.refs[1]} } + +// BE returns the BE field. +func (x All) BE() BinExpr { return BinExpr{x.ref.refs[2]} } + +// BO returns the BO field. +func (x All) BO() BinOp { return BinOp(x.ref.nums[1]) } + +// A returns the A field. +func (x All) A() AllOrExpr { return AllOrExpr{AllOrExprTag(x.ref.nums[2]), x.ref.refs[3]} } + +// V unpacks a reference into a value. +func (x All) V() AllValue { + return AllValue{ + E: Expr{ExprTag(x.ref.nums[0]), x.ref.refs[0]}, + CE: ConstExpr{x.ref.refs[1]}, + BE: BinExpr{x.ref.refs[2]}, + BO: BinOp(x.ref.nums[1]), + A: AllOrExpr{AllOrExprTag(x.ref.nums[2]), x.ref.refs[3]}, + } +} + +// WithE constructs a new value where the value of E has been replaced by +// the argument. +func (x AllValue) WithE(y Expr) AllValue { + x.E = y + return x +} + +// WithCE constructs a new value where the value of CE has been replaced by +// the argument. +func (x AllValue) WithCE(y ConstExpr) AllValue { + x.CE = y + return x +} + +// WithBE constructs a new value where the value of BE has been replaced by +// the argument. +func (x AllValue) WithBE(y BinExpr) AllValue { + x.BE = y + return x +} + +// WithBO constructs a new value where the value of BO has been replaced by +// the argument. +func (x AllValue) WithBO(y BinOp) AllValue { + x.BO = y + return x +} + +// WithA constructs a new value where the value of A has been replaced by +// the argument. +func (x AllValue) WithA(y AllOrExpr) AllValue { + x.A = y + return x +} + +// ---- Expr ---- // + +// Expr is the type of a tagged union of records. +type Expr struct { + tag ExprTag + ref *node +} + +// ExprTag is the tag type. +type ExprTag enum + +// ExprTag constants. +const ( + ExprConstExpr ExprTag = 1 + ExprBinExpr ExprTag = 2 +) + +func (x ExprTag) String() string { + switch x { + case ExprConstExpr: + return "ConstExpr" + case ExprBinExpr: + return "BinExpr" + default: + return fmt.Sprintf("", x) + } +} + +// Tag returns the tag. +func (x Expr) Tag() ExprTag { return x.tag } + +// Expr performs an upcast. +func (x ConstExpr) Expr() Expr { return Expr{ExprConstExpr, x.ref} } + +// ConstExpr performs a downcast. If the downcast fails, return false. +func (x Expr) ConstExpr() (ConstExpr, bool) { + if x.tag != ExprConstExpr { + return ConstExpr{}, false + } + return ConstExpr{x.ref}, true +} + +// MustBeConstExpr performs a downcast. If the downcast fails, panic. +func (x Expr) MustBeConstExpr() ConstExpr { + if x.tag != ExprConstExpr { + panic(fmt.Sprintf("type assertion failed: expected ConstExpr but got %s", x.tag)) + } + return ConstExpr{x.ref} +} + +// Expr performs an upcast. +func (x BinExpr) Expr() Expr { return Expr{ExprBinExpr, x.ref} } + +// BinExpr performs a downcast. If the downcast fails, return false. +func (x Expr) BinExpr() (BinExpr, bool) { + if x.tag != ExprBinExpr { + return BinExpr{}, false + } + return BinExpr{x.ref}, true +} + +// MustBeBinExpr performs a downcast. If the downcast fails, panic. +func (x Expr) MustBeBinExpr() BinExpr { + if x.tag != ExprBinExpr { + panic(fmt.Sprintf("type assertion failed: expected BinExpr but got %s", x.tag)) + } + return BinExpr{x.ref} +} + +// ---- AllOrExpr ---- // + +// AllOrExpr is the type of a tagged union of records. +type AllOrExpr struct { + tag AllOrExprTag + ref *node +} + +// AllOrExprTag is the tag type. +type AllOrExprTag enum + +// AllOrExprTag constants. +const ( + AllOrExprAll AllOrExprTag = 1 + AllOrExprBinExpr AllOrExprTag = 2 +) + +func (x AllOrExprTag) String() string { + switch x { + case AllOrExprAll: + return "All" + case AllOrExprBinExpr: + return "BinExpr" + default: + return fmt.Sprintf("", x) + } +} + +// Tag returns the tag. +func (x AllOrExpr) Tag() AllOrExprTag { return x.tag } + +// AllOrExpr performs an upcast. +func (x All) AllOrExpr() AllOrExpr { return AllOrExpr{AllOrExprAll, x.ref} } + +// All performs a downcast. If the downcast fails, return false. +func (x AllOrExpr) All() (All, bool) { + if x.tag != AllOrExprAll { + return All{}, false + } + return All{x.ref}, true +} + +// MustBeAll performs a downcast. If the downcast fails, panic. +func (x AllOrExpr) MustBeAll() All { + if x.tag != AllOrExprAll { + panic(fmt.Sprintf("type assertion failed: expected All but got %s", x.tag)) + } + return All{x.ref} +} + +// AllOrExpr performs an upcast. +func (x BinExpr) AllOrExpr() AllOrExpr { return AllOrExpr{AllOrExprBinExpr, x.ref} } + +// BinExpr performs a downcast. If the downcast fails, return false. +func (x AllOrExpr) BinExpr() (BinExpr, bool) { + if x.tag != AllOrExprBinExpr { + return BinExpr{}, false + } + return BinExpr{x.ref}, true +} + +// MustBeBinExpr performs a downcast. If the downcast fails, panic. +func (x AllOrExpr) MustBeBinExpr() BinExpr { + if x.tag != AllOrExprBinExpr { + panic(fmt.Sprintf("type assertion failed: expected BinExpr but got %s", x.tag)) + } + return BinExpr{x.ref} +} + +// Codegen parameters: +// {NumNumericSlots:20 NumericSlotSize:64 NumRefSlots:20 NumStrSlots:20 Pack:false} +// diff --git a/pkg/sql/ir/tests/expanded/example/base/sexpr.ir.go b/pkg/sql/ir/tests/expanded/example/base/sexpr.ir.go new file mode 100644 index 000000000000..f56dcea564a6 --- /dev/null +++ b/pkg/sql/ir/tests/expanded/example/base/sexpr.ir.go @@ -0,0 +1,125 @@ +// Code generated by irgen/irgen base/sexpr.tmpl.go tests/example.def. DO NOT EDIT. +// GENERATED FILE DO NOT EDIT +// Copyright 2017 The Cockroach Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. + +package base + +import ( + "bytes" + "fmt" +) + +type SexprFormatter interface { + FormatSExpr(buf *bytes.Buffer) +} + +func FormatSExprBool(buf *bytes.Buffer, x bool) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt64(buf *bytes.Buffer, x int64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt32(buf *bytes.Buffer, x int32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt16(buf *bytes.Buffer, x int16) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt8(buf *bytes.Buffer, x int8) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint64(buf *bytes.Buffer, x uint64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint32(buf *bytes.Buffer, x uint32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint16(buf *bytes.Buffer, x uint16) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint8(buf *bytes.Buffer, x uint8) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprFloat32(buf *bytes.Buffer, x float32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprFloat64(buf *bytes.Buffer, x float64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprString(buf *bytes.Buffer, x string) { fmt.Fprintf(buf, "%q", x) } + +func (x BinOp) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString(x.String()) +} + +func (x ConstExpr) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(ConstExpr") + + buf.WriteString(" Datum: ") + FormatSExprInt64(buf, x.Datum()) + + buf.WriteByte(')') +} + +func (x BinExpr) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(BinExpr") + + buf.WriteString(" Left: ") + x.Left().FormatSExpr(buf) + + buf.WriteString(" Op: ") + x.Op().FormatSExpr(buf) + + buf.WriteString(" Right: ") + x.Right().FormatSExpr(buf) + + buf.WriteByte(')') +} + +func (x TriExpr) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(TriExpr") + + buf.WriteString(" One: ") + x.One().FormatSExpr(buf) + + buf.WriteString(" Two: ") + x.Two().FormatSExpr(buf) + + buf.WriteString(" Three: ") + x.Three().FormatSExpr(buf) + + buf.WriteByte(')') +} + +func (x All) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(All") + + buf.WriteString(" E: ") + x.E().FormatSExpr(buf) + + buf.WriteString(" CE: ") + x.CE().FormatSExpr(buf) + + buf.WriteString(" BE: ") + x.BE().FormatSExpr(buf) + + buf.WriteString(" BO: ") + x.BO().FormatSExpr(buf) + + buf.WriteString(" A: ") + x.A().FormatSExpr(buf) + + buf.WriteByte(')') +} + +func (x Expr) FormatSExpr(buf *bytes.Buffer) { + switch x.Tag() { + case ExprConstExpr: + x.MustBeConstExpr().FormatSExpr(buf) + case ExprBinExpr: + x.MustBeBinExpr().FormatSExpr(buf) + } +} + +func (x AllOrExpr) FormatSExpr(buf *bytes.Buffer) { + switch x.Tag() { + case AllOrExprAll: + x.MustBeAll().FormatSExpr(buf) + case AllOrExprBinExpr: + x.MustBeBinExpr().FormatSExpr(buf) + } +} + +// Codegen parameters: +// {NumNumericSlots:20 NumericSlotSize:64 NumRefSlots:20 NumStrSlots:20 Pack:false} +// diff --git a/pkg/sql/ir/tests/expanded/expanded_cfg_test.go b/pkg/sql/ir/tests/expanded/expanded_cfg_test.go new file mode 100644 index 000000000000..1659268c8fd5 --- /dev/null +++ b/pkg/sql/ir/tests/expanded/expanded_cfg_test.go @@ -0,0 +1,249 @@ +// Code generated by make. DO NOT EDIT. +// GENERATED FILE DO NOT EDIT +// Copyright 2017 The Cockroach Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. + +package expanded + +import ( + "bytes" + "fmt" + "reflect" + "strconv" + "strings" + "testing" + + d "github.com/cockroachdb/cockroach/pkg/sql/ir/tests/expanded/example/base" + p "github.com/cockroachdb/cockroach/pkg/sql/ir/tests/expanded/prims/base" +) + +func makeSampleExpr(a *d.Allocator) d.Expr { + c1 := d.ConstExprValue{Datum: 1}.R(a).Expr() + c2 := d.ConstExprValue{Datum: 2}.R(a).Expr() + c3 := d.ConstExprValue{Datum: 3}.R(a).Expr() + b4 := d.BinExprValue{Left: c1, Op: d.BinOpAdd, Right: c2}.R(a).Expr() + b5 := d.BinExprValue{Left: c3, Op: d.BinOpMul, Right: b4}.R(a).Expr() + return b5 +} + +func assertEq(t *testing.T, n int, val interface{}, exp interface{}) { + if !reflect.DeepEqual(val, exp) { + t.Errorf("equal failed %d: expected %v, got %v", n, exp, val) + } +} + +func TestExprValues(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + b5 := e.MustBeBinExpr() + assertEq(t, 1, b5.Op(), d.BinOpMul) + assertEq(t, 2, b5.Left().MustBeConstExpr().Datum(), int64(3)) + b4 := b5.Right().MustBeBinExpr() + assertEq(t, 3, b4.Op(), d.BinOpAdd) + assertEq(t, 4, b4.Left().MustBeConstExpr().Datum(), int64(1)) + assertEq(t, 5, b4.Right().MustBeConstExpr().Datum(), int64(2)) +} + +func format(ref d.Expr) string { + switch ref.Tag() { + case d.ExprConstExpr: + c := ref.MustBeConstExpr() + return strconv.FormatInt(c.Datum(), 10) + case d.ExprBinExpr: + b := ref.MustBeBinExpr() + var op string + switch b.Op() { + case d.BinOpAdd: + op = "+" + case d.BinOpMul: + op = "*" + default: + panic("unknown BinOp") + } + return fmt.Sprintf("(%s %s %s)", format(b.Left()), op, format(b.Right())) + default: + panic("unknown Expr tag") + } +} + +func TestExprFormatSExpr(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + + var buf bytes.Buffer + e.FormatSExpr(&buf) + if buf.String() != "(BinExpr Left: (ConstExpr Datum: 3) Op: Mul Right: (BinExpr Left: (ConstExpr Datum: 1) Op: Add Right: (ConstExpr Datum: 2)))" { + t.Fatalf("unexpected: %q", buf.String()) + } +} + +func TestFormat(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + const expected = "(3 * (1 + 2))" + if got := format(e); got != expected { + t.Fatalf("expected %q but got %q", expected, got) + } +} + +func reverse(ref d.Expr, a *d.Allocator) d.Expr { + if ref.Tag() != d.ExprBinExpr { + return ref + } + b := ref.MustBeBinExpr() + revLeft := reverse(b.Left(), a) + revRight := reverse(b.Right(), a) + return b.V().WithLeft(revRight).WithRight(revLeft).R(a).Expr() +} + +func TestReverse(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + const expected = "((2 + 1) * 3)" + if got := format(reverse(e, a)); got != expected { + t.Fatalf("expected %q but got %q", expected, got) + } +} + +func TestDoubleReverse(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + if got0, got2 := format(e), format(reverse(reverse(e, a), a)); got0 != got2 { + t.Fatalf("reverse is not an involution: %q != %q", got0, got2) + } +} + +func deepEqual(ref1 d.Expr, ref2 d.Expr) bool { + if ref1.Tag() != ref2.Tag() { + return false + } + switch ref1.Tag() { + case d.ExprConstExpr: + return ref1.MustBeConstExpr().Datum() == ref2.MustBeConstExpr().Datum() + case d.ExprBinExpr: + b1 := ref1.MustBeBinExpr() + b2 := ref2.MustBeBinExpr() + return b1.Op() == b2.Op() && + deepEqual(b1.Left(), b2.Left()) && deepEqual(b1.Right(), b2.Right()) + default: + panic("unknown Expr tag") + } +} + +func TestDeepEqual(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + if deepEqual(e, reverse(e, a)) { + t.Fatalf("expected expression not to be deepEqual to its reverse") + } + if !deepEqual(e, reverse(reverse(e, a), a)) { + t.Fatalf("expected expression to be deepEqual to the reverse of its reverse") + } +} + +func TestPrimValues(t *testing.T) { + a := p.NewAllocator() + all := p.AllValue{ + B: true, + I8: 'b', + U8: 'c', + I16: 0x1234, + U16: 0x4321, + I32: 0x12345678, + U32: 0x87654321, + I64: 0x123456789abcdef0, + U64: 0x0fedcba987654321, + S: "k", + F32: 1.234, + F64: 5.678, + }.R(a) + assertEq(t, 1, all.B(), true) + assertEq(t, 2, all.I8(), int8('b')) + assertEq(t, 3, all.U8(), uint8('c')) + assertEq(t, 4, all.I16(), int16(0x1234)) + assertEq(t, 5, all.U16(), uint16(0x4321)) + assertEq(t, 6, all.I32(), int32(0x12345678)) + assertEq(t, 7, all.U32(), uint32(0x87654321)) + assertEq(t, 8, all.I64(), int64(0x123456789abcdef0)) + assertEq(t, 9, all.U64(), uint64(0x0fedcba987654321)) + assertEq(t, 10, all.S(), "k") + assertEq(t, 11, all.F32(), float32(1.234)) + assertEq(t, 12, all.F64(), float64(5.678)) + + var buf bytes.Buffer + all.FormatSExpr(&buf) + assertEq(t, 100, buf.String(), strings.TrimSpace(` +(All B: true I8: 98 U8: 99 I16: 4660 U16: 17185 I32: 305419896 U32: 2271560481 I64: 1311768467463790320 U64: 1147797409030816545 S: "k" F32: 1.234 F64: 5.678) +`)) +} + +func TestPrimValues2(t *testing.T) { + a := p.NewAllocator() + v := p.SmallBeforeValue{ + A: true, + B: false, + C: 'c', + D: 'd', + E: 'e', + F: 0x1234, + G: 0x4321, + H: 0x12345678, + I: 0x123456789abcdef0, + }.R(a) + assertEq(t, 1, v.A(), true) + assertEq(t, 2, v.B(), false) + assertEq(t, 3, v.C(), uint8('c')) + assertEq(t, 4, v.D(), uint8('d')) + assertEq(t, 5, v.E(), uint8('e')) + assertEq(t, 6, v.F(), uint16(0x1234)) + assertEq(t, 7, v.G(), uint16(0x4321)) + assertEq(t, 8, v.H(), uint32(0x12345678)) + assertEq(t, 9, v.I(), uint64(0x123456789abcdef0)) + + var buf bytes.Buffer + v.FormatSExpr(&buf) + assertEq(t, 100, buf.String(), strings.TrimSpace(` +(SmallBefore A: true B: false C: 99 D: 100 E: 101 F: 4660 G: 17185 H: 305419896 I: 1311768467463790320) +`)) +} + +func TestPrimValues3(t *testing.T) { + a := p.NewAllocator() + v := p.BigBeforeValue{ + A: 0x123456789abcdef0, + B: 0x12345678, + C: 0x1234, + D: 0x4321, + E: 'e', + F: 'f', + G: 'g', + H: false, + I: true, + }.R(a) + assertEq(t, 1, v.A(), uint64(0x123456789abcdef0)) + assertEq(t, 2, v.B(), uint32(0x12345678)) + assertEq(t, 3, v.C(), uint16(0x1234)) + assertEq(t, 4, v.D(), uint16(0x4321)) + assertEq(t, 5, v.E(), uint8('e')) + assertEq(t, 6, v.F(), uint8('f')) + assertEq(t, 7, v.G(), uint8('g')) + assertEq(t, 8, v.H(), false) + assertEq(t, 9, v.I(), true) + + var buf bytes.Buffer + v.FormatSExpr(&buf) + assertEq(t, 100, buf.String(), strings.TrimSpace(` +(BigBefore A: 1311768467463790320 B: 305419896 C: 4660 D: 17185 E: 101 F: 102 G: 103 H: false I: true) +`)) +} diff --git a/pkg/sql/ir/tests/expanded/prims/base/base.ir.go b/pkg/sql/ir/tests/expanded/prims/base/base.ir.go new file mode 100644 index 000000000000..a1479ddbec1f --- /dev/null +++ b/pkg/sql/ir/tests/expanded/prims/base/base.ir.go @@ -0,0 +1,794 @@ +// Code generated by irgen/irgen base/base.tmpl.go tests/prims.def. DO NOT EDIT. +// GENERATED FILE DO NOT EDIT +// Copyright 2017 The Cockroach Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. + +package base + +import "math" + +// node is a generic ADT node type, with slots for references to other nodes and +// enumeration values. Values that don't fit and values of other types go in the +// extra field. +type node struct { + refs [20]*node + nums [20]numvalslot + strs [20]string + extra +} + +// enum is the type to define the tag part for working copies of IR +// node with sum and enum types. +type enum uint32 + +// numvalslot is the type used to store integer values in persistent IR nodes. +// must be larger than or as large as enum. +type numvalslot uint64 + +type extra interface { + extraRefs() []*node +} + +// Allocator allocates nodes in batches. Construct Allocators with NewAllocator +// and pass them by value. +type Allocator struct { + nodes []node +} + +// MakeAllocator constructs a new Allocator. +func MakeAllocator() Allocator { + nodes := make([]node, 16) + return Allocator{nodes} +} + +// NewAllocator allocates a new Allocator. +func NewAllocator() *Allocator { + a := MakeAllocator() + return &a +} + +// new allocates a new node. Users of this package should use the appropriate +// R() method, which is type safe. +func (a *Allocator) new() *node { + nodes := a.nodes + if len(nodes) == 0 { + nodes = make([]node, 256) + } + x := &nodes[0] + a.nodes = nodes[1:] + return x +} + +// ---- All ---- // + +// All is the type of a reference to an immutable record. +type All struct{ ref *node } + +const All_Slot_B_Type = 1 +const All_Slot_B_Num = 0 +const All_Slot_B_BitSize = 64 +const All_Slot_B_BitOffset = 0 +const All_Slot_B_ByteSize = 8 +const All_Slot_B_ByteOffset = 0 +const All_Slot_B_ValueMask = 0xffffffffffffffff + +const All_Slot_F32_Type = 1 +const All_Slot_F32_Num = 9 +const All_Slot_F32_BitSize = 64 +const All_Slot_F32_BitOffset = 0 +const All_Slot_F32_ByteSize = 8 +const All_Slot_F32_ByteOffset = 0 +const All_Slot_F32_ValueMask = 0xffffffffffffffff + +const All_Slot_F64_Type = 1 +const All_Slot_F64_Num = 10 +const All_Slot_F64_BitSize = 64 +const All_Slot_F64_BitOffset = 0 +const All_Slot_F64_ByteSize = 8 +const All_Slot_F64_ByteOffset = 0 +const All_Slot_F64_ValueMask = 0xffffffffffffffff + +const All_Slot_I16_Type = 1 +const All_Slot_I16_Num = 3 +const All_Slot_I16_BitSize = 64 +const All_Slot_I16_BitOffset = 0 +const All_Slot_I16_ByteSize = 8 +const All_Slot_I16_ByteOffset = 0 +const All_Slot_I16_ValueMask = 0xffffffffffffffff + +const All_Slot_I32_Type = 1 +const All_Slot_I32_Num = 5 +const All_Slot_I32_BitSize = 64 +const All_Slot_I32_BitOffset = 0 +const All_Slot_I32_ByteSize = 8 +const All_Slot_I32_ByteOffset = 0 +const All_Slot_I32_ValueMask = 0xffffffffffffffff + +const All_Slot_I64_Type = 1 +const All_Slot_I64_Num = 7 +const All_Slot_I64_BitSize = 64 +const All_Slot_I64_BitOffset = 0 +const All_Slot_I64_ByteSize = 8 +const All_Slot_I64_ByteOffset = 0 +const All_Slot_I64_ValueMask = 0xffffffffffffffff + +const All_Slot_I8_Type = 1 +const All_Slot_I8_Num = 1 +const All_Slot_I8_BitSize = 64 +const All_Slot_I8_BitOffset = 0 +const All_Slot_I8_ByteSize = 8 +const All_Slot_I8_ByteOffset = 0 +const All_Slot_I8_ValueMask = 0xffffffffffffffff + +const All_Slot_S_Type = 2 +const All_Slot_S_Num = 0 +const All_Slot_S_BitSize = -1 +const All_Slot_S_BitOffset = -1 +const All_Slot_S_ByteSize = -1 +const All_Slot_S_ByteOffset = -1 +const All_Slot_S_ValueMask = -1 + +const All_Slot_U16_Type = 1 +const All_Slot_U16_Num = 4 +const All_Slot_U16_BitSize = 64 +const All_Slot_U16_BitOffset = 0 +const All_Slot_U16_ByteSize = 8 +const All_Slot_U16_ByteOffset = 0 +const All_Slot_U16_ValueMask = 0xffffffffffffffff + +const All_Slot_U32_Type = 1 +const All_Slot_U32_Num = 6 +const All_Slot_U32_BitSize = 64 +const All_Slot_U32_BitOffset = 0 +const All_Slot_U32_ByteSize = 8 +const All_Slot_U32_ByteOffset = 0 +const All_Slot_U32_ValueMask = 0xffffffffffffffff + +const All_Slot_U64_Type = 1 +const All_Slot_U64_Num = 8 +const All_Slot_U64_BitSize = 64 +const All_Slot_U64_BitOffset = 0 +const All_Slot_U64_ByteSize = 8 +const All_Slot_U64_ByteOffset = 0 +const All_Slot_U64_ValueMask = 0xffffffffffffffff + +const All_Slot_U8_Type = 1 +const All_Slot_U8_Num = 2 +const All_Slot_U8_BitSize = 64 +const All_Slot_U8_BitOffset = 0 +const All_Slot_U8_ByteSize = 8 +const All_Slot_U8_ByteOffset = 0 +const All_Slot_U8_ValueMask = 0xffffffffffffffff + +// AllValue is the logical type of a record. Immutable records are stored in +// nodes. +type AllValue struct { + B bool // 1 + I8 int8 // 2 + U8 uint8 // 3 + I16 int16 // 4 + U16 uint16 // 5 + I32 int32 // 6 + U32 uint32 // 7 + I64 int64 // 8 + U64 uint64 // 9 + S string // 10 + F32 float32 // 11 + F64 float64 // 12 +} + +// R constructs a reference to an immutable record. +func (x AllValue) R(a *Allocator) All { + ref := a.new() + + if x.B { + ref.nums[0] = 1 + } else { + ref.nums[0] = 0 + } + ref.nums[1] = numvalslot(x.I8) + ref.nums[2] = numvalslot(x.U8) + ref.nums[3] = numvalslot(x.I16) + ref.nums[4] = numvalslot(x.U16) + ref.nums[5] = numvalslot(x.I32) + ref.nums[6] = numvalslot(x.U32) + ref.nums[7] = numvalslot(x.I64) + ref.nums[8] = numvalslot(x.U64) + ref.strs[0] = x.S + ref.nums[9] = numvalslot(math.Float32bits(x.F32)) + ref.nums[10] = numvalslot(math.Float64bits(x.F64)) + return All{ref} +} + +// B returns the B field. +func (x All) B() bool { return !(0 == x.ref.nums[0]) } + +// I8 returns the I8 field. +func (x All) I8() int8 { return int8(x.ref.nums[1]) } + +// U8 returns the U8 field. +func (x All) U8() uint8 { return uint8(x.ref.nums[2]) } + +// I16 returns the I16 field. +func (x All) I16() int16 { return int16(x.ref.nums[3]) } + +// U16 returns the U16 field. +func (x All) U16() uint16 { return uint16(x.ref.nums[4]) } + +// I32 returns the I32 field. +func (x All) I32() int32 { return int32(x.ref.nums[5]) } + +// U32 returns the U32 field. +func (x All) U32() uint32 { return uint32(x.ref.nums[6]) } + +// I64 returns the I64 field. +func (x All) I64() int64 { return int64(x.ref.nums[7]) } + +// U64 returns the U64 field. +func (x All) U64() uint64 { return uint64(x.ref.nums[8]) } + +// S returns the S field. +func (x All) S() string { return x.ref.strs[0] } + +// F32 returns the F32 field. +func (x All) F32() float32 { return math.Float32frombits(uint32(x.ref.nums[9])) } + +// F64 returns the F64 field. +func (x All) F64() float64 { return math.Float64frombits(uint64(x.ref.nums[10])) } + +// V unpacks a reference into a value. +func (x All) V() AllValue { + return AllValue{ + B: !(0 == x.ref.nums[0]), + I8: int8(x.ref.nums[1]), + U8: uint8(x.ref.nums[2]), + I16: int16(x.ref.nums[3]), + U16: uint16(x.ref.nums[4]), + I32: int32(x.ref.nums[5]), + U32: uint32(x.ref.nums[6]), + I64: int64(x.ref.nums[7]), + U64: uint64(x.ref.nums[8]), + S: x.ref.strs[0], + F32: math.Float32frombits(uint32(x.ref.nums[9])), + F64: math.Float64frombits(uint64(x.ref.nums[10])), + } +} + +// WithB constructs a new value where the value of B has been replaced by +// the argument. +func (x AllValue) WithB(y bool) AllValue { + x.B = y + return x +} + +// WithI8 constructs a new value where the value of I8 has been replaced by +// the argument. +func (x AllValue) WithI8(y int8) AllValue { + x.I8 = y + return x +} + +// WithU8 constructs a new value where the value of U8 has been replaced by +// the argument. +func (x AllValue) WithU8(y uint8) AllValue { + x.U8 = y + return x +} + +// WithI16 constructs a new value where the value of I16 has been replaced by +// the argument. +func (x AllValue) WithI16(y int16) AllValue { + x.I16 = y + return x +} + +// WithU16 constructs a new value where the value of U16 has been replaced by +// the argument. +func (x AllValue) WithU16(y uint16) AllValue { + x.U16 = y + return x +} + +// WithI32 constructs a new value where the value of I32 has been replaced by +// the argument. +func (x AllValue) WithI32(y int32) AllValue { + x.I32 = y + return x +} + +// WithU32 constructs a new value where the value of U32 has been replaced by +// the argument. +func (x AllValue) WithU32(y uint32) AllValue { + x.U32 = y + return x +} + +// WithI64 constructs a new value where the value of I64 has been replaced by +// the argument. +func (x AllValue) WithI64(y int64) AllValue { + x.I64 = y + return x +} + +// WithU64 constructs a new value where the value of U64 has been replaced by +// the argument. +func (x AllValue) WithU64(y uint64) AllValue { + x.U64 = y + return x +} + +// WithS constructs a new value where the value of S has been replaced by +// the argument. +func (x AllValue) WithS(y string) AllValue { + x.S = y + return x +} + +// WithF32 constructs a new value where the value of F32 has been replaced by +// the argument. +func (x AllValue) WithF32(y float32) AllValue { + x.F32 = y + return x +} + +// WithF64 constructs a new value where the value of F64 has been replaced by +// the argument. +func (x AllValue) WithF64(y float64) AllValue { + x.F64 = y + return x +} + +// ---- SmallBefore ---- // + +// SmallBefore is the type of a reference to an immutable record. +type SmallBefore struct{ ref *node } + +const SmallBefore_Slot_A_Type = 1 +const SmallBefore_Slot_A_Num = 0 +const SmallBefore_Slot_A_BitSize = 64 +const SmallBefore_Slot_A_BitOffset = 0 +const SmallBefore_Slot_A_ByteSize = 8 +const SmallBefore_Slot_A_ByteOffset = 0 +const SmallBefore_Slot_A_ValueMask = 0xffffffffffffffff + +const SmallBefore_Slot_B_Type = 1 +const SmallBefore_Slot_B_Num = 1 +const SmallBefore_Slot_B_BitSize = 64 +const SmallBefore_Slot_B_BitOffset = 0 +const SmallBefore_Slot_B_ByteSize = 8 +const SmallBefore_Slot_B_ByteOffset = 0 +const SmallBefore_Slot_B_ValueMask = 0xffffffffffffffff + +const SmallBefore_Slot_C_Type = 1 +const SmallBefore_Slot_C_Num = 2 +const SmallBefore_Slot_C_BitSize = 64 +const SmallBefore_Slot_C_BitOffset = 0 +const SmallBefore_Slot_C_ByteSize = 8 +const SmallBefore_Slot_C_ByteOffset = 0 +const SmallBefore_Slot_C_ValueMask = 0xffffffffffffffff + +const SmallBefore_Slot_D_Type = 1 +const SmallBefore_Slot_D_Num = 3 +const SmallBefore_Slot_D_BitSize = 64 +const SmallBefore_Slot_D_BitOffset = 0 +const SmallBefore_Slot_D_ByteSize = 8 +const SmallBefore_Slot_D_ByteOffset = 0 +const SmallBefore_Slot_D_ValueMask = 0xffffffffffffffff + +const SmallBefore_Slot_E_Type = 1 +const SmallBefore_Slot_E_Num = 4 +const SmallBefore_Slot_E_BitSize = 64 +const SmallBefore_Slot_E_BitOffset = 0 +const SmallBefore_Slot_E_ByteSize = 8 +const SmallBefore_Slot_E_ByteOffset = 0 +const SmallBefore_Slot_E_ValueMask = 0xffffffffffffffff + +const SmallBefore_Slot_F_Type = 1 +const SmallBefore_Slot_F_Num = 5 +const SmallBefore_Slot_F_BitSize = 64 +const SmallBefore_Slot_F_BitOffset = 0 +const SmallBefore_Slot_F_ByteSize = 8 +const SmallBefore_Slot_F_ByteOffset = 0 +const SmallBefore_Slot_F_ValueMask = 0xffffffffffffffff + +const SmallBefore_Slot_G_Type = 1 +const SmallBefore_Slot_G_Num = 6 +const SmallBefore_Slot_G_BitSize = 64 +const SmallBefore_Slot_G_BitOffset = 0 +const SmallBefore_Slot_G_ByteSize = 8 +const SmallBefore_Slot_G_ByteOffset = 0 +const SmallBefore_Slot_G_ValueMask = 0xffffffffffffffff + +const SmallBefore_Slot_H_Type = 1 +const SmallBefore_Slot_H_Num = 7 +const SmallBefore_Slot_H_BitSize = 64 +const SmallBefore_Slot_H_BitOffset = 0 +const SmallBefore_Slot_H_ByteSize = 8 +const SmallBefore_Slot_H_ByteOffset = 0 +const SmallBefore_Slot_H_ValueMask = 0xffffffffffffffff + +const SmallBefore_Slot_I_Type = 1 +const SmallBefore_Slot_I_Num = 8 +const SmallBefore_Slot_I_BitSize = 64 +const SmallBefore_Slot_I_BitOffset = 0 +const SmallBefore_Slot_I_ByteSize = 8 +const SmallBefore_Slot_I_ByteOffset = 0 +const SmallBefore_Slot_I_ValueMask = 0xffffffffffffffff + +// SmallBeforeValue is the logical type of a record. Immutable records are stored in +// nodes. +type SmallBeforeValue struct { + A bool // 1 + B bool // 2 + C uint8 // 3 + D uint8 // 4 + E uint8 // 5 + F uint16 // 6 + G uint16 // 7 + H uint32 // 8 + I uint64 // 9 +} + +// R constructs a reference to an immutable record. +func (x SmallBeforeValue) R(a *Allocator) SmallBefore { + ref := a.new() + + if x.A { + ref.nums[0] = 1 + } else { + ref.nums[0] = 0 + } + if x.B { + ref.nums[1] = 1 + } else { + ref.nums[1] = 0 + } + ref.nums[2] = numvalslot(x.C) + ref.nums[3] = numvalslot(x.D) + ref.nums[4] = numvalslot(x.E) + ref.nums[5] = numvalslot(x.F) + ref.nums[6] = numvalslot(x.G) + ref.nums[7] = numvalslot(x.H) + ref.nums[8] = numvalslot(x.I) + return SmallBefore{ref} +} + +// A returns the A field. +func (x SmallBefore) A() bool { return !(0 == x.ref.nums[0]) } + +// B returns the B field. +func (x SmallBefore) B() bool { return !(0 == x.ref.nums[1]) } + +// C returns the C field. +func (x SmallBefore) C() uint8 { return uint8(x.ref.nums[2]) } + +// D returns the D field. +func (x SmallBefore) D() uint8 { return uint8(x.ref.nums[3]) } + +// E returns the E field. +func (x SmallBefore) E() uint8 { return uint8(x.ref.nums[4]) } + +// F returns the F field. +func (x SmallBefore) F() uint16 { return uint16(x.ref.nums[5]) } + +// G returns the G field. +func (x SmallBefore) G() uint16 { return uint16(x.ref.nums[6]) } + +// H returns the H field. +func (x SmallBefore) H() uint32 { return uint32(x.ref.nums[7]) } + +// I returns the I field. +func (x SmallBefore) I() uint64 { return uint64(x.ref.nums[8]) } + +// V unpacks a reference into a value. +func (x SmallBefore) V() SmallBeforeValue { + return SmallBeforeValue{ + A: !(0 == x.ref.nums[0]), + B: !(0 == x.ref.nums[1]), + C: uint8(x.ref.nums[2]), + D: uint8(x.ref.nums[3]), + E: uint8(x.ref.nums[4]), + F: uint16(x.ref.nums[5]), + G: uint16(x.ref.nums[6]), + H: uint32(x.ref.nums[7]), + I: uint64(x.ref.nums[8]), + } +} + +// WithA constructs a new value where the value of A has been replaced by +// the argument. +func (x SmallBeforeValue) WithA(y bool) SmallBeforeValue { + x.A = y + return x +} + +// WithB constructs a new value where the value of B has been replaced by +// the argument. +func (x SmallBeforeValue) WithB(y bool) SmallBeforeValue { + x.B = y + return x +} + +// WithC constructs a new value where the value of C has been replaced by +// the argument. +func (x SmallBeforeValue) WithC(y uint8) SmallBeforeValue { + x.C = y + return x +} + +// WithD constructs a new value where the value of D has been replaced by +// the argument. +func (x SmallBeforeValue) WithD(y uint8) SmallBeforeValue { + x.D = y + return x +} + +// WithE constructs a new value where the value of E has been replaced by +// the argument. +func (x SmallBeforeValue) WithE(y uint8) SmallBeforeValue { + x.E = y + return x +} + +// WithF constructs a new value where the value of F has been replaced by +// the argument. +func (x SmallBeforeValue) WithF(y uint16) SmallBeforeValue { + x.F = y + return x +} + +// WithG constructs a new value where the value of G has been replaced by +// the argument. +func (x SmallBeforeValue) WithG(y uint16) SmallBeforeValue { + x.G = y + return x +} + +// WithH constructs a new value where the value of H has been replaced by +// the argument. +func (x SmallBeforeValue) WithH(y uint32) SmallBeforeValue { + x.H = y + return x +} + +// WithI constructs a new value where the value of I has been replaced by +// the argument. +func (x SmallBeforeValue) WithI(y uint64) SmallBeforeValue { + x.I = y + return x +} + +// ---- BigBefore ---- // + +// BigBefore is the type of a reference to an immutable record. +type BigBefore struct{ ref *node } + +const BigBefore_Slot_A_Type = 1 +const BigBefore_Slot_A_Num = 0 +const BigBefore_Slot_A_BitSize = 64 +const BigBefore_Slot_A_BitOffset = 0 +const BigBefore_Slot_A_ByteSize = 8 +const BigBefore_Slot_A_ByteOffset = 0 +const BigBefore_Slot_A_ValueMask = 0xffffffffffffffff + +const BigBefore_Slot_B_Type = 1 +const BigBefore_Slot_B_Num = 1 +const BigBefore_Slot_B_BitSize = 64 +const BigBefore_Slot_B_BitOffset = 0 +const BigBefore_Slot_B_ByteSize = 8 +const BigBefore_Slot_B_ByteOffset = 0 +const BigBefore_Slot_B_ValueMask = 0xffffffffffffffff + +const BigBefore_Slot_C_Type = 1 +const BigBefore_Slot_C_Num = 2 +const BigBefore_Slot_C_BitSize = 64 +const BigBefore_Slot_C_BitOffset = 0 +const BigBefore_Slot_C_ByteSize = 8 +const BigBefore_Slot_C_ByteOffset = 0 +const BigBefore_Slot_C_ValueMask = 0xffffffffffffffff + +const BigBefore_Slot_D_Type = 1 +const BigBefore_Slot_D_Num = 3 +const BigBefore_Slot_D_BitSize = 64 +const BigBefore_Slot_D_BitOffset = 0 +const BigBefore_Slot_D_ByteSize = 8 +const BigBefore_Slot_D_ByteOffset = 0 +const BigBefore_Slot_D_ValueMask = 0xffffffffffffffff + +const BigBefore_Slot_E_Type = 1 +const BigBefore_Slot_E_Num = 4 +const BigBefore_Slot_E_BitSize = 64 +const BigBefore_Slot_E_BitOffset = 0 +const BigBefore_Slot_E_ByteSize = 8 +const BigBefore_Slot_E_ByteOffset = 0 +const BigBefore_Slot_E_ValueMask = 0xffffffffffffffff + +const BigBefore_Slot_F_Type = 1 +const BigBefore_Slot_F_Num = 5 +const BigBefore_Slot_F_BitSize = 64 +const BigBefore_Slot_F_BitOffset = 0 +const BigBefore_Slot_F_ByteSize = 8 +const BigBefore_Slot_F_ByteOffset = 0 +const BigBefore_Slot_F_ValueMask = 0xffffffffffffffff + +const BigBefore_Slot_G_Type = 1 +const BigBefore_Slot_G_Num = 6 +const BigBefore_Slot_G_BitSize = 64 +const BigBefore_Slot_G_BitOffset = 0 +const BigBefore_Slot_G_ByteSize = 8 +const BigBefore_Slot_G_ByteOffset = 0 +const BigBefore_Slot_G_ValueMask = 0xffffffffffffffff + +const BigBefore_Slot_H_Type = 1 +const BigBefore_Slot_H_Num = 7 +const BigBefore_Slot_H_BitSize = 64 +const BigBefore_Slot_H_BitOffset = 0 +const BigBefore_Slot_H_ByteSize = 8 +const BigBefore_Slot_H_ByteOffset = 0 +const BigBefore_Slot_H_ValueMask = 0xffffffffffffffff + +const BigBefore_Slot_I_Type = 1 +const BigBefore_Slot_I_Num = 8 +const BigBefore_Slot_I_BitSize = 64 +const BigBefore_Slot_I_BitOffset = 0 +const BigBefore_Slot_I_ByteSize = 8 +const BigBefore_Slot_I_ByteOffset = 0 +const BigBefore_Slot_I_ValueMask = 0xffffffffffffffff + +// BigBeforeValue is the logical type of a record. Immutable records are stored in +// nodes. +type BigBeforeValue struct { + A uint64 // 1 + B uint32 // 2 + C uint16 // 3 + D uint16 // 4 + E uint8 // 5 + F uint8 // 6 + G uint8 // 7 + H bool // 8 + I bool // 9 +} + +// R constructs a reference to an immutable record. +func (x BigBeforeValue) R(a *Allocator) BigBefore { + ref := a.new() + + ref.nums[0] = numvalslot(x.A) + ref.nums[1] = numvalslot(x.B) + ref.nums[2] = numvalslot(x.C) + ref.nums[3] = numvalslot(x.D) + ref.nums[4] = numvalslot(x.E) + ref.nums[5] = numvalslot(x.F) + ref.nums[6] = numvalslot(x.G) + if x.H { + ref.nums[7] = 1 + } else { + ref.nums[7] = 0 + } + if x.I { + ref.nums[8] = 1 + } else { + ref.nums[8] = 0 + } + return BigBefore{ref} +} + +// A returns the A field. +func (x BigBefore) A() uint64 { return uint64(x.ref.nums[0]) } + +// B returns the B field. +func (x BigBefore) B() uint32 { return uint32(x.ref.nums[1]) } + +// C returns the C field. +func (x BigBefore) C() uint16 { return uint16(x.ref.nums[2]) } + +// D returns the D field. +func (x BigBefore) D() uint16 { return uint16(x.ref.nums[3]) } + +// E returns the E field. +func (x BigBefore) E() uint8 { return uint8(x.ref.nums[4]) } + +// F returns the F field. +func (x BigBefore) F() uint8 { return uint8(x.ref.nums[5]) } + +// G returns the G field. +func (x BigBefore) G() uint8 { return uint8(x.ref.nums[6]) } + +// H returns the H field. +func (x BigBefore) H() bool { return !(0 == x.ref.nums[7]) } + +// I returns the I field. +func (x BigBefore) I() bool { return !(0 == x.ref.nums[8]) } + +// V unpacks a reference into a value. +func (x BigBefore) V() BigBeforeValue { + return BigBeforeValue{ + A: uint64(x.ref.nums[0]), + B: uint32(x.ref.nums[1]), + C: uint16(x.ref.nums[2]), + D: uint16(x.ref.nums[3]), + E: uint8(x.ref.nums[4]), + F: uint8(x.ref.nums[5]), + G: uint8(x.ref.nums[6]), + H: !(0 == x.ref.nums[7]), + I: !(0 == x.ref.nums[8]), + } +} + +// WithA constructs a new value where the value of A has been replaced by +// the argument. +func (x BigBeforeValue) WithA(y uint64) BigBeforeValue { + x.A = y + return x +} + +// WithB constructs a new value where the value of B has been replaced by +// the argument. +func (x BigBeforeValue) WithB(y uint32) BigBeforeValue { + x.B = y + return x +} + +// WithC constructs a new value where the value of C has been replaced by +// the argument. +func (x BigBeforeValue) WithC(y uint16) BigBeforeValue { + x.C = y + return x +} + +// WithD constructs a new value where the value of D has been replaced by +// the argument. +func (x BigBeforeValue) WithD(y uint16) BigBeforeValue { + x.D = y + return x +} + +// WithE constructs a new value where the value of E has been replaced by +// the argument. +func (x BigBeforeValue) WithE(y uint8) BigBeforeValue { + x.E = y + return x +} + +// WithF constructs a new value where the value of F has been replaced by +// the argument. +func (x BigBeforeValue) WithF(y uint8) BigBeforeValue { + x.F = y + return x +} + +// WithG constructs a new value where the value of G has been replaced by +// the argument. +func (x BigBeforeValue) WithG(y uint8) BigBeforeValue { + x.G = y + return x +} + +// WithH constructs a new value where the value of H has been replaced by +// the argument. +func (x BigBeforeValue) WithH(y bool) BigBeforeValue { + x.H = y + return x +} + +// WithI constructs a new value where the value of I has been replaced by +// the argument. +func (x BigBeforeValue) WithI(y bool) BigBeforeValue { + x.I = y + return x +} + +// Codegen parameters: +// {NumNumericSlots:20 NumericSlotSize:64 NumRefSlots:20 NumStrSlots:20 Pack:false} +// diff --git a/pkg/sql/ir/tests/expanded/prims/base/sexpr.ir.go b/pkg/sql/ir/tests/expanded/prims/base/sexpr.ir.go new file mode 100644 index 000000000000..5214a8012013 --- /dev/null +++ b/pkg/sql/ir/tests/expanded/prims/base/sexpr.ir.go @@ -0,0 +1,151 @@ +// Code generated by irgen/irgen base/sexpr.tmpl.go tests/prims.def. DO NOT EDIT. +// GENERATED FILE DO NOT EDIT +// Copyright 2017 The Cockroach Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. + +package base + +import ( + "bytes" + "fmt" +) + +type SexprFormatter interface { + FormatSExpr(buf *bytes.Buffer) +} + +func FormatSExprBool(buf *bytes.Buffer, x bool) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt64(buf *bytes.Buffer, x int64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt32(buf *bytes.Buffer, x int32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt16(buf *bytes.Buffer, x int16) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt8(buf *bytes.Buffer, x int8) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint64(buf *bytes.Buffer, x uint64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint32(buf *bytes.Buffer, x uint32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint16(buf *bytes.Buffer, x uint16) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint8(buf *bytes.Buffer, x uint8) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprFloat32(buf *bytes.Buffer, x float32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprFloat64(buf *bytes.Buffer, x float64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprString(buf *bytes.Buffer, x string) { fmt.Fprintf(buf, "%q", x) } + +func (x All) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(All") + + buf.WriteString(" B: ") + FormatSExprBool(buf, x.B()) + + buf.WriteString(" I8: ") + FormatSExprInt8(buf, x.I8()) + + buf.WriteString(" U8: ") + FormatSExprUint8(buf, x.U8()) + + buf.WriteString(" I16: ") + FormatSExprInt16(buf, x.I16()) + + buf.WriteString(" U16: ") + FormatSExprUint16(buf, x.U16()) + + buf.WriteString(" I32: ") + FormatSExprInt32(buf, x.I32()) + + buf.WriteString(" U32: ") + FormatSExprUint32(buf, x.U32()) + + buf.WriteString(" I64: ") + FormatSExprInt64(buf, x.I64()) + + buf.WriteString(" U64: ") + FormatSExprUint64(buf, x.U64()) + + buf.WriteString(" S: ") + FormatSExprString(buf, x.S()) + + buf.WriteString(" F32: ") + FormatSExprFloat32(buf, x.F32()) + + buf.WriteString(" F64: ") + FormatSExprFloat64(buf, x.F64()) + + buf.WriteByte(')') +} + +func (x SmallBefore) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(SmallBefore") + + buf.WriteString(" A: ") + FormatSExprBool(buf, x.A()) + + buf.WriteString(" B: ") + FormatSExprBool(buf, x.B()) + + buf.WriteString(" C: ") + FormatSExprUint8(buf, x.C()) + + buf.WriteString(" D: ") + FormatSExprUint8(buf, x.D()) + + buf.WriteString(" E: ") + FormatSExprUint8(buf, x.E()) + + buf.WriteString(" F: ") + FormatSExprUint16(buf, x.F()) + + buf.WriteString(" G: ") + FormatSExprUint16(buf, x.G()) + + buf.WriteString(" H: ") + FormatSExprUint32(buf, x.H()) + + buf.WriteString(" I: ") + FormatSExprUint64(buf, x.I()) + + buf.WriteByte(')') +} + +func (x BigBefore) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(BigBefore") + + buf.WriteString(" A: ") + FormatSExprUint64(buf, x.A()) + + buf.WriteString(" B: ") + FormatSExprUint32(buf, x.B()) + + buf.WriteString(" C: ") + FormatSExprUint16(buf, x.C()) + + buf.WriteString(" D: ") + FormatSExprUint16(buf, x.D()) + + buf.WriteString(" E: ") + FormatSExprUint8(buf, x.E()) + + buf.WriteString(" F: ") + FormatSExprUint8(buf, x.F()) + + buf.WriteString(" G: ") + FormatSExprUint8(buf, x.G()) + + buf.WriteString(" H: ") + FormatSExprBool(buf, x.H()) + + buf.WriteString(" I: ") + FormatSExprBool(buf, x.I()) + + buf.WriteByte(')') +} + +// Codegen parameters: +// {NumNumericSlots:20 NumericSlotSize:64 NumRefSlots:20 NumStrSlots:20 Pack:false} +// diff --git a/pkg/sql/ir/tests/expandedpack/example/base/base.ir.go b/pkg/sql/ir/tests/expandedpack/example/base/base.ir.go new file mode 100644 index 000000000000..3e047294b86d --- /dev/null +++ b/pkg/sql/ir/tests/expandedpack/example/base/base.ir.go @@ -0,0 +1,662 @@ +// Code generated by irgen/irgen base/base.tmpl.go tests/example.def. DO NOT EDIT. +// GENERATED FILE DO NOT EDIT +// Copyright 2017 The Cockroach Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. + +package base + +import ( + "fmt" +) + +// node is a generic ADT node type, with slots for references to other nodes and +// enumeration values. Values that don't fit and values of other types go in the +// extra field. +type node struct { + refs [20]*node + nums [20]numvalslot + strs [20]string + extra +} + +// enum is the type to define the tag part for working copies of IR +// node with sum and enum types. +type enum uint32 + +// numvalslot is the type used to store integer values in persistent IR nodes. +// must be larger than or as large as enum. +type numvalslot uint64 + +type extra interface { + extraRefs() []*node +} + +// Allocator allocates nodes in batches. Construct Allocators with NewAllocator +// and pass them by value. +type Allocator struct { + nodes []node +} + +// MakeAllocator constructs a new Allocator. +func MakeAllocator() Allocator { + nodes := make([]node, 16) + return Allocator{nodes} +} + +// NewAllocator allocates a new Allocator. +func NewAllocator() *Allocator { + a := MakeAllocator() + return &a +} + +// new allocates a new node. Users of this package should use the appropriate +// R() method, which is type safe. +func (a *Allocator) new() *node { + nodes := a.nodes + if len(nodes) == 0 { + nodes = make([]node, 256) + } + x := &nodes[0] + a.nodes = nodes[1:] + return x +} + +// ---- BinOp ---- // + +// BinOp is an enumeration type. +type BinOp enum + +// BinOp constants. +const ( + BinOpAdd BinOp = 1 + BinOpMul BinOp = 2 +) + +func (x BinOp) String() string { + switch x { + case BinOpAdd: + return "Add" + case BinOpMul: + return "Mul" + default: + return fmt.Sprintf("", x) + } +} + +// ---- ConstExpr ---- // + +// ConstExpr is the type of a reference to an immutable record. +type ConstExpr struct{ ref *node } + +const ConstExpr_Slot_Datum_Type = 1 +const ConstExpr_Slot_Datum_Num = 0 +const ConstExpr_Slot_Datum_BitSize = 64 +const ConstExpr_Slot_Datum_BitOffset = 0 +const ConstExpr_Slot_Datum_ByteSize = 8 +const ConstExpr_Slot_Datum_ByteOffset = 0 +const ConstExpr_Slot_Datum_ValueMask = 0xffffffffffffffff + +// ConstExprValue is the logical type of a record. Immutable records are stored in +// nodes. +type ConstExprValue struct { + Datum int64 // 1 +} + +// R constructs a reference to an immutable record. +func (x ConstExprValue) R(a *Allocator) ConstExpr { + ref := a.new() + + ref.nums[0] = numvalslot(x.Datum) + return ConstExpr{ref} +} + +// Datum returns the Datum field. +func (x ConstExpr) Datum() int64 { return int64(x.ref.nums[0]) } + +// V unpacks a reference into a value. +func (x ConstExpr) V() ConstExprValue { + return ConstExprValue{ + Datum: int64(x.ref.nums[0]), + } +} + +// WithDatum constructs a new value where the value of Datum has been replaced by +// the argument. +func (x ConstExprValue) WithDatum(y int64) ConstExprValue { + x.Datum = y + return x +} + +// ---- BinExpr ---- // + +// BinExpr is the type of a reference to an immutable record. +type BinExpr struct{ ref *node } + +const BinExpr_Slot_Left_Type = 0 +const BinExpr_Slot_Left_Num = 0 +const BinExpr_Slot_Left_BitSize = -1 +const BinExpr_Slot_Left_BitOffset = -1 +const BinExpr_Slot_Left_ByteSize = -1 +const BinExpr_Slot_Left_ByteOffset = -1 +const BinExpr_Slot_Left_ValueMask = -1 + +const BinExpr_Slot_Left__Tag_Type = 1 +const BinExpr_Slot_Left__Tag_Num = 0 +const BinExpr_Slot_Left__Tag_BitSize = 2 +const BinExpr_Slot_Left__Tag_BitOffset = 0 +const BinExpr_Slot_Left__Tag_ByteSize = 1 +const BinExpr_Slot_Left__Tag_ByteOffset = 0 +const BinExpr_Slot_Left__Tag_ValueMask = 0x3 + +const BinExpr_Slot_Op_Type = 1 +const BinExpr_Slot_Op_Num = 0 +const BinExpr_Slot_Op_BitSize = 2 +const BinExpr_Slot_Op_BitOffset = 2 +const BinExpr_Slot_Op_ByteSize = 1 +const BinExpr_Slot_Op_ByteOffset = 0 +const BinExpr_Slot_Op_ValueMask = 0x3 + +const BinExpr_Slot_Right_Type = 0 +const BinExpr_Slot_Right_Num = 1 +const BinExpr_Slot_Right_BitSize = -1 +const BinExpr_Slot_Right_BitOffset = -1 +const BinExpr_Slot_Right_ByteSize = -1 +const BinExpr_Slot_Right_ByteOffset = -1 +const BinExpr_Slot_Right_ValueMask = -1 + +const BinExpr_Slot_Right__Tag_Type = 1 +const BinExpr_Slot_Right__Tag_Num = 0 +const BinExpr_Slot_Right__Tag_BitSize = 2 +const BinExpr_Slot_Right__Tag_BitOffset = 4 +const BinExpr_Slot_Right__Tag_ByteSize = 1 +const BinExpr_Slot_Right__Tag_ByteOffset = 0 +const BinExpr_Slot_Right__Tag_ValueMask = 0x3 + +// BinExprValue is the logical type of a record. Immutable records are stored in +// nodes. +type BinExprValue struct { + Left Expr // 1 + Op BinOp // 2 + Right Expr // 3 +} + +// R constructs a reference to an immutable record. +func (x BinExprValue) R(a *Allocator) BinExpr { + ref := a.new() + + ref.nums[0] = (ref.nums[0] &^ (BinExpr_Slot_Left__Tag_ValueMask << BinExpr_Slot_Left__Tag_BitOffset)) | (numvalslot(x.Left.tag) << BinExpr_Slot_Left__Tag_BitOffset) + ref.refs[0] = x.Left.ref + ref.nums[0] = (ref.nums[0] &^ (BinExpr_Slot_Op_ValueMask << BinExpr_Slot_Op_BitOffset)) | (numvalslot(x.Op) << BinExpr_Slot_Op_BitOffset) + ref.nums[0] = (ref.nums[0] &^ (BinExpr_Slot_Right__Tag_ValueMask << BinExpr_Slot_Right__Tag_BitOffset)) | (numvalslot(x.Right.tag) << BinExpr_Slot_Right__Tag_BitOffset) + ref.refs[1] = x.Right.ref + return BinExpr{ref} +} + +// Left returns the Left field. +func (x BinExpr) Left() Expr { + return Expr{ExprTag((x.ref.nums[0] >> BinExpr_Slot_Left__Tag_BitOffset) & BinExpr_Slot_Left__Tag_ValueMask), x.ref.refs[0]} +} + +// Op returns the Op field. +func (x BinExpr) Op() BinOp { + return BinOp((x.ref.nums[0] >> BinExpr_Slot_Op_BitOffset) & BinExpr_Slot_Op_ValueMask) +} + +// Right returns the Right field. +func (x BinExpr) Right() Expr { + return Expr{ExprTag((x.ref.nums[0] >> BinExpr_Slot_Right__Tag_BitOffset) & BinExpr_Slot_Right__Tag_ValueMask), x.ref.refs[1]} +} + +// V unpacks a reference into a value. +func (x BinExpr) V() BinExprValue { + return BinExprValue{ + Left: Expr{ExprTag((x.ref.nums[0] >> BinExpr_Slot_Left__Tag_BitOffset) & BinExpr_Slot_Left__Tag_ValueMask), x.ref.refs[0]}, + Op: BinOp((x.ref.nums[0] >> BinExpr_Slot_Op_BitOffset) & BinExpr_Slot_Op_ValueMask), + Right: Expr{ExprTag((x.ref.nums[0] >> BinExpr_Slot_Right__Tag_BitOffset) & BinExpr_Slot_Right__Tag_ValueMask), x.ref.refs[1]}, + } +} + +// WithLeft constructs a new value where the value of Left has been replaced by +// the argument. +func (x BinExprValue) WithLeft(y Expr) BinExprValue { + x.Left = y + return x +} + +// WithOp constructs a new value where the value of Op has been replaced by +// the argument. +func (x BinExprValue) WithOp(y BinOp) BinExprValue { + x.Op = y + return x +} + +// WithRight constructs a new value where the value of Right has been replaced by +// the argument. +func (x BinExprValue) WithRight(y Expr) BinExprValue { + x.Right = y + return x +} + +// ---- TriExpr ---- // + +// TriExpr is the type of a reference to an immutable record. +type TriExpr struct{ ref *node } + +const TriExpr_Slot_One_Type = 0 +const TriExpr_Slot_One_Num = 0 +const TriExpr_Slot_One_BitSize = -1 +const TriExpr_Slot_One_BitOffset = -1 +const TriExpr_Slot_One_ByteSize = -1 +const TriExpr_Slot_One_ByteOffset = -1 +const TriExpr_Slot_One_ValueMask = -1 + +const TriExpr_Slot_One__Tag_Type = 1 +const TriExpr_Slot_One__Tag_Num = 0 +const TriExpr_Slot_One__Tag_BitSize = 2 +const TriExpr_Slot_One__Tag_BitOffset = 0 +const TriExpr_Slot_One__Tag_ByteSize = 1 +const TriExpr_Slot_One__Tag_ByteOffset = 0 +const TriExpr_Slot_One__Tag_ValueMask = 0x3 + +const TriExpr_Slot_Three_Type = 0 +const TriExpr_Slot_Three_Num = 2 +const TriExpr_Slot_Three_BitSize = -1 +const TriExpr_Slot_Three_BitOffset = -1 +const TriExpr_Slot_Three_ByteSize = -1 +const TriExpr_Slot_Three_ByteOffset = -1 +const TriExpr_Slot_Three_ValueMask = -1 + +const TriExpr_Slot_Three__Tag_Type = 1 +const TriExpr_Slot_Three__Tag_Num = 0 +const TriExpr_Slot_Three__Tag_BitSize = 2 +const TriExpr_Slot_Three__Tag_BitOffset = 4 +const TriExpr_Slot_Three__Tag_ByteSize = 1 +const TriExpr_Slot_Three__Tag_ByteOffset = 0 +const TriExpr_Slot_Three__Tag_ValueMask = 0x3 + +const TriExpr_Slot_Two_Type = 0 +const TriExpr_Slot_Two_Num = 1 +const TriExpr_Slot_Two_BitSize = -1 +const TriExpr_Slot_Two_BitOffset = -1 +const TriExpr_Slot_Two_ByteSize = -1 +const TriExpr_Slot_Two_ByteOffset = -1 +const TriExpr_Slot_Two_ValueMask = -1 + +const TriExpr_Slot_Two__Tag_Type = 1 +const TriExpr_Slot_Two__Tag_Num = 0 +const TriExpr_Slot_Two__Tag_BitSize = 2 +const TriExpr_Slot_Two__Tag_BitOffset = 2 +const TriExpr_Slot_Two__Tag_ByteSize = 1 +const TriExpr_Slot_Two__Tag_ByteOffset = 0 +const TriExpr_Slot_Two__Tag_ValueMask = 0x3 + +// TriExprValue is the logical type of a record. Immutable records are stored in +// nodes. +type TriExprValue struct { + One Expr // 1 + Two Expr // 2 + Three Expr // 4 +} + +// R constructs a reference to an immutable record. +func (x TriExprValue) R(a *Allocator) TriExpr { + ref := a.new() + + ref.nums[0] = (ref.nums[0] &^ (TriExpr_Slot_One__Tag_ValueMask << TriExpr_Slot_One__Tag_BitOffset)) | (numvalslot(x.One.tag) << TriExpr_Slot_One__Tag_BitOffset) + ref.refs[0] = x.One.ref + ref.nums[0] = (ref.nums[0] &^ (TriExpr_Slot_Two__Tag_ValueMask << TriExpr_Slot_Two__Tag_BitOffset)) | (numvalslot(x.Two.tag) << TriExpr_Slot_Two__Tag_BitOffset) + ref.refs[1] = x.Two.ref + ref.nums[0] = (ref.nums[0] &^ (TriExpr_Slot_Three__Tag_ValueMask << TriExpr_Slot_Three__Tag_BitOffset)) | (numvalslot(x.Three.tag) << TriExpr_Slot_Three__Tag_BitOffset) + ref.refs[2] = x.Three.ref + return TriExpr{ref} +} + +// One returns the One field. +func (x TriExpr) One() Expr { + return Expr{ExprTag((x.ref.nums[0] >> TriExpr_Slot_One__Tag_BitOffset) & TriExpr_Slot_One__Tag_ValueMask), x.ref.refs[0]} +} + +// Two returns the Two field. +func (x TriExpr) Two() Expr { + return Expr{ExprTag((x.ref.nums[0] >> TriExpr_Slot_Two__Tag_BitOffset) & TriExpr_Slot_Two__Tag_ValueMask), x.ref.refs[1]} +} + +// Three returns the Three field. +func (x TriExpr) Three() Expr { + return Expr{ExprTag((x.ref.nums[0] >> TriExpr_Slot_Three__Tag_BitOffset) & TriExpr_Slot_Three__Tag_ValueMask), x.ref.refs[2]} +} + +// V unpacks a reference into a value. +func (x TriExpr) V() TriExprValue { + return TriExprValue{ + One: Expr{ExprTag((x.ref.nums[0] >> TriExpr_Slot_One__Tag_BitOffset) & TriExpr_Slot_One__Tag_ValueMask), x.ref.refs[0]}, + Two: Expr{ExprTag((x.ref.nums[0] >> TriExpr_Slot_Two__Tag_BitOffset) & TriExpr_Slot_Two__Tag_ValueMask), x.ref.refs[1]}, + Three: Expr{ExprTag((x.ref.nums[0] >> TriExpr_Slot_Three__Tag_BitOffset) & TriExpr_Slot_Three__Tag_ValueMask), x.ref.refs[2]}, + } +} + +// WithOne constructs a new value where the value of One has been replaced by +// the argument. +func (x TriExprValue) WithOne(y Expr) TriExprValue { + x.One = y + return x +} + +// WithTwo constructs a new value where the value of Two has been replaced by +// the argument. +func (x TriExprValue) WithTwo(y Expr) TriExprValue { + x.Two = y + return x +} + +// WithThree constructs a new value where the value of Three has been replaced by +// the argument. +func (x TriExprValue) WithThree(y Expr) TriExprValue { + x.Three = y + return x +} + +// ---- All ---- // + +// All is the type of a reference to an immutable record. +type All struct{ ref *node } + +const All_Slot_A_Type = 0 +const All_Slot_A_Num = 3 +const All_Slot_A_BitSize = -1 +const All_Slot_A_BitOffset = -1 +const All_Slot_A_ByteSize = -1 +const All_Slot_A_ByteOffset = -1 +const All_Slot_A_ValueMask = -1 + +const All_Slot_A__Tag_Type = 1 +const All_Slot_A__Tag_Num = 0 +const All_Slot_A__Tag_BitSize = 2 +const All_Slot_A__Tag_BitOffset = 4 +const All_Slot_A__Tag_ByteSize = 1 +const All_Slot_A__Tag_ByteOffset = 0 +const All_Slot_A__Tag_ValueMask = 0x3 + +const All_Slot_BE_Type = 0 +const All_Slot_BE_Num = 2 +const All_Slot_BE_BitSize = -1 +const All_Slot_BE_BitOffset = -1 +const All_Slot_BE_ByteSize = -1 +const All_Slot_BE_ByteOffset = -1 +const All_Slot_BE_ValueMask = -1 + +const All_Slot_BO_Type = 1 +const All_Slot_BO_Num = 0 +const All_Slot_BO_BitSize = 2 +const All_Slot_BO_BitOffset = 2 +const All_Slot_BO_ByteSize = 1 +const All_Slot_BO_ByteOffset = 0 +const All_Slot_BO_ValueMask = 0x3 + +const All_Slot_CE_Type = 0 +const All_Slot_CE_Num = 1 +const All_Slot_CE_BitSize = -1 +const All_Slot_CE_BitOffset = -1 +const All_Slot_CE_ByteSize = -1 +const All_Slot_CE_ByteOffset = -1 +const All_Slot_CE_ValueMask = -1 + +const All_Slot_E_Type = 0 +const All_Slot_E_Num = 0 +const All_Slot_E_BitSize = -1 +const All_Slot_E_BitOffset = -1 +const All_Slot_E_ByteSize = -1 +const All_Slot_E_ByteOffset = -1 +const All_Slot_E_ValueMask = -1 + +const All_Slot_E__Tag_Type = 1 +const All_Slot_E__Tag_Num = 0 +const All_Slot_E__Tag_BitSize = 2 +const All_Slot_E__Tag_BitOffset = 0 +const All_Slot_E__Tag_ByteSize = 1 +const All_Slot_E__Tag_ByteOffset = 0 +const All_Slot_E__Tag_ValueMask = 0x3 + +// AllValue is the logical type of a record. Immutable records are stored in +// nodes. +type AllValue struct { + E Expr // 1 + CE ConstExpr // 2 + BE BinExpr // 3 + BO BinOp // 4 + A AllOrExpr // 5 +} + +// R constructs a reference to an immutable record. +func (x AllValue) R(a *Allocator) All { + ref := a.new() + + ref.nums[0] = (ref.nums[0] &^ (All_Slot_E__Tag_ValueMask << All_Slot_E__Tag_BitOffset)) | (numvalslot(x.E.tag) << All_Slot_E__Tag_BitOffset) + ref.refs[0] = x.E.ref + ref.refs[1] = x.CE.ref + ref.refs[2] = x.BE.ref + ref.nums[0] = (ref.nums[0] &^ (All_Slot_BO_ValueMask << All_Slot_BO_BitOffset)) | (numvalslot(x.BO) << All_Slot_BO_BitOffset) + ref.nums[0] = (ref.nums[0] &^ (All_Slot_A__Tag_ValueMask << All_Slot_A__Tag_BitOffset)) | (numvalslot(x.A.tag) << All_Slot_A__Tag_BitOffset) + ref.refs[3] = x.A.ref + return All{ref} +} + +// E returns the E field. +func (x All) E() Expr { + return Expr{ExprTag((x.ref.nums[0] >> All_Slot_E__Tag_BitOffset) & All_Slot_E__Tag_ValueMask), x.ref.refs[0]} +} + +// CE returns the CE field. +func (x All) CE() ConstExpr { return ConstExpr{x.ref.refs[1]} } + +// BE returns the BE field. +func (x All) BE() BinExpr { return BinExpr{x.ref.refs[2]} } + +// BO returns the BO field. +func (x All) BO() BinOp { + return BinOp((x.ref.nums[0] >> All_Slot_BO_BitOffset) & All_Slot_BO_ValueMask) +} + +// A returns the A field. +func (x All) A() AllOrExpr { + return AllOrExpr{AllOrExprTag((x.ref.nums[0] >> All_Slot_A__Tag_BitOffset) & All_Slot_A__Tag_ValueMask), x.ref.refs[3]} +} + +// V unpacks a reference into a value. +func (x All) V() AllValue { + return AllValue{ + E: Expr{ExprTag((x.ref.nums[0] >> All_Slot_E__Tag_BitOffset) & All_Slot_E__Tag_ValueMask), x.ref.refs[0]}, + CE: ConstExpr{x.ref.refs[1]}, + BE: BinExpr{x.ref.refs[2]}, + BO: BinOp((x.ref.nums[0] >> All_Slot_BO_BitOffset) & All_Slot_BO_ValueMask), + A: AllOrExpr{AllOrExprTag((x.ref.nums[0] >> All_Slot_A__Tag_BitOffset) & All_Slot_A__Tag_ValueMask), x.ref.refs[3]}, + } +} + +// WithE constructs a new value where the value of E has been replaced by +// the argument. +func (x AllValue) WithE(y Expr) AllValue { + x.E = y + return x +} + +// WithCE constructs a new value where the value of CE has been replaced by +// the argument. +func (x AllValue) WithCE(y ConstExpr) AllValue { + x.CE = y + return x +} + +// WithBE constructs a new value where the value of BE has been replaced by +// the argument. +func (x AllValue) WithBE(y BinExpr) AllValue { + x.BE = y + return x +} + +// WithBO constructs a new value where the value of BO has been replaced by +// the argument. +func (x AllValue) WithBO(y BinOp) AllValue { + x.BO = y + return x +} + +// WithA constructs a new value where the value of A has been replaced by +// the argument. +func (x AllValue) WithA(y AllOrExpr) AllValue { + x.A = y + return x +} + +// ---- Expr ---- // + +// Expr is the type of a tagged union of records. +type Expr struct { + tag ExprTag + ref *node +} + +// ExprTag is the tag type. +type ExprTag enum + +// ExprTag constants. +const ( + ExprConstExpr ExprTag = 1 + ExprBinExpr ExprTag = 2 +) + +func (x ExprTag) String() string { + switch x { + case ExprConstExpr: + return "ConstExpr" + case ExprBinExpr: + return "BinExpr" + default: + return fmt.Sprintf("", x) + } +} + +// Tag returns the tag. +func (x Expr) Tag() ExprTag { return x.tag } + +// Expr performs an upcast. +func (x ConstExpr) Expr() Expr { return Expr{ExprConstExpr, x.ref} } + +// ConstExpr performs a downcast. If the downcast fails, return false. +func (x Expr) ConstExpr() (ConstExpr, bool) { + if x.tag != ExprConstExpr { + return ConstExpr{}, false + } + return ConstExpr{x.ref}, true +} + +// MustBeConstExpr performs a downcast. If the downcast fails, panic. +func (x Expr) MustBeConstExpr() ConstExpr { + if x.tag != ExprConstExpr { + panic(fmt.Sprintf("type assertion failed: expected ConstExpr but got %s", x.tag)) + } + return ConstExpr{x.ref} +} + +// Expr performs an upcast. +func (x BinExpr) Expr() Expr { return Expr{ExprBinExpr, x.ref} } + +// BinExpr performs a downcast. If the downcast fails, return false. +func (x Expr) BinExpr() (BinExpr, bool) { + if x.tag != ExprBinExpr { + return BinExpr{}, false + } + return BinExpr{x.ref}, true +} + +// MustBeBinExpr performs a downcast. If the downcast fails, panic. +func (x Expr) MustBeBinExpr() BinExpr { + if x.tag != ExprBinExpr { + panic(fmt.Sprintf("type assertion failed: expected BinExpr but got %s", x.tag)) + } + return BinExpr{x.ref} +} + +// ---- AllOrExpr ---- // + +// AllOrExpr is the type of a tagged union of records. +type AllOrExpr struct { + tag AllOrExprTag + ref *node +} + +// AllOrExprTag is the tag type. +type AllOrExprTag enum + +// AllOrExprTag constants. +const ( + AllOrExprAll AllOrExprTag = 1 + AllOrExprBinExpr AllOrExprTag = 2 +) + +func (x AllOrExprTag) String() string { + switch x { + case AllOrExprAll: + return "All" + case AllOrExprBinExpr: + return "BinExpr" + default: + return fmt.Sprintf("", x) + } +} + +// Tag returns the tag. +func (x AllOrExpr) Tag() AllOrExprTag { return x.tag } + +// AllOrExpr performs an upcast. +func (x All) AllOrExpr() AllOrExpr { return AllOrExpr{AllOrExprAll, x.ref} } + +// All performs a downcast. If the downcast fails, return false. +func (x AllOrExpr) All() (All, bool) { + if x.tag != AllOrExprAll { + return All{}, false + } + return All{x.ref}, true +} + +// MustBeAll performs a downcast. If the downcast fails, panic. +func (x AllOrExpr) MustBeAll() All { + if x.tag != AllOrExprAll { + panic(fmt.Sprintf("type assertion failed: expected All but got %s", x.tag)) + } + return All{x.ref} +} + +// AllOrExpr performs an upcast. +func (x BinExpr) AllOrExpr() AllOrExpr { return AllOrExpr{AllOrExprBinExpr, x.ref} } + +// BinExpr performs a downcast. If the downcast fails, return false. +func (x AllOrExpr) BinExpr() (BinExpr, bool) { + if x.tag != AllOrExprBinExpr { + return BinExpr{}, false + } + return BinExpr{x.ref}, true +} + +// MustBeBinExpr performs a downcast. If the downcast fails, panic. +func (x AllOrExpr) MustBeBinExpr() BinExpr { + if x.tag != AllOrExprBinExpr { + panic(fmt.Sprintf("type assertion failed: expected BinExpr but got %s", x.tag)) + } + return BinExpr{x.ref} +} + +// Codegen parameters: +// {NumNumericSlots:20 NumericSlotSize:64 NumRefSlots:20 NumStrSlots:20 Pack:true} +// diff --git a/pkg/sql/ir/tests/expandedpack/example/base/sexpr.ir.go b/pkg/sql/ir/tests/expandedpack/example/base/sexpr.ir.go new file mode 100644 index 000000000000..6b21020c84c5 --- /dev/null +++ b/pkg/sql/ir/tests/expandedpack/example/base/sexpr.ir.go @@ -0,0 +1,125 @@ +// Code generated by irgen/irgen base/sexpr.tmpl.go tests/example.def. DO NOT EDIT. +// GENERATED FILE DO NOT EDIT +// Copyright 2017 The Cockroach Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. + +package base + +import ( + "bytes" + "fmt" +) + +type SexprFormatter interface { + FormatSExpr(buf *bytes.Buffer) +} + +func FormatSExprBool(buf *bytes.Buffer, x bool) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt64(buf *bytes.Buffer, x int64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt32(buf *bytes.Buffer, x int32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt16(buf *bytes.Buffer, x int16) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt8(buf *bytes.Buffer, x int8) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint64(buf *bytes.Buffer, x uint64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint32(buf *bytes.Buffer, x uint32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint16(buf *bytes.Buffer, x uint16) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint8(buf *bytes.Buffer, x uint8) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprFloat32(buf *bytes.Buffer, x float32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprFloat64(buf *bytes.Buffer, x float64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprString(buf *bytes.Buffer, x string) { fmt.Fprintf(buf, "%q", x) } + +func (x BinOp) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString(x.String()) +} + +func (x ConstExpr) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(ConstExpr") + + buf.WriteString(" Datum: ") + FormatSExprInt64(buf, x.Datum()) + + buf.WriteByte(')') +} + +func (x BinExpr) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(BinExpr") + + buf.WriteString(" Left: ") + x.Left().FormatSExpr(buf) + + buf.WriteString(" Op: ") + x.Op().FormatSExpr(buf) + + buf.WriteString(" Right: ") + x.Right().FormatSExpr(buf) + + buf.WriteByte(')') +} + +func (x TriExpr) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(TriExpr") + + buf.WriteString(" One: ") + x.One().FormatSExpr(buf) + + buf.WriteString(" Two: ") + x.Two().FormatSExpr(buf) + + buf.WriteString(" Three: ") + x.Three().FormatSExpr(buf) + + buf.WriteByte(')') +} + +func (x All) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(All") + + buf.WriteString(" E: ") + x.E().FormatSExpr(buf) + + buf.WriteString(" CE: ") + x.CE().FormatSExpr(buf) + + buf.WriteString(" BE: ") + x.BE().FormatSExpr(buf) + + buf.WriteString(" BO: ") + x.BO().FormatSExpr(buf) + + buf.WriteString(" A: ") + x.A().FormatSExpr(buf) + + buf.WriteByte(')') +} + +func (x Expr) FormatSExpr(buf *bytes.Buffer) { + switch x.Tag() { + case ExprConstExpr: + x.MustBeConstExpr().FormatSExpr(buf) + case ExprBinExpr: + x.MustBeBinExpr().FormatSExpr(buf) + } +} + +func (x AllOrExpr) FormatSExpr(buf *bytes.Buffer) { + switch x.Tag() { + case AllOrExprAll: + x.MustBeAll().FormatSExpr(buf) + case AllOrExprBinExpr: + x.MustBeBinExpr().FormatSExpr(buf) + } +} + +// Codegen parameters: +// {NumNumericSlots:20 NumericSlotSize:64 NumRefSlots:20 NumStrSlots:20 Pack:true} +// diff --git a/pkg/sql/ir/tests/expandedpack/expandedpack_cfg_test.go b/pkg/sql/ir/tests/expandedpack/expandedpack_cfg_test.go new file mode 100644 index 000000000000..ed6251b71d6b --- /dev/null +++ b/pkg/sql/ir/tests/expandedpack/expandedpack_cfg_test.go @@ -0,0 +1,249 @@ +// Code generated by make. DO NOT EDIT. +// GENERATED FILE DO NOT EDIT +// Copyright 2017 The Cockroach Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. + +package expandedpack + +import ( + "bytes" + "fmt" + "reflect" + "strconv" + "strings" + "testing" + + d "github.com/cockroachdb/cockroach/pkg/sql/ir/tests/expandedpack/example/base" + p "github.com/cockroachdb/cockroach/pkg/sql/ir/tests/expandedpack/prims/base" +) + +func makeSampleExpr(a *d.Allocator) d.Expr { + c1 := d.ConstExprValue{Datum: 1}.R(a).Expr() + c2 := d.ConstExprValue{Datum: 2}.R(a).Expr() + c3 := d.ConstExprValue{Datum: 3}.R(a).Expr() + b4 := d.BinExprValue{Left: c1, Op: d.BinOpAdd, Right: c2}.R(a).Expr() + b5 := d.BinExprValue{Left: c3, Op: d.BinOpMul, Right: b4}.R(a).Expr() + return b5 +} + +func assertEq(t *testing.T, n int, val interface{}, exp interface{}) { + if !reflect.DeepEqual(val, exp) { + t.Errorf("equal failed %d: expected %v, got %v", n, exp, val) + } +} + +func TestExprValues(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + b5 := e.MustBeBinExpr() + assertEq(t, 1, b5.Op(), d.BinOpMul) + assertEq(t, 2, b5.Left().MustBeConstExpr().Datum(), int64(3)) + b4 := b5.Right().MustBeBinExpr() + assertEq(t, 3, b4.Op(), d.BinOpAdd) + assertEq(t, 4, b4.Left().MustBeConstExpr().Datum(), int64(1)) + assertEq(t, 5, b4.Right().MustBeConstExpr().Datum(), int64(2)) +} + +func format(ref d.Expr) string { + switch ref.Tag() { + case d.ExprConstExpr: + c := ref.MustBeConstExpr() + return strconv.FormatInt(c.Datum(), 10) + case d.ExprBinExpr: + b := ref.MustBeBinExpr() + var op string + switch b.Op() { + case d.BinOpAdd: + op = "+" + case d.BinOpMul: + op = "*" + default: + panic("unknown BinOp") + } + return fmt.Sprintf("(%s %s %s)", format(b.Left()), op, format(b.Right())) + default: + panic("unknown Expr tag") + } +} + +func TestExprFormatSExpr(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + + var buf bytes.Buffer + e.FormatSExpr(&buf) + if buf.String() != "(BinExpr Left: (ConstExpr Datum: 3) Op: Mul Right: (BinExpr Left: (ConstExpr Datum: 1) Op: Add Right: (ConstExpr Datum: 2)))" { + t.Fatalf("unexpected: %q", buf.String()) + } +} + +func TestFormat(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + const expected = "(3 * (1 + 2))" + if got := format(e); got != expected { + t.Fatalf("expected %q but got %q", expected, got) + } +} + +func reverse(ref d.Expr, a *d.Allocator) d.Expr { + if ref.Tag() != d.ExprBinExpr { + return ref + } + b := ref.MustBeBinExpr() + revLeft := reverse(b.Left(), a) + revRight := reverse(b.Right(), a) + return b.V().WithLeft(revRight).WithRight(revLeft).R(a).Expr() +} + +func TestReverse(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + const expected = "((2 + 1) * 3)" + if got := format(reverse(e, a)); got != expected { + t.Fatalf("expected %q but got %q", expected, got) + } +} + +func TestDoubleReverse(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + if got0, got2 := format(e), format(reverse(reverse(e, a), a)); got0 != got2 { + t.Fatalf("reverse is not an involution: %q != %q", got0, got2) + } +} + +func deepEqual(ref1 d.Expr, ref2 d.Expr) bool { + if ref1.Tag() != ref2.Tag() { + return false + } + switch ref1.Tag() { + case d.ExprConstExpr: + return ref1.MustBeConstExpr().Datum() == ref2.MustBeConstExpr().Datum() + case d.ExprBinExpr: + b1 := ref1.MustBeBinExpr() + b2 := ref2.MustBeBinExpr() + return b1.Op() == b2.Op() && + deepEqual(b1.Left(), b2.Left()) && deepEqual(b1.Right(), b2.Right()) + default: + panic("unknown Expr tag") + } +} + +func TestDeepEqual(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + if deepEqual(e, reverse(e, a)) { + t.Fatalf("expected expression not to be deepEqual to its reverse") + } + if !deepEqual(e, reverse(reverse(e, a), a)) { + t.Fatalf("expected expression to be deepEqual to the reverse of its reverse") + } +} + +func TestPrimValues(t *testing.T) { + a := p.NewAllocator() + all := p.AllValue{ + B: true, + I8: 'b', + U8: 'c', + I16: 0x1234, + U16: 0x4321, + I32: 0x12345678, + U32: 0x87654321, + I64: 0x123456789abcdef0, + U64: 0x0fedcba987654321, + S: "k", + F32: 1.234, + F64: 5.678, + }.R(a) + assertEq(t, 1, all.B(), true) + assertEq(t, 2, all.I8(), int8('b')) + assertEq(t, 3, all.U8(), uint8('c')) + assertEq(t, 4, all.I16(), int16(0x1234)) + assertEq(t, 5, all.U16(), uint16(0x4321)) + assertEq(t, 6, all.I32(), int32(0x12345678)) + assertEq(t, 7, all.U32(), uint32(0x87654321)) + assertEq(t, 8, all.I64(), int64(0x123456789abcdef0)) + assertEq(t, 9, all.U64(), uint64(0x0fedcba987654321)) + assertEq(t, 10, all.S(), "k") + assertEq(t, 11, all.F32(), float32(1.234)) + assertEq(t, 12, all.F64(), float64(5.678)) + + var buf bytes.Buffer + all.FormatSExpr(&buf) + assertEq(t, 100, buf.String(), strings.TrimSpace(` +(All B: true I8: 98 U8: 99 I16: 4660 U16: 17185 I32: 305419896 U32: 2271560481 I64: 1311768467463790320 U64: 1147797409030816545 S: "k" F32: 1.234 F64: 5.678) +`)) +} + +func TestPrimValues2(t *testing.T) { + a := p.NewAllocator() + v := p.SmallBeforeValue{ + A: true, + B: false, + C: 'c', + D: 'd', + E: 'e', + F: 0x1234, + G: 0x4321, + H: 0x12345678, + I: 0x123456789abcdef0, + }.R(a) + assertEq(t, 1, v.A(), true) + assertEq(t, 2, v.B(), false) + assertEq(t, 3, v.C(), uint8('c')) + assertEq(t, 4, v.D(), uint8('d')) + assertEq(t, 5, v.E(), uint8('e')) + assertEq(t, 6, v.F(), uint16(0x1234)) + assertEq(t, 7, v.G(), uint16(0x4321)) + assertEq(t, 8, v.H(), uint32(0x12345678)) + assertEq(t, 9, v.I(), uint64(0x123456789abcdef0)) + + var buf bytes.Buffer + v.FormatSExpr(&buf) + assertEq(t, 100, buf.String(), strings.TrimSpace(` +(SmallBefore A: true B: false C: 99 D: 100 E: 101 F: 4660 G: 17185 H: 305419896 I: 1311768467463790320) +`)) +} + +func TestPrimValues3(t *testing.T) { + a := p.NewAllocator() + v := p.BigBeforeValue{ + A: 0x123456789abcdef0, + B: 0x12345678, + C: 0x1234, + D: 0x4321, + E: 'e', + F: 'f', + G: 'g', + H: false, + I: true, + }.R(a) + assertEq(t, 1, v.A(), uint64(0x123456789abcdef0)) + assertEq(t, 2, v.B(), uint32(0x12345678)) + assertEq(t, 3, v.C(), uint16(0x1234)) + assertEq(t, 4, v.D(), uint16(0x4321)) + assertEq(t, 5, v.E(), uint8('e')) + assertEq(t, 6, v.F(), uint8('f')) + assertEq(t, 7, v.G(), uint8('g')) + assertEq(t, 8, v.H(), false) + assertEq(t, 9, v.I(), true) + + var buf bytes.Buffer + v.FormatSExpr(&buf) + assertEq(t, 100, buf.String(), strings.TrimSpace(` +(BigBefore A: 1311768467463790320 B: 305419896 C: 4660 D: 17185 E: 101 F: 102 G: 103 H: false I: true) +`)) +} diff --git a/pkg/sql/ir/tests/expandedpack/prims/base/base.ir.go b/pkg/sql/ir/tests/expandedpack/prims/base/base.ir.go new file mode 100644 index 000000000000..a3bb1ed88177 --- /dev/null +++ b/pkg/sql/ir/tests/expandedpack/prims/base/base.ir.go @@ -0,0 +1,838 @@ +// Code generated by irgen/irgen base/base.tmpl.go tests/prims.def. DO NOT EDIT. +// GENERATED FILE DO NOT EDIT +// Copyright 2017 The Cockroach Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. + +package base + +import "math" + +// node is a generic ADT node type, with slots for references to other nodes and +// enumeration values. Values that don't fit and values of other types go in the +// extra field. +type node struct { + refs [20]*node + nums [20]numvalslot + strs [20]string + extra +} + +// enum is the type to define the tag part for working copies of IR +// node with sum and enum types. +type enum uint32 + +// numvalslot is the type used to store integer values in persistent IR nodes. +// must be larger than or as large as enum. +type numvalslot uint64 + +type extra interface { + extraRefs() []*node +} + +// Allocator allocates nodes in batches. Construct Allocators with NewAllocator +// and pass them by value. +type Allocator struct { + nodes []node +} + +// MakeAllocator constructs a new Allocator. +func MakeAllocator() Allocator { + nodes := make([]node, 16) + return Allocator{nodes} +} + +// NewAllocator allocates a new Allocator. +func NewAllocator() *Allocator { + a := MakeAllocator() + return &a +} + +// new allocates a new node. Users of this package should use the appropriate +// R() method, which is type safe. +func (a *Allocator) new() *node { + nodes := a.nodes + if len(nodes) == 0 { + nodes = make([]node, 256) + } + x := &nodes[0] + a.nodes = nodes[1:] + return x +} + +// ---- All ---- // + +// All is the type of a reference to an immutable record. +type All struct{ ref *node } + +const All_Slot_B_Type = 1 +const All_Slot_B_Num = 5 +const All_Slot_B_BitSize = 1 +const All_Slot_B_BitOffset = 16 +const All_Slot_B_ByteSize = 1 +const All_Slot_B_ByteOffset = 2 +const All_Slot_B_ValueMask = 0x1 + +const All_Slot_F32_Type = 1 +const All_Slot_F32_Num = 4 +const All_Slot_F32_BitSize = 32 +const All_Slot_F32_BitOffset = 0 +const All_Slot_F32_ByteSize = 4 +const All_Slot_F32_ByteOffset = 0 +const All_Slot_F32_ValueMask = 0xffffffff + +const All_Slot_F64_Type = 1 +const All_Slot_F64_Num = 2 +const All_Slot_F64_BitSize = 64 +const All_Slot_F64_BitOffset = 0 +const All_Slot_F64_ByteSize = 8 +const All_Slot_F64_ByteOffset = 0 +const All_Slot_F64_ValueMask = 0xffffffffffffffff + +const All_Slot_I16_Type = 1 +const All_Slot_I16_Num = 4 +const All_Slot_I16_BitSize = 16 +const All_Slot_I16_BitOffset = 32 +const All_Slot_I16_ByteSize = 2 +const All_Slot_I16_ByteOffset = 4 +const All_Slot_I16_ValueMask = 0xffff + +const All_Slot_I32_Type = 1 +const All_Slot_I32_Num = 3 +const All_Slot_I32_BitSize = 32 +const All_Slot_I32_BitOffset = 0 +const All_Slot_I32_ByteSize = 4 +const All_Slot_I32_ByteOffset = 0 +const All_Slot_I32_ValueMask = 0xffffffff + +const All_Slot_I64_Type = 1 +const All_Slot_I64_Num = 0 +const All_Slot_I64_BitSize = 64 +const All_Slot_I64_BitOffset = 0 +const All_Slot_I64_ByteSize = 8 +const All_Slot_I64_ByteOffset = 0 +const All_Slot_I64_ValueMask = 0xffffffffffffffff + +const All_Slot_I8_Type = 1 +const All_Slot_I8_Num = 5 +const All_Slot_I8_BitSize = 8 +const All_Slot_I8_BitOffset = 0 +const All_Slot_I8_ByteSize = 1 +const All_Slot_I8_ByteOffset = 0 +const All_Slot_I8_ValueMask = 0xff + +const All_Slot_S_Type = 2 +const All_Slot_S_Num = 0 +const All_Slot_S_BitSize = -1 +const All_Slot_S_BitOffset = -1 +const All_Slot_S_ByteSize = -1 +const All_Slot_S_ByteOffset = -1 +const All_Slot_S_ValueMask = -1 + +const All_Slot_U16_Type = 1 +const All_Slot_U16_Num = 4 +const All_Slot_U16_BitSize = 16 +const All_Slot_U16_BitOffset = 48 +const All_Slot_U16_ByteSize = 2 +const All_Slot_U16_ByteOffset = 6 +const All_Slot_U16_ValueMask = 0xffff + +const All_Slot_U32_Type = 1 +const All_Slot_U32_Num = 3 +const All_Slot_U32_BitSize = 32 +const All_Slot_U32_BitOffset = 32 +const All_Slot_U32_ByteSize = 4 +const All_Slot_U32_ByteOffset = 4 +const All_Slot_U32_ValueMask = 0xffffffff + +const All_Slot_U64_Type = 1 +const All_Slot_U64_Num = 1 +const All_Slot_U64_BitSize = 64 +const All_Slot_U64_BitOffset = 0 +const All_Slot_U64_ByteSize = 8 +const All_Slot_U64_ByteOffset = 0 +const All_Slot_U64_ValueMask = 0xffffffffffffffff + +const All_Slot_U8_Type = 1 +const All_Slot_U8_Num = 5 +const All_Slot_U8_BitSize = 8 +const All_Slot_U8_BitOffset = 8 +const All_Slot_U8_ByteSize = 1 +const All_Slot_U8_ByteOffset = 1 +const All_Slot_U8_ValueMask = 0xff + +// AllValue is the logical type of a record. Immutable records are stored in +// nodes. +type AllValue struct { + B bool // 1 + I8 int8 // 2 + U8 uint8 // 3 + I16 int16 // 4 + U16 uint16 // 5 + I32 int32 // 6 + U32 uint32 // 7 + I64 int64 // 8 + U64 uint64 // 9 + S string // 10 + F32 float32 // 11 + F64 float64 // 12 +} + +// R constructs a reference to an immutable record. +func (x AllValue) R(a *Allocator) All { + ref := a.new() + + if x.B { + ref.nums[5] |= (numvalslot(1) << All_Slot_B_BitOffset) + } else { + ref.nums[5] &^= (numvalslot(1) << All_Slot_B_BitOffset) + } + ref.nums[5] = (ref.nums[5] &^ (All_Slot_I8_ValueMask << All_Slot_I8_BitOffset)) | (numvalslot(x.I8) << All_Slot_I8_BitOffset) + ref.nums[5] = (ref.nums[5] &^ (All_Slot_U8_ValueMask << All_Slot_U8_BitOffset)) | (numvalslot(x.U8) << All_Slot_U8_BitOffset) + ref.nums[4] = (ref.nums[4] &^ (All_Slot_I16_ValueMask << All_Slot_I16_BitOffset)) | (numvalslot(x.I16) << All_Slot_I16_BitOffset) + ref.nums[4] = (ref.nums[4] &^ (All_Slot_U16_ValueMask << All_Slot_U16_BitOffset)) | (numvalslot(x.U16) << All_Slot_U16_BitOffset) + ref.nums[3] = (ref.nums[3] &^ (All_Slot_I32_ValueMask << All_Slot_I32_BitOffset)) | (numvalslot(x.I32) << All_Slot_I32_BitOffset) + ref.nums[3] = (ref.nums[3] &^ (All_Slot_U32_ValueMask << All_Slot_U32_BitOffset)) | (numvalslot(x.U32) << All_Slot_U32_BitOffset) + ref.nums[0] = numvalslot(x.I64) + ref.nums[1] = numvalslot(x.U64) + ref.strs[0] = x.S + ref.nums[4] = (ref.nums[4] &^ (All_Slot_F32_ValueMask << All_Slot_F32_BitOffset)) | (numvalslot(math.Float32bits(x.F32)) << All_Slot_F32_BitOffset) + ref.nums[2] = numvalslot(math.Float64bits(x.F64)) + return All{ref} +} + +// B returns the B field. +func (x All) B() bool { return !(0 == (x.ref.nums[5] >> All_Slot_B_BitOffset & All_Slot_B_ValueMask)) } + +// I8 returns the I8 field. +func (x All) I8() int8 { return int8((x.ref.nums[5] >> All_Slot_I8_BitOffset) & All_Slot_I8_ValueMask) } + +// U8 returns the U8 field. +func (x All) U8() uint8 { + return uint8((x.ref.nums[5] >> All_Slot_U8_BitOffset) & All_Slot_U8_ValueMask) +} + +// I16 returns the I16 field. +func (x All) I16() int16 { + return int16((x.ref.nums[4] >> All_Slot_I16_BitOffset) & All_Slot_I16_ValueMask) +} + +// U16 returns the U16 field. +func (x All) U16() uint16 { + return uint16((x.ref.nums[4] >> All_Slot_U16_BitOffset) & All_Slot_U16_ValueMask) +} + +// I32 returns the I32 field. +func (x All) I32() int32 { + return int32((x.ref.nums[3] >> All_Slot_I32_BitOffset) & All_Slot_I32_ValueMask) +} + +// U32 returns the U32 field. +func (x All) U32() uint32 { + return uint32((x.ref.nums[3] >> All_Slot_U32_BitOffset) & All_Slot_U32_ValueMask) +} + +// I64 returns the I64 field. +func (x All) I64() int64 { return int64(x.ref.nums[0]) } + +// U64 returns the U64 field. +func (x All) U64() uint64 { return uint64(x.ref.nums[1]) } + +// S returns the S field. +func (x All) S() string { return x.ref.strs[0] } + +// F32 returns the F32 field. +func (x All) F32() float32 { + return math.Float32frombits(uint32((x.ref.nums[4] >> All_Slot_F32_BitOffset) & All_Slot_F32_ValueMask)) +} + +// F64 returns the F64 field. +func (x All) F64() float64 { return math.Float64frombits(uint64(x.ref.nums[2])) } + +// V unpacks a reference into a value. +func (x All) V() AllValue { + return AllValue{ + B: !(0 == (x.ref.nums[5] >> All_Slot_B_BitOffset & All_Slot_B_ValueMask)), + I8: int8((x.ref.nums[5] >> All_Slot_I8_BitOffset) & All_Slot_I8_ValueMask), + U8: uint8((x.ref.nums[5] >> All_Slot_U8_BitOffset) & All_Slot_U8_ValueMask), + I16: int16((x.ref.nums[4] >> All_Slot_I16_BitOffset) & All_Slot_I16_ValueMask), + U16: uint16((x.ref.nums[4] >> All_Slot_U16_BitOffset) & All_Slot_U16_ValueMask), + I32: int32((x.ref.nums[3] >> All_Slot_I32_BitOffset) & All_Slot_I32_ValueMask), + U32: uint32((x.ref.nums[3] >> All_Slot_U32_BitOffset) & All_Slot_U32_ValueMask), + I64: int64(x.ref.nums[0]), + U64: uint64(x.ref.nums[1]), + S: x.ref.strs[0], + F32: math.Float32frombits(uint32((x.ref.nums[4] >> All_Slot_F32_BitOffset) & All_Slot_F32_ValueMask)), + F64: math.Float64frombits(uint64(x.ref.nums[2])), + } +} + +// WithB constructs a new value where the value of B has been replaced by +// the argument. +func (x AllValue) WithB(y bool) AllValue { + x.B = y + return x +} + +// WithI8 constructs a new value where the value of I8 has been replaced by +// the argument. +func (x AllValue) WithI8(y int8) AllValue { + x.I8 = y + return x +} + +// WithU8 constructs a new value where the value of U8 has been replaced by +// the argument. +func (x AllValue) WithU8(y uint8) AllValue { + x.U8 = y + return x +} + +// WithI16 constructs a new value where the value of I16 has been replaced by +// the argument. +func (x AllValue) WithI16(y int16) AllValue { + x.I16 = y + return x +} + +// WithU16 constructs a new value where the value of U16 has been replaced by +// the argument. +func (x AllValue) WithU16(y uint16) AllValue { + x.U16 = y + return x +} + +// WithI32 constructs a new value where the value of I32 has been replaced by +// the argument. +func (x AllValue) WithI32(y int32) AllValue { + x.I32 = y + return x +} + +// WithU32 constructs a new value where the value of U32 has been replaced by +// the argument. +func (x AllValue) WithU32(y uint32) AllValue { + x.U32 = y + return x +} + +// WithI64 constructs a new value where the value of I64 has been replaced by +// the argument. +func (x AllValue) WithI64(y int64) AllValue { + x.I64 = y + return x +} + +// WithU64 constructs a new value where the value of U64 has been replaced by +// the argument. +func (x AllValue) WithU64(y uint64) AllValue { + x.U64 = y + return x +} + +// WithS constructs a new value where the value of S has been replaced by +// the argument. +func (x AllValue) WithS(y string) AllValue { + x.S = y + return x +} + +// WithF32 constructs a new value where the value of F32 has been replaced by +// the argument. +func (x AllValue) WithF32(y float32) AllValue { + x.F32 = y + return x +} + +// WithF64 constructs a new value where the value of F64 has been replaced by +// the argument. +func (x AllValue) WithF64(y float64) AllValue { + x.F64 = y + return x +} + +// ---- SmallBefore ---- // + +// SmallBefore is the type of a reference to an immutable record. +type SmallBefore struct{ ref *node } + +const SmallBefore_Slot_A_Type = 1 +const SmallBefore_Slot_A_Num = 2 +const SmallBefore_Slot_A_BitSize = 1 +const SmallBefore_Slot_A_BitOffset = 24 +const SmallBefore_Slot_A_ByteSize = 1 +const SmallBefore_Slot_A_ByteOffset = 3 +const SmallBefore_Slot_A_ValueMask = 0x1 + +const SmallBefore_Slot_B_Type = 1 +const SmallBefore_Slot_B_Num = 2 +const SmallBefore_Slot_B_BitSize = 1 +const SmallBefore_Slot_B_BitOffset = 25 +const SmallBefore_Slot_B_ByteSize = 1 +const SmallBefore_Slot_B_ByteOffset = 3 +const SmallBefore_Slot_B_ValueMask = 0x1 + +const SmallBefore_Slot_C_Type = 1 +const SmallBefore_Slot_C_Num = 2 +const SmallBefore_Slot_C_BitSize = 8 +const SmallBefore_Slot_C_BitOffset = 0 +const SmallBefore_Slot_C_ByteSize = 1 +const SmallBefore_Slot_C_ByteOffset = 0 +const SmallBefore_Slot_C_ValueMask = 0xff + +const SmallBefore_Slot_D_Type = 1 +const SmallBefore_Slot_D_Num = 2 +const SmallBefore_Slot_D_BitSize = 8 +const SmallBefore_Slot_D_BitOffset = 8 +const SmallBefore_Slot_D_ByteSize = 1 +const SmallBefore_Slot_D_ByteOffset = 1 +const SmallBefore_Slot_D_ValueMask = 0xff + +const SmallBefore_Slot_E_Type = 1 +const SmallBefore_Slot_E_Num = 2 +const SmallBefore_Slot_E_BitSize = 8 +const SmallBefore_Slot_E_BitOffset = 16 +const SmallBefore_Slot_E_ByteSize = 1 +const SmallBefore_Slot_E_ByteOffset = 2 +const SmallBefore_Slot_E_ValueMask = 0xff + +const SmallBefore_Slot_F_Type = 1 +const SmallBefore_Slot_F_Num = 1 +const SmallBefore_Slot_F_BitSize = 16 +const SmallBefore_Slot_F_BitOffset = 32 +const SmallBefore_Slot_F_ByteSize = 2 +const SmallBefore_Slot_F_ByteOffset = 4 +const SmallBefore_Slot_F_ValueMask = 0xffff + +const SmallBefore_Slot_G_Type = 1 +const SmallBefore_Slot_G_Num = 1 +const SmallBefore_Slot_G_BitSize = 16 +const SmallBefore_Slot_G_BitOffset = 48 +const SmallBefore_Slot_G_ByteSize = 2 +const SmallBefore_Slot_G_ByteOffset = 6 +const SmallBefore_Slot_G_ValueMask = 0xffff + +const SmallBefore_Slot_H_Type = 1 +const SmallBefore_Slot_H_Num = 1 +const SmallBefore_Slot_H_BitSize = 32 +const SmallBefore_Slot_H_BitOffset = 0 +const SmallBefore_Slot_H_ByteSize = 4 +const SmallBefore_Slot_H_ByteOffset = 0 +const SmallBefore_Slot_H_ValueMask = 0xffffffff + +const SmallBefore_Slot_I_Type = 1 +const SmallBefore_Slot_I_Num = 0 +const SmallBefore_Slot_I_BitSize = 64 +const SmallBefore_Slot_I_BitOffset = 0 +const SmallBefore_Slot_I_ByteSize = 8 +const SmallBefore_Slot_I_ByteOffset = 0 +const SmallBefore_Slot_I_ValueMask = 0xffffffffffffffff + +// SmallBeforeValue is the logical type of a record. Immutable records are stored in +// nodes. +type SmallBeforeValue struct { + A bool // 1 + B bool // 2 + C uint8 // 3 + D uint8 // 4 + E uint8 // 5 + F uint16 // 6 + G uint16 // 7 + H uint32 // 8 + I uint64 // 9 +} + +// R constructs a reference to an immutable record. +func (x SmallBeforeValue) R(a *Allocator) SmallBefore { + ref := a.new() + + if x.A { + ref.nums[2] |= (numvalslot(1) << SmallBefore_Slot_A_BitOffset) + } else { + ref.nums[2] &^= (numvalslot(1) << SmallBefore_Slot_A_BitOffset) + } + if x.B { + ref.nums[2] |= (numvalslot(1) << SmallBefore_Slot_B_BitOffset) + } else { + ref.nums[2] &^= (numvalslot(1) << SmallBefore_Slot_B_BitOffset) + } + ref.nums[2] = (ref.nums[2] &^ (SmallBefore_Slot_C_ValueMask << SmallBefore_Slot_C_BitOffset)) | (numvalslot(x.C) << SmallBefore_Slot_C_BitOffset) + ref.nums[2] = (ref.nums[2] &^ (SmallBefore_Slot_D_ValueMask << SmallBefore_Slot_D_BitOffset)) | (numvalslot(x.D) << SmallBefore_Slot_D_BitOffset) + ref.nums[2] = (ref.nums[2] &^ (SmallBefore_Slot_E_ValueMask << SmallBefore_Slot_E_BitOffset)) | (numvalslot(x.E) << SmallBefore_Slot_E_BitOffset) + ref.nums[1] = (ref.nums[1] &^ (SmallBefore_Slot_F_ValueMask << SmallBefore_Slot_F_BitOffset)) | (numvalslot(x.F) << SmallBefore_Slot_F_BitOffset) + ref.nums[1] = (ref.nums[1] &^ (SmallBefore_Slot_G_ValueMask << SmallBefore_Slot_G_BitOffset)) | (numvalslot(x.G) << SmallBefore_Slot_G_BitOffset) + ref.nums[1] = (ref.nums[1] &^ (SmallBefore_Slot_H_ValueMask << SmallBefore_Slot_H_BitOffset)) | (numvalslot(x.H) << SmallBefore_Slot_H_BitOffset) + ref.nums[0] = numvalslot(x.I) + return SmallBefore{ref} +} + +// A returns the A field. +func (x SmallBefore) A() bool { + return !(0 == (x.ref.nums[2] >> SmallBefore_Slot_A_BitOffset & SmallBefore_Slot_A_ValueMask)) +} + +// B returns the B field. +func (x SmallBefore) B() bool { + return !(0 == (x.ref.nums[2] >> SmallBefore_Slot_B_BitOffset & SmallBefore_Slot_B_ValueMask)) +} + +// C returns the C field. +func (x SmallBefore) C() uint8 { + return uint8((x.ref.nums[2] >> SmallBefore_Slot_C_BitOffset) & SmallBefore_Slot_C_ValueMask) +} + +// D returns the D field. +func (x SmallBefore) D() uint8 { + return uint8((x.ref.nums[2] >> SmallBefore_Slot_D_BitOffset) & SmallBefore_Slot_D_ValueMask) +} + +// E returns the E field. +func (x SmallBefore) E() uint8 { + return uint8((x.ref.nums[2] >> SmallBefore_Slot_E_BitOffset) & SmallBefore_Slot_E_ValueMask) +} + +// F returns the F field. +func (x SmallBefore) F() uint16 { + return uint16((x.ref.nums[1] >> SmallBefore_Slot_F_BitOffset) & SmallBefore_Slot_F_ValueMask) +} + +// G returns the G field. +func (x SmallBefore) G() uint16 { + return uint16((x.ref.nums[1] >> SmallBefore_Slot_G_BitOffset) & SmallBefore_Slot_G_ValueMask) +} + +// H returns the H field. +func (x SmallBefore) H() uint32 { + return uint32((x.ref.nums[1] >> SmallBefore_Slot_H_BitOffset) & SmallBefore_Slot_H_ValueMask) +} + +// I returns the I field. +func (x SmallBefore) I() uint64 { return uint64(x.ref.nums[0]) } + +// V unpacks a reference into a value. +func (x SmallBefore) V() SmallBeforeValue { + return SmallBeforeValue{ + A: !(0 == (x.ref.nums[2] >> SmallBefore_Slot_A_BitOffset & SmallBefore_Slot_A_ValueMask)), + B: !(0 == (x.ref.nums[2] >> SmallBefore_Slot_B_BitOffset & SmallBefore_Slot_B_ValueMask)), + C: uint8((x.ref.nums[2] >> SmallBefore_Slot_C_BitOffset) & SmallBefore_Slot_C_ValueMask), + D: uint8((x.ref.nums[2] >> SmallBefore_Slot_D_BitOffset) & SmallBefore_Slot_D_ValueMask), + E: uint8((x.ref.nums[2] >> SmallBefore_Slot_E_BitOffset) & SmallBefore_Slot_E_ValueMask), + F: uint16((x.ref.nums[1] >> SmallBefore_Slot_F_BitOffset) & SmallBefore_Slot_F_ValueMask), + G: uint16((x.ref.nums[1] >> SmallBefore_Slot_G_BitOffset) & SmallBefore_Slot_G_ValueMask), + H: uint32((x.ref.nums[1] >> SmallBefore_Slot_H_BitOffset) & SmallBefore_Slot_H_ValueMask), + I: uint64(x.ref.nums[0]), + } +} + +// WithA constructs a new value where the value of A has been replaced by +// the argument. +func (x SmallBeforeValue) WithA(y bool) SmallBeforeValue { + x.A = y + return x +} + +// WithB constructs a new value where the value of B has been replaced by +// the argument. +func (x SmallBeforeValue) WithB(y bool) SmallBeforeValue { + x.B = y + return x +} + +// WithC constructs a new value where the value of C has been replaced by +// the argument. +func (x SmallBeforeValue) WithC(y uint8) SmallBeforeValue { + x.C = y + return x +} + +// WithD constructs a new value where the value of D has been replaced by +// the argument. +func (x SmallBeforeValue) WithD(y uint8) SmallBeforeValue { + x.D = y + return x +} + +// WithE constructs a new value where the value of E has been replaced by +// the argument. +func (x SmallBeforeValue) WithE(y uint8) SmallBeforeValue { + x.E = y + return x +} + +// WithF constructs a new value where the value of F has been replaced by +// the argument. +func (x SmallBeforeValue) WithF(y uint16) SmallBeforeValue { + x.F = y + return x +} + +// WithG constructs a new value where the value of G has been replaced by +// the argument. +func (x SmallBeforeValue) WithG(y uint16) SmallBeforeValue { + x.G = y + return x +} + +// WithH constructs a new value where the value of H has been replaced by +// the argument. +func (x SmallBeforeValue) WithH(y uint32) SmallBeforeValue { + x.H = y + return x +} + +// WithI constructs a new value where the value of I has been replaced by +// the argument. +func (x SmallBeforeValue) WithI(y uint64) SmallBeforeValue { + x.I = y + return x +} + +// ---- BigBefore ---- // + +// BigBefore is the type of a reference to an immutable record. +type BigBefore struct{ ref *node } + +const BigBefore_Slot_A_Type = 1 +const BigBefore_Slot_A_Num = 0 +const BigBefore_Slot_A_BitSize = 64 +const BigBefore_Slot_A_BitOffset = 0 +const BigBefore_Slot_A_ByteSize = 8 +const BigBefore_Slot_A_ByteOffset = 0 +const BigBefore_Slot_A_ValueMask = 0xffffffffffffffff + +const BigBefore_Slot_B_Type = 1 +const BigBefore_Slot_B_Num = 1 +const BigBefore_Slot_B_BitSize = 32 +const BigBefore_Slot_B_BitOffset = 0 +const BigBefore_Slot_B_ByteSize = 4 +const BigBefore_Slot_B_ByteOffset = 0 +const BigBefore_Slot_B_ValueMask = 0xffffffff + +const BigBefore_Slot_C_Type = 1 +const BigBefore_Slot_C_Num = 1 +const BigBefore_Slot_C_BitSize = 16 +const BigBefore_Slot_C_BitOffset = 32 +const BigBefore_Slot_C_ByteSize = 2 +const BigBefore_Slot_C_ByteOffset = 4 +const BigBefore_Slot_C_ValueMask = 0xffff + +const BigBefore_Slot_D_Type = 1 +const BigBefore_Slot_D_Num = 1 +const BigBefore_Slot_D_BitSize = 16 +const BigBefore_Slot_D_BitOffset = 48 +const BigBefore_Slot_D_ByteSize = 2 +const BigBefore_Slot_D_ByteOffset = 6 +const BigBefore_Slot_D_ValueMask = 0xffff + +const BigBefore_Slot_E_Type = 1 +const BigBefore_Slot_E_Num = 2 +const BigBefore_Slot_E_BitSize = 8 +const BigBefore_Slot_E_BitOffset = 0 +const BigBefore_Slot_E_ByteSize = 1 +const BigBefore_Slot_E_ByteOffset = 0 +const BigBefore_Slot_E_ValueMask = 0xff + +const BigBefore_Slot_F_Type = 1 +const BigBefore_Slot_F_Num = 2 +const BigBefore_Slot_F_BitSize = 8 +const BigBefore_Slot_F_BitOffset = 8 +const BigBefore_Slot_F_ByteSize = 1 +const BigBefore_Slot_F_ByteOffset = 1 +const BigBefore_Slot_F_ValueMask = 0xff + +const BigBefore_Slot_G_Type = 1 +const BigBefore_Slot_G_Num = 2 +const BigBefore_Slot_G_BitSize = 8 +const BigBefore_Slot_G_BitOffset = 16 +const BigBefore_Slot_G_ByteSize = 1 +const BigBefore_Slot_G_ByteOffset = 2 +const BigBefore_Slot_G_ValueMask = 0xff + +const BigBefore_Slot_H_Type = 1 +const BigBefore_Slot_H_Num = 2 +const BigBefore_Slot_H_BitSize = 1 +const BigBefore_Slot_H_BitOffset = 24 +const BigBefore_Slot_H_ByteSize = 1 +const BigBefore_Slot_H_ByteOffset = 3 +const BigBefore_Slot_H_ValueMask = 0x1 + +const BigBefore_Slot_I_Type = 1 +const BigBefore_Slot_I_Num = 2 +const BigBefore_Slot_I_BitSize = 1 +const BigBefore_Slot_I_BitOffset = 25 +const BigBefore_Slot_I_ByteSize = 1 +const BigBefore_Slot_I_ByteOffset = 3 +const BigBefore_Slot_I_ValueMask = 0x1 + +// BigBeforeValue is the logical type of a record. Immutable records are stored in +// nodes. +type BigBeforeValue struct { + A uint64 // 1 + B uint32 // 2 + C uint16 // 3 + D uint16 // 4 + E uint8 // 5 + F uint8 // 6 + G uint8 // 7 + H bool // 8 + I bool // 9 +} + +// R constructs a reference to an immutable record. +func (x BigBeforeValue) R(a *Allocator) BigBefore { + ref := a.new() + + ref.nums[0] = numvalslot(x.A) + ref.nums[1] = (ref.nums[1] &^ (BigBefore_Slot_B_ValueMask << BigBefore_Slot_B_BitOffset)) | (numvalslot(x.B) << BigBefore_Slot_B_BitOffset) + ref.nums[1] = (ref.nums[1] &^ (BigBefore_Slot_C_ValueMask << BigBefore_Slot_C_BitOffset)) | (numvalslot(x.C) << BigBefore_Slot_C_BitOffset) + ref.nums[1] = (ref.nums[1] &^ (BigBefore_Slot_D_ValueMask << BigBefore_Slot_D_BitOffset)) | (numvalslot(x.D) << BigBefore_Slot_D_BitOffset) + ref.nums[2] = (ref.nums[2] &^ (BigBefore_Slot_E_ValueMask << BigBefore_Slot_E_BitOffset)) | (numvalslot(x.E) << BigBefore_Slot_E_BitOffset) + ref.nums[2] = (ref.nums[2] &^ (BigBefore_Slot_F_ValueMask << BigBefore_Slot_F_BitOffset)) | (numvalslot(x.F) << BigBefore_Slot_F_BitOffset) + ref.nums[2] = (ref.nums[2] &^ (BigBefore_Slot_G_ValueMask << BigBefore_Slot_G_BitOffset)) | (numvalslot(x.G) << BigBefore_Slot_G_BitOffset) + if x.H { + ref.nums[2] |= (numvalslot(1) << BigBefore_Slot_H_BitOffset) + } else { + ref.nums[2] &^= (numvalslot(1) << BigBefore_Slot_H_BitOffset) + } + if x.I { + ref.nums[2] |= (numvalslot(1) << BigBefore_Slot_I_BitOffset) + } else { + ref.nums[2] &^= (numvalslot(1) << BigBefore_Slot_I_BitOffset) + } + return BigBefore{ref} +} + +// A returns the A field. +func (x BigBefore) A() uint64 { return uint64(x.ref.nums[0]) } + +// B returns the B field. +func (x BigBefore) B() uint32 { + return uint32((x.ref.nums[1] >> BigBefore_Slot_B_BitOffset) & BigBefore_Slot_B_ValueMask) +} + +// C returns the C field. +func (x BigBefore) C() uint16 { + return uint16((x.ref.nums[1] >> BigBefore_Slot_C_BitOffset) & BigBefore_Slot_C_ValueMask) +} + +// D returns the D field. +func (x BigBefore) D() uint16 { + return uint16((x.ref.nums[1] >> BigBefore_Slot_D_BitOffset) & BigBefore_Slot_D_ValueMask) +} + +// E returns the E field. +func (x BigBefore) E() uint8 { + return uint8((x.ref.nums[2] >> BigBefore_Slot_E_BitOffset) & BigBefore_Slot_E_ValueMask) +} + +// F returns the F field. +func (x BigBefore) F() uint8 { + return uint8((x.ref.nums[2] >> BigBefore_Slot_F_BitOffset) & BigBefore_Slot_F_ValueMask) +} + +// G returns the G field. +func (x BigBefore) G() uint8 { + return uint8((x.ref.nums[2] >> BigBefore_Slot_G_BitOffset) & BigBefore_Slot_G_ValueMask) +} + +// H returns the H field. +func (x BigBefore) H() bool { + return !(0 == (x.ref.nums[2] >> BigBefore_Slot_H_BitOffset & BigBefore_Slot_H_ValueMask)) +} + +// I returns the I field. +func (x BigBefore) I() bool { + return !(0 == (x.ref.nums[2] >> BigBefore_Slot_I_BitOffset & BigBefore_Slot_I_ValueMask)) +} + +// V unpacks a reference into a value. +func (x BigBefore) V() BigBeforeValue { + return BigBeforeValue{ + A: uint64(x.ref.nums[0]), + B: uint32((x.ref.nums[1] >> BigBefore_Slot_B_BitOffset) & BigBefore_Slot_B_ValueMask), + C: uint16((x.ref.nums[1] >> BigBefore_Slot_C_BitOffset) & BigBefore_Slot_C_ValueMask), + D: uint16((x.ref.nums[1] >> BigBefore_Slot_D_BitOffset) & BigBefore_Slot_D_ValueMask), + E: uint8((x.ref.nums[2] >> BigBefore_Slot_E_BitOffset) & BigBefore_Slot_E_ValueMask), + F: uint8((x.ref.nums[2] >> BigBefore_Slot_F_BitOffset) & BigBefore_Slot_F_ValueMask), + G: uint8((x.ref.nums[2] >> BigBefore_Slot_G_BitOffset) & BigBefore_Slot_G_ValueMask), + H: !(0 == (x.ref.nums[2] >> BigBefore_Slot_H_BitOffset & BigBefore_Slot_H_ValueMask)), + I: !(0 == (x.ref.nums[2] >> BigBefore_Slot_I_BitOffset & BigBefore_Slot_I_ValueMask)), + } +} + +// WithA constructs a new value where the value of A has been replaced by +// the argument. +func (x BigBeforeValue) WithA(y uint64) BigBeforeValue { + x.A = y + return x +} + +// WithB constructs a new value where the value of B has been replaced by +// the argument. +func (x BigBeforeValue) WithB(y uint32) BigBeforeValue { + x.B = y + return x +} + +// WithC constructs a new value where the value of C has been replaced by +// the argument. +func (x BigBeforeValue) WithC(y uint16) BigBeforeValue { + x.C = y + return x +} + +// WithD constructs a new value where the value of D has been replaced by +// the argument. +func (x BigBeforeValue) WithD(y uint16) BigBeforeValue { + x.D = y + return x +} + +// WithE constructs a new value where the value of E has been replaced by +// the argument. +func (x BigBeforeValue) WithE(y uint8) BigBeforeValue { + x.E = y + return x +} + +// WithF constructs a new value where the value of F has been replaced by +// the argument. +func (x BigBeforeValue) WithF(y uint8) BigBeforeValue { + x.F = y + return x +} + +// WithG constructs a new value where the value of G has been replaced by +// the argument. +func (x BigBeforeValue) WithG(y uint8) BigBeforeValue { + x.G = y + return x +} + +// WithH constructs a new value where the value of H has been replaced by +// the argument. +func (x BigBeforeValue) WithH(y bool) BigBeforeValue { + x.H = y + return x +} + +// WithI constructs a new value where the value of I has been replaced by +// the argument. +func (x BigBeforeValue) WithI(y bool) BigBeforeValue { + x.I = y + return x +} + +// Codegen parameters: +// {NumNumericSlots:20 NumericSlotSize:64 NumRefSlots:20 NumStrSlots:20 Pack:true} +// diff --git a/pkg/sql/ir/tests/expandedpack/prims/base/sexpr.ir.go b/pkg/sql/ir/tests/expandedpack/prims/base/sexpr.ir.go new file mode 100644 index 000000000000..7548aabfc698 --- /dev/null +++ b/pkg/sql/ir/tests/expandedpack/prims/base/sexpr.ir.go @@ -0,0 +1,151 @@ +// Code generated by irgen/irgen base/sexpr.tmpl.go tests/prims.def. DO NOT EDIT. +// GENERATED FILE DO NOT EDIT +// Copyright 2017 The Cockroach Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. + +package base + +import ( + "bytes" + "fmt" +) + +type SexprFormatter interface { + FormatSExpr(buf *bytes.Buffer) +} + +func FormatSExprBool(buf *bytes.Buffer, x bool) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt64(buf *bytes.Buffer, x int64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt32(buf *bytes.Buffer, x int32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt16(buf *bytes.Buffer, x int16) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt8(buf *bytes.Buffer, x int8) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint64(buf *bytes.Buffer, x uint64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint32(buf *bytes.Buffer, x uint32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint16(buf *bytes.Buffer, x uint16) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint8(buf *bytes.Buffer, x uint8) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprFloat32(buf *bytes.Buffer, x float32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprFloat64(buf *bytes.Buffer, x float64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprString(buf *bytes.Buffer, x string) { fmt.Fprintf(buf, "%q", x) } + +func (x All) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(All") + + buf.WriteString(" B: ") + FormatSExprBool(buf, x.B()) + + buf.WriteString(" I8: ") + FormatSExprInt8(buf, x.I8()) + + buf.WriteString(" U8: ") + FormatSExprUint8(buf, x.U8()) + + buf.WriteString(" I16: ") + FormatSExprInt16(buf, x.I16()) + + buf.WriteString(" U16: ") + FormatSExprUint16(buf, x.U16()) + + buf.WriteString(" I32: ") + FormatSExprInt32(buf, x.I32()) + + buf.WriteString(" U32: ") + FormatSExprUint32(buf, x.U32()) + + buf.WriteString(" I64: ") + FormatSExprInt64(buf, x.I64()) + + buf.WriteString(" U64: ") + FormatSExprUint64(buf, x.U64()) + + buf.WriteString(" S: ") + FormatSExprString(buf, x.S()) + + buf.WriteString(" F32: ") + FormatSExprFloat32(buf, x.F32()) + + buf.WriteString(" F64: ") + FormatSExprFloat64(buf, x.F64()) + + buf.WriteByte(')') +} + +func (x SmallBefore) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(SmallBefore") + + buf.WriteString(" A: ") + FormatSExprBool(buf, x.A()) + + buf.WriteString(" B: ") + FormatSExprBool(buf, x.B()) + + buf.WriteString(" C: ") + FormatSExprUint8(buf, x.C()) + + buf.WriteString(" D: ") + FormatSExprUint8(buf, x.D()) + + buf.WriteString(" E: ") + FormatSExprUint8(buf, x.E()) + + buf.WriteString(" F: ") + FormatSExprUint16(buf, x.F()) + + buf.WriteString(" G: ") + FormatSExprUint16(buf, x.G()) + + buf.WriteString(" H: ") + FormatSExprUint32(buf, x.H()) + + buf.WriteString(" I: ") + FormatSExprUint64(buf, x.I()) + + buf.WriteByte(')') +} + +func (x BigBefore) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(BigBefore") + + buf.WriteString(" A: ") + FormatSExprUint64(buf, x.A()) + + buf.WriteString(" B: ") + FormatSExprUint32(buf, x.B()) + + buf.WriteString(" C: ") + FormatSExprUint16(buf, x.C()) + + buf.WriteString(" D: ") + FormatSExprUint16(buf, x.D()) + + buf.WriteString(" E: ") + FormatSExprUint8(buf, x.E()) + + buf.WriteString(" F: ") + FormatSExprUint8(buf, x.F()) + + buf.WriteString(" G: ") + FormatSExprUint8(buf, x.G()) + + buf.WriteString(" H: ") + FormatSExprBool(buf, x.H()) + + buf.WriteString(" I: ") + FormatSExprBool(buf, x.I()) + + buf.WriteByte(')') +} + +// Codegen parameters: +// {NumNumericSlots:20 NumericSlotSize:64 NumRefSlots:20 NumStrSlots:20 Pack:true} +// diff --git a/pkg/sql/ir/irgen_test.go b/pkg/sql/ir/tests/irgen_test.go similarity index 51% rename from pkg/sql/ir/irgen_test.go rename to pkg/sql/ir/tests/irgen_test.go index 9b64895f0078..ec3f41da07aa 100644 --- a/pkg/sql/ir/irgen_test.go +++ b/pkg/sql/ir/tests/irgen_test.go @@ -17,10 +17,13 @@ package main import ( "bytes" "fmt" + "reflect" "strconv" + "strings" "testing" - d "github.com/cockroachdb/cockroach/pkg/sql/ir/example/base" + d "github.com/cockroachdb/cockroach/pkg/sql/ir/tests/defcfg/example/base" + p "github.com/cockroachdb/cockroach/pkg/sql/ir/tests/defcfg/prims/base" ) func makeSampleExpr(a *d.Allocator) d.Expr { @@ -32,6 +35,24 @@ func makeSampleExpr(a *d.Allocator) d.Expr { return b5 } +func assertEq(t *testing.T, n int, val interface{}, exp interface{}) { + if !reflect.DeepEqual(val, exp) { + t.Errorf("equal failed %d: expected %v, got %v", n, exp, val) + } +} + +func TestExprValues(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + b5 := e.MustBeBinExpr() + assertEq(t, 1, b5.Op(), d.BinOpMul) + assertEq(t, 2, b5.Left().MustBeConstExpr().Datum(), int64(3)) + b4 := b5.Right().MustBeBinExpr() + assertEq(t, 3, b4.Op(), d.BinOpAdd) + assertEq(t, 4, b4.Left().MustBeConstExpr().Datum(), int64(1)) + assertEq(t, 5, b4.Right().MustBeConstExpr().Datum(), int64(2)) +} + func format(ref d.Expr) string { switch ref.Tag() { case d.ExprConstExpr: @@ -128,3 +149,99 @@ func TestDeepEqual(t *testing.T) { t.Fatalf("expected expression to be deepEqual to the reverse of its reverse") } } + +func TestPrimValues(t *testing.T) { + a := p.NewAllocator() + all := p.AllValue{ + B: true, + I8: 'b', + U8: 'c', + I16: 0x1234, + U16: 0x4321, + I32: 0x12345678, + U32: 0x87654321, + I64: 0x123456789abcdef0, + U64: 0x0fedcba987654321, + S: "k", + F32: 1.234, + F64: 5.678, + }.R(a) + assertEq(t, 1, all.B(), true) + assertEq(t, 2, all.I8(), int8('b')) + assertEq(t, 3, all.U8(), uint8('c')) + assertEq(t, 4, all.I16(), int16(0x1234)) + assertEq(t, 5, all.U16(), uint16(0x4321)) + assertEq(t, 6, all.I32(), int32(0x12345678)) + assertEq(t, 7, all.U32(), uint32(0x87654321)) + assertEq(t, 8, all.I64(), int64(0x123456789abcdef0)) + assertEq(t, 9, all.U64(), uint64(0x0fedcba987654321)) + assertEq(t, 10, all.S(), "k") + assertEq(t, 11, all.F32(), float32(1.234)) + assertEq(t, 12, all.F64(), float64(5.678)) + + var buf bytes.Buffer + all.FormatSExpr(&buf) + assertEq(t, 100, buf.String(), strings.TrimSpace(` +(All B: true I8: 98 U8: 99 I16: 4660 U16: 17185 I32: 305419896 U32: 2271560481 I64: 1311768467463790320 U64: 1147797409030816545 S: "k" F32: 1.234 F64: 5.678) +`)) +} + +func TestPrimValues2(t *testing.T) { + a := p.NewAllocator() + v := p.SmallBeforeValue{ + A: true, + B: false, + C: 'c', + D: 'd', + E: 'e', + F: 0x1234, + G: 0x4321, + H: 0x12345678, + I: 0x123456789abcdef0, + }.R(a) + assertEq(t, 1, v.A(), true) + assertEq(t, 2, v.B(), false) + assertEq(t, 3, v.C(), uint8('c')) + assertEq(t, 4, v.D(), uint8('d')) + assertEq(t, 5, v.E(), uint8('e')) + assertEq(t, 6, v.F(), uint16(0x1234)) + assertEq(t, 7, v.G(), uint16(0x4321)) + assertEq(t, 8, v.H(), uint32(0x12345678)) + assertEq(t, 9, v.I(), uint64(0x123456789abcdef0)) + + var buf bytes.Buffer + v.FormatSExpr(&buf) + assertEq(t, 100, buf.String(), strings.TrimSpace(` +(SmallBefore A: true B: false C: 99 D: 100 E: 101 F: 4660 G: 17185 H: 305419896 I: 1311768467463790320) +`)) +} + +func TestPrimValues3(t *testing.T) { + a := p.NewAllocator() + v := p.BigBeforeValue{ + A: 0x123456789abcdef0, + B: 0x12345678, + C: 0x1234, + D: 0x4321, + E: 'e', + F: 'f', + G: 'g', + H: false, + I: true, + }.R(a) + assertEq(t, 1, v.A(), uint64(0x123456789abcdef0)) + assertEq(t, 2, v.B(), uint32(0x12345678)) + assertEq(t, 3, v.C(), uint16(0x1234)) + assertEq(t, 4, v.D(), uint16(0x4321)) + assertEq(t, 5, v.E(), uint8('e')) + assertEq(t, 6, v.F(), uint8('f')) + assertEq(t, 7, v.G(), uint8('g')) + assertEq(t, 8, v.H(), false) + assertEq(t, 9, v.I(), true) + + var buf bytes.Buffer + v.FormatSExpr(&buf) + assertEq(t, 100, buf.String(), strings.TrimSpace(` +(BigBefore A: 1311768467463790320 B: 305419896 C: 4660 D: 17185 E: 101 F: 102 G: 103 H: false I: true) +`)) +} diff --git a/pkg/sql/ir/tests/nopack/example/base/base.ir.go b/pkg/sql/ir/tests/nopack/example/base/base.ir.go new file mode 100644 index 000000000000..36c6a10bf87b --- /dev/null +++ b/pkg/sql/ir/tests/nopack/example/base/base.ir.go @@ -0,0 +1,650 @@ +// Code generated by irgen/irgen base/base.tmpl.go tests/example.def. DO NOT EDIT. +// GENERATED FILE DO NOT EDIT +// Copyright 2017 The Cockroach Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. + +package base + +import ( + "fmt" +) + +// node is a generic ADT node type, with slots for references to other nodes and +// enumeration values. Values that don't fit and values of other types go in the +// extra field. +type node struct { + refs [2]*node + nums [2]numvalslot + strs [1]string + extra +} + +// enum is the type to define the tag part for working copies of IR +// node with sum and enum types. +type enum uint32 + +// numvalslot is the type used to store integer values in persistent IR nodes. +// must be larger than or as large as enum. +type numvalslot uint64 + +type extra interface { + extraRefs() []*node +} + +// Allocator allocates nodes in batches. Construct Allocators with NewAllocator +// and pass them by value. +type Allocator struct { + nodes []node +} + +// MakeAllocator constructs a new Allocator. +func MakeAllocator() Allocator { + nodes := make([]node, 16) + return Allocator{nodes} +} + +// NewAllocator allocates a new Allocator. +func NewAllocator() *Allocator { + a := MakeAllocator() + return &a +} + +// new allocates a new node. Users of this package should use the appropriate +// R() method, which is type safe. +func (a *Allocator) new() *node { + nodes := a.nodes + if len(nodes) == 0 { + nodes = make([]node, 256) + } + x := &nodes[0] + a.nodes = nodes[1:] + return x +} + +// ---- BinOp ---- // + +// BinOp is an enumeration type. +type BinOp enum + +// BinOp constants. +const ( + BinOpAdd BinOp = 1 + BinOpMul BinOp = 2 +) + +func (x BinOp) String() string { + switch x { + case BinOpAdd: + return "Add" + case BinOpMul: + return "Mul" + default: + return fmt.Sprintf("", x) + } +} + +// ---- ConstExpr ---- // + +// ConstExpr is the type of a reference to an immutable record. +type ConstExpr struct{ ref *node } + +const ConstExpr_Slot_Datum_Type = 1 +const ConstExpr_Slot_Datum_Num = 0 +const ConstExpr_Slot_Datum_BitSize = 64 +const ConstExpr_Slot_Datum_BitOffset = 0 +const ConstExpr_Slot_Datum_ByteSize = 8 +const ConstExpr_Slot_Datum_ByteOffset = 0 +const ConstExpr_Slot_Datum_ValueMask = 0xffffffffffffffff + +// ConstExprValue is the logical type of a record. Immutable records are stored in +// nodes. +type ConstExprValue struct { + Datum int64 // 1 +} + +// R constructs a reference to an immutable record. +func (x ConstExprValue) R(a *Allocator) ConstExpr { + ref := a.new() + + ref.nums[0] = numvalslot(x.Datum) + return ConstExpr{ref} +} + +// Datum returns the Datum field. +func (x ConstExpr) Datum() int64 { return int64(x.ref.nums[0]) } + +// V unpacks a reference into a value. +func (x ConstExpr) V() ConstExprValue { + return ConstExprValue{ + Datum: int64(x.ref.nums[0]), + } +} + +// WithDatum constructs a new value where the value of Datum has been replaced by +// the argument. +func (x ConstExprValue) WithDatum(y int64) ConstExprValue { + x.Datum = y + return x +} + +// ---- BinExpr ---- // + +// BinExpr is the type of a reference to an immutable record. +type BinExpr struct{ ref *node } + +const BinExpr_Slot_Left_Type = 0 +const BinExpr_Slot_Left_Num = 0 +const BinExpr_Slot_Left_BitSize = -1 +const BinExpr_Slot_Left_BitOffset = -1 +const BinExpr_Slot_Left_ByteSize = -1 +const BinExpr_Slot_Left_ByteOffset = -1 +const BinExpr_Slot_Left_ValueMask = -1 + +const BinExpr_Slot_Left__Tag_Type = 1 +const BinExpr_Slot_Left__Tag_Num = 0 +const BinExpr_Slot_Left__Tag_BitSize = 64 +const BinExpr_Slot_Left__Tag_BitOffset = 0 +const BinExpr_Slot_Left__Tag_ByteSize = 8 +const BinExpr_Slot_Left__Tag_ByteOffset = 0 +const BinExpr_Slot_Left__Tag_ValueMask = 0xffffffffffffffff + +const BinExpr_Slot_Op_Type = 1 +const BinExpr_Slot_Op_Num = 1 +const BinExpr_Slot_Op_BitSize = 64 +const BinExpr_Slot_Op_BitOffset = 0 +const BinExpr_Slot_Op_ByteSize = 8 +const BinExpr_Slot_Op_ByteOffset = 0 +const BinExpr_Slot_Op_ValueMask = 0xffffffffffffffff + +const BinExpr_Slot_Right_Type = 0 +const BinExpr_Slot_Right_Num = 1 +const BinExpr_Slot_Right_BitSize = -1 +const BinExpr_Slot_Right_BitOffset = -1 +const BinExpr_Slot_Right_ByteSize = -1 +const BinExpr_Slot_Right_ByteOffset = -1 +const BinExpr_Slot_Right_ValueMask = -1 + +// BinExprValue is the logical type of a record. Immutable records are stored in +// nodes. +type BinExprValue struct { + Left Expr // 1 + Op BinOp // 2 + Right Expr // 3 +} + +type extraBinExpr struct { + Right__Tag ExprTag +} + +func (x extraBinExpr) extraRefs() []*node { return nil } + +// R constructs a reference to an immutable record. +func (x BinExprValue) R(a *Allocator) BinExpr { + ref := a.new() + extra := &extraBinExpr{} + ref.extra = extra + + ref.nums[0] = numvalslot(x.Left.tag) + ref.refs[0] = x.Left.ref + ref.nums[1] = numvalslot(x.Op) + extra.Right__Tag = x.Right.tag + ref.refs[1] = x.Right.ref + return BinExpr{ref} +} + +// Left returns the Left field. +func (x BinExpr) Left() Expr { return Expr{ExprTag(x.ref.nums[0]), x.ref.refs[0]} } + +// Op returns the Op field. +func (x BinExpr) Op() BinOp { return BinOp(x.ref.nums[1]) } + +// Right returns the Right field. +func (x BinExpr) Right() Expr { return Expr{x.ref.extra.(*extraBinExpr).Right__Tag, x.ref.refs[1]} } + +// V unpacks a reference into a value. +func (x BinExpr) V() BinExprValue { + return BinExprValue{ + Left: Expr{ExprTag(x.ref.nums[0]), x.ref.refs[0]}, + Op: BinOp(x.ref.nums[1]), + Right: Expr{x.ref.extra.(*extraBinExpr).Right__Tag, x.ref.refs[1]}, + } +} + +// WithLeft constructs a new value where the value of Left has been replaced by +// the argument. +func (x BinExprValue) WithLeft(y Expr) BinExprValue { + x.Left = y + return x +} + +// WithOp constructs a new value where the value of Op has been replaced by +// the argument. +func (x BinExprValue) WithOp(y BinOp) BinExprValue { + x.Op = y + return x +} + +// WithRight constructs a new value where the value of Right has been replaced by +// the argument. +func (x BinExprValue) WithRight(y Expr) BinExprValue { + x.Right = y + return x +} + +// ---- TriExpr ---- // + +// TriExpr is the type of a reference to an immutable record. +type TriExpr struct{ ref *node } + +const TriExpr_Slot_One_Type = 0 +const TriExpr_Slot_One_Num = 0 +const TriExpr_Slot_One_BitSize = -1 +const TriExpr_Slot_One_BitOffset = -1 +const TriExpr_Slot_One_ByteSize = -1 +const TriExpr_Slot_One_ByteOffset = -1 +const TriExpr_Slot_One_ValueMask = -1 + +const TriExpr_Slot_One__Tag_Type = 1 +const TriExpr_Slot_One__Tag_Num = 0 +const TriExpr_Slot_One__Tag_BitSize = 64 +const TriExpr_Slot_One__Tag_BitOffset = 0 +const TriExpr_Slot_One__Tag_ByteSize = 8 +const TriExpr_Slot_One__Tag_ByteOffset = 0 +const TriExpr_Slot_One__Tag_ValueMask = 0xffffffffffffffff + +const TriExpr_Slot_Three_Type = 4 +const TriExpr_Slot_Three_Num = 0 +const TriExpr_Slot_Three_BitSize = -1 +const TriExpr_Slot_Three_BitOffset = -1 +const TriExpr_Slot_Three_ByteSize = -1 +const TriExpr_Slot_Three_ByteOffset = -1 +const TriExpr_Slot_Three_ValueMask = -1 + +const TriExpr_Slot_Two_Type = 0 +const TriExpr_Slot_Two_Num = 1 +const TriExpr_Slot_Two_BitSize = -1 +const TriExpr_Slot_Two_BitOffset = -1 +const TriExpr_Slot_Two_ByteSize = -1 +const TriExpr_Slot_Two_ByteOffset = -1 +const TriExpr_Slot_Two_ValueMask = -1 + +const TriExpr_Slot_Two__Tag_Type = 1 +const TriExpr_Slot_Two__Tag_Num = 1 +const TriExpr_Slot_Two__Tag_BitSize = 64 +const TriExpr_Slot_Two__Tag_BitOffset = 0 +const TriExpr_Slot_Two__Tag_ByteSize = 8 +const TriExpr_Slot_Two__Tag_ByteOffset = 0 +const TriExpr_Slot_Two__Tag_ValueMask = 0xffffffffffffffff + +// TriExprValue is the logical type of a record. Immutable records are stored in +// nodes. +type TriExprValue struct { + One Expr // 1 + Two Expr // 2 + Three Expr // 4 +} + +type extraTriExpr struct { + Three__Tag ExprTag + refs [1]*node +} + +func (x extraTriExpr) extraRefs() []*node { return x.refs[:] } + +// R constructs a reference to an immutable record. +func (x TriExprValue) R(a *Allocator) TriExpr { + ref := a.new() + extra := &extraTriExpr{} + ref.extra = extra + + ref.nums[0] = numvalslot(x.One.tag) + ref.refs[0] = x.One.ref + ref.nums[1] = numvalslot(x.Two.tag) + ref.refs[1] = x.Two.ref + extra.Three__Tag = x.Three.tag + extra.refs[0] = x.Three.ref + return TriExpr{ref} +} + +// One returns the One field. +func (x TriExpr) One() Expr { return Expr{ExprTag(x.ref.nums[0]), x.ref.refs[0]} } + +// Two returns the Two field. +func (x TriExpr) Two() Expr { return Expr{ExprTag(x.ref.nums[1]), x.ref.refs[1]} } + +// Three returns the Three field. +func (x TriExpr) Three() Expr { + return Expr{x.ref.extra.(*extraTriExpr).Three__Tag, x.ref.extra.(*extraTriExpr).refs[0]} +} + +// V unpacks a reference into a value. +func (x TriExpr) V() TriExprValue { + return TriExprValue{ + One: Expr{ExprTag(x.ref.nums[0]), x.ref.refs[0]}, + Two: Expr{ExprTag(x.ref.nums[1]), x.ref.refs[1]}, + Three: Expr{x.ref.extra.(*extraTriExpr).Three__Tag, x.ref.extra.(*extraTriExpr).refs[0]}, + } +} + +// WithOne constructs a new value where the value of One has been replaced by +// the argument. +func (x TriExprValue) WithOne(y Expr) TriExprValue { + x.One = y + return x +} + +// WithTwo constructs a new value where the value of Two has been replaced by +// the argument. +func (x TriExprValue) WithTwo(y Expr) TriExprValue { + x.Two = y + return x +} + +// WithThree constructs a new value where the value of Three has been replaced by +// the argument. +func (x TriExprValue) WithThree(y Expr) TriExprValue { + x.Three = y + return x +} + +// ---- All ---- // + +// All is the type of a reference to an immutable record. +type All struct{ ref *node } + +const All_Slot_A_Type = 4 +const All_Slot_A_Num = 1 +const All_Slot_A_BitSize = -1 +const All_Slot_A_BitOffset = -1 +const All_Slot_A_ByteSize = -1 +const All_Slot_A_ByteOffset = -1 +const All_Slot_A_ValueMask = -1 + +const All_Slot_BE_Type = 4 +const All_Slot_BE_Num = 0 +const All_Slot_BE_BitSize = -1 +const All_Slot_BE_BitOffset = -1 +const All_Slot_BE_ByteSize = -1 +const All_Slot_BE_ByteOffset = -1 +const All_Slot_BE_ValueMask = -1 + +const All_Slot_BO_Type = 1 +const All_Slot_BO_Num = 1 +const All_Slot_BO_BitSize = 64 +const All_Slot_BO_BitOffset = 0 +const All_Slot_BO_ByteSize = 8 +const All_Slot_BO_ByteOffset = 0 +const All_Slot_BO_ValueMask = 0xffffffffffffffff + +const All_Slot_CE_Type = 0 +const All_Slot_CE_Num = 1 +const All_Slot_CE_BitSize = -1 +const All_Slot_CE_BitOffset = -1 +const All_Slot_CE_ByteSize = -1 +const All_Slot_CE_ByteOffset = -1 +const All_Slot_CE_ValueMask = -1 + +const All_Slot_E_Type = 0 +const All_Slot_E_Num = 0 +const All_Slot_E_BitSize = -1 +const All_Slot_E_BitOffset = -1 +const All_Slot_E_ByteSize = -1 +const All_Slot_E_ByteOffset = -1 +const All_Slot_E_ValueMask = -1 + +const All_Slot_E__Tag_Type = 1 +const All_Slot_E__Tag_Num = 0 +const All_Slot_E__Tag_BitSize = 64 +const All_Slot_E__Tag_BitOffset = 0 +const All_Slot_E__Tag_ByteSize = 8 +const All_Slot_E__Tag_ByteOffset = 0 +const All_Slot_E__Tag_ValueMask = 0xffffffffffffffff + +// AllValue is the logical type of a record. Immutable records are stored in +// nodes. +type AllValue struct { + E Expr // 1 + CE ConstExpr // 2 + BE BinExpr // 3 + BO BinOp // 4 + A AllOrExpr // 5 +} + +type extraAll struct { + A__Tag AllOrExprTag + refs [2]*node +} + +func (x extraAll) extraRefs() []*node { return x.refs[:] } + +// R constructs a reference to an immutable record. +func (x AllValue) R(a *Allocator) All { + ref := a.new() + extra := &extraAll{} + ref.extra = extra + + ref.nums[0] = numvalslot(x.E.tag) + ref.refs[0] = x.E.ref + ref.refs[1] = x.CE.ref + extra.refs[0] = x.BE.ref + ref.nums[1] = numvalslot(x.BO) + extra.A__Tag = x.A.tag + extra.refs[1] = x.A.ref + return All{ref} +} + +// E returns the E field. +func (x All) E() Expr { return Expr{ExprTag(x.ref.nums[0]), x.ref.refs[0]} } + +// CE returns the CE field. +func (x All) CE() ConstExpr { return ConstExpr{x.ref.refs[1]} } + +// BE returns the BE field. +func (x All) BE() BinExpr { return BinExpr{x.ref.extra.(*extraAll).refs[0]} } + +// BO returns the BO field. +func (x All) BO() BinOp { return BinOp(x.ref.nums[1]) } + +// A returns the A field. +func (x All) A() AllOrExpr { + return AllOrExpr{x.ref.extra.(*extraAll).A__Tag, x.ref.extra.(*extraAll).refs[1]} +} + +// V unpacks a reference into a value. +func (x All) V() AllValue { + return AllValue{ + E: Expr{ExprTag(x.ref.nums[0]), x.ref.refs[0]}, + CE: ConstExpr{x.ref.refs[1]}, + BE: BinExpr{x.ref.extra.(*extraAll).refs[0]}, + BO: BinOp(x.ref.nums[1]), + A: AllOrExpr{x.ref.extra.(*extraAll).A__Tag, x.ref.extra.(*extraAll).refs[1]}, + } +} + +// WithE constructs a new value where the value of E has been replaced by +// the argument. +func (x AllValue) WithE(y Expr) AllValue { + x.E = y + return x +} + +// WithCE constructs a new value where the value of CE has been replaced by +// the argument. +func (x AllValue) WithCE(y ConstExpr) AllValue { + x.CE = y + return x +} + +// WithBE constructs a new value where the value of BE has been replaced by +// the argument. +func (x AllValue) WithBE(y BinExpr) AllValue { + x.BE = y + return x +} + +// WithBO constructs a new value where the value of BO has been replaced by +// the argument. +func (x AllValue) WithBO(y BinOp) AllValue { + x.BO = y + return x +} + +// WithA constructs a new value where the value of A has been replaced by +// the argument. +func (x AllValue) WithA(y AllOrExpr) AllValue { + x.A = y + return x +} + +// ---- Expr ---- // + +// Expr is the type of a tagged union of records. +type Expr struct { + tag ExprTag + ref *node +} + +// ExprTag is the tag type. +type ExprTag enum + +// ExprTag constants. +const ( + ExprConstExpr ExprTag = 1 + ExprBinExpr ExprTag = 2 +) + +func (x ExprTag) String() string { + switch x { + case ExprConstExpr: + return "ConstExpr" + case ExprBinExpr: + return "BinExpr" + default: + return fmt.Sprintf("", x) + } +} + +// Tag returns the tag. +func (x Expr) Tag() ExprTag { return x.tag } + +// Expr performs an upcast. +func (x ConstExpr) Expr() Expr { return Expr{ExprConstExpr, x.ref} } + +// ConstExpr performs a downcast. If the downcast fails, return false. +func (x Expr) ConstExpr() (ConstExpr, bool) { + if x.tag != ExprConstExpr { + return ConstExpr{}, false + } + return ConstExpr{x.ref}, true +} + +// MustBeConstExpr performs a downcast. If the downcast fails, panic. +func (x Expr) MustBeConstExpr() ConstExpr { + if x.tag != ExprConstExpr { + panic(fmt.Sprintf("type assertion failed: expected ConstExpr but got %s", x.tag)) + } + return ConstExpr{x.ref} +} + +// Expr performs an upcast. +func (x BinExpr) Expr() Expr { return Expr{ExprBinExpr, x.ref} } + +// BinExpr performs a downcast. If the downcast fails, return false. +func (x Expr) BinExpr() (BinExpr, bool) { + if x.tag != ExprBinExpr { + return BinExpr{}, false + } + return BinExpr{x.ref}, true +} + +// MustBeBinExpr performs a downcast. If the downcast fails, panic. +func (x Expr) MustBeBinExpr() BinExpr { + if x.tag != ExprBinExpr { + panic(fmt.Sprintf("type assertion failed: expected BinExpr but got %s", x.tag)) + } + return BinExpr{x.ref} +} + +// ---- AllOrExpr ---- // + +// AllOrExpr is the type of a tagged union of records. +type AllOrExpr struct { + tag AllOrExprTag + ref *node +} + +// AllOrExprTag is the tag type. +type AllOrExprTag enum + +// AllOrExprTag constants. +const ( + AllOrExprAll AllOrExprTag = 1 + AllOrExprBinExpr AllOrExprTag = 2 +) + +func (x AllOrExprTag) String() string { + switch x { + case AllOrExprAll: + return "All" + case AllOrExprBinExpr: + return "BinExpr" + default: + return fmt.Sprintf("", x) + } +} + +// Tag returns the tag. +func (x AllOrExpr) Tag() AllOrExprTag { return x.tag } + +// AllOrExpr performs an upcast. +func (x All) AllOrExpr() AllOrExpr { return AllOrExpr{AllOrExprAll, x.ref} } + +// All performs a downcast. If the downcast fails, return false. +func (x AllOrExpr) All() (All, bool) { + if x.tag != AllOrExprAll { + return All{}, false + } + return All{x.ref}, true +} + +// MustBeAll performs a downcast. If the downcast fails, panic. +func (x AllOrExpr) MustBeAll() All { + if x.tag != AllOrExprAll { + panic(fmt.Sprintf("type assertion failed: expected All but got %s", x.tag)) + } + return All{x.ref} +} + +// AllOrExpr performs an upcast. +func (x BinExpr) AllOrExpr() AllOrExpr { return AllOrExpr{AllOrExprBinExpr, x.ref} } + +// BinExpr performs a downcast. If the downcast fails, return false. +func (x AllOrExpr) BinExpr() (BinExpr, bool) { + if x.tag != AllOrExprBinExpr { + return BinExpr{}, false + } + return BinExpr{x.ref}, true +} + +// MustBeBinExpr performs a downcast. If the downcast fails, panic. +func (x AllOrExpr) MustBeBinExpr() BinExpr { + if x.tag != AllOrExprBinExpr { + panic(fmt.Sprintf("type assertion failed: expected BinExpr but got %s", x.tag)) + } + return BinExpr{x.ref} +} + +// Codegen parameters: +// {NumNumericSlots:2 NumericSlotSize:64 NumRefSlots:2 NumStrSlots:1 Pack:false} +// diff --git a/pkg/sql/ir/tests/nopack/example/base/sexpr.ir.go b/pkg/sql/ir/tests/nopack/example/base/sexpr.ir.go new file mode 100644 index 000000000000..68ca33467dbb --- /dev/null +++ b/pkg/sql/ir/tests/nopack/example/base/sexpr.ir.go @@ -0,0 +1,125 @@ +// Code generated by irgen/irgen base/sexpr.tmpl.go tests/example.def. DO NOT EDIT. +// GENERATED FILE DO NOT EDIT +// Copyright 2017 The Cockroach Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. + +package base + +import ( + "bytes" + "fmt" +) + +type SexprFormatter interface { + FormatSExpr(buf *bytes.Buffer) +} + +func FormatSExprBool(buf *bytes.Buffer, x bool) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt64(buf *bytes.Buffer, x int64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt32(buf *bytes.Buffer, x int32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt16(buf *bytes.Buffer, x int16) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt8(buf *bytes.Buffer, x int8) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint64(buf *bytes.Buffer, x uint64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint32(buf *bytes.Buffer, x uint32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint16(buf *bytes.Buffer, x uint16) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint8(buf *bytes.Buffer, x uint8) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprFloat32(buf *bytes.Buffer, x float32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprFloat64(buf *bytes.Buffer, x float64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprString(buf *bytes.Buffer, x string) { fmt.Fprintf(buf, "%q", x) } + +func (x BinOp) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString(x.String()) +} + +func (x ConstExpr) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(ConstExpr") + + buf.WriteString(" Datum: ") + FormatSExprInt64(buf, x.Datum()) + + buf.WriteByte(')') +} + +func (x BinExpr) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(BinExpr") + + buf.WriteString(" Left: ") + x.Left().FormatSExpr(buf) + + buf.WriteString(" Op: ") + x.Op().FormatSExpr(buf) + + buf.WriteString(" Right: ") + x.Right().FormatSExpr(buf) + + buf.WriteByte(')') +} + +func (x TriExpr) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(TriExpr") + + buf.WriteString(" One: ") + x.One().FormatSExpr(buf) + + buf.WriteString(" Two: ") + x.Two().FormatSExpr(buf) + + buf.WriteString(" Three: ") + x.Three().FormatSExpr(buf) + + buf.WriteByte(')') +} + +func (x All) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(All") + + buf.WriteString(" E: ") + x.E().FormatSExpr(buf) + + buf.WriteString(" CE: ") + x.CE().FormatSExpr(buf) + + buf.WriteString(" BE: ") + x.BE().FormatSExpr(buf) + + buf.WriteString(" BO: ") + x.BO().FormatSExpr(buf) + + buf.WriteString(" A: ") + x.A().FormatSExpr(buf) + + buf.WriteByte(')') +} + +func (x Expr) FormatSExpr(buf *bytes.Buffer) { + switch x.Tag() { + case ExprConstExpr: + x.MustBeConstExpr().FormatSExpr(buf) + case ExprBinExpr: + x.MustBeBinExpr().FormatSExpr(buf) + } +} + +func (x AllOrExpr) FormatSExpr(buf *bytes.Buffer) { + switch x.Tag() { + case AllOrExprAll: + x.MustBeAll().FormatSExpr(buf) + case AllOrExprBinExpr: + x.MustBeBinExpr().FormatSExpr(buf) + } +} + +// Codegen parameters: +// {NumNumericSlots:2 NumericSlotSize:64 NumRefSlots:2 NumStrSlots:1 Pack:false} +// diff --git a/pkg/sql/ir/tests/nopack/nopack_cfg_test.go b/pkg/sql/ir/tests/nopack/nopack_cfg_test.go new file mode 100644 index 000000000000..08253b7c52e4 --- /dev/null +++ b/pkg/sql/ir/tests/nopack/nopack_cfg_test.go @@ -0,0 +1,249 @@ +// Code generated by make. DO NOT EDIT. +// GENERATED FILE DO NOT EDIT +// Copyright 2017 The Cockroach Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. + +package nopack + +import ( + "bytes" + "fmt" + "reflect" + "strconv" + "strings" + "testing" + + d "github.com/cockroachdb/cockroach/pkg/sql/ir/tests/nopack/example/base" + p "github.com/cockroachdb/cockroach/pkg/sql/ir/tests/nopack/prims/base" +) + +func makeSampleExpr(a *d.Allocator) d.Expr { + c1 := d.ConstExprValue{Datum: 1}.R(a).Expr() + c2 := d.ConstExprValue{Datum: 2}.R(a).Expr() + c3 := d.ConstExprValue{Datum: 3}.R(a).Expr() + b4 := d.BinExprValue{Left: c1, Op: d.BinOpAdd, Right: c2}.R(a).Expr() + b5 := d.BinExprValue{Left: c3, Op: d.BinOpMul, Right: b4}.R(a).Expr() + return b5 +} + +func assertEq(t *testing.T, n int, val interface{}, exp interface{}) { + if !reflect.DeepEqual(val, exp) { + t.Errorf("equal failed %d: expected %v, got %v", n, exp, val) + } +} + +func TestExprValues(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + b5 := e.MustBeBinExpr() + assertEq(t, 1, b5.Op(), d.BinOpMul) + assertEq(t, 2, b5.Left().MustBeConstExpr().Datum(), int64(3)) + b4 := b5.Right().MustBeBinExpr() + assertEq(t, 3, b4.Op(), d.BinOpAdd) + assertEq(t, 4, b4.Left().MustBeConstExpr().Datum(), int64(1)) + assertEq(t, 5, b4.Right().MustBeConstExpr().Datum(), int64(2)) +} + +func format(ref d.Expr) string { + switch ref.Tag() { + case d.ExprConstExpr: + c := ref.MustBeConstExpr() + return strconv.FormatInt(c.Datum(), 10) + case d.ExprBinExpr: + b := ref.MustBeBinExpr() + var op string + switch b.Op() { + case d.BinOpAdd: + op = "+" + case d.BinOpMul: + op = "*" + default: + panic("unknown BinOp") + } + return fmt.Sprintf("(%s %s %s)", format(b.Left()), op, format(b.Right())) + default: + panic("unknown Expr tag") + } +} + +func TestExprFormatSExpr(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + + var buf bytes.Buffer + e.FormatSExpr(&buf) + if buf.String() != "(BinExpr Left: (ConstExpr Datum: 3) Op: Mul Right: (BinExpr Left: (ConstExpr Datum: 1) Op: Add Right: (ConstExpr Datum: 2)))" { + t.Fatalf("unexpected: %q", buf.String()) + } +} + +func TestFormat(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + const expected = "(3 * (1 + 2))" + if got := format(e); got != expected { + t.Fatalf("expected %q but got %q", expected, got) + } +} + +func reverse(ref d.Expr, a *d.Allocator) d.Expr { + if ref.Tag() != d.ExprBinExpr { + return ref + } + b := ref.MustBeBinExpr() + revLeft := reverse(b.Left(), a) + revRight := reverse(b.Right(), a) + return b.V().WithLeft(revRight).WithRight(revLeft).R(a).Expr() +} + +func TestReverse(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + const expected = "((2 + 1) * 3)" + if got := format(reverse(e, a)); got != expected { + t.Fatalf("expected %q but got %q", expected, got) + } +} + +func TestDoubleReverse(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + if got0, got2 := format(e), format(reverse(reverse(e, a), a)); got0 != got2 { + t.Fatalf("reverse is not an involution: %q != %q", got0, got2) + } +} + +func deepEqual(ref1 d.Expr, ref2 d.Expr) bool { + if ref1.Tag() != ref2.Tag() { + return false + } + switch ref1.Tag() { + case d.ExprConstExpr: + return ref1.MustBeConstExpr().Datum() == ref2.MustBeConstExpr().Datum() + case d.ExprBinExpr: + b1 := ref1.MustBeBinExpr() + b2 := ref2.MustBeBinExpr() + return b1.Op() == b2.Op() && + deepEqual(b1.Left(), b2.Left()) && deepEqual(b1.Right(), b2.Right()) + default: + panic("unknown Expr tag") + } +} + +func TestDeepEqual(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + if deepEqual(e, reverse(e, a)) { + t.Fatalf("expected expression not to be deepEqual to its reverse") + } + if !deepEqual(e, reverse(reverse(e, a), a)) { + t.Fatalf("expected expression to be deepEqual to the reverse of its reverse") + } +} + +func TestPrimValues(t *testing.T) { + a := p.NewAllocator() + all := p.AllValue{ + B: true, + I8: 'b', + U8: 'c', + I16: 0x1234, + U16: 0x4321, + I32: 0x12345678, + U32: 0x87654321, + I64: 0x123456789abcdef0, + U64: 0x0fedcba987654321, + S: "k", + F32: 1.234, + F64: 5.678, + }.R(a) + assertEq(t, 1, all.B(), true) + assertEq(t, 2, all.I8(), int8('b')) + assertEq(t, 3, all.U8(), uint8('c')) + assertEq(t, 4, all.I16(), int16(0x1234)) + assertEq(t, 5, all.U16(), uint16(0x4321)) + assertEq(t, 6, all.I32(), int32(0x12345678)) + assertEq(t, 7, all.U32(), uint32(0x87654321)) + assertEq(t, 8, all.I64(), int64(0x123456789abcdef0)) + assertEq(t, 9, all.U64(), uint64(0x0fedcba987654321)) + assertEq(t, 10, all.S(), "k") + assertEq(t, 11, all.F32(), float32(1.234)) + assertEq(t, 12, all.F64(), float64(5.678)) + + var buf bytes.Buffer + all.FormatSExpr(&buf) + assertEq(t, 100, buf.String(), strings.TrimSpace(` +(All B: true I8: 98 U8: 99 I16: 4660 U16: 17185 I32: 305419896 U32: 2271560481 I64: 1311768467463790320 U64: 1147797409030816545 S: "k" F32: 1.234 F64: 5.678) +`)) +} + +func TestPrimValues2(t *testing.T) { + a := p.NewAllocator() + v := p.SmallBeforeValue{ + A: true, + B: false, + C: 'c', + D: 'd', + E: 'e', + F: 0x1234, + G: 0x4321, + H: 0x12345678, + I: 0x123456789abcdef0, + }.R(a) + assertEq(t, 1, v.A(), true) + assertEq(t, 2, v.B(), false) + assertEq(t, 3, v.C(), uint8('c')) + assertEq(t, 4, v.D(), uint8('d')) + assertEq(t, 5, v.E(), uint8('e')) + assertEq(t, 6, v.F(), uint16(0x1234)) + assertEq(t, 7, v.G(), uint16(0x4321)) + assertEq(t, 8, v.H(), uint32(0x12345678)) + assertEq(t, 9, v.I(), uint64(0x123456789abcdef0)) + + var buf bytes.Buffer + v.FormatSExpr(&buf) + assertEq(t, 100, buf.String(), strings.TrimSpace(` +(SmallBefore A: true B: false C: 99 D: 100 E: 101 F: 4660 G: 17185 H: 305419896 I: 1311768467463790320) +`)) +} + +func TestPrimValues3(t *testing.T) { + a := p.NewAllocator() + v := p.BigBeforeValue{ + A: 0x123456789abcdef0, + B: 0x12345678, + C: 0x1234, + D: 0x4321, + E: 'e', + F: 'f', + G: 'g', + H: false, + I: true, + }.R(a) + assertEq(t, 1, v.A(), uint64(0x123456789abcdef0)) + assertEq(t, 2, v.B(), uint32(0x12345678)) + assertEq(t, 3, v.C(), uint16(0x1234)) + assertEq(t, 4, v.D(), uint16(0x4321)) + assertEq(t, 5, v.E(), uint8('e')) + assertEq(t, 6, v.F(), uint8('f')) + assertEq(t, 7, v.G(), uint8('g')) + assertEq(t, 8, v.H(), false) + assertEq(t, 9, v.I(), true) + + var buf bytes.Buffer + v.FormatSExpr(&buf) + assertEq(t, 100, buf.String(), strings.TrimSpace(` +(BigBefore A: 1311768467463790320 B: 305419896 C: 4660 D: 17185 E: 101 F: 102 G: 103 H: false I: true) +`)) +} diff --git a/pkg/sql/ir/tests/nopack/prims/base/base.ir.go b/pkg/sql/ir/tests/nopack/prims/base/base.ir.go new file mode 100644 index 000000000000..49148fbe5add --- /dev/null +++ b/pkg/sql/ir/tests/nopack/prims/base/base.ir.go @@ -0,0 +1,828 @@ +// Code generated by irgen/irgen base/base.tmpl.go tests/prims.def. DO NOT EDIT. +// GENERATED FILE DO NOT EDIT +// Copyright 2017 The Cockroach Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. + +package base + +// node is a generic ADT node type, with slots for references to other nodes and +// enumeration values. Values that don't fit and values of other types go in the +// extra field. +type node struct { + refs [2]*node + nums [2]numvalslot + strs [1]string + extra +} + +// enum is the type to define the tag part for working copies of IR +// node with sum and enum types. +type enum uint32 + +// numvalslot is the type used to store integer values in persistent IR nodes. +// must be larger than or as large as enum. +type numvalslot uint64 + +type extra interface { + extraRefs() []*node +} + +// Allocator allocates nodes in batches. Construct Allocators with NewAllocator +// and pass them by value. +type Allocator struct { + nodes []node +} + +// MakeAllocator constructs a new Allocator. +func MakeAllocator() Allocator { + nodes := make([]node, 16) + return Allocator{nodes} +} + +// NewAllocator allocates a new Allocator. +func NewAllocator() *Allocator { + a := MakeAllocator() + return &a +} + +// new allocates a new node. Users of this package should use the appropriate +// R() method, which is type safe. +func (a *Allocator) new() *node { + nodes := a.nodes + if len(nodes) == 0 { + nodes = make([]node, 256) + } + x := &nodes[0] + a.nodes = nodes[1:] + return x +} + +// ---- All ---- // + +// All is the type of a reference to an immutable record. +type All struct{ ref *node } + +const All_Slot_B_Type = 1 +const All_Slot_B_Num = 0 +const All_Slot_B_BitSize = 64 +const All_Slot_B_BitOffset = 0 +const All_Slot_B_ByteSize = 8 +const All_Slot_B_ByteOffset = 0 +const All_Slot_B_ValueMask = 0xffffffffffffffff + +const All_Slot_F32_Type = 3 +const All_Slot_F32_Num = -1 +const All_Slot_F32_BitSize = -1 +const All_Slot_F32_BitOffset = -1 +const All_Slot_F32_ByteSize = -1 +const All_Slot_F32_ByteOffset = -1 +const All_Slot_F32_ValueMask = -1 + +const All_Slot_F64_Type = 3 +const All_Slot_F64_Num = -1 +const All_Slot_F64_BitSize = -1 +const All_Slot_F64_BitOffset = -1 +const All_Slot_F64_ByteSize = -1 +const All_Slot_F64_ByteOffset = -1 +const All_Slot_F64_ValueMask = -1 + +const All_Slot_I16_Type = 3 +const All_Slot_I16_Num = -1 +const All_Slot_I16_BitSize = -1 +const All_Slot_I16_BitOffset = -1 +const All_Slot_I16_ByteSize = -1 +const All_Slot_I16_ByteOffset = -1 +const All_Slot_I16_ValueMask = -1 + +const All_Slot_I32_Type = 3 +const All_Slot_I32_Num = -1 +const All_Slot_I32_BitSize = -1 +const All_Slot_I32_BitOffset = -1 +const All_Slot_I32_ByteSize = -1 +const All_Slot_I32_ByteOffset = -1 +const All_Slot_I32_ValueMask = -1 + +const All_Slot_I64_Type = 3 +const All_Slot_I64_Num = -1 +const All_Slot_I64_BitSize = -1 +const All_Slot_I64_BitOffset = -1 +const All_Slot_I64_ByteSize = -1 +const All_Slot_I64_ByteOffset = -1 +const All_Slot_I64_ValueMask = -1 + +const All_Slot_I8_Type = 1 +const All_Slot_I8_Num = 1 +const All_Slot_I8_BitSize = 64 +const All_Slot_I8_BitOffset = 0 +const All_Slot_I8_ByteSize = 8 +const All_Slot_I8_ByteOffset = 0 +const All_Slot_I8_ValueMask = 0xffffffffffffffff + +const All_Slot_S_Type = 2 +const All_Slot_S_Num = 0 +const All_Slot_S_BitSize = -1 +const All_Slot_S_BitOffset = -1 +const All_Slot_S_ByteSize = -1 +const All_Slot_S_ByteOffset = -1 +const All_Slot_S_ValueMask = -1 + +const All_Slot_U16_Type = 3 +const All_Slot_U16_Num = -1 +const All_Slot_U16_BitSize = -1 +const All_Slot_U16_BitOffset = -1 +const All_Slot_U16_ByteSize = -1 +const All_Slot_U16_ByteOffset = -1 +const All_Slot_U16_ValueMask = -1 + +const All_Slot_U32_Type = 3 +const All_Slot_U32_Num = -1 +const All_Slot_U32_BitSize = -1 +const All_Slot_U32_BitOffset = -1 +const All_Slot_U32_ByteSize = -1 +const All_Slot_U32_ByteOffset = -1 +const All_Slot_U32_ValueMask = -1 + +const All_Slot_U64_Type = 3 +const All_Slot_U64_Num = -1 +const All_Slot_U64_BitSize = -1 +const All_Slot_U64_BitOffset = -1 +const All_Slot_U64_ByteSize = -1 +const All_Slot_U64_ByteOffset = -1 +const All_Slot_U64_ValueMask = -1 + +const All_Slot_U8_Type = 3 +const All_Slot_U8_Num = -1 +const All_Slot_U8_BitSize = -1 +const All_Slot_U8_BitOffset = -1 +const All_Slot_U8_ByteSize = -1 +const All_Slot_U8_ByteOffset = -1 +const All_Slot_U8_ValueMask = -1 + +// AllValue is the logical type of a record. Immutable records are stored in +// nodes. +type AllValue struct { + B bool // 1 + I8 int8 // 2 + U8 uint8 // 3 + I16 int16 // 4 + U16 uint16 // 5 + I32 int32 // 6 + U32 uint32 // 7 + I64 int64 // 8 + U64 uint64 // 9 + S string // 10 + F32 float32 // 11 + F64 float64 // 12 +} + +type extraAll struct { + U8 uint8 + I16 int16 + U16 uint16 + I32 int32 + U32 uint32 + I64 int64 + U64 uint64 + F32 float32 + F64 float64 +} + +func (x extraAll) extraRefs() []*node { return nil } + +// R constructs a reference to an immutable record. +func (x AllValue) R(a *Allocator) All { + ref := a.new() + extra := &extraAll{} + ref.extra = extra + + if x.B { + ref.nums[0] = 1 + } else { + ref.nums[0] = 0 + } + ref.nums[1] = numvalslot(x.I8) + extra.U8 = x.U8 + extra.I16 = x.I16 + extra.U16 = x.U16 + extra.I32 = x.I32 + extra.U32 = x.U32 + extra.I64 = x.I64 + extra.U64 = x.U64 + ref.strs[0] = x.S + extra.F32 = x.F32 + extra.F64 = x.F64 + return All{ref} +} + +// B returns the B field. +func (x All) B() bool { return !(0 == x.ref.nums[0]) } + +// I8 returns the I8 field. +func (x All) I8() int8 { return int8(x.ref.nums[1]) } + +// U8 returns the U8 field. +func (x All) U8() uint8 { return x.ref.extra.(*extraAll).U8 } + +// I16 returns the I16 field. +func (x All) I16() int16 { return x.ref.extra.(*extraAll).I16 } + +// U16 returns the U16 field. +func (x All) U16() uint16 { return x.ref.extra.(*extraAll).U16 } + +// I32 returns the I32 field. +func (x All) I32() int32 { return x.ref.extra.(*extraAll).I32 } + +// U32 returns the U32 field. +func (x All) U32() uint32 { return x.ref.extra.(*extraAll).U32 } + +// I64 returns the I64 field. +func (x All) I64() int64 { return x.ref.extra.(*extraAll).I64 } + +// U64 returns the U64 field. +func (x All) U64() uint64 { return x.ref.extra.(*extraAll).U64 } + +// S returns the S field. +func (x All) S() string { return x.ref.strs[0] } + +// F32 returns the F32 field. +func (x All) F32() float32 { return x.ref.extra.(*extraAll).F32 } + +// F64 returns the F64 field. +func (x All) F64() float64 { return x.ref.extra.(*extraAll).F64 } + +// V unpacks a reference into a value. +func (x All) V() AllValue { + return AllValue{ + B: !(0 == x.ref.nums[0]), + I8: int8(x.ref.nums[1]), + U8: x.ref.extra.(*extraAll).U8, + I16: x.ref.extra.(*extraAll).I16, + U16: x.ref.extra.(*extraAll).U16, + I32: x.ref.extra.(*extraAll).I32, + U32: x.ref.extra.(*extraAll).U32, + I64: x.ref.extra.(*extraAll).I64, + U64: x.ref.extra.(*extraAll).U64, + S: x.ref.strs[0], + F32: x.ref.extra.(*extraAll).F32, + F64: x.ref.extra.(*extraAll).F64, + } +} + +// WithB constructs a new value where the value of B has been replaced by +// the argument. +func (x AllValue) WithB(y bool) AllValue { + x.B = y + return x +} + +// WithI8 constructs a new value where the value of I8 has been replaced by +// the argument. +func (x AllValue) WithI8(y int8) AllValue { + x.I8 = y + return x +} + +// WithU8 constructs a new value where the value of U8 has been replaced by +// the argument. +func (x AllValue) WithU8(y uint8) AllValue { + x.U8 = y + return x +} + +// WithI16 constructs a new value where the value of I16 has been replaced by +// the argument. +func (x AllValue) WithI16(y int16) AllValue { + x.I16 = y + return x +} + +// WithU16 constructs a new value where the value of U16 has been replaced by +// the argument. +func (x AllValue) WithU16(y uint16) AllValue { + x.U16 = y + return x +} + +// WithI32 constructs a new value where the value of I32 has been replaced by +// the argument. +func (x AllValue) WithI32(y int32) AllValue { + x.I32 = y + return x +} + +// WithU32 constructs a new value where the value of U32 has been replaced by +// the argument. +func (x AllValue) WithU32(y uint32) AllValue { + x.U32 = y + return x +} + +// WithI64 constructs a new value where the value of I64 has been replaced by +// the argument. +func (x AllValue) WithI64(y int64) AllValue { + x.I64 = y + return x +} + +// WithU64 constructs a new value where the value of U64 has been replaced by +// the argument. +func (x AllValue) WithU64(y uint64) AllValue { + x.U64 = y + return x +} + +// WithS constructs a new value where the value of S has been replaced by +// the argument. +func (x AllValue) WithS(y string) AllValue { + x.S = y + return x +} + +// WithF32 constructs a new value where the value of F32 has been replaced by +// the argument. +func (x AllValue) WithF32(y float32) AllValue { + x.F32 = y + return x +} + +// WithF64 constructs a new value where the value of F64 has been replaced by +// the argument. +func (x AllValue) WithF64(y float64) AllValue { + x.F64 = y + return x +} + +// ---- SmallBefore ---- // + +// SmallBefore is the type of a reference to an immutable record. +type SmallBefore struct{ ref *node } + +const SmallBefore_Slot_A_Type = 1 +const SmallBefore_Slot_A_Num = 0 +const SmallBefore_Slot_A_BitSize = 64 +const SmallBefore_Slot_A_BitOffset = 0 +const SmallBefore_Slot_A_ByteSize = 8 +const SmallBefore_Slot_A_ByteOffset = 0 +const SmallBefore_Slot_A_ValueMask = 0xffffffffffffffff + +const SmallBefore_Slot_B_Type = 1 +const SmallBefore_Slot_B_Num = 1 +const SmallBefore_Slot_B_BitSize = 64 +const SmallBefore_Slot_B_BitOffset = 0 +const SmallBefore_Slot_B_ByteSize = 8 +const SmallBefore_Slot_B_ByteOffset = 0 +const SmallBefore_Slot_B_ValueMask = 0xffffffffffffffff + +const SmallBefore_Slot_C_Type = 3 +const SmallBefore_Slot_C_Num = -1 +const SmallBefore_Slot_C_BitSize = -1 +const SmallBefore_Slot_C_BitOffset = -1 +const SmallBefore_Slot_C_ByteSize = -1 +const SmallBefore_Slot_C_ByteOffset = -1 +const SmallBefore_Slot_C_ValueMask = -1 + +const SmallBefore_Slot_D_Type = 3 +const SmallBefore_Slot_D_Num = -1 +const SmallBefore_Slot_D_BitSize = -1 +const SmallBefore_Slot_D_BitOffset = -1 +const SmallBefore_Slot_D_ByteSize = -1 +const SmallBefore_Slot_D_ByteOffset = -1 +const SmallBefore_Slot_D_ValueMask = -1 + +const SmallBefore_Slot_E_Type = 3 +const SmallBefore_Slot_E_Num = -1 +const SmallBefore_Slot_E_BitSize = -1 +const SmallBefore_Slot_E_BitOffset = -1 +const SmallBefore_Slot_E_ByteSize = -1 +const SmallBefore_Slot_E_ByteOffset = -1 +const SmallBefore_Slot_E_ValueMask = -1 + +const SmallBefore_Slot_F_Type = 3 +const SmallBefore_Slot_F_Num = -1 +const SmallBefore_Slot_F_BitSize = -1 +const SmallBefore_Slot_F_BitOffset = -1 +const SmallBefore_Slot_F_ByteSize = -1 +const SmallBefore_Slot_F_ByteOffset = -1 +const SmallBefore_Slot_F_ValueMask = -1 + +const SmallBefore_Slot_G_Type = 3 +const SmallBefore_Slot_G_Num = -1 +const SmallBefore_Slot_G_BitSize = -1 +const SmallBefore_Slot_G_BitOffset = -1 +const SmallBefore_Slot_G_ByteSize = -1 +const SmallBefore_Slot_G_ByteOffset = -1 +const SmallBefore_Slot_G_ValueMask = -1 + +const SmallBefore_Slot_H_Type = 3 +const SmallBefore_Slot_H_Num = -1 +const SmallBefore_Slot_H_BitSize = -1 +const SmallBefore_Slot_H_BitOffset = -1 +const SmallBefore_Slot_H_ByteSize = -1 +const SmallBefore_Slot_H_ByteOffset = -1 +const SmallBefore_Slot_H_ValueMask = -1 + +const SmallBefore_Slot_I_Type = 3 +const SmallBefore_Slot_I_Num = -1 +const SmallBefore_Slot_I_BitSize = -1 +const SmallBefore_Slot_I_BitOffset = -1 +const SmallBefore_Slot_I_ByteSize = -1 +const SmallBefore_Slot_I_ByteOffset = -1 +const SmallBefore_Slot_I_ValueMask = -1 + +// SmallBeforeValue is the logical type of a record. Immutable records are stored in +// nodes. +type SmallBeforeValue struct { + A bool // 1 + B bool // 2 + C uint8 // 3 + D uint8 // 4 + E uint8 // 5 + F uint16 // 6 + G uint16 // 7 + H uint32 // 8 + I uint64 // 9 +} + +type extraSmallBefore struct { + C uint8 + D uint8 + E uint8 + F uint16 + G uint16 + H uint32 + I uint64 +} + +func (x extraSmallBefore) extraRefs() []*node { return nil } + +// R constructs a reference to an immutable record. +func (x SmallBeforeValue) R(a *Allocator) SmallBefore { + ref := a.new() + extra := &extraSmallBefore{} + ref.extra = extra + + if x.A { + ref.nums[0] = 1 + } else { + ref.nums[0] = 0 + } + if x.B { + ref.nums[1] = 1 + } else { + ref.nums[1] = 0 + } + extra.C = x.C + extra.D = x.D + extra.E = x.E + extra.F = x.F + extra.G = x.G + extra.H = x.H + extra.I = x.I + return SmallBefore{ref} +} + +// A returns the A field. +func (x SmallBefore) A() bool { return !(0 == x.ref.nums[0]) } + +// B returns the B field. +func (x SmallBefore) B() bool { return !(0 == x.ref.nums[1]) } + +// C returns the C field. +func (x SmallBefore) C() uint8 { return x.ref.extra.(*extraSmallBefore).C } + +// D returns the D field. +func (x SmallBefore) D() uint8 { return x.ref.extra.(*extraSmallBefore).D } + +// E returns the E field. +func (x SmallBefore) E() uint8 { return x.ref.extra.(*extraSmallBefore).E } + +// F returns the F field. +func (x SmallBefore) F() uint16 { return x.ref.extra.(*extraSmallBefore).F } + +// G returns the G field. +func (x SmallBefore) G() uint16 { return x.ref.extra.(*extraSmallBefore).G } + +// H returns the H field. +func (x SmallBefore) H() uint32 { return x.ref.extra.(*extraSmallBefore).H } + +// I returns the I field. +func (x SmallBefore) I() uint64 { return x.ref.extra.(*extraSmallBefore).I } + +// V unpacks a reference into a value. +func (x SmallBefore) V() SmallBeforeValue { + return SmallBeforeValue{ + A: !(0 == x.ref.nums[0]), + B: !(0 == x.ref.nums[1]), + C: x.ref.extra.(*extraSmallBefore).C, + D: x.ref.extra.(*extraSmallBefore).D, + E: x.ref.extra.(*extraSmallBefore).E, + F: x.ref.extra.(*extraSmallBefore).F, + G: x.ref.extra.(*extraSmallBefore).G, + H: x.ref.extra.(*extraSmallBefore).H, + I: x.ref.extra.(*extraSmallBefore).I, + } +} + +// WithA constructs a new value where the value of A has been replaced by +// the argument. +func (x SmallBeforeValue) WithA(y bool) SmallBeforeValue { + x.A = y + return x +} + +// WithB constructs a new value where the value of B has been replaced by +// the argument. +func (x SmallBeforeValue) WithB(y bool) SmallBeforeValue { + x.B = y + return x +} + +// WithC constructs a new value where the value of C has been replaced by +// the argument. +func (x SmallBeforeValue) WithC(y uint8) SmallBeforeValue { + x.C = y + return x +} + +// WithD constructs a new value where the value of D has been replaced by +// the argument. +func (x SmallBeforeValue) WithD(y uint8) SmallBeforeValue { + x.D = y + return x +} + +// WithE constructs a new value where the value of E has been replaced by +// the argument. +func (x SmallBeforeValue) WithE(y uint8) SmallBeforeValue { + x.E = y + return x +} + +// WithF constructs a new value where the value of F has been replaced by +// the argument. +func (x SmallBeforeValue) WithF(y uint16) SmallBeforeValue { + x.F = y + return x +} + +// WithG constructs a new value where the value of G has been replaced by +// the argument. +func (x SmallBeforeValue) WithG(y uint16) SmallBeforeValue { + x.G = y + return x +} + +// WithH constructs a new value where the value of H has been replaced by +// the argument. +func (x SmallBeforeValue) WithH(y uint32) SmallBeforeValue { + x.H = y + return x +} + +// WithI constructs a new value where the value of I has been replaced by +// the argument. +func (x SmallBeforeValue) WithI(y uint64) SmallBeforeValue { + x.I = y + return x +} + +// ---- BigBefore ---- // + +// BigBefore is the type of a reference to an immutable record. +type BigBefore struct{ ref *node } + +const BigBefore_Slot_A_Type = 1 +const BigBefore_Slot_A_Num = 0 +const BigBefore_Slot_A_BitSize = 64 +const BigBefore_Slot_A_BitOffset = 0 +const BigBefore_Slot_A_ByteSize = 8 +const BigBefore_Slot_A_ByteOffset = 0 +const BigBefore_Slot_A_ValueMask = 0xffffffffffffffff + +const BigBefore_Slot_B_Type = 1 +const BigBefore_Slot_B_Num = 1 +const BigBefore_Slot_B_BitSize = 64 +const BigBefore_Slot_B_BitOffset = 0 +const BigBefore_Slot_B_ByteSize = 8 +const BigBefore_Slot_B_ByteOffset = 0 +const BigBefore_Slot_B_ValueMask = 0xffffffffffffffff + +const BigBefore_Slot_C_Type = 3 +const BigBefore_Slot_C_Num = -1 +const BigBefore_Slot_C_BitSize = -1 +const BigBefore_Slot_C_BitOffset = -1 +const BigBefore_Slot_C_ByteSize = -1 +const BigBefore_Slot_C_ByteOffset = -1 +const BigBefore_Slot_C_ValueMask = -1 + +const BigBefore_Slot_D_Type = 3 +const BigBefore_Slot_D_Num = -1 +const BigBefore_Slot_D_BitSize = -1 +const BigBefore_Slot_D_BitOffset = -1 +const BigBefore_Slot_D_ByteSize = -1 +const BigBefore_Slot_D_ByteOffset = -1 +const BigBefore_Slot_D_ValueMask = -1 + +const BigBefore_Slot_E_Type = 3 +const BigBefore_Slot_E_Num = -1 +const BigBefore_Slot_E_BitSize = -1 +const BigBefore_Slot_E_BitOffset = -1 +const BigBefore_Slot_E_ByteSize = -1 +const BigBefore_Slot_E_ByteOffset = -1 +const BigBefore_Slot_E_ValueMask = -1 + +const BigBefore_Slot_F_Type = 3 +const BigBefore_Slot_F_Num = -1 +const BigBefore_Slot_F_BitSize = -1 +const BigBefore_Slot_F_BitOffset = -1 +const BigBefore_Slot_F_ByteSize = -1 +const BigBefore_Slot_F_ByteOffset = -1 +const BigBefore_Slot_F_ValueMask = -1 + +const BigBefore_Slot_G_Type = 3 +const BigBefore_Slot_G_Num = -1 +const BigBefore_Slot_G_BitSize = -1 +const BigBefore_Slot_G_BitOffset = -1 +const BigBefore_Slot_G_ByteSize = -1 +const BigBefore_Slot_G_ByteOffset = -1 +const BigBefore_Slot_G_ValueMask = -1 + +const BigBefore_Slot_H_Type = 3 +const BigBefore_Slot_H_Num = -1 +const BigBefore_Slot_H_BitSize = -1 +const BigBefore_Slot_H_BitOffset = -1 +const BigBefore_Slot_H_ByteSize = -1 +const BigBefore_Slot_H_ByteOffset = -1 +const BigBefore_Slot_H_ValueMask = -1 + +const BigBefore_Slot_I_Type = 3 +const BigBefore_Slot_I_Num = -1 +const BigBefore_Slot_I_BitSize = -1 +const BigBefore_Slot_I_BitOffset = -1 +const BigBefore_Slot_I_ByteSize = -1 +const BigBefore_Slot_I_ByteOffset = -1 +const BigBefore_Slot_I_ValueMask = -1 + +// BigBeforeValue is the logical type of a record. Immutable records are stored in +// nodes. +type BigBeforeValue struct { + A uint64 // 1 + B uint32 // 2 + C uint16 // 3 + D uint16 // 4 + E uint8 // 5 + F uint8 // 6 + G uint8 // 7 + H bool // 8 + I bool // 9 +} + +type extraBigBefore struct { + C uint16 + D uint16 + E uint8 + F uint8 + G uint8 + H bool + I bool +} + +func (x extraBigBefore) extraRefs() []*node { return nil } + +// R constructs a reference to an immutable record. +func (x BigBeforeValue) R(a *Allocator) BigBefore { + ref := a.new() + extra := &extraBigBefore{} + ref.extra = extra + + ref.nums[0] = numvalslot(x.A) + ref.nums[1] = numvalslot(x.B) + extra.C = x.C + extra.D = x.D + extra.E = x.E + extra.F = x.F + extra.G = x.G + extra.H = x.H + extra.I = x.I + return BigBefore{ref} +} + +// A returns the A field. +func (x BigBefore) A() uint64 { return uint64(x.ref.nums[0]) } + +// B returns the B field. +func (x BigBefore) B() uint32 { return uint32(x.ref.nums[1]) } + +// C returns the C field. +func (x BigBefore) C() uint16 { return x.ref.extra.(*extraBigBefore).C } + +// D returns the D field. +func (x BigBefore) D() uint16 { return x.ref.extra.(*extraBigBefore).D } + +// E returns the E field. +func (x BigBefore) E() uint8 { return x.ref.extra.(*extraBigBefore).E } + +// F returns the F field. +func (x BigBefore) F() uint8 { return x.ref.extra.(*extraBigBefore).F } + +// G returns the G field. +func (x BigBefore) G() uint8 { return x.ref.extra.(*extraBigBefore).G } + +// H returns the H field. +func (x BigBefore) H() bool { return x.ref.extra.(*extraBigBefore).H } + +// I returns the I field. +func (x BigBefore) I() bool { return x.ref.extra.(*extraBigBefore).I } + +// V unpacks a reference into a value. +func (x BigBefore) V() BigBeforeValue { + return BigBeforeValue{ + A: uint64(x.ref.nums[0]), + B: uint32(x.ref.nums[1]), + C: x.ref.extra.(*extraBigBefore).C, + D: x.ref.extra.(*extraBigBefore).D, + E: x.ref.extra.(*extraBigBefore).E, + F: x.ref.extra.(*extraBigBefore).F, + G: x.ref.extra.(*extraBigBefore).G, + H: x.ref.extra.(*extraBigBefore).H, + I: x.ref.extra.(*extraBigBefore).I, + } +} + +// WithA constructs a new value where the value of A has been replaced by +// the argument. +func (x BigBeforeValue) WithA(y uint64) BigBeforeValue { + x.A = y + return x +} + +// WithB constructs a new value where the value of B has been replaced by +// the argument. +func (x BigBeforeValue) WithB(y uint32) BigBeforeValue { + x.B = y + return x +} + +// WithC constructs a new value where the value of C has been replaced by +// the argument. +func (x BigBeforeValue) WithC(y uint16) BigBeforeValue { + x.C = y + return x +} + +// WithD constructs a new value where the value of D has been replaced by +// the argument. +func (x BigBeforeValue) WithD(y uint16) BigBeforeValue { + x.D = y + return x +} + +// WithE constructs a new value where the value of E has been replaced by +// the argument. +func (x BigBeforeValue) WithE(y uint8) BigBeforeValue { + x.E = y + return x +} + +// WithF constructs a new value where the value of F has been replaced by +// the argument. +func (x BigBeforeValue) WithF(y uint8) BigBeforeValue { + x.F = y + return x +} + +// WithG constructs a new value where the value of G has been replaced by +// the argument. +func (x BigBeforeValue) WithG(y uint8) BigBeforeValue { + x.G = y + return x +} + +// WithH constructs a new value where the value of H has been replaced by +// the argument. +func (x BigBeforeValue) WithH(y bool) BigBeforeValue { + x.H = y + return x +} + +// WithI constructs a new value where the value of I has been replaced by +// the argument. +func (x BigBeforeValue) WithI(y bool) BigBeforeValue { + x.I = y + return x +} + +// Codegen parameters: +// {NumNumericSlots:2 NumericSlotSize:64 NumRefSlots:2 NumStrSlots:1 Pack:false} +// diff --git a/pkg/sql/ir/tests/nopack/prims/base/sexpr.ir.go b/pkg/sql/ir/tests/nopack/prims/base/sexpr.ir.go new file mode 100644 index 000000000000..ecbfc22a48a9 --- /dev/null +++ b/pkg/sql/ir/tests/nopack/prims/base/sexpr.ir.go @@ -0,0 +1,151 @@ +// Code generated by irgen/irgen base/sexpr.tmpl.go tests/prims.def. DO NOT EDIT. +// GENERATED FILE DO NOT EDIT +// Copyright 2017 The Cockroach Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. + +package base + +import ( + "bytes" + "fmt" +) + +type SexprFormatter interface { + FormatSExpr(buf *bytes.Buffer) +} + +func FormatSExprBool(buf *bytes.Buffer, x bool) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt64(buf *bytes.Buffer, x int64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt32(buf *bytes.Buffer, x int32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt16(buf *bytes.Buffer, x int16) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt8(buf *bytes.Buffer, x int8) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint64(buf *bytes.Buffer, x uint64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint32(buf *bytes.Buffer, x uint32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint16(buf *bytes.Buffer, x uint16) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint8(buf *bytes.Buffer, x uint8) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprFloat32(buf *bytes.Buffer, x float32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprFloat64(buf *bytes.Buffer, x float64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprString(buf *bytes.Buffer, x string) { fmt.Fprintf(buf, "%q", x) } + +func (x All) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(All") + + buf.WriteString(" B: ") + FormatSExprBool(buf, x.B()) + + buf.WriteString(" I8: ") + FormatSExprInt8(buf, x.I8()) + + buf.WriteString(" U8: ") + FormatSExprUint8(buf, x.U8()) + + buf.WriteString(" I16: ") + FormatSExprInt16(buf, x.I16()) + + buf.WriteString(" U16: ") + FormatSExprUint16(buf, x.U16()) + + buf.WriteString(" I32: ") + FormatSExprInt32(buf, x.I32()) + + buf.WriteString(" U32: ") + FormatSExprUint32(buf, x.U32()) + + buf.WriteString(" I64: ") + FormatSExprInt64(buf, x.I64()) + + buf.WriteString(" U64: ") + FormatSExprUint64(buf, x.U64()) + + buf.WriteString(" S: ") + FormatSExprString(buf, x.S()) + + buf.WriteString(" F32: ") + FormatSExprFloat32(buf, x.F32()) + + buf.WriteString(" F64: ") + FormatSExprFloat64(buf, x.F64()) + + buf.WriteByte(')') +} + +func (x SmallBefore) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(SmallBefore") + + buf.WriteString(" A: ") + FormatSExprBool(buf, x.A()) + + buf.WriteString(" B: ") + FormatSExprBool(buf, x.B()) + + buf.WriteString(" C: ") + FormatSExprUint8(buf, x.C()) + + buf.WriteString(" D: ") + FormatSExprUint8(buf, x.D()) + + buf.WriteString(" E: ") + FormatSExprUint8(buf, x.E()) + + buf.WriteString(" F: ") + FormatSExprUint16(buf, x.F()) + + buf.WriteString(" G: ") + FormatSExprUint16(buf, x.G()) + + buf.WriteString(" H: ") + FormatSExprUint32(buf, x.H()) + + buf.WriteString(" I: ") + FormatSExprUint64(buf, x.I()) + + buf.WriteByte(')') +} + +func (x BigBefore) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(BigBefore") + + buf.WriteString(" A: ") + FormatSExprUint64(buf, x.A()) + + buf.WriteString(" B: ") + FormatSExprUint32(buf, x.B()) + + buf.WriteString(" C: ") + FormatSExprUint16(buf, x.C()) + + buf.WriteString(" D: ") + FormatSExprUint16(buf, x.D()) + + buf.WriteString(" E: ") + FormatSExprUint8(buf, x.E()) + + buf.WriteString(" F: ") + FormatSExprUint8(buf, x.F()) + + buf.WriteString(" G: ") + FormatSExprUint8(buf, x.G()) + + buf.WriteString(" H: ") + FormatSExprBool(buf, x.H()) + + buf.WriteString(" I: ") + FormatSExprBool(buf, x.I()) + + buf.WriteByte(')') +} + +// Codegen parameters: +// {NumNumericSlots:2 NumericSlotSize:64 NumRefSlots:2 NumStrSlots:1 Pack:false} +// diff --git a/pkg/sql/ir/example/base/base.ir.go b/pkg/sql/ir/tests/onlyextra/example/base/base.ir.go similarity index 56% rename from pkg/sql/ir/example/base/base.ir.go rename to pkg/sql/ir/tests/onlyextra/example/base/base.ir.go index a08fa82044de..a8c7dbb6003e 100644 --- a/pkg/sql/ir/example/base/base.ir.go +++ b/pkg/sql/ir/tests/onlyextra/example/base/base.ir.go @@ -1,4 +1,4 @@ -// Code generated by irgen/irgen base/base.tmpl.go example.def. DO NOT EDIT. +// Code generated by irgen/irgen base/base.tmpl.go tests/example.def. DO NOT EDIT. // GENERATED FILE DO NOT EDIT // Copyright 2017 The Cockroach Authors. // @@ -16,18 +16,27 @@ package base -import "fmt" +import ( + "fmt" +) // node is a generic ADT node type, with slots for references to other nodes and // enumeration values. Values that don't fit and values of other types go in the // extra field. type node struct { - refs [1]*node - enums [2]enum + refs [0]*node + nums [0]numvalslot + strs [0]string extra } -type enum int32 +// enum is the type to define the tag part for working copies of IR +// node with sum and enum types. +type enum uint32 + +// numvalslot is the type used to store integer values in persistent IR nodes. +// must be larger than or as large as enum. +type numvalslot uint64 type extra interface { extraRefs() []*node @@ -90,6 +99,14 @@ func (x BinOp) String() string { // ConstExpr is the type of a reference to an immutable record. type ConstExpr struct{ ref *node } +const ConstExpr_Slot_Datum_Type = 3 +const ConstExpr_Slot_Datum_Num = -1 +const ConstExpr_Slot_Datum_BitSize = -1 +const ConstExpr_Slot_Datum_BitOffset = -1 +const ConstExpr_Slot_Datum_ByteSize = -1 +const ConstExpr_Slot_Datum_ByteOffset = -1 +const ConstExpr_Slot_Datum_ValueMask = -1 + // ConstExprValue is the logical type of a record. Immutable records are stored in // nodes. type ConstExprValue struct { @@ -118,7 +135,7 @@ func (x ConstExpr) Datum() int64 { return x.ref.extra.(*extraConstExpr).Datum } // V unpacks a reference into a value. func (x ConstExpr) V() ConstExprValue { return ConstExprValue{ - x.ref.extra.(*extraConstExpr).Datum, + Datum: x.ref.extra.(*extraConstExpr).Datum, } } @@ -134,6 +151,30 @@ func (x ConstExprValue) WithDatum(y int64) ConstExprValue { // BinExpr is the type of a reference to an immutable record. type BinExpr struct{ ref *node } +const BinExpr_Slot_Left_Type = 4 +const BinExpr_Slot_Left_Num = 0 +const BinExpr_Slot_Left_BitSize = -1 +const BinExpr_Slot_Left_BitOffset = -1 +const BinExpr_Slot_Left_ByteSize = -1 +const BinExpr_Slot_Left_ByteOffset = -1 +const BinExpr_Slot_Left_ValueMask = -1 + +const BinExpr_Slot_Op_Type = 3 +const BinExpr_Slot_Op_Num = -1 +const BinExpr_Slot_Op_BitSize = -1 +const BinExpr_Slot_Op_BitOffset = -1 +const BinExpr_Slot_Op_ByteSize = -1 +const BinExpr_Slot_Op_ByteOffset = -1 +const BinExpr_Slot_Op_ValueMask = -1 + +const BinExpr_Slot_Right_Type = 4 +const BinExpr_Slot_Right_Num = 1 +const BinExpr_Slot_Right_BitSize = -1 +const BinExpr_Slot_Right_BitOffset = -1 +const BinExpr_Slot_Right_ByteSize = -1 +const BinExpr_Slot_Right_ByteOffset = -1 +const BinExpr_Slot_Right_ValueMask = -1 + // BinExprValue is the logical type of a record. Immutable records are stored in // nodes. type BinExprValue struct { @@ -143,8 +184,10 @@ type BinExprValue struct { } type extraBinExpr struct { - Right ExprTag - refs [1]*node + Left__Tag ExprTag + Op BinOp + Right__Tag ExprTag + refs [2]*node } func (x extraBinExpr) extraRefs() []*node { return x.refs[:] } @@ -155,31 +198,33 @@ func (x BinExprValue) R(a *Allocator) BinExpr { extra := &extraBinExpr{} ref.extra = extra - ref.enums[1] = enum(x.Left.tag) - ref.refs[0] = x.Left.ref - ref.enums[0] = enum(x.Op) - extra.Right = x.Right.tag - extra.refs[0] = x.Right.ref + extra.Left__Tag = x.Left.tag + extra.refs[0] = x.Left.ref + extra.Op = x.Op + extra.Right__Tag = x.Right.tag + extra.refs[1] = x.Right.ref return BinExpr{ref} } // Left returns the Left field. -func (x BinExpr) Left() Expr { return Expr{ExprTag(x.ref.enums[1]), x.ref.refs[0]} } +func (x BinExpr) Left() Expr { + return Expr{x.ref.extra.(*extraBinExpr).Left__Tag, x.ref.extra.(*extraBinExpr).refs[0]} +} // Op returns the Op field. -func (x BinExpr) Op() BinOp { return BinOp(x.ref.enums[0]) } +func (x BinExpr) Op() BinOp { return x.ref.extra.(*extraBinExpr).Op } // Right returns the Right field. func (x BinExpr) Right() Expr { - return Expr{x.ref.extra.(*extraBinExpr).Right, x.ref.extra.(*extraBinExpr).refs[0]} + return Expr{x.ref.extra.(*extraBinExpr).Right__Tag, x.ref.extra.(*extraBinExpr).refs[1]} } // V unpacks a reference into a value. func (x BinExpr) V() BinExprValue { return BinExprValue{ - Expr{ExprTag(x.ref.enums[1]), x.ref.refs[0]}, - BinOp(x.ref.enums[0]), - Expr{x.ref.extra.(*extraBinExpr).Right, x.ref.extra.(*extraBinExpr).refs[0]}, + Left: Expr{x.ref.extra.(*extraBinExpr).Left__Tag, x.ref.extra.(*extraBinExpr).refs[0]}, + Op: x.ref.extra.(*extraBinExpr).Op, + Right: Expr{x.ref.extra.(*extraBinExpr).Right__Tag, x.ref.extra.(*extraBinExpr).refs[1]}, } } @@ -204,11 +249,157 @@ func (x BinExprValue) WithRight(y Expr) BinExprValue { return x } +// ---- TriExpr ---- // + +// TriExpr is the type of a reference to an immutable record. +type TriExpr struct{ ref *node } + +const TriExpr_Slot_One_Type = 4 +const TriExpr_Slot_One_Num = 0 +const TriExpr_Slot_One_BitSize = -1 +const TriExpr_Slot_One_BitOffset = -1 +const TriExpr_Slot_One_ByteSize = -1 +const TriExpr_Slot_One_ByteOffset = -1 +const TriExpr_Slot_One_ValueMask = -1 + +const TriExpr_Slot_Three_Type = 4 +const TriExpr_Slot_Three_Num = 2 +const TriExpr_Slot_Three_BitSize = -1 +const TriExpr_Slot_Three_BitOffset = -1 +const TriExpr_Slot_Three_ByteSize = -1 +const TriExpr_Slot_Three_ByteOffset = -1 +const TriExpr_Slot_Three_ValueMask = -1 + +const TriExpr_Slot_Two_Type = 4 +const TriExpr_Slot_Two_Num = 1 +const TriExpr_Slot_Two_BitSize = -1 +const TriExpr_Slot_Two_BitOffset = -1 +const TriExpr_Slot_Two_ByteSize = -1 +const TriExpr_Slot_Two_ByteOffset = -1 +const TriExpr_Slot_Two_ValueMask = -1 + +// TriExprValue is the logical type of a record. Immutable records are stored in +// nodes. +type TriExprValue struct { + One Expr // 1 + Two Expr // 2 + Three Expr // 4 +} + +type extraTriExpr struct { + One__Tag ExprTag + Two__Tag ExprTag + Three__Tag ExprTag + refs [3]*node +} + +func (x extraTriExpr) extraRefs() []*node { return x.refs[:] } + +// R constructs a reference to an immutable record. +func (x TriExprValue) R(a *Allocator) TriExpr { + ref := a.new() + extra := &extraTriExpr{} + ref.extra = extra + + extra.One__Tag = x.One.tag + extra.refs[0] = x.One.ref + extra.Two__Tag = x.Two.tag + extra.refs[1] = x.Two.ref + extra.Three__Tag = x.Three.tag + extra.refs[2] = x.Three.ref + return TriExpr{ref} +} + +// One returns the One field. +func (x TriExpr) One() Expr { + return Expr{x.ref.extra.(*extraTriExpr).One__Tag, x.ref.extra.(*extraTriExpr).refs[0]} +} + +// Two returns the Two field. +func (x TriExpr) Two() Expr { + return Expr{x.ref.extra.(*extraTriExpr).Two__Tag, x.ref.extra.(*extraTriExpr).refs[1]} +} + +// Three returns the Three field. +func (x TriExpr) Three() Expr { + return Expr{x.ref.extra.(*extraTriExpr).Three__Tag, x.ref.extra.(*extraTriExpr).refs[2]} +} + +// V unpacks a reference into a value. +func (x TriExpr) V() TriExprValue { + return TriExprValue{ + One: Expr{x.ref.extra.(*extraTriExpr).One__Tag, x.ref.extra.(*extraTriExpr).refs[0]}, + Two: Expr{x.ref.extra.(*extraTriExpr).Two__Tag, x.ref.extra.(*extraTriExpr).refs[1]}, + Three: Expr{x.ref.extra.(*extraTriExpr).Three__Tag, x.ref.extra.(*extraTriExpr).refs[2]}, + } +} + +// WithOne constructs a new value where the value of One has been replaced by +// the argument. +func (x TriExprValue) WithOne(y Expr) TriExprValue { + x.One = y + return x +} + +// WithTwo constructs a new value where the value of Two has been replaced by +// the argument. +func (x TriExprValue) WithTwo(y Expr) TriExprValue { + x.Two = y + return x +} + +// WithThree constructs a new value where the value of Three has been replaced by +// the argument. +func (x TriExprValue) WithThree(y Expr) TriExprValue { + x.Three = y + return x +} + // ---- All ---- // // All is the type of a reference to an immutable record. type All struct{ ref *node } +const All_Slot_A_Type = 4 +const All_Slot_A_Num = 3 +const All_Slot_A_BitSize = -1 +const All_Slot_A_BitOffset = -1 +const All_Slot_A_ByteSize = -1 +const All_Slot_A_ByteOffset = -1 +const All_Slot_A_ValueMask = -1 + +const All_Slot_BE_Type = 4 +const All_Slot_BE_Num = 2 +const All_Slot_BE_BitSize = -1 +const All_Slot_BE_BitOffset = -1 +const All_Slot_BE_ByteSize = -1 +const All_Slot_BE_ByteOffset = -1 +const All_Slot_BE_ValueMask = -1 + +const All_Slot_BO_Type = 3 +const All_Slot_BO_Num = -1 +const All_Slot_BO_BitSize = -1 +const All_Slot_BO_BitOffset = -1 +const All_Slot_BO_ByteSize = -1 +const All_Slot_BO_ByteOffset = -1 +const All_Slot_BO_ValueMask = -1 + +const All_Slot_CE_Type = 4 +const All_Slot_CE_Num = 1 +const All_Slot_CE_BitSize = -1 +const All_Slot_CE_BitOffset = -1 +const All_Slot_CE_ByteSize = -1 +const All_Slot_CE_ByteOffset = -1 +const All_Slot_CE_ValueMask = -1 + +const All_Slot_E_Type = 4 +const All_Slot_E_Num = 0 +const All_Slot_E_BitSize = -1 +const All_Slot_E_BitOffset = -1 +const All_Slot_E_ByteSize = -1 +const All_Slot_E_ByteOffset = -1 +const All_Slot_E_ValueMask = -1 + // AllValue is the logical type of a record. Immutable records are stored in // nodes. type AllValue struct { @@ -220,8 +411,10 @@ type AllValue struct { } type extraAll struct { - A AllOrExprTag - refs [3]*node + E__Tag ExprTag + BO BinOp + A__Tag AllOrExprTag + refs [4]*node } func (x extraAll) extraRefs() []*node { return x.refs[:] } @@ -232,41 +425,41 @@ func (x AllValue) R(a *Allocator) All { extra := &extraAll{} ref.extra = extra - ref.enums[1] = enum(x.E.tag) - ref.refs[0] = x.E.ref - extra.refs[0] = x.CE.ref - extra.refs[1] = x.BE.ref - ref.enums[0] = enum(x.BO) - extra.A = x.A.tag - extra.refs[2] = x.A.ref + extra.E__Tag = x.E.tag + extra.refs[0] = x.E.ref + extra.refs[1] = x.CE.ref + extra.refs[2] = x.BE.ref + extra.BO = x.BO + extra.A__Tag = x.A.tag + extra.refs[3] = x.A.ref return All{ref} } // E returns the E field. -func (x All) E() Expr { return Expr{ExprTag(x.ref.enums[1]), x.ref.refs[0]} } +func (x All) E() Expr { return Expr{x.ref.extra.(*extraAll).E__Tag, x.ref.extra.(*extraAll).refs[0]} } // CE returns the CE field. -func (x All) CE() ConstExpr { return ConstExpr{x.ref.extra.(*extraAll).refs[0]} } +func (x All) CE() ConstExpr { return ConstExpr{x.ref.extra.(*extraAll).refs[1]} } // BE returns the BE field. -func (x All) BE() BinExpr { return BinExpr{x.ref.extra.(*extraAll).refs[1]} } +func (x All) BE() BinExpr { return BinExpr{x.ref.extra.(*extraAll).refs[2]} } // BO returns the BO field. -func (x All) BO() BinOp { return BinOp(x.ref.enums[0]) } +func (x All) BO() BinOp { return x.ref.extra.(*extraAll).BO } // A returns the A field. func (x All) A() AllOrExpr { - return AllOrExpr{x.ref.extra.(*extraAll).A, x.ref.extra.(*extraAll).refs[2]} + return AllOrExpr{x.ref.extra.(*extraAll).A__Tag, x.ref.extra.(*extraAll).refs[3]} } // V unpacks a reference into a value. func (x All) V() AllValue { return AllValue{ - Expr{ExprTag(x.ref.enums[1]), x.ref.refs[0]}, - ConstExpr{x.ref.extra.(*extraAll).refs[0]}, - BinExpr{x.ref.extra.(*extraAll).refs[1]}, - BinOp(x.ref.enums[0]), - AllOrExpr{x.ref.extra.(*extraAll).A, x.ref.extra.(*extraAll).refs[2]}, + E: Expr{x.ref.extra.(*extraAll).E__Tag, x.ref.extra.(*extraAll).refs[0]}, + CE: ConstExpr{x.ref.extra.(*extraAll).refs[1]}, + BE: BinExpr{x.ref.extra.(*extraAll).refs[2]}, + BO: x.ref.extra.(*extraAll).BO, + A: AllOrExpr{x.ref.extra.(*extraAll).A__Tag, x.ref.extra.(*extraAll).refs[3]}, } } @@ -442,3 +635,7 @@ func (x AllOrExpr) MustBeBinExpr() BinExpr { } return BinExpr{x.ref} } + +// Codegen parameters: +// {NumNumericSlots:0 NumericSlotSize:64 NumRefSlots:0 NumStrSlots:0 Pack:false} +// diff --git a/pkg/sql/ir/tests/onlyextra/example/base/sexpr.ir.go b/pkg/sql/ir/tests/onlyextra/example/base/sexpr.ir.go new file mode 100644 index 000000000000..87595759f55f --- /dev/null +++ b/pkg/sql/ir/tests/onlyextra/example/base/sexpr.ir.go @@ -0,0 +1,125 @@ +// Code generated by irgen/irgen base/sexpr.tmpl.go tests/example.def. DO NOT EDIT. +// GENERATED FILE DO NOT EDIT +// Copyright 2017 The Cockroach Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. + +package base + +import ( + "bytes" + "fmt" +) + +type SexprFormatter interface { + FormatSExpr(buf *bytes.Buffer) +} + +func FormatSExprBool(buf *bytes.Buffer, x bool) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt64(buf *bytes.Buffer, x int64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt32(buf *bytes.Buffer, x int32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt16(buf *bytes.Buffer, x int16) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt8(buf *bytes.Buffer, x int8) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint64(buf *bytes.Buffer, x uint64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint32(buf *bytes.Buffer, x uint32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint16(buf *bytes.Buffer, x uint16) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint8(buf *bytes.Buffer, x uint8) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprFloat32(buf *bytes.Buffer, x float32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprFloat64(buf *bytes.Buffer, x float64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprString(buf *bytes.Buffer, x string) { fmt.Fprintf(buf, "%q", x) } + +func (x BinOp) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString(x.String()) +} + +func (x ConstExpr) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(ConstExpr") + + buf.WriteString(" Datum: ") + FormatSExprInt64(buf, x.Datum()) + + buf.WriteByte(')') +} + +func (x BinExpr) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(BinExpr") + + buf.WriteString(" Left: ") + x.Left().FormatSExpr(buf) + + buf.WriteString(" Op: ") + x.Op().FormatSExpr(buf) + + buf.WriteString(" Right: ") + x.Right().FormatSExpr(buf) + + buf.WriteByte(')') +} + +func (x TriExpr) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(TriExpr") + + buf.WriteString(" One: ") + x.One().FormatSExpr(buf) + + buf.WriteString(" Two: ") + x.Two().FormatSExpr(buf) + + buf.WriteString(" Three: ") + x.Three().FormatSExpr(buf) + + buf.WriteByte(')') +} + +func (x All) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(All") + + buf.WriteString(" E: ") + x.E().FormatSExpr(buf) + + buf.WriteString(" CE: ") + x.CE().FormatSExpr(buf) + + buf.WriteString(" BE: ") + x.BE().FormatSExpr(buf) + + buf.WriteString(" BO: ") + x.BO().FormatSExpr(buf) + + buf.WriteString(" A: ") + x.A().FormatSExpr(buf) + + buf.WriteByte(')') +} + +func (x Expr) FormatSExpr(buf *bytes.Buffer) { + switch x.Tag() { + case ExprConstExpr: + x.MustBeConstExpr().FormatSExpr(buf) + case ExprBinExpr: + x.MustBeBinExpr().FormatSExpr(buf) + } +} + +func (x AllOrExpr) FormatSExpr(buf *bytes.Buffer) { + switch x.Tag() { + case AllOrExprAll: + x.MustBeAll().FormatSExpr(buf) + case AllOrExprBinExpr: + x.MustBeBinExpr().FormatSExpr(buf) + } +} + +// Codegen parameters: +// {NumNumericSlots:0 NumericSlotSize:64 NumRefSlots:0 NumStrSlots:0 Pack:false} +// diff --git a/pkg/sql/ir/tests/onlyextra/onlyextra_cfg_test.go b/pkg/sql/ir/tests/onlyextra/onlyextra_cfg_test.go new file mode 100644 index 000000000000..52ae374b27c8 --- /dev/null +++ b/pkg/sql/ir/tests/onlyextra/onlyextra_cfg_test.go @@ -0,0 +1,249 @@ +// Code generated by make. DO NOT EDIT. +// GENERATED FILE DO NOT EDIT +// Copyright 2017 The Cockroach Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. + +package onlyextra + +import ( + "bytes" + "fmt" + "reflect" + "strconv" + "strings" + "testing" + + d "github.com/cockroachdb/cockroach/pkg/sql/ir/tests/onlyextra/example/base" + p "github.com/cockroachdb/cockroach/pkg/sql/ir/tests/onlyextra/prims/base" +) + +func makeSampleExpr(a *d.Allocator) d.Expr { + c1 := d.ConstExprValue{Datum: 1}.R(a).Expr() + c2 := d.ConstExprValue{Datum: 2}.R(a).Expr() + c3 := d.ConstExprValue{Datum: 3}.R(a).Expr() + b4 := d.BinExprValue{Left: c1, Op: d.BinOpAdd, Right: c2}.R(a).Expr() + b5 := d.BinExprValue{Left: c3, Op: d.BinOpMul, Right: b4}.R(a).Expr() + return b5 +} + +func assertEq(t *testing.T, n int, val interface{}, exp interface{}) { + if !reflect.DeepEqual(val, exp) { + t.Errorf("equal failed %d: expected %v, got %v", n, exp, val) + } +} + +func TestExprValues(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + b5 := e.MustBeBinExpr() + assertEq(t, 1, b5.Op(), d.BinOpMul) + assertEq(t, 2, b5.Left().MustBeConstExpr().Datum(), int64(3)) + b4 := b5.Right().MustBeBinExpr() + assertEq(t, 3, b4.Op(), d.BinOpAdd) + assertEq(t, 4, b4.Left().MustBeConstExpr().Datum(), int64(1)) + assertEq(t, 5, b4.Right().MustBeConstExpr().Datum(), int64(2)) +} + +func format(ref d.Expr) string { + switch ref.Tag() { + case d.ExprConstExpr: + c := ref.MustBeConstExpr() + return strconv.FormatInt(c.Datum(), 10) + case d.ExprBinExpr: + b := ref.MustBeBinExpr() + var op string + switch b.Op() { + case d.BinOpAdd: + op = "+" + case d.BinOpMul: + op = "*" + default: + panic("unknown BinOp") + } + return fmt.Sprintf("(%s %s %s)", format(b.Left()), op, format(b.Right())) + default: + panic("unknown Expr tag") + } +} + +func TestExprFormatSExpr(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + + var buf bytes.Buffer + e.FormatSExpr(&buf) + if buf.String() != "(BinExpr Left: (ConstExpr Datum: 3) Op: Mul Right: (BinExpr Left: (ConstExpr Datum: 1) Op: Add Right: (ConstExpr Datum: 2)))" { + t.Fatalf("unexpected: %q", buf.String()) + } +} + +func TestFormat(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + const expected = "(3 * (1 + 2))" + if got := format(e); got != expected { + t.Fatalf("expected %q but got %q", expected, got) + } +} + +func reverse(ref d.Expr, a *d.Allocator) d.Expr { + if ref.Tag() != d.ExprBinExpr { + return ref + } + b := ref.MustBeBinExpr() + revLeft := reverse(b.Left(), a) + revRight := reverse(b.Right(), a) + return b.V().WithLeft(revRight).WithRight(revLeft).R(a).Expr() +} + +func TestReverse(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + const expected = "((2 + 1) * 3)" + if got := format(reverse(e, a)); got != expected { + t.Fatalf("expected %q but got %q", expected, got) + } +} + +func TestDoubleReverse(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + if got0, got2 := format(e), format(reverse(reverse(e, a), a)); got0 != got2 { + t.Fatalf("reverse is not an involution: %q != %q", got0, got2) + } +} + +func deepEqual(ref1 d.Expr, ref2 d.Expr) bool { + if ref1.Tag() != ref2.Tag() { + return false + } + switch ref1.Tag() { + case d.ExprConstExpr: + return ref1.MustBeConstExpr().Datum() == ref2.MustBeConstExpr().Datum() + case d.ExprBinExpr: + b1 := ref1.MustBeBinExpr() + b2 := ref2.MustBeBinExpr() + return b1.Op() == b2.Op() && + deepEqual(b1.Left(), b2.Left()) && deepEqual(b1.Right(), b2.Right()) + default: + panic("unknown Expr tag") + } +} + +func TestDeepEqual(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + if deepEqual(e, reverse(e, a)) { + t.Fatalf("expected expression not to be deepEqual to its reverse") + } + if !deepEqual(e, reverse(reverse(e, a), a)) { + t.Fatalf("expected expression to be deepEqual to the reverse of its reverse") + } +} + +func TestPrimValues(t *testing.T) { + a := p.NewAllocator() + all := p.AllValue{ + B: true, + I8: 'b', + U8: 'c', + I16: 0x1234, + U16: 0x4321, + I32: 0x12345678, + U32: 0x87654321, + I64: 0x123456789abcdef0, + U64: 0x0fedcba987654321, + S: "k", + F32: 1.234, + F64: 5.678, + }.R(a) + assertEq(t, 1, all.B(), true) + assertEq(t, 2, all.I8(), int8('b')) + assertEq(t, 3, all.U8(), uint8('c')) + assertEq(t, 4, all.I16(), int16(0x1234)) + assertEq(t, 5, all.U16(), uint16(0x4321)) + assertEq(t, 6, all.I32(), int32(0x12345678)) + assertEq(t, 7, all.U32(), uint32(0x87654321)) + assertEq(t, 8, all.I64(), int64(0x123456789abcdef0)) + assertEq(t, 9, all.U64(), uint64(0x0fedcba987654321)) + assertEq(t, 10, all.S(), "k") + assertEq(t, 11, all.F32(), float32(1.234)) + assertEq(t, 12, all.F64(), float64(5.678)) + + var buf bytes.Buffer + all.FormatSExpr(&buf) + assertEq(t, 100, buf.String(), strings.TrimSpace(` +(All B: true I8: 98 U8: 99 I16: 4660 U16: 17185 I32: 305419896 U32: 2271560481 I64: 1311768467463790320 U64: 1147797409030816545 S: "k" F32: 1.234 F64: 5.678) +`)) +} + +func TestPrimValues2(t *testing.T) { + a := p.NewAllocator() + v := p.SmallBeforeValue{ + A: true, + B: false, + C: 'c', + D: 'd', + E: 'e', + F: 0x1234, + G: 0x4321, + H: 0x12345678, + I: 0x123456789abcdef0, + }.R(a) + assertEq(t, 1, v.A(), true) + assertEq(t, 2, v.B(), false) + assertEq(t, 3, v.C(), uint8('c')) + assertEq(t, 4, v.D(), uint8('d')) + assertEq(t, 5, v.E(), uint8('e')) + assertEq(t, 6, v.F(), uint16(0x1234)) + assertEq(t, 7, v.G(), uint16(0x4321)) + assertEq(t, 8, v.H(), uint32(0x12345678)) + assertEq(t, 9, v.I(), uint64(0x123456789abcdef0)) + + var buf bytes.Buffer + v.FormatSExpr(&buf) + assertEq(t, 100, buf.String(), strings.TrimSpace(` +(SmallBefore A: true B: false C: 99 D: 100 E: 101 F: 4660 G: 17185 H: 305419896 I: 1311768467463790320) +`)) +} + +func TestPrimValues3(t *testing.T) { + a := p.NewAllocator() + v := p.BigBeforeValue{ + A: 0x123456789abcdef0, + B: 0x12345678, + C: 0x1234, + D: 0x4321, + E: 'e', + F: 'f', + G: 'g', + H: false, + I: true, + }.R(a) + assertEq(t, 1, v.A(), uint64(0x123456789abcdef0)) + assertEq(t, 2, v.B(), uint32(0x12345678)) + assertEq(t, 3, v.C(), uint16(0x1234)) + assertEq(t, 4, v.D(), uint16(0x4321)) + assertEq(t, 5, v.E(), uint8('e')) + assertEq(t, 6, v.F(), uint8('f')) + assertEq(t, 7, v.G(), uint8('g')) + assertEq(t, 8, v.H(), false) + assertEq(t, 9, v.I(), true) + + var buf bytes.Buffer + v.FormatSExpr(&buf) + assertEq(t, 100, buf.String(), strings.TrimSpace(` +(BigBefore A: 1311768467463790320 B: 305419896 C: 4660 D: 17185 E: 101 F: 102 G: 103 H: false I: true) +`)) +} diff --git a/pkg/sql/ir/tests/onlyextra/prims/base/base.ir.go b/pkg/sql/ir/tests/onlyextra/prims/base/base.ir.go new file mode 100644 index 000000000000..8f69d9c00c6b --- /dev/null +++ b/pkg/sql/ir/tests/onlyextra/prims/base/base.ir.go @@ -0,0 +1,823 @@ +// Code generated by irgen/irgen base/base.tmpl.go tests/prims.def. DO NOT EDIT. +// GENERATED FILE DO NOT EDIT +// Copyright 2017 The Cockroach Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. + +package base + +// node is a generic ADT node type, with slots for references to other nodes and +// enumeration values. Values that don't fit and values of other types go in the +// extra field. +type node struct { + refs [0]*node + nums [0]numvalslot + strs [0]string + extra +} + +// enum is the type to define the tag part for working copies of IR +// node with sum and enum types. +type enum uint32 + +// numvalslot is the type used to store integer values in persistent IR nodes. +// must be larger than or as large as enum. +type numvalslot uint64 + +type extra interface { + extraRefs() []*node +} + +// Allocator allocates nodes in batches. Construct Allocators with NewAllocator +// and pass them by value. +type Allocator struct { + nodes []node +} + +// MakeAllocator constructs a new Allocator. +func MakeAllocator() Allocator { + nodes := make([]node, 16) + return Allocator{nodes} +} + +// NewAllocator allocates a new Allocator. +func NewAllocator() *Allocator { + a := MakeAllocator() + return &a +} + +// new allocates a new node. Users of this package should use the appropriate +// R() method, which is type safe. +func (a *Allocator) new() *node { + nodes := a.nodes + if len(nodes) == 0 { + nodes = make([]node, 256) + } + x := &nodes[0] + a.nodes = nodes[1:] + return x +} + +// ---- All ---- // + +// All is the type of a reference to an immutable record. +type All struct{ ref *node } + +const All_Slot_B_Type = 3 +const All_Slot_B_Num = -1 +const All_Slot_B_BitSize = -1 +const All_Slot_B_BitOffset = -1 +const All_Slot_B_ByteSize = -1 +const All_Slot_B_ByteOffset = -1 +const All_Slot_B_ValueMask = -1 + +const All_Slot_F32_Type = 3 +const All_Slot_F32_Num = -1 +const All_Slot_F32_BitSize = -1 +const All_Slot_F32_BitOffset = -1 +const All_Slot_F32_ByteSize = -1 +const All_Slot_F32_ByteOffset = -1 +const All_Slot_F32_ValueMask = -1 + +const All_Slot_F64_Type = 3 +const All_Slot_F64_Num = -1 +const All_Slot_F64_BitSize = -1 +const All_Slot_F64_BitOffset = -1 +const All_Slot_F64_ByteSize = -1 +const All_Slot_F64_ByteOffset = -1 +const All_Slot_F64_ValueMask = -1 + +const All_Slot_I16_Type = 3 +const All_Slot_I16_Num = -1 +const All_Slot_I16_BitSize = -1 +const All_Slot_I16_BitOffset = -1 +const All_Slot_I16_ByteSize = -1 +const All_Slot_I16_ByteOffset = -1 +const All_Slot_I16_ValueMask = -1 + +const All_Slot_I32_Type = 3 +const All_Slot_I32_Num = -1 +const All_Slot_I32_BitSize = -1 +const All_Slot_I32_BitOffset = -1 +const All_Slot_I32_ByteSize = -1 +const All_Slot_I32_ByteOffset = -1 +const All_Slot_I32_ValueMask = -1 + +const All_Slot_I64_Type = 3 +const All_Slot_I64_Num = -1 +const All_Slot_I64_BitSize = -1 +const All_Slot_I64_BitOffset = -1 +const All_Slot_I64_ByteSize = -1 +const All_Slot_I64_ByteOffset = -1 +const All_Slot_I64_ValueMask = -1 + +const All_Slot_I8_Type = 3 +const All_Slot_I8_Num = -1 +const All_Slot_I8_BitSize = -1 +const All_Slot_I8_BitOffset = -1 +const All_Slot_I8_ByteSize = -1 +const All_Slot_I8_ByteOffset = -1 +const All_Slot_I8_ValueMask = -1 + +const All_Slot_S_Type = 3 +const All_Slot_S_Num = -1 +const All_Slot_S_BitSize = -1 +const All_Slot_S_BitOffset = -1 +const All_Slot_S_ByteSize = -1 +const All_Slot_S_ByteOffset = -1 +const All_Slot_S_ValueMask = -1 + +const All_Slot_U16_Type = 3 +const All_Slot_U16_Num = -1 +const All_Slot_U16_BitSize = -1 +const All_Slot_U16_BitOffset = -1 +const All_Slot_U16_ByteSize = -1 +const All_Slot_U16_ByteOffset = -1 +const All_Slot_U16_ValueMask = -1 + +const All_Slot_U32_Type = 3 +const All_Slot_U32_Num = -1 +const All_Slot_U32_BitSize = -1 +const All_Slot_U32_BitOffset = -1 +const All_Slot_U32_ByteSize = -1 +const All_Slot_U32_ByteOffset = -1 +const All_Slot_U32_ValueMask = -1 + +const All_Slot_U64_Type = 3 +const All_Slot_U64_Num = -1 +const All_Slot_U64_BitSize = -1 +const All_Slot_U64_BitOffset = -1 +const All_Slot_U64_ByteSize = -1 +const All_Slot_U64_ByteOffset = -1 +const All_Slot_U64_ValueMask = -1 + +const All_Slot_U8_Type = 3 +const All_Slot_U8_Num = -1 +const All_Slot_U8_BitSize = -1 +const All_Slot_U8_BitOffset = -1 +const All_Slot_U8_ByteSize = -1 +const All_Slot_U8_ByteOffset = -1 +const All_Slot_U8_ValueMask = -1 + +// AllValue is the logical type of a record. Immutable records are stored in +// nodes. +type AllValue struct { + B bool // 1 + I8 int8 // 2 + U8 uint8 // 3 + I16 int16 // 4 + U16 uint16 // 5 + I32 int32 // 6 + U32 uint32 // 7 + I64 int64 // 8 + U64 uint64 // 9 + S string // 10 + F32 float32 // 11 + F64 float64 // 12 +} + +type extraAll struct { + B bool + I8 int8 + U8 uint8 + I16 int16 + U16 uint16 + I32 int32 + U32 uint32 + I64 int64 + U64 uint64 + S string + F32 float32 + F64 float64 +} + +func (x extraAll) extraRefs() []*node { return nil } + +// R constructs a reference to an immutable record. +func (x AllValue) R(a *Allocator) All { + ref := a.new() + extra := &extraAll{} + ref.extra = extra + + extra.B = x.B + extra.I8 = x.I8 + extra.U8 = x.U8 + extra.I16 = x.I16 + extra.U16 = x.U16 + extra.I32 = x.I32 + extra.U32 = x.U32 + extra.I64 = x.I64 + extra.U64 = x.U64 + extra.S = x.S + extra.F32 = x.F32 + extra.F64 = x.F64 + return All{ref} +} + +// B returns the B field. +func (x All) B() bool { return x.ref.extra.(*extraAll).B } + +// I8 returns the I8 field. +func (x All) I8() int8 { return x.ref.extra.(*extraAll).I8 } + +// U8 returns the U8 field. +func (x All) U8() uint8 { return x.ref.extra.(*extraAll).U8 } + +// I16 returns the I16 field. +func (x All) I16() int16 { return x.ref.extra.(*extraAll).I16 } + +// U16 returns the U16 field. +func (x All) U16() uint16 { return x.ref.extra.(*extraAll).U16 } + +// I32 returns the I32 field. +func (x All) I32() int32 { return x.ref.extra.(*extraAll).I32 } + +// U32 returns the U32 field. +func (x All) U32() uint32 { return x.ref.extra.(*extraAll).U32 } + +// I64 returns the I64 field. +func (x All) I64() int64 { return x.ref.extra.(*extraAll).I64 } + +// U64 returns the U64 field. +func (x All) U64() uint64 { return x.ref.extra.(*extraAll).U64 } + +// S returns the S field. +func (x All) S() string { return x.ref.extra.(*extraAll).S } + +// F32 returns the F32 field. +func (x All) F32() float32 { return x.ref.extra.(*extraAll).F32 } + +// F64 returns the F64 field. +func (x All) F64() float64 { return x.ref.extra.(*extraAll).F64 } + +// V unpacks a reference into a value. +func (x All) V() AllValue { + return AllValue{ + B: x.ref.extra.(*extraAll).B, + I8: x.ref.extra.(*extraAll).I8, + U8: x.ref.extra.(*extraAll).U8, + I16: x.ref.extra.(*extraAll).I16, + U16: x.ref.extra.(*extraAll).U16, + I32: x.ref.extra.(*extraAll).I32, + U32: x.ref.extra.(*extraAll).U32, + I64: x.ref.extra.(*extraAll).I64, + U64: x.ref.extra.(*extraAll).U64, + S: x.ref.extra.(*extraAll).S, + F32: x.ref.extra.(*extraAll).F32, + F64: x.ref.extra.(*extraAll).F64, + } +} + +// WithB constructs a new value where the value of B has been replaced by +// the argument. +func (x AllValue) WithB(y bool) AllValue { + x.B = y + return x +} + +// WithI8 constructs a new value where the value of I8 has been replaced by +// the argument. +func (x AllValue) WithI8(y int8) AllValue { + x.I8 = y + return x +} + +// WithU8 constructs a new value where the value of U8 has been replaced by +// the argument. +func (x AllValue) WithU8(y uint8) AllValue { + x.U8 = y + return x +} + +// WithI16 constructs a new value where the value of I16 has been replaced by +// the argument. +func (x AllValue) WithI16(y int16) AllValue { + x.I16 = y + return x +} + +// WithU16 constructs a new value where the value of U16 has been replaced by +// the argument. +func (x AllValue) WithU16(y uint16) AllValue { + x.U16 = y + return x +} + +// WithI32 constructs a new value where the value of I32 has been replaced by +// the argument. +func (x AllValue) WithI32(y int32) AllValue { + x.I32 = y + return x +} + +// WithU32 constructs a new value where the value of U32 has been replaced by +// the argument. +func (x AllValue) WithU32(y uint32) AllValue { + x.U32 = y + return x +} + +// WithI64 constructs a new value where the value of I64 has been replaced by +// the argument. +func (x AllValue) WithI64(y int64) AllValue { + x.I64 = y + return x +} + +// WithU64 constructs a new value where the value of U64 has been replaced by +// the argument. +func (x AllValue) WithU64(y uint64) AllValue { + x.U64 = y + return x +} + +// WithS constructs a new value where the value of S has been replaced by +// the argument. +func (x AllValue) WithS(y string) AllValue { + x.S = y + return x +} + +// WithF32 constructs a new value where the value of F32 has been replaced by +// the argument. +func (x AllValue) WithF32(y float32) AllValue { + x.F32 = y + return x +} + +// WithF64 constructs a new value where the value of F64 has been replaced by +// the argument. +func (x AllValue) WithF64(y float64) AllValue { + x.F64 = y + return x +} + +// ---- SmallBefore ---- // + +// SmallBefore is the type of a reference to an immutable record. +type SmallBefore struct{ ref *node } + +const SmallBefore_Slot_A_Type = 3 +const SmallBefore_Slot_A_Num = -1 +const SmallBefore_Slot_A_BitSize = -1 +const SmallBefore_Slot_A_BitOffset = -1 +const SmallBefore_Slot_A_ByteSize = -1 +const SmallBefore_Slot_A_ByteOffset = -1 +const SmallBefore_Slot_A_ValueMask = -1 + +const SmallBefore_Slot_B_Type = 3 +const SmallBefore_Slot_B_Num = -1 +const SmallBefore_Slot_B_BitSize = -1 +const SmallBefore_Slot_B_BitOffset = -1 +const SmallBefore_Slot_B_ByteSize = -1 +const SmallBefore_Slot_B_ByteOffset = -1 +const SmallBefore_Slot_B_ValueMask = -1 + +const SmallBefore_Slot_C_Type = 3 +const SmallBefore_Slot_C_Num = -1 +const SmallBefore_Slot_C_BitSize = -1 +const SmallBefore_Slot_C_BitOffset = -1 +const SmallBefore_Slot_C_ByteSize = -1 +const SmallBefore_Slot_C_ByteOffset = -1 +const SmallBefore_Slot_C_ValueMask = -1 + +const SmallBefore_Slot_D_Type = 3 +const SmallBefore_Slot_D_Num = -1 +const SmallBefore_Slot_D_BitSize = -1 +const SmallBefore_Slot_D_BitOffset = -1 +const SmallBefore_Slot_D_ByteSize = -1 +const SmallBefore_Slot_D_ByteOffset = -1 +const SmallBefore_Slot_D_ValueMask = -1 + +const SmallBefore_Slot_E_Type = 3 +const SmallBefore_Slot_E_Num = -1 +const SmallBefore_Slot_E_BitSize = -1 +const SmallBefore_Slot_E_BitOffset = -1 +const SmallBefore_Slot_E_ByteSize = -1 +const SmallBefore_Slot_E_ByteOffset = -1 +const SmallBefore_Slot_E_ValueMask = -1 + +const SmallBefore_Slot_F_Type = 3 +const SmallBefore_Slot_F_Num = -1 +const SmallBefore_Slot_F_BitSize = -1 +const SmallBefore_Slot_F_BitOffset = -1 +const SmallBefore_Slot_F_ByteSize = -1 +const SmallBefore_Slot_F_ByteOffset = -1 +const SmallBefore_Slot_F_ValueMask = -1 + +const SmallBefore_Slot_G_Type = 3 +const SmallBefore_Slot_G_Num = -1 +const SmallBefore_Slot_G_BitSize = -1 +const SmallBefore_Slot_G_BitOffset = -1 +const SmallBefore_Slot_G_ByteSize = -1 +const SmallBefore_Slot_G_ByteOffset = -1 +const SmallBefore_Slot_G_ValueMask = -1 + +const SmallBefore_Slot_H_Type = 3 +const SmallBefore_Slot_H_Num = -1 +const SmallBefore_Slot_H_BitSize = -1 +const SmallBefore_Slot_H_BitOffset = -1 +const SmallBefore_Slot_H_ByteSize = -1 +const SmallBefore_Slot_H_ByteOffset = -1 +const SmallBefore_Slot_H_ValueMask = -1 + +const SmallBefore_Slot_I_Type = 3 +const SmallBefore_Slot_I_Num = -1 +const SmallBefore_Slot_I_BitSize = -1 +const SmallBefore_Slot_I_BitOffset = -1 +const SmallBefore_Slot_I_ByteSize = -1 +const SmallBefore_Slot_I_ByteOffset = -1 +const SmallBefore_Slot_I_ValueMask = -1 + +// SmallBeforeValue is the logical type of a record. Immutable records are stored in +// nodes. +type SmallBeforeValue struct { + A bool // 1 + B bool // 2 + C uint8 // 3 + D uint8 // 4 + E uint8 // 5 + F uint16 // 6 + G uint16 // 7 + H uint32 // 8 + I uint64 // 9 +} + +type extraSmallBefore struct { + A bool + B bool + C uint8 + D uint8 + E uint8 + F uint16 + G uint16 + H uint32 + I uint64 +} + +func (x extraSmallBefore) extraRefs() []*node { return nil } + +// R constructs a reference to an immutable record. +func (x SmallBeforeValue) R(a *Allocator) SmallBefore { + ref := a.new() + extra := &extraSmallBefore{} + ref.extra = extra + + extra.A = x.A + extra.B = x.B + extra.C = x.C + extra.D = x.D + extra.E = x.E + extra.F = x.F + extra.G = x.G + extra.H = x.H + extra.I = x.I + return SmallBefore{ref} +} + +// A returns the A field. +func (x SmallBefore) A() bool { return x.ref.extra.(*extraSmallBefore).A } + +// B returns the B field. +func (x SmallBefore) B() bool { return x.ref.extra.(*extraSmallBefore).B } + +// C returns the C field. +func (x SmallBefore) C() uint8 { return x.ref.extra.(*extraSmallBefore).C } + +// D returns the D field. +func (x SmallBefore) D() uint8 { return x.ref.extra.(*extraSmallBefore).D } + +// E returns the E field. +func (x SmallBefore) E() uint8 { return x.ref.extra.(*extraSmallBefore).E } + +// F returns the F field. +func (x SmallBefore) F() uint16 { return x.ref.extra.(*extraSmallBefore).F } + +// G returns the G field. +func (x SmallBefore) G() uint16 { return x.ref.extra.(*extraSmallBefore).G } + +// H returns the H field. +func (x SmallBefore) H() uint32 { return x.ref.extra.(*extraSmallBefore).H } + +// I returns the I field. +func (x SmallBefore) I() uint64 { return x.ref.extra.(*extraSmallBefore).I } + +// V unpacks a reference into a value. +func (x SmallBefore) V() SmallBeforeValue { + return SmallBeforeValue{ + A: x.ref.extra.(*extraSmallBefore).A, + B: x.ref.extra.(*extraSmallBefore).B, + C: x.ref.extra.(*extraSmallBefore).C, + D: x.ref.extra.(*extraSmallBefore).D, + E: x.ref.extra.(*extraSmallBefore).E, + F: x.ref.extra.(*extraSmallBefore).F, + G: x.ref.extra.(*extraSmallBefore).G, + H: x.ref.extra.(*extraSmallBefore).H, + I: x.ref.extra.(*extraSmallBefore).I, + } +} + +// WithA constructs a new value where the value of A has been replaced by +// the argument. +func (x SmallBeforeValue) WithA(y bool) SmallBeforeValue { + x.A = y + return x +} + +// WithB constructs a new value where the value of B has been replaced by +// the argument. +func (x SmallBeforeValue) WithB(y bool) SmallBeforeValue { + x.B = y + return x +} + +// WithC constructs a new value where the value of C has been replaced by +// the argument. +func (x SmallBeforeValue) WithC(y uint8) SmallBeforeValue { + x.C = y + return x +} + +// WithD constructs a new value where the value of D has been replaced by +// the argument. +func (x SmallBeforeValue) WithD(y uint8) SmallBeforeValue { + x.D = y + return x +} + +// WithE constructs a new value where the value of E has been replaced by +// the argument. +func (x SmallBeforeValue) WithE(y uint8) SmallBeforeValue { + x.E = y + return x +} + +// WithF constructs a new value where the value of F has been replaced by +// the argument. +func (x SmallBeforeValue) WithF(y uint16) SmallBeforeValue { + x.F = y + return x +} + +// WithG constructs a new value where the value of G has been replaced by +// the argument. +func (x SmallBeforeValue) WithG(y uint16) SmallBeforeValue { + x.G = y + return x +} + +// WithH constructs a new value where the value of H has been replaced by +// the argument. +func (x SmallBeforeValue) WithH(y uint32) SmallBeforeValue { + x.H = y + return x +} + +// WithI constructs a new value where the value of I has been replaced by +// the argument. +func (x SmallBeforeValue) WithI(y uint64) SmallBeforeValue { + x.I = y + return x +} + +// ---- BigBefore ---- // + +// BigBefore is the type of a reference to an immutable record. +type BigBefore struct{ ref *node } + +const BigBefore_Slot_A_Type = 3 +const BigBefore_Slot_A_Num = -1 +const BigBefore_Slot_A_BitSize = -1 +const BigBefore_Slot_A_BitOffset = -1 +const BigBefore_Slot_A_ByteSize = -1 +const BigBefore_Slot_A_ByteOffset = -1 +const BigBefore_Slot_A_ValueMask = -1 + +const BigBefore_Slot_B_Type = 3 +const BigBefore_Slot_B_Num = -1 +const BigBefore_Slot_B_BitSize = -1 +const BigBefore_Slot_B_BitOffset = -1 +const BigBefore_Slot_B_ByteSize = -1 +const BigBefore_Slot_B_ByteOffset = -1 +const BigBefore_Slot_B_ValueMask = -1 + +const BigBefore_Slot_C_Type = 3 +const BigBefore_Slot_C_Num = -1 +const BigBefore_Slot_C_BitSize = -1 +const BigBefore_Slot_C_BitOffset = -1 +const BigBefore_Slot_C_ByteSize = -1 +const BigBefore_Slot_C_ByteOffset = -1 +const BigBefore_Slot_C_ValueMask = -1 + +const BigBefore_Slot_D_Type = 3 +const BigBefore_Slot_D_Num = -1 +const BigBefore_Slot_D_BitSize = -1 +const BigBefore_Slot_D_BitOffset = -1 +const BigBefore_Slot_D_ByteSize = -1 +const BigBefore_Slot_D_ByteOffset = -1 +const BigBefore_Slot_D_ValueMask = -1 + +const BigBefore_Slot_E_Type = 3 +const BigBefore_Slot_E_Num = -1 +const BigBefore_Slot_E_BitSize = -1 +const BigBefore_Slot_E_BitOffset = -1 +const BigBefore_Slot_E_ByteSize = -1 +const BigBefore_Slot_E_ByteOffset = -1 +const BigBefore_Slot_E_ValueMask = -1 + +const BigBefore_Slot_F_Type = 3 +const BigBefore_Slot_F_Num = -1 +const BigBefore_Slot_F_BitSize = -1 +const BigBefore_Slot_F_BitOffset = -1 +const BigBefore_Slot_F_ByteSize = -1 +const BigBefore_Slot_F_ByteOffset = -1 +const BigBefore_Slot_F_ValueMask = -1 + +const BigBefore_Slot_G_Type = 3 +const BigBefore_Slot_G_Num = -1 +const BigBefore_Slot_G_BitSize = -1 +const BigBefore_Slot_G_BitOffset = -1 +const BigBefore_Slot_G_ByteSize = -1 +const BigBefore_Slot_G_ByteOffset = -1 +const BigBefore_Slot_G_ValueMask = -1 + +const BigBefore_Slot_H_Type = 3 +const BigBefore_Slot_H_Num = -1 +const BigBefore_Slot_H_BitSize = -1 +const BigBefore_Slot_H_BitOffset = -1 +const BigBefore_Slot_H_ByteSize = -1 +const BigBefore_Slot_H_ByteOffset = -1 +const BigBefore_Slot_H_ValueMask = -1 + +const BigBefore_Slot_I_Type = 3 +const BigBefore_Slot_I_Num = -1 +const BigBefore_Slot_I_BitSize = -1 +const BigBefore_Slot_I_BitOffset = -1 +const BigBefore_Slot_I_ByteSize = -1 +const BigBefore_Slot_I_ByteOffset = -1 +const BigBefore_Slot_I_ValueMask = -1 + +// BigBeforeValue is the logical type of a record. Immutable records are stored in +// nodes. +type BigBeforeValue struct { + A uint64 // 1 + B uint32 // 2 + C uint16 // 3 + D uint16 // 4 + E uint8 // 5 + F uint8 // 6 + G uint8 // 7 + H bool // 8 + I bool // 9 +} + +type extraBigBefore struct { + A uint64 + B uint32 + C uint16 + D uint16 + E uint8 + F uint8 + G uint8 + H bool + I bool +} + +func (x extraBigBefore) extraRefs() []*node { return nil } + +// R constructs a reference to an immutable record. +func (x BigBeforeValue) R(a *Allocator) BigBefore { + ref := a.new() + extra := &extraBigBefore{} + ref.extra = extra + + extra.A = x.A + extra.B = x.B + extra.C = x.C + extra.D = x.D + extra.E = x.E + extra.F = x.F + extra.G = x.G + extra.H = x.H + extra.I = x.I + return BigBefore{ref} +} + +// A returns the A field. +func (x BigBefore) A() uint64 { return x.ref.extra.(*extraBigBefore).A } + +// B returns the B field. +func (x BigBefore) B() uint32 { return x.ref.extra.(*extraBigBefore).B } + +// C returns the C field. +func (x BigBefore) C() uint16 { return x.ref.extra.(*extraBigBefore).C } + +// D returns the D field. +func (x BigBefore) D() uint16 { return x.ref.extra.(*extraBigBefore).D } + +// E returns the E field. +func (x BigBefore) E() uint8 { return x.ref.extra.(*extraBigBefore).E } + +// F returns the F field. +func (x BigBefore) F() uint8 { return x.ref.extra.(*extraBigBefore).F } + +// G returns the G field. +func (x BigBefore) G() uint8 { return x.ref.extra.(*extraBigBefore).G } + +// H returns the H field. +func (x BigBefore) H() bool { return x.ref.extra.(*extraBigBefore).H } + +// I returns the I field. +func (x BigBefore) I() bool { return x.ref.extra.(*extraBigBefore).I } + +// V unpacks a reference into a value. +func (x BigBefore) V() BigBeforeValue { + return BigBeforeValue{ + A: x.ref.extra.(*extraBigBefore).A, + B: x.ref.extra.(*extraBigBefore).B, + C: x.ref.extra.(*extraBigBefore).C, + D: x.ref.extra.(*extraBigBefore).D, + E: x.ref.extra.(*extraBigBefore).E, + F: x.ref.extra.(*extraBigBefore).F, + G: x.ref.extra.(*extraBigBefore).G, + H: x.ref.extra.(*extraBigBefore).H, + I: x.ref.extra.(*extraBigBefore).I, + } +} + +// WithA constructs a new value where the value of A has been replaced by +// the argument. +func (x BigBeforeValue) WithA(y uint64) BigBeforeValue { + x.A = y + return x +} + +// WithB constructs a new value where the value of B has been replaced by +// the argument. +func (x BigBeforeValue) WithB(y uint32) BigBeforeValue { + x.B = y + return x +} + +// WithC constructs a new value where the value of C has been replaced by +// the argument. +func (x BigBeforeValue) WithC(y uint16) BigBeforeValue { + x.C = y + return x +} + +// WithD constructs a new value where the value of D has been replaced by +// the argument. +func (x BigBeforeValue) WithD(y uint16) BigBeforeValue { + x.D = y + return x +} + +// WithE constructs a new value where the value of E has been replaced by +// the argument. +func (x BigBeforeValue) WithE(y uint8) BigBeforeValue { + x.E = y + return x +} + +// WithF constructs a new value where the value of F has been replaced by +// the argument. +func (x BigBeforeValue) WithF(y uint8) BigBeforeValue { + x.F = y + return x +} + +// WithG constructs a new value where the value of G has been replaced by +// the argument. +func (x BigBeforeValue) WithG(y uint8) BigBeforeValue { + x.G = y + return x +} + +// WithH constructs a new value where the value of H has been replaced by +// the argument. +func (x BigBeforeValue) WithH(y bool) BigBeforeValue { + x.H = y + return x +} + +// WithI constructs a new value where the value of I has been replaced by +// the argument. +func (x BigBeforeValue) WithI(y bool) BigBeforeValue { + x.I = y + return x +} + +// Codegen parameters: +// {NumNumericSlots:0 NumericSlotSize:64 NumRefSlots:0 NumStrSlots:0 Pack:false} +// diff --git a/pkg/sql/ir/tests/onlyextra/prims/base/sexpr.ir.go b/pkg/sql/ir/tests/onlyextra/prims/base/sexpr.ir.go new file mode 100644 index 000000000000..df520ce96fb8 --- /dev/null +++ b/pkg/sql/ir/tests/onlyextra/prims/base/sexpr.ir.go @@ -0,0 +1,151 @@ +// Code generated by irgen/irgen base/sexpr.tmpl.go tests/prims.def. DO NOT EDIT. +// GENERATED FILE DO NOT EDIT +// Copyright 2017 The Cockroach Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. + +package base + +import ( + "bytes" + "fmt" +) + +type SexprFormatter interface { + FormatSExpr(buf *bytes.Buffer) +} + +func FormatSExprBool(buf *bytes.Buffer, x bool) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt64(buf *bytes.Buffer, x int64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt32(buf *bytes.Buffer, x int32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt16(buf *bytes.Buffer, x int16) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt8(buf *bytes.Buffer, x int8) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint64(buf *bytes.Buffer, x uint64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint32(buf *bytes.Buffer, x uint32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint16(buf *bytes.Buffer, x uint16) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint8(buf *bytes.Buffer, x uint8) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprFloat32(buf *bytes.Buffer, x float32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprFloat64(buf *bytes.Buffer, x float64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprString(buf *bytes.Buffer, x string) { fmt.Fprintf(buf, "%q", x) } + +func (x All) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(All") + + buf.WriteString(" B: ") + FormatSExprBool(buf, x.B()) + + buf.WriteString(" I8: ") + FormatSExprInt8(buf, x.I8()) + + buf.WriteString(" U8: ") + FormatSExprUint8(buf, x.U8()) + + buf.WriteString(" I16: ") + FormatSExprInt16(buf, x.I16()) + + buf.WriteString(" U16: ") + FormatSExprUint16(buf, x.U16()) + + buf.WriteString(" I32: ") + FormatSExprInt32(buf, x.I32()) + + buf.WriteString(" U32: ") + FormatSExprUint32(buf, x.U32()) + + buf.WriteString(" I64: ") + FormatSExprInt64(buf, x.I64()) + + buf.WriteString(" U64: ") + FormatSExprUint64(buf, x.U64()) + + buf.WriteString(" S: ") + FormatSExprString(buf, x.S()) + + buf.WriteString(" F32: ") + FormatSExprFloat32(buf, x.F32()) + + buf.WriteString(" F64: ") + FormatSExprFloat64(buf, x.F64()) + + buf.WriteByte(')') +} + +func (x SmallBefore) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(SmallBefore") + + buf.WriteString(" A: ") + FormatSExprBool(buf, x.A()) + + buf.WriteString(" B: ") + FormatSExprBool(buf, x.B()) + + buf.WriteString(" C: ") + FormatSExprUint8(buf, x.C()) + + buf.WriteString(" D: ") + FormatSExprUint8(buf, x.D()) + + buf.WriteString(" E: ") + FormatSExprUint8(buf, x.E()) + + buf.WriteString(" F: ") + FormatSExprUint16(buf, x.F()) + + buf.WriteString(" G: ") + FormatSExprUint16(buf, x.G()) + + buf.WriteString(" H: ") + FormatSExprUint32(buf, x.H()) + + buf.WriteString(" I: ") + FormatSExprUint64(buf, x.I()) + + buf.WriteByte(')') +} + +func (x BigBefore) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(BigBefore") + + buf.WriteString(" A: ") + FormatSExprUint64(buf, x.A()) + + buf.WriteString(" B: ") + FormatSExprUint32(buf, x.B()) + + buf.WriteString(" C: ") + FormatSExprUint16(buf, x.C()) + + buf.WriteString(" D: ") + FormatSExprUint16(buf, x.D()) + + buf.WriteString(" E: ") + FormatSExprUint8(buf, x.E()) + + buf.WriteString(" F: ") + FormatSExprUint8(buf, x.F()) + + buf.WriteString(" G: ") + FormatSExprUint8(buf, x.G()) + + buf.WriteString(" H: ") + FormatSExprBool(buf, x.H()) + + buf.WriteString(" I: ") + FormatSExprBool(buf, x.I()) + + buf.WriteByte(')') +} + +// Codegen parameters: +// {NumNumericSlots:0 NumericSlotSize:64 NumRefSlots:0 NumStrSlots:0 Pack:false} +// diff --git a/pkg/sql/ir/tests/prims.def b/pkg/sql/ir/tests/prims.def new file mode 100644 index 000000000000..bdccf9018637 --- /dev/null +++ b/pkg/sql/ir/tests/prims.def @@ -0,0 +1,38 @@ +struct All { + bool B = 1 + int8 I8 = 2 + uint8 U8 = 3 + int16 I16 = 4 + uint16 U16 = 5 + int32 I32 = 6 + uint32 U32 = 7 + int64 I64 = 8 + uint64 U64 = 9 + string S = 10 + float32 F32 = 11 + float64 F64 = 12 +} + +struct SmallBefore { + bool A = 1 + bool B = 2 + uint8 C = 3 + uint8 D = 4 + uint8 E = 5 + uint16 F = 6 + uint16 G = 7 + uint32 H = 8 + uint64 I = 9 +} + +struct BigBefore { + uint64 A = 1 + uint32 B = 2 + uint16 C = 3 + uint16 D = 4 + uint8 E = 5 + uint8 F = 6 + uint8 G = 7 + bool H = 8 + bool I = 9 +} diff --git a/pkg/sql/ir/tests/smallslots/example/base/base.ir.go b/pkg/sql/ir/tests/smallslots/example/base/base.ir.go new file mode 100644 index 000000000000..7a5eea53b8f9 --- /dev/null +++ b/pkg/sql/ir/tests/smallslots/example/base/base.ir.go @@ -0,0 +1,686 @@ +// Code generated by irgen/irgen base/base.tmpl.go tests/example.def. DO NOT EDIT. +// GENERATED FILE DO NOT EDIT +// Copyright 2017 The Cockroach Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. + +package base + +import ( + "fmt" +) + +// node is a generic ADT node type, with slots for references to other nodes and +// enumeration values. Values that don't fit and values of other types go in the +// extra field. +type node struct { + refs [2]*node + nums [20]numvalslot + strs [1]string + extra +} + +// enum is the type to define the tag part for working copies of IR +// node with sum and enum types. +type enum uint32 + +// numvalslot is the type used to store integer values in persistent IR nodes. +// must be larger than or as large as enum. +type numvalslot uint16 + +type extra interface { + extraRefs() []*node +} + +// Allocator allocates nodes in batches. Construct Allocators with NewAllocator +// and pass them by value. +type Allocator struct { + nodes []node +} + +// MakeAllocator constructs a new Allocator. +func MakeAllocator() Allocator { + nodes := make([]node, 16) + return Allocator{nodes} +} + +// NewAllocator allocates a new Allocator. +func NewAllocator() *Allocator { + a := MakeAllocator() + return &a +} + +// new allocates a new node. Users of this package should use the appropriate +// R() method, which is type safe. +func (a *Allocator) new() *node { + nodes := a.nodes + if len(nodes) == 0 { + nodes = make([]node, 256) + } + x := &nodes[0] + a.nodes = nodes[1:] + return x +} + +// ---- BinOp ---- // + +// BinOp is an enumeration type. +type BinOp enum + +// BinOp constants. +const ( + BinOpAdd BinOp = 1 + BinOpMul BinOp = 2 +) + +func (x BinOp) String() string { + switch x { + case BinOpAdd: + return "Add" + case BinOpMul: + return "Mul" + default: + return fmt.Sprintf("", x) + } +} + +// ---- ConstExpr ---- // + +// ConstExpr is the type of a reference to an immutable record. +type ConstExpr struct{ ref *node } + +const ConstExpr_Slot_Datum_Type = 3 +const ConstExpr_Slot_Datum_Num = -1 +const ConstExpr_Slot_Datum_BitSize = -1 +const ConstExpr_Slot_Datum_BitOffset = -1 +const ConstExpr_Slot_Datum_ByteSize = -1 +const ConstExpr_Slot_Datum_ByteOffset = -1 +const ConstExpr_Slot_Datum_ValueMask = -1 + +// ConstExprValue is the logical type of a record. Immutable records are stored in +// nodes. +type ConstExprValue struct { + Datum int64 // 1 +} + +type extraConstExpr struct { + Datum int64 +} + +func (x extraConstExpr) extraRefs() []*node { return nil } + +// R constructs a reference to an immutable record. +func (x ConstExprValue) R(a *Allocator) ConstExpr { + ref := a.new() + extra := &extraConstExpr{} + ref.extra = extra + + extra.Datum = x.Datum + return ConstExpr{ref} +} + +// Datum returns the Datum field. +func (x ConstExpr) Datum() int64 { return x.ref.extra.(*extraConstExpr).Datum } + +// V unpacks a reference into a value. +func (x ConstExpr) V() ConstExprValue { + return ConstExprValue{ + Datum: x.ref.extra.(*extraConstExpr).Datum, + } +} + +// WithDatum constructs a new value where the value of Datum has been replaced by +// the argument. +func (x ConstExprValue) WithDatum(y int64) ConstExprValue { + x.Datum = y + return x +} + +// ---- BinExpr ---- // + +// BinExpr is the type of a reference to an immutable record. +type BinExpr struct{ ref *node } + +const BinExpr_Slot_Left_Type = 0 +const BinExpr_Slot_Left_Num = 0 +const BinExpr_Slot_Left_BitSize = -1 +const BinExpr_Slot_Left_BitOffset = -1 +const BinExpr_Slot_Left_ByteSize = -1 +const BinExpr_Slot_Left_ByteOffset = -1 +const BinExpr_Slot_Left_ValueMask = -1 + +const BinExpr_Slot_Left__Tag_Type = 1 +const BinExpr_Slot_Left__Tag_Num = 0 +const BinExpr_Slot_Left__Tag_BitSize = 2 +const BinExpr_Slot_Left__Tag_BitOffset = 0 +const BinExpr_Slot_Left__Tag_ByteSize = 1 +const BinExpr_Slot_Left__Tag_ByteOffset = 0 +const BinExpr_Slot_Left__Tag_ValueMask = 0x3 + +const BinExpr_Slot_Op_Type = 1 +const BinExpr_Slot_Op_Num = 0 +const BinExpr_Slot_Op_BitSize = 2 +const BinExpr_Slot_Op_BitOffset = 2 +const BinExpr_Slot_Op_ByteSize = 1 +const BinExpr_Slot_Op_ByteOffset = 0 +const BinExpr_Slot_Op_ValueMask = 0x3 + +const BinExpr_Slot_Right_Type = 0 +const BinExpr_Slot_Right_Num = 1 +const BinExpr_Slot_Right_BitSize = -1 +const BinExpr_Slot_Right_BitOffset = -1 +const BinExpr_Slot_Right_ByteSize = -1 +const BinExpr_Slot_Right_ByteOffset = -1 +const BinExpr_Slot_Right_ValueMask = -1 + +const BinExpr_Slot_Right__Tag_Type = 1 +const BinExpr_Slot_Right__Tag_Num = 0 +const BinExpr_Slot_Right__Tag_BitSize = 2 +const BinExpr_Slot_Right__Tag_BitOffset = 4 +const BinExpr_Slot_Right__Tag_ByteSize = 1 +const BinExpr_Slot_Right__Tag_ByteOffset = 0 +const BinExpr_Slot_Right__Tag_ValueMask = 0x3 + +// BinExprValue is the logical type of a record. Immutable records are stored in +// nodes. +type BinExprValue struct { + Left Expr // 1 + Op BinOp // 2 + Right Expr // 3 +} + +// R constructs a reference to an immutable record. +func (x BinExprValue) R(a *Allocator) BinExpr { + ref := a.new() + + ref.nums[0] = (ref.nums[0] &^ (BinExpr_Slot_Left__Tag_ValueMask << BinExpr_Slot_Left__Tag_BitOffset)) | (numvalslot(x.Left.tag) << BinExpr_Slot_Left__Tag_BitOffset) + ref.refs[0] = x.Left.ref + ref.nums[0] = (ref.nums[0] &^ (BinExpr_Slot_Op_ValueMask << BinExpr_Slot_Op_BitOffset)) | (numvalslot(x.Op) << BinExpr_Slot_Op_BitOffset) + ref.nums[0] = (ref.nums[0] &^ (BinExpr_Slot_Right__Tag_ValueMask << BinExpr_Slot_Right__Tag_BitOffset)) | (numvalslot(x.Right.tag) << BinExpr_Slot_Right__Tag_BitOffset) + ref.refs[1] = x.Right.ref + return BinExpr{ref} +} + +// Left returns the Left field. +func (x BinExpr) Left() Expr { + return Expr{ExprTag((x.ref.nums[0] >> BinExpr_Slot_Left__Tag_BitOffset) & BinExpr_Slot_Left__Tag_ValueMask), x.ref.refs[0]} +} + +// Op returns the Op field. +func (x BinExpr) Op() BinOp { + return BinOp((x.ref.nums[0] >> BinExpr_Slot_Op_BitOffset) & BinExpr_Slot_Op_ValueMask) +} + +// Right returns the Right field. +func (x BinExpr) Right() Expr { + return Expr{ExprTag((x.ref.nums[0] >> BinExpr_Slot_Right__Tag_BitOffset) & BinExpr_Slot_Right__Tag_ValueMask), x.ref.refs[1]} +} + +// V unpacks a reference into a value. +func (x BinExpr) V() BinExprValue { + return BinExprValue{ + Left: Expr{ExprTag((x.ref.nums[0] >> BinExpr_Slot_Left__Tag_BitOffset) & BinExpr_Slot_Left__Tag_ValueMask), x.ref.refs[0]}, + Op: BinOp((x.ref.nums[0] >> BinExpr_Slot_Op_BitOffset) & BinExpr_Slot_Op_ValueMask), + Right: Expr{ExprTag((x.ref.nums[0] >> BinExpr_Slot_Right__Tag_BitOffset) & BinExpr_Slot_Right__Tag_ValueMask), x.ref.refs[1]}, + } +} + +// WithLeft constructs a new value where the value of Left has been replaced by +// the argument. +func (x BinExprValue) WithLeft(y Expr) BinExprValue { + x.Left = y + return x +} + +// WithOp constructs a new value where the value of Op has been replaced by +// the argument. +func (x BinExprValue) WithOp(y BinOp) BinExprValue { + x.Op = y + return x +} + +// WithRight constructs a new value where the value of Right has been replaced by +// the argument. +func (x BinExprValue) WithRight(y Expr) BinExprValue { + x.Right = y + return x +} + +// ---- TriExpr ---- // + +// TriExpr is the type of a reference to an immutable record. +type TriExpr struct{ ref *node } + +const TriExpr_Slot_One_Type = 0 +const TriExpr_Slot_One_Num = 0 +const TriExpr_Slot_One_BitSize = -1 +const TriExpr_Slot_One_BitOffset = -1 +const TriExpr_Slot_One_ByteSize = -1 +const TriExpr_Slot_One_ByteOffset = -1 +const TriExpr_Slot_One_ValueMask = -1 + +const TriExpr_Slot_One__Tag_Type = 1 +const TriExpr_Slot_One__Tag_Num = 0 +const TriExpr_Slot_One__Tag_BitSize = 2 +const TriExpr_Slot_One__Tag_BitOffset = 0 +const TriExpr_Slot_One__Tag_ByteSize = 1 +const TriExpr_Slot_One__Tag_ByteOffset = 0 +const TriExpr_Slot_One__Tag_ValueMask = 0x3 + +const TriExpr_Slot_Three_Type = 4 +const TriExpr_Slot_Three_Num = 0 +const TriExpr_Slot_Three_BitSize = -1 +const TriExpr_Slot_Three_BitOffset = -1 +const TriExpr_Slot_Three_ByteSize = -1 +const TriExpr_Slot_Three_ByteOffset = -1 +const TriExpr_Slot_Three_ValueMask = -1 + +const TriExpr_Slot_Three__Tag_Type = 1 +const TriExpr_Slot_Three__Tag_Num = 0 +const TriExpr_Slot_Three__Tag_BitSize = 2 +const TriExpr_Slot_Three__Tag_BitOffset = 4 +const TriExpr_Slot_Three__Tag_ByteSize = 1 +const TriExpr_Slot_Three__Tag_ByteOffset = 0 +const TriExpr_Slot_Three__Tag_ValueMask = 0x3 + +const TriExpr_Slot_Two_Type = 0 +const TriExpr_Slot_Two_Num = 1 +const TriExpr_Slot_Two_BitSize = -1 +const TriExpr_Slot_Two_BitOffset = -1 +const TriExpr_Slot_Two_ByteSize = -1 +const TriExpr_Slot_Two_ByteOffset = -1 +const TriExpr_Slot_Two_ValueMask = -1 + +const TriExpr_Slot_Two__Tag_Type = 1 +const TriExpr_Slot_Two__Tag_Num = 0 +const TriExpr_Slot_Two__Tag_BitSize = 2 +const TriExpr_Slot_Two__Tag_BitOffset = 2 +const TriExpr_Slot_Two__Tag_ByteSize = 1 +const TriExpr_Slot_Two__Tag_ByteOffset = 0 +const TriExpr_Slot_Two__Tag_ValueMask = 0x3 + +// TriExprValue is the logical type of a record. Immutable records are stored in +// nodes. +type TriExprValue struct { + One Expr // 1 + Two Expr // 2 + Three Expr // 4 +} + +type extraTriExpr struct { + refs [1]*node +} + +func (x extraTriExpr) extraRefs() []*node { return x.refs[:] } + +// R constructs a reference to an immutable record. +func (x TriExprValue) R(a *Allocator) TriExpr { + ref := a.new() + extra := &extraTriExpr{} + ref.extra = extra + + ref.nums[0] = (ref.nums[0] &^ (TriExpr_Slot_One__Tag_ValueMask << TriExpr_Slot_One__Tag_BitOffset)) | (numvalslot(x.One.tag) << TriExpr_Slot_One__Tag_BitOffset) + ref.refs[0] = x.One.ref + ref.nums[0] = (ref.nums[0] &^ (TriExpr_Slot_Two__Tag_ValueMask << TriExpr_Slot_Two__Tag_BitOffset)) | (numvalslot(x.Two.tag) << TriExpr_Slot_Two__Tag_BitOffset) + ref.refs[1] = x.Two.ref + ref.nums[0] = (ref.nums[0] &^ (TriExpr_Slot_Three__Tag_ValueMask << TriExpr_Slot_Three__Tag_BitOffset)) | (numvalslot(x.Three.tag) << TriExpr_Slot_Three__Tag_BitOffset) + extra.refs[0] = x.Three.ref + return TriExpr{ref} +} + +// One returns the One field. +func (x TriExpr) One() Expr { + return Expr{ExprTag((x.ref.nums[0] >> TriExpr_Slot_One__Tag_BitOffset) & TriExpr_Slot_One__Tag_ValueMask), x.ref.refs[0]} +} + +// Two returns the Two field. +func (x TriExpr) Two() Expr { + return Expr{ExprTag((x.ref.nums[0] >> TriExpr_Slot_Two__Tag_BitOffset) & TriExpr_Slot_Two__Tag_ValueMask), x.ref.refs[1]} +} + +// Three returns the Three field. +func (x TriExpr) Three() Expr { + return Expr{ExprTag((x.ref.nums[0] >> TriExpr_Slot_Three__Tag_BitOffset) & TriExpr_Slot_Three__Tag_ValueMask), x.ref.extra.(*extraTriExpr).refs[0]} +} + +// V unpacks a reference into a value. +func (x TriExpr) V() TriExprValue { + return TriExprValue{ + One: Expr{ExprTag((x.ref.nums[0] >> TriExpr_Slot_One__Tag_BitOffset) & TriExpr_Slot_One__Tag_ValueMask), x.ref.refs[0]}, + Two: Expr{ExprTag((x.ref.nums[0] >> TriExpr_Slot_Two__Tag_BitOffset) & TriExpr_Slot_Two__Tag_ValueMask), x.ref.refs[1]}, + Three: Expr{ExprTag((x.ref.nums[0] >> TriExpr_Slot_Three__Tag_BitOffset) & TriExpr_Slot_Three__Tag_ValueMask), x.ref.extra.(*extraTriExpr).refs[0]}, + } +} + +// WithOne constructs a new value where the value of One has been replaced by +// the argument. +func (x TriExprValue) WithOne(y Expr) TriExprValue { + x.One = y + return x +} + +// WithTwo constructs a new value where the value of Two has been replaced by +// the argument. +func (x TriExprValue) WithTwo(y Expr) TriExprValue { + x.Two = y + return x +} + +// WithThree constructs a new value where the value of Three has been replaced by +// the argument. +func (x TriExprValue) WithThree(y Expr) TriExprValue { + x.Three = y + return x +} + +// ---- All ---- // + +// All is the type of a reference to an immutable record. +type All struct{ ref *node } + +const All_Slot_A_Type = 4 +const All_Slot_A_Num = 1 +const All_Slot_A_BitSize = -1 +const All_Slot_A_BitOffset = -1 +const All_Slot_A_ByteSize = -1 +const All_Slot_A_ByteOffset = -1 +const All_Slot_A_ValueMask = -1 + +const All_Slot_A__Tag_Type = 1 +const All_Slot_A__Tag_Num = 0 +const All_Slot_A__Tag_BitSize = 2 +const All_Slot_A__Tag_BitOffset = 4 +const All_Slot_A__Tag_ByteSize = 1 +const All_Slot_A__Tag_ByteOffset = 0 +const All_Slot_A__Tag_ValueMask = 0x3 + +const All_Slot_BE_Type = 4 +const All_Slot_BE_Num = 0 +const All_Slot_BE_BitSize = -1 +const All_Slot_BE_BitOffset = -1 +const All_Slot_BE_ByteSize = -1 +const All_Slot_BE_ByteOffset = -1 +const All_Slot_BE_ValueMask = -1 + +const All_Slot_BO_Type = 1 +const All_Slot_BO_Num = 0 +const All_Slot_BO_BitSize = 2 +const All_Slot_BO_BitOffset = 2 +const All_Slot_BO_ByteSize = 1 +const All_Slot_BO_ByteOffset = 0 +const All_Slot_BO_ValueMask = 0x3 + +const All_Slot_CE_Type = 0 +const All_Slot_CE_Num = 1 +const All_Slot_CE_BitSize = -1 +const All_Slot_CE_BitOffset = -1 +const All_Slot_CE_ByteSize = -1 +const All_Slot_CE_ByteOffset = -1 +const All_Slot_CE_ValueMask = -1 + +const All_Slot_E_Type = 0 +const All_Slot_E_Num = 0 +const All_Slot_E_BitSize = -1 +const All_Slot_E_BitOffset = -1 +const All_Slot_E_ByteSize = -1 +const All_Slot_E_ByteOffset = -1 +const All_Slot_E_ValueMask = -1 + +const All_Slot_E__Tag_Type = 1 +const All_Slot_E__Tag_Num = 0 +const All_Slot_E__Tag_BitSize = 2 +const All_Slot_E__Tag_BitOffset = 0 +const All_Slot_E__Tag_ByteSize = 1 +const All_Slot_E__Tag_ByteOffset = 0 +const All_Slot_E__Tag_ValueMask = 0x3 + +// AllValue is the logical type of a record. Immutable records are stored in +// nodes. +type AllValue struct { + E Expr // 1 + CE ConstExpr // 2 + BE BinExpr // 3 + BO BinOp // 4 + A AllOrExpr // 5 +} + +type extraAll struct { + refs [2]*node +} + +func (x extraAll) extraRefs() []*node { return x.refs[:] } + +// R constructs a reference to an immutable record. +func (x AllValue) R(a *Allocator) All { + ref := a.new() + extra := &extraAll{} + ref.extra = extra + + ref.nums[0] = (ref.nums[0] &^ (All_Slot_E__Tag_ValueMask << All_Slot_E__Tag_BitOffset)) | (numvalslot(x.E.tag) << All_Slot_E__Tag_BitOffset) + ref.refs[0] = x.E.ref + ref.refs[1] = x.CE.ref + extra.refs[0] = x.BE.ref + ref.nums[0] = (ref.nums[0] &^ (All_Slot_BO_ValueMask << All_Slot_BO_BitOffset)) | (numvalslot(x.BO) << All_Slot_BO_BitOffset) + ref.nums[0] = (ref.nums[0] &^ (All_Slot_A__Tag_ValueMask << All_Slot_A__Tag_BitOffset)) | (numvalslot(x.A.tag) << All_Slot_A__Tag_BitOffset) + extra.refs[1] = x.A.ref + return All{ref} +} + +// E returns the E field. +func (x All) E() Expr { + return Expr{ExprTag((x.ref.nums[0] >> All_Slot_E__Tag_BitOffset) & All_Slot_E__Tag_ValueMask), x.ref.refs[0]} +} + +// CE returns the CE field. +func (x All) CE() ConstExpr { return ConstExpr{x.ref.refs[1]} } + +// BE returns the BE field. +func (x All) BE() BinExpr { return BinExpr{x.ref.extra.(*extraAll).refs[0]} } + +// BO returns the BO field. +func (x All) BO() BinOp { + return BinOp((x.ref.nums[0] >> All_Slot_BO_BitOffset) & All_Slot_BO_ValueMask) +} + +// A returns the A field. +func (x All) A() AllOrExpr { + return AllOrExpr{AllOrExprTag((x.ref.nums[0] >> All_Slot_A__Tag_BitOffset) & All_Slot_A__Tag_ValueMask), x.ref.extra.(*extraAll).refs[1]} +} + +// V unpacks a reference into a value. +func (x All) V() AllValue { + return AllValue{ + E: Expr{ExprTag((x.ref.nums[0] >> All_Slot_E__Tag_BitOffset) & All_Slot_E__Tag_ValueMask), x.ref.refs[0]}, + CE: ConstExpr{x.ref.refs[1]}, + BE: BinExpr{x.ref.extra.(*extraAll).refs[0]}, + BO: BinOp((x.ref.nums[0] >> All_Slot_BO_BitOffset) & All_Slot_BO_ValueMask), + A: AllOrExpr{AllOrExprTag((x.ref.nums[0] >> All_Slot_A__Tag_BitOffset) & All_Slot_A__Tag_ValueMask), x.ref.extra.(*extraAll).refs[1]}, + } +} + +// WithE constructs a new value where the value of E has been replaced by +// the argument. +func (x AllValue) WithE(y Expr) AllValue { + x.E = y + return x +} + +// WithCE constructs a new value where the value of CE has been replaced by +// the argument. +func (x AllValue) WithCE(y ConstExpr) AllValue { + x.CE = y + return x +} + +// WithBE constructs a new value where the value of BE has been replaced by +// the argument. +func (x AllValue) WithBE(y BinExpr) AllValue { + x.BE = y + return x +} + +// WithBO constructs a new value where the value of BO has been replaced by +// the argument. +func (x AllValue) WithBO(y BinOp) AllValue { + x.BO = y + return x +} + +// WithA constructs a new value where the value of A has been replaced by +// the argument. +func (x AllValue) WithA(y AllOrExpr) AllValue { + x.A = y + return x +} + +// ---- Expr ---- // + +// Expr is the type of a tagged union of records. +type Expr struct { + tag ExprTag + ref *node +} + +// ExprTag is the tag type. +type ExprTag enum + +// ExprTag constants. +const ( + ExprConstExpr ExprTag = 1 + ExprBinExpr ExprTag = 2 +) + +func (x ExprTag) String() string { + switch x { + case ExprConstExpr: + return "ConstExpr" + case ExprBinExpr: + return "BinExpr" + default: + return fmt.Sprintf("", x) + } +} + +// Tag returns the tag. +func (x Expr) Tag() ExprTag { return x.tag } + +// Expr performs an upcast. +func (x ConstExpr) Expr() Expr { return Expr{ExprConstExpr, x.ref} } + +// ConstExpr performs a downcast. If the downcast fails, return false. +func (x Expr) ConstExpr() (ConstExpr, bool) { + if x.tag != ExprConstExpr { + return ConstExpr{}, false + } + return ConstExpr{x.ref}, true +} + +// MustBeConstExpr performs a downcast. If the downcast fails, panic. +func (x Expr) MustBeConstExpr() ConstExpr { + if x.tag != ExprConstExpr { + panic(fmt.Sprintf("type assertion failed: expected ConstExpr but got %s", x.tag)) + } + return ConstExpr{x.ref} +} + +// Expr performs an upcast. +func (x BinExpr) Expr() Expr { return Expr{ExprBinExpr, x.ref} } + +// BinExpr performs a downcast. If the downcast fails, return false. +func (x Expr) BinExpr() (BinExpr, bool) { + if x.tag != ExprBinExpr { + return BinExpr{}, false + } + return BinExpr{x.ref}, true +} + +// MustBeBinExpr performs a downcast. If the downcast fails, panic. +func (x Expr) MustBeBinExpr() BinExpr { + if x.tag != ExprBinExpr { + panic(fmt.Sprintf("type assertion failed: expected BinExpr but got %s", x.tag)) + } + return BinExpr{x.ref} +} + +// ---- AllOrExpr ---- // + +// AllOrExpr is the type of a tagged union of records. +type AllOrExpr struct { + tag AllOrExprTag + ref *node +} + +// AllOrExprTag is the tag type. +type AllOrExprTag enum + +// AllOrExprTag constants. +const ( + AllOrExprAll AllOrExprTag = 1 + AllOrExprBinExpr AllOrExprTag = 2 +) + +func (x AllOrExprTag) String() string { + switch x { + case AllOrExprAll: + return "All" + case AllOrExprBinExpr: + return "BinExpr" + default: + return fmt.Sprintf("", x) + } +} + +// Tag returns the tag. +func (x AllOrExpr) Tag() AllOrExprTag { return x.tag } + +// AllOrExpr performs an upcast. +func (x All) AllOrExpr() AllOrExpr { return AllOrExpr{AllOrExprAll, x.ref} } + +// All performs a downcast. If the downcast fails, return false. +func (x AllOrExpr) All() (All, bool) { + if x.tag != AllOrExprAll { + return All{}, false + } + return All{x.ref}, true +} + +// MustBeAll performs a downcast. If the downcast fails, panic. +func (x AllOrExpr) MustBeAll() All { + if x.tag != AllOrExprAll { + panic(fmt.Sprintf("type assertion failed: expected All but got %s", x.tag)) + } + return All{x.ref} +} + +// AllOrExpr performs an upcast. +func (x BinExpr) AllOrExpr() AllOrExpr { return AllOrExpr{AllOrExprBinExpr, x.ref} } + +// BinExpr performs a downcast. If the downcast fails, return false. +func (x AllOrExpr) BinExpr() (BinExpr, bool) { + if x.tag != AllOrExprBinExpr { + return BinExpr{}, false + } + return BinExpr{x.ref}, true +} + +// MustBeBinExpr performs a downcast. If the downcast fails, panic. +func (x AllOrExpr) MustBeBinExpr() BinExpr { + if x.tag != AllOrExprBinExpr { + panic(fmt.Sprintf("type assertion failed: expected BinExpr but got %s", x.tag)) + } + return BinExpr{x.ref} +} + +// Codegen parameters: +// {NumNumericSlots:20 NumericSlotSize:16 NumRefSlots:2 NumStrSlots:1 Pack:true} +// diff --git a/pkg/sql/ir/tests/smallslots/example/base/sexpr.ir.go b/pkg/sql/ir/tests/smallslots/example/base/sexpr.ir.go new file mode 100644 index 000000000000..a7b04405be67 --- /dev/null +++ b/pkg/sql/ir/tests/smallslots/example/base/sexpr.ir.go @@ -0,0 +1,125 @@ +// Code generated by irgen/irgen base/sexpr.tmpl.go tests/example.def. DO NOT EDIT. +// GENERATED FILE DO NOT EDIT +// Copyright 2017 The Cockroach Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. + +package base + +import ( + "bytes" + "fmt" +) + +type SexprFormatter interface { + FormatSExpr(buf *bytes.Buffer) +} + +func FormatSExprBool(buf *bytes.Buffer, x bool) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt64(buf *bytes.Buffer, x int64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt32(buf *bytes.Buffer, x int32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt16(buf *bytes.Buffer, x int16) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt8(buf *bytes.Buffer, x int8) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint64(buf *bytes.Buffer, x uint64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint32(buf *bytes.Buffer, x uint32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint16(buf *bytes.Buffer, x uint16) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint8(buf *bytes.Buffer, x uint8) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprFloat32(buf *bytes.Buffer, x float32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprFloat64(buf *bytes.Buffer, x float64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprString(buf *bytes.Buffer, x string) { fmt.Fprintf(buf, "%q", x) } + +func (x BinOp) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString(x.String()) +} + +func (x ConstExpr) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(ConstExpr") + + buf.WriteString(" Datum: ") + FormatSExprInt64(buf, x.Datum()) + + buf.WriteByte(')') +} + +func (x BinExpr) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(BinExpr") + + buf.WriteString(" Left: ") + x.Left().FormatSExpr(buf) + + buf.WriteString(" Op: ") + x.Op().FormatSExpr(buf) + + buf.WriteString(" Right: ") + x.Right().FormatSExpr(buf) + + buf.WriteByte(')') +} + +func (x TriExpr) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(TriExpr") + + buf.WriteString(" One: ") + x.One().FormatSExpr(buf) + + buf.WriteString(" Two: ") + x.Two().FormatSExpr(buf) + + buf.WriteString(" Three: ") + x.Three().FormatSExpr(buf) + + buf.WriteByte(')') +} + +func (x All) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(All") + + buf.WriteString(" E: ") + x.E().FormatSExpr(buf) + + buf.WriteString(" CE: ") + x.CE().FormatSExpr(buf) + + buf.WriteString(" BE: ") + x.BE().FormatSExpr(buf) + + buf.WriteString(" BO: ") + x.BO().FormatSExpr(buf) + + buf.WriteString(" A: ") + x.A().FormatSExpr(buf) + + buf.WriteByte(')') +} + +func (x Expr) FormatSExpr(buf *bytes.Buffer) { + switch x.Tag() { + case ExprConstExpr: + x.MustBeConstExpr().FormatSExpr(buf) + case ExprBinExpr: + x.MustBeBinExpr().FormatSExpr(buf) + } +} + +func (x AllOrExpr) FormatSExpr(buf *bytes.Buffer) { + switch x.Tag() { + case AllOrExprAll: + x.MustBeAll().FormatSExpr(buf) + case AllOrExprBinExpr: + x.MustBeBinExpr().FormatSExpr(buf) + } +} + +// Codegen parameters: +// {NumNumericSlots:20 NumericSlotSize:16 NumRefSlots:2 NumStrSlots:1 Pack:true} +// diff --git a/pkg/sql/ir/tests/smallslots/prims/base/base.ir.go b/pkg/sql/ir/tests/smallslots/prims/base/base.ir.go new file mode 100644 index 000000000000..37c1039b9085 --- /dev/null +++ b/pkg/sql/ir/tests/smallslots/prims/base/base.ir.go @@ -0,0 +1,845 @@ +// Code generated by irgen/irgen base/base.tmpl.go tests/prims.def. DO NOT EDIT. +// GENERATED FILE DO NOT EDIT +// Copyright 2017 The Cockroach Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. + +package base + +// node is a generic ADT node type, with slots for references to other nodes and +// enumeration values. Values that don't fit and values of other types go in the +// extra field. +type node struct { + refs [2]*node + nums [20]numvalslot + strs [1]string + extra +} + +// enum is the type to define the tag part for working copies of IR +// node with sum and enum types. +type enum uint32 + +// numvalslot is the type used to store integer values in persistent IR nodes. +// must be larger than or as large as enum. +type numvalslot uint16 + +type extra interface { + extraRefs() []*node +} + +// Allocator allocates nodes in batches. Construct Allocators with NewAllocator +// and pass them by value. +type Allocator struct { + nodes []node +} + +// MakeAllocator constructs a new Allocator. +func MakeAllocator() Allocator { + nodes := make([]node, 16) + return Allocator{nodes} +} + +// NewAllocator allocates a new Allocator. +func NewAllocator() *Allocator { + a := MakeAllocator() + return &a +} + +// new allocates a new node. Users of this package should use the appropriate +// R() method, which is type safe. +func (a *Allocator) new() *node { + nodes := a.nodes + if len(nodes) == 0 { + nodes = make([]node, 256) + } + x := &nodes[0] + a.nodes = nodes[1:] + return x +} + +// ---- All ---- // + +// All is the type of a reference to an immutable record. +type All struct{ ref *node } + +const All_Slot_B_Type = 1 +const All_Slot_B_Num = 3 +const All_Slot_B_BitSize = 1 +const All_Slot_B_BitOffset = 0 +const All_Slot_B_ByteSize = 1 +const All_Slot_B_ByteOffset = 0 +const All_Slot_B_ValueMask = 0x1 + +const All_Slot_F32_Type = 3 +const All_Slot_F32_Num = -1 +const All_Slot_F32_BitSize = -1 +const All_Slot_F32_BitOffset = -1 +const All_Slot_F32_ByteSize = -1 +const All_Slot_F32_ByteOffset = -1 +const All_Slot_F32_ValueMask = -1 + +const All_Slot_F64_Type = 3 +const All_Slot_F64_Num = -1 +const All_Slot_F64_BitSize = -1 +const All_Slot_F64_BitOffset = -1 +const All_Slot_F64_ByteSize = -1 +const All_Slot_F64_ByteOffset = -1 +const All_Slot_F64_ValueMask = -1 + +const All_Slot_I16_Type = 1 +const All_Slot_I16_Num = 0 +const All_Slot_I16_BitSize = 16 +const All_Slot_I16_BitOffset = 0 +const All_Slot_I16_ByteSize = 2 +const All_Slot_I16_ByteOffset = 0 +const All_Slot_I16_ValueMask = 0xffff + +const All_Slot_I32_Type = 3 +const All_Slot_I32_Num = -1 +const All_Slot_I32_BitSize = -1 +const All_Slot_I32_BitOffset = -1 +const All_Slot_I32_ByteSize = -1 +const All_Slot_I32_ByteOffset = -1 +const All_Slot_I32_ValueMask = -1 + +const All_Slot_I64_Type = 3 +const All_Slot_I64_Num = -1 +const All_Slot_I64_BitSize = -1 +const All_Slot_I64_BitOffset = -1 +const All_Slot_I64_ByteSize = -1 +const All_Slot_I64_ByteOffset = -1 +const All_Slot_I64_ValueMask = -1 + +const All_Slot_I8_Type = 1 +const All_Slot_I8_Num = 2 +const All_Slot_I8_BitSize = 8 +const All_Slot_I8_BitOffset = 0 +const All_Slot_I8_ByteSize = 1 +const All_Slot_I8_ByteOffset = 0 +const All_Slot_I8_ValueMask = 0xff + +const All_Slot_S_Type = 2 +const All_Slot_S_Num = 0 +const All_Slot_S_BitSize = -1 +const All_Slot_S_BitOffset = -1 +const All_Slot_S_ByteSize = -1 +const All_Slot_S_ByteOffset = -1 +const All_Slot_S_ValueMask = -1 + +const All_Slot_U16_Type = 1 +const All_Slot_U16_Num = 1 +const All_Slot_U16_BitSize = 16 +const All_Slot_U16_BitOffset = 0 +const All_Slot_U16_ByteSize = 2 +const All_Slot_U16_ByteOffset = 0 +const All_Slot_U16_ValueMask = 0xffff + +const All_Slot_U32_Type = 3 +const All_Slot_U32_Num = -1 +const All_Slot_U32_BitSize = -1 +const All_Slot_U32_BitOffset = -1 +const All_Slot_U32_ByteSize = -1 +const All_Slot_U32_ByteOffset = -1 +const All_Slot_U32_ValueMask = -1 + +const All_Slot_U64_Type = 3 +const All_Slot_U64_Num = -1 +const All_Slot_U64_BitSize = -1 +const All_Slot_U64_BitOffset = -1 +const All_Slot_U64_ByteSize = -1 +const All_Slot_U64_ByteOffset = -1 +const All_Slot_U64_ValueMask = -1 + +const All_Slot_U8_Type = 1 +const All_Slot_U8_Num = 2 +const All_Slot_U8_BitSize = 8 +const All_Slot_U8_BitOffset = 8 +const All_Slot_U8_ByteSize = 1 +const All_Slot_U8_ByteOffset = 1 +const All_Slot_U8_ValueMask = 0xff + +// AllValue is the logical type of a record. Immutable records are stored in +// nodes. +type AllValue struct { + B bool // 1 + I8 int8 // 2 + U8 uint8 // 3 + I16 int16 // 4 + U16 uint16 // 5 + I32 int32 // 6 + U32 uint32 // 7 + I64 int64 // 8 + U64 uint64 // 9 + S string // 10 + F32 float32 // 11 + F64 float64 // 12 +} + +type extraAll struct { + I32 int32 + U32 uint32 + I64 int64 + U64 uint64 + F32 float32 + F64 float64 +} + +func (x extraAll) extraRefs() []*node { return nil } + +// R constructs a reference to an immutable record. +func (x AllValue) R(a *Allocator) All { + ref := a.new() + extra := &extraAll{} + ref.extra = extra + + if x.B { + ref.nums[3] |= (numvalslot(1) << All_Slot_B_BitOffset) + } else { + ref.nums[3] &^= (numvalslot(1) << All_Slot_B_BitOffset) + } + ref.nums[2] = (ref.nums[2] &^ (All_Slot_I8_ValueMask << All_Slot_I8_BitOffset)) | (numvalslot(x.I8) << All_Slot_I8_BitOffset) + ref.nums[2] = (ref.nums[2] &^ (All_Slot_U8_ValueMask << All_Slot_U8_BitOffset)) | (numvalslot(x.U8) << All_Slot_U8_BitOffset) + ref.nums[0] = numvalslot(x.I16) + ref.nums[1] = numvalslot(x.U16) + extra.I32 = x.I32 + extra.U32 = x.U32 + extra.I64 = x.I64 + extra.U64 = x.U64 + ref.strs[0] = x.S + extra.F32 = x.F32 + extra.F64 = x.F64 + return All{ref} +} + +// B returns the B field. +func (x All) B() bool { return !(0 == (x.ref.nums[3] >> All_Slot_B_BitOffset & All_Slot_B_ValueMask)) } + +// I8 returns the I8 field. +func (x All) I8() int8 { return int8((x.ref.nums[2] >> All_Slot_I8_BitOffset) & All_Slot_I8_ValueMask) } + +// U8 returns the U8 field. +func (x All) U8() uint8 { + return uint8((x.ref.nums[2] >> All_Slot_U8_BitOffset) & All_Slot_U8_ValueMask) +} + +// I16 returns the I16 field. +func (x All) I16() int16 { return int16(x.ref.nums[0]) } + +// U16 returns the U16 field. +func (x All) U16() uint16 { return uint16(x.ref.nums[1]) } + +// I32 returns the I32 field. +func (x All) I32() int32 { return x.ref.extra.(*extraAll).I32 } + +// U32 returns the U32 field. +func (x All) U32() uint32 { return x.ref.extra.(*extraAll).U32 } + +// I64 returns the I64 field. +func (x All) I64() int64 { return x.ref.extra.(*extraAll).I64 } + +// U64 returns the U64 field. +func (x All) U64() uint64 { return x.ref.extra.(*extraAll).U64 } + +// S returns the S field. +func (x All) S() string { return x.ref.strs[0] } + +// F32 returns the F32 field. +func (x All) F32() float32 { return x.ref.extra.(*extraAll).F32 } + +// F64 returns the F64 field. +func (x All) F64() float64 { return x.ref.extra.(*extraAll).F64 } + +// V unpacks a reference into a value. +func (x All) V() AllValue { + return AllValue{ + B: !(0 == (x.ref.nums[3] >> All_Slot_B_BitOffset & All_Slot_B_ValueMask)), + I8: int8((x.ref.nums[2] >> All_Slot_I8_BitOffset) & All_Slot_I8_ValueMask), + U8: uint8((x.ref.nums[2] >> All_Slot_U8_BitOffset) & All_Slot_U8_ValueMask), + I16: int16(x.ref.nums[0]), + U16: uint16(x.ref.nums[1]), + I32: x.ref.extra.(*extraAll).I32, + U32: x.ref.extra.(*extraAll).U32, + I64: x.ref.extra.(*extraAll).I64, + U64: x.ref.extra.(*extraAll).U64, + S: x.ref.strs[0], + F32: x.ref.extra.(*extraAll).F32, + F64: x.ref.extra.(*extraAll).F64, + } +} + +// WithB constructs a new value where the value of B has been replaced by +// the argument. +func (x AllValue) WithB(y bool) AllValue { + x.B = y + return x +} + +// WithI8 constructs a new value where the value of I8 has been replaced by +// the argument. +func (x AllValue) WithI8(y int8) AllValue { + x.I8 = y + return x +} + +// WithU8 constructs a new value where the value of U8 has been replaced by +// the argument. +func (x AllValue) WithU8(y uint8) AllValue { + x.U8 = y + return x +} + +// WithI16 constructs a new value where the value of I16 has been replaced by +// the argument. +func (x AllValue) WithI16(y int16) AllValue { + x.I16 = y + return x +} + +// WithU16 constructs a new value where the value of U16 has been replaced by +// the argument. +func (x AllValue) WithU16(y uint16) AllValue { + x.U16 = y + return x +} + +// WithI32 constructs a new value where the value of I32 has been replaced by +// the argument. +func (x AllValue) WithI32(y int32) AllValue { + x.I32 = y + return x +} + +// WithU32 constructs a new value where the value of U32 has been replaced by +// the argument. +func (x AllValue) WithU32(y uint32) AllValue { + x.U32 = y + return x +} + +// WithI64 constructs a new value where the value of I64 has been replaced by +// the argument. +func (x AllValue) WithI64(y int64) AllValue { + x.I64 = y + return x +} + +// WithU64 constructs a new value where the value of U64 has been replaced by +// the argument. +func (x AllValue) WithU64(y uint64) AllValue { + x.U64 = y + return x +} + +// WithS constructs a new value where the value of S has been replaced by +// the argument. +func (x AllValue) WithS(y string) AllValue { + x.S = y + return x +} + +// WithF32 constructs a new value where the value of F32 has been replaced by +// the argument. +func (x AllValue) WithF32(y float32) AllValue { + x.F32 = y + return x +} + +// WithF64 constructs a new value where the value of F64 has been replaced by +// the argument. +func (x AllValue) WithF64(y float64) AllValue { + x.F64 = y + return x +} + +// ---- SmallBefore ---- // + +// SmallBefore is the type of a reference to an immutable record. +type SmallBefore struct{ ref *node } + +const SmallBefore_Slot_A_Type = 1 +const SmallBefore_Slot_A_Num = 3 +const SmallBefore_Slot_A_BitSize = 1 +const SmallBefore_Slot_A_BitOffset = 8 +const SmallBefore_Slot_A_ByteSize = 1 +const SmallBefore_Slot_A_ByteOffset = 1 +const SmallBefore_Slot_A_ValueMask = 0x1 + +const SmallBefore_Slot_B_Type = 1 +const SmallBefore_Slot_B_Num = 3 +const SmallBefore_Slot_B_BitSize = 1 +const SmallBefore_Slot_B_BitOffset = 9 +const SmallBefore_Slot_B_ByteSize = 1 +const SmallBefore_Slot_B_ByteOffset = 1 +const SmallBefore_Slot_B_ValueMask = 0x1 + +const SmallBefore_Slot_C_Type = 1 +const SmallBefore_Slot_C_Num = 2 +const SmallBefore_Slot_C_BitSize = 8 +const SmallBefore_Slot_C_BitOffset = 0 +const SmallBefore_Slot_C_ByteSize = 1 +const SmallBefore_Slot_C_ByteOffset = 0 +const SmallBefore_Slot_C_ValueMask = 0xff + +const SmallBefore_Slot_D_Type = 1 +const SmallBefore_Slot_D_Num = 2 +const SmallBefore_Slot_D_BitSize = 8 +const SmallBefore_Slot_D_BitOffset = 8 +const SmallBefore_Slot_D_ByteSize = 1 +const SmallBefore_Slot_D_ByteOffset = 1 +const SmallBefore_Slot_D_ValueMask = 0xff + +const SmallBefore_Slot_E_Type = 1 +const SmallBefore_Slot_E_Num = 3 +const SmallBefore_Slot_E_BitSize = 8 +const SmallBefore_Slot_E_BitOffset = 0 +const SmallBefore_Slot_E_ByteSize = 1 +const SmallBefore_Slot_E_ByteOffset = 0 +const SmallBefore_Slot_E_ValueMask = 0xff + +const SmallBefore_Slot_F_Type = 1 +const SmallBefore_Slot_F_Num = 0 +const SmallBefore_Slot_F_BitSize = 16 +const SmallBefore_Slot_F_BitOffset = 0 +const SmallBefore_Slot_F_ByteSize = 2 +const SmallBefore_Slot_F_ByteOffset = 0 +const SmallBefore_Slot_F_ValueMask = 0xffff + +const SmallBefore_Slot_G_Type = 1 +const SmallBefore_Slot_G_Num = 1 +const SmallBefore_Slot_G_BitSize = 16 +const SmallBefore_Slot_G_BitOffset = 0 +const SmallBefore_Slot_G_ByteSize = 2 +const SmallBefore_Slot_G_ByteOffset = 0 +const SmallBefore_Slot_G_ValueMask = 0xffff + +const SmallBefore_Slot_H_Type = 3 +const SmallBefore_Slot_H_Num = -1 +const SmallBefore_Slot_H_BitSize = -1 +const SmallBefore_Slot_H_BitOffset = -1 +const SmallBefore_Slot_H_ByteSize = -1 +const SmallBefore_Slot_H_ByteOffset = -1 +const SmallBefore_Slot_H_ValueMask = -1 + +const SmallBefore_Slot_I_Type = 3 +const SmallBefore_Slot_I_Num = -1 +const SmallBefore_Slot_I_BitSize = -1 +const SmallBefore_Slot_I_BitOffset = -1 +const SmallBefore_Slot_I_ByteSize = -1 +const SmallBefore_Slot_I_ByteOffset = -1 +const SmallBefore_Slot_I_ValueMask = -1 + +// SmallBeforeValue is the logical type of a record. Immutable records are stored in +// nodes. +type SmallBeforeValue struct { + A bool // 1 + B bool // 2 + C uint8 // 3 + D uint8 // 4 + E uint8 // 5 + F uint16 // 6 + G uint16 // 7 + H uint32 // 8 + I uint64 // 9 +} + +type extraSmallBefore struct { + H uint32 + I uint64 +} + +func (x extraSmallBefore) extraRefs() []*node { return nil } + +// R constructs a reference to an immutable record. +func (x SmallBeforeValue) R(a *Allocator) SmallBefore { + ref := a.new() + extra := &extraSmallBefore{} + ref.extra = extra + + if x.A { + ref.nums[3] |= (numvalslot(1) << SmallBefore_Slot_A_BitOffset) + } else { + ref.nums[3] &^= (numvalslot(1) << SmallBefore_Slot_A_BitOffset) + } + if x.B { + ref.nums[3] |= (numvalslot(1) << SmallBefore_Slot_B_BitOffset) + } else { + ref.nums[3] &^= (numvalslot(1) << SmallBefore_Slot_B_BitOffset) + } + ref.nums[2] = (ref.nums[2] &^ (SmallBefore_Slot_C_ValueMask << SmallBefore_Slot_C_BitOffset)) | (numvalslot(x.C) << SmallBefore_Slot_C_BitOffset) + ref.nums[2] = (ref.nums[2] &^ (SmallBefore_Slot_D_ValueMask << SmallBefore_Slot_D_BitOffset)) | (numvalslot(x.D) << SmallBefore_Slot_D_BitOffset) + ref.nums[3] = (ref.nums[3] &^ (SmallBefore_Slot_E_ValueMask << SmallBefore_Slot_E_BitOffset)) | (numvalslot(x.E) << SmallBefore_Slot_E_BitOffset) + ref.nums[0] = numvalslot(x.F) + ref.nums[1] = numvalslot(x.G) + extra.H = x.H + extra.I = x.I + return SmallBefore{ref} +} + +// A returns the A field. +func (x SmallBefore) A() bool { + return !(0 == (x.ref.nums[3] >> SmallBefore_Slot_A_BitOffset & SmallBefore_Slot_A_ValueMask)) +} + +// B returns the B field. +func (x SmallBefore) B() bool { + return !(0 == (x.ref.nums[3] >> SmallBefore_Slot_B_BitOffset & SmallBefore_Slot_B_ValueMask)) +} + +// C returns the C field. +func (x SmallBefore) C() uint8 { + return uint8((x.ref.nums[2] >> SmallBefore_Slot_C_BitOffset) & SmallBefore_Slot_C_ValueMask) +} + +// D returns the D field. +func (x SmallBefore) D() uint8 { + return uint8((x.ref.nums[2] >> SmallBefore_Slot_D_BitOffset) & SmallBefore_Slot_D_ValueMask) +} + +// E returns the E field. +func (x SmallBefore) E() uint8 { + return uint8((x.ref.nums[3] >> SmallBefore_Slot_E_BitOffset) & SmallBefore_Slot_E_ValueMask) +} + +// F returns the F field. +func (x SmallBefore) F() uint16 { return uint16(x.ref.nums[0]) } + +// G returns the G field. +func (x SmallBefore) G() uint16 { return uint16(x.ref.nums[1]) } + +// H returns the H field. +func (x SmallBefore) H() uint32 { return x.ref.extra.(*extraSmallBefore).H } + +// I returns the I field. +func (x SmallBefore) I() uint64 { return x.ref.extra.(*extraSmallBefore).I } + +// V unpacks a reference into a value. +func (x SmallBefore) V() SmallBeforeValue { + return SmallBeforeValue{ + A: !(0 == (x.ref.nums[3] >> SmallBefore_Slot_A_BitOffset & SmallBefore_Slot_A_ValueMask)), + B: !(0 == (x.ref.nums[3] >> SmallBefore_Slot_B_BitOffset & SmallBefore_Slot_B_ValueMask)), + C: uint8((x.ref.nums[2] >> SmallBefore_Slot_C_BitOffset) & SmallBefore_Slot_C_ValueMask), + D: uint8((x.ref.nums[2] >> SmallBefore_Slot_D_BitOffset) & SmallBefore_Slot_D_ValueMask), + E: uint8((x.ref.nums[3] >> SmallBefore_Slot_E_BitOffset) & SmallBefore_Slot_E_ValueMask), + F: uint16(x.ref.nums[0]), + G: uint16(x.ref.nums[1]), + H: x.ref.extra.(*extraSmallBefore).H, + I: x.ref.extra.(*extraSmallBefore).I, + } +} + +// WithA constructs a new value where the value of A has been replaced by +// the argument. +func (x SmallBeforeValue) WithA(y bool) SmallBeforeValue { + x.A = y + return x +} + +// WithB constructs a new value where the value of B has been replaced by +// the argument. +func (x SmallBeforeValue) WithB(y bool) SmallBeforeValue { + x.B = y + return x +} + +// WithC constructs a new value where the value of C has been replaced by +// the argument. +func (x SmallBeforeValue) WithC(y uint8) SmallBeforeValue { + x.C = y + return x +} + +// WithD constructs a new value where the value of D has been replaced by +// the argument. +func (x SmallBeforeValue) WithD(y uint8) SmallBeforeValue { + x.D = y + return x +} + +// WithE constructs a new value where the value of E has been replaced by +// the argument. +func (x SmallBeforeValue) WithE(y uint8) SmallBeforeValue { + x.E = y + return x +} + +// WithF constructs a new value where the value of F has been replaced by +// the argument. +func (x SmallBeforeValue) WithF(y uint16) SmallBeforeValue { + x.F = y + return x +} + +// WithG constructs a new value where the value of G has been replaced by +// the argument. +func (x SmallBeforeValue) WithG(y uint16) SmallBeforeValue { + x.G = y + return x +} + +// WithH constructs a new value where the value of H has been replaced by +// the argument. +func (x SmallBeforeValue) WithH(y uint32) SmallBeforeValue { + x.H = y + return x +} + +// WithI constructs a new value where the value of I has been replaced by +// the argument. +func (x SmallBeforeValue) WithI(y uint64) SmallBeforeValue { + x.I = y + return x +} + +// ---- BigBefore ---- // + +// BigBefore is the type of a reference to an immutable record. +type BigBefore struct{ ref *node } + +const BigBefore_Slot_A_Type = 3 +const BigBefore_Slot_A_Num = -1 +const BigBefore_Slot_A_BitSize = -1 +const BigBefore_Slot_A_BitOffset = -1 +const BigBefore_Slot_A_ByteSize = -1 +const BigBefore_Slot_A_ByteOffset = -1 +const BigBefore_Slot_A_ValueMask = -1 + +const BigBefore_Slot_B_Type = 3 +const BigBefore_Slot_B_Num = -1 +const BigBefore_Slot_B_BitSize = -1 +const BigBefore_Slot_B_BitOffset = -1 +const BigBefore_Slot_B_ByteSize = -1 +const BigBefore_Slot_B_ByteOffset = -1 +const BigBefore_Slot_B_ValueMask = -1 + +const BigBefore_Slot_C_Type = 1 +const BigBefore_Slot_C_Num = 0 +const BigBefore_Slot_C_BitSize = 16 +const BigBefore_Slot_C_BitOffset = 0 +const BigBefore_Slot_C_ByteSize = 2 +const BigBefore_Slot_C_ByteOffset = 0 +const BigBefore_Slot_C_ValueMask = 0xffff + +const BigBefore_Slot_D_Type = 1 +const BigBefore_Slot_D_Num = 1 +const BigBefore_Slot_D_BitSize = 16 +const BigBefore_Slot_D_BitOffset = 0 +const BigBefore_Slot_D_ByteSize = 2 +const BigBefore_Slot_D_ByteOffset = 0 +const BigBefore_Slot_D_ValueMask = 0xffff + +const BigBefore_Slot_E_Type = 1 +const BigBefore_Slot_E_Num = 2 +const BigBefore_Slot_E_BitSize = 8 +const BigBefore_Slot_E_BitOffset = 0 +const BigBefore_Slot_E_ByteSize = 1 +const BigBefore_Slot_E_ByteOffset = 0 +const BigBefore_Slot_E_ValueMask = 0xff + +const BigBefore_Slot_F_Type = 1 +const BigBefore_Slot_F_Num = 2 +const BigBefore_Slot_F_BitSize = 8 +const BigBefore_Slot_F_BitOffset = 8 +const BigBefore_Slot_F_ByteSize = 1 +const BigBefore_Slot_F_ByteOffset = 1 +const BigBefore_Slot_F_ValueMask = 0xff + +const BigBefore_Slot_G_Type = 1 +const BigBefore_Slot_G_Num = 3 +const BigBefore_Slot_G_BitSize = 8 +const BigBefore_Slot_G_BitOffset = 0 +const BigBefore_Slot_G_ByteSize = 1 +const BigBefore_Slot_G_ByteOffset = 0 +const BigBefore_Slot_G_ValueMask = 0xff + +const BigBefore_Slot_H_Type = 1 +const BigBefore_Slot_H_Num = 3 +const BigBefore_Slot_H_BitSize = 1 +const BigBefore_Slot_H_BitOffset = 8 +const BigBefore_Slot_H_ByteSize = 1 +const BigBefore_Slot_H_ByteOffset = 1 +const BigBefore_Slot_H_ValueMask = 0x1 + +const BigBefore_Slot_I_Type = 1 +const BigBefore_Slot_I_Num = 3 +const BigBefore_Slot_I_BitSize = 1 +const BigBefore_Slot_I_BitOffset = 9 +const BigBefore_Slot_I_ByteSize = 1 +const BigBefore_Slot_I_ByteOffset = 1 +const BigBefore_Slot_I_ValueMask = 0x1 + +// BigBeforeValue is the logical type of a record. Immutable records are stored in +// nodes. +type BigBeforeValue struct { + A uint64 // 1 + B uint32 // 2 + C uint16 // 3 + D uint16 // 4 + E uint8 // 5 + F uint8 // 6 + G uint8 // 7 + H bool // 8 + I bool // 9 +} + +type extraBigBefore struct { + A uint64 + B uint32 +} + +func (x extraBigBefore) extraRefs() []*node { return nil } + +// R constructs a reference to an immutable record. +func (x BigBeforeValue) R(a *Allocator) BigBefore { + ref := a.new() + extra := &extraBigBefore{} + ref.extra = extra + + extra.A = x.A + extra.B = x.B + ref.nums[0] = numvalslot(x.C) + ref.nums[1] = numvalslot(x.D) + ref.nums[2] = (ref.nums[2] &^ (BigBefore_Slot_E_ValueMask << BigBefore_Slot_E_BitOffset)) | (numvalslot(x.E) << BigBefore_Slot_E_BitOffset) + ref.nums[2] = (ref.nums[2] &^ (BigBefore_Slot_F_ValueMask << BigBefore_Slot_F_BitOffset)) | (numvalslot(x.F) << BigBefore_Slot_F_BitOffset) + ref.nums[3] = (ref.nums[3] &^ (BigBefore_Slot_G_ValueMask << BigBefore_Slot_G_BitOffset)) | (numvalslot(x.G) << BigBefore_Slot_G_BitOffset) + if x.H { + ref.nums[3] |= (numvalslot(1) << BigBefore_Slot_H_BitOffset) + } else { + ref.nums[3] &^= (numvalslot(1) << BigBefore_Slot_H_BitOffset) + } + if x.I { + ref.nums[3] |= (numvalslot(1) << BigBefore_Slot_I_BitOffset) + } else { + ref.nums[3] &^= (numvalslot(1) << BigBefore_Slot_I_BitOffset) + } + return BigBefore{ref} +} + +// A returns the A field. +func (x BigBefore) A() uint64 { return x.ref.extra.(*extraBigBefore).A } + +// B returns the B field. +func (x BigBefore) B() uint32 { return x.ref.extra.(*extraBigBefore).B } + +// C returns the C field. +func (x BigBefore) C() uint16 { return uint16(x.ref.nums[0]) } + +// D returns the D field. +func (x BigBefore) D() uint16 { return uint16(x.ref.nums[1]) } + +// E returns the E field. +func (x BigBefore) E() uint8 { + return uint8((x.ref.nums[2] >> BigBefore_Slot_E_BitOffset) & BigBefore_Slot_E_ValueMask) +} + +// F returns the F field. +func (x BigBefore) F() uint8 { + return uint8((x.ref.nums[2] >> BigBefore_Slot_F_BitOffset) & BigBefore_Slot_F_ValueMask) +} + +// G returns the G field. +func (x BigBefore) G() uint8 { + return uint8((x.ref.nums[3] >> BigBefore_Slot_G_BitOffset) & BigBefore_Slot_G_ValueMask) +} + +// H returns the H field. +func (x BigBefore) H() bool { + return !(0 == (x.ref.nums[3] >> BigBefore_Slot_H_BitOffset & BigBefore_Slot_H_ValueMask)) +} + +// I returns the I field. +func (x BigBefore) I() bool { + return !(0 == (x.ref.nums[3] >> BigBefore_Slot_I_BitOffset & BigBefore_Slot_I_ValueMask)) +} + +// V unpacks a reference into a value. +func (x BigBefore) V() BigBeforeValue { + return BigBeforeValue{ + A: x.ref.extra.(*extraBigBefore).A, + B: x.ref.extra.(*extraBigBefore).B, + C: uint16(x.ref.nums[0]), + D: uint16(x.ref.nums[1]), + E: uint8((x.ref.nums[2] >> BigBefore_Slot_E_BitOffset) & BigBefore_Slot_E_ValueMask), + F: uint8((x.ref.nums[2] >> BigBefore_Slot_F_BitOffset) & BigBefore_Slot_F_ValueMask), + G: uint8((x.ref.nums[3] >> BigBefore_Slot_G_BitOffset) & BigBefore_Slot_G_ValueMask), + H: !(0 == (x.ref.nums[3] >> BigBefore_Slot_H_BitOffset & BigBefore_Slot_H_ValueMask)), + I: !(0 == (x.ref.nums[3] >> BigBefore_Slot_I_BitOffset & BigBefore_Slot_I_ValueMask)), + } +} + +// WithA constructs a new value where the value of A has been replaced by +// the argument. +func (x BigBeforeValue) WithA(y uint64) BigBeforeValue { + x.A = y + return x +} + +// WithB constructs a new value where the value of B has been replaced by +// the argument. +func (x BigBeforeValue) WithB(y uint32) BigBeforeValue { + x.B = y + return x +} + +// WithC constructs a new value where the value of C has been replaced by +// the argument. +func (x BigBeforeValue) WithC(y uint16) BigBeforeValue { + x.C = y + return x +} + +// WithD constructs a new value where the value of D has been replaced by +// the argument. +func (x BigBeforeValue) WithD(y uint16) BigBeforeValue { + x.D = y + return x +} + +// WithE constructs a new value where the value of E has been replaced by +// the argument. +func (x BigBeforeValue) WithE(y uint8) BigBeforeValue { + x.E = y + return x +} + +// WithF constructs a new value where the value of F has been replaced by +// the argument. +func (x BigBeforeValue) WithF(y uint8) BigBeforeValue { + x.F = y + return x +} + +// WithG constructs a new value where the value of G has been replaced by +// the argument. +func (x BigBeforeValue) WithG(y uint8) BigBeforeValue { + x.G = y + return x +} + +// WithH constructs a new value where the value of H has been replaced by +// the argument. +func (x BigBeforeValue) WithH(y bool) BigBeforeValue { + x.H = y + return x +} + +// WithI constructs a new value where the value of I has been replaced by +// the argument. +func (x BigBeforeValue) WithI(y bool) BigBeforeValue { + x.I = y + return x +} + +// Codegen parameters: +// {NumNumericSlots:20 NumericSlotSize:16 NumRefSlots:2 NumStrSlots:1 Pack:true} +// diff --git a/pkg/sql/ir/tests/smallslots/prims/base/sexpr.ir.go b/pkg/sql/ir/tests/smallslots/prims/base/sexpr.ir.go new file mode 100644 index 000000000000..9a73ffd00555 --- /dev/null +++ b/pkg/sql/ir/tests/smallslots/prims/base/sexpr.ir.go @@ -0,0 +1,151 @@ +// Code generated by irgen/irgen base/sexpr.tmpl.go tests/prims.def. DO NOT EDIT. +// GENERATED FILE DO NOT EDIT +// Copyright 2017 The Cockroach Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. + +package base + +import ( + "bytes" + "fmt" +) + +type SexprFormatter interface { + FormatSExpr(buf *bytes.Buffer) +} + +func FormatSExprBool(buf *bytes.Buffer, x bool) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt64(buf *bytes.Buffer, x int64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt32(buf *bytes.Buffer, x int32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt16(buf *bytes.Buffer, x int16) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprInt8(buf *bytes.Buffer, x int8) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint64(buf *bytes.Buffer, x uint64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint32(buf *bytes.Buffer, x uint32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint16(buf *bytes.Buffer, x uint16) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprUint8(buf *bytes.Buffer, x uint8) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprFloat32(buf *bytes.Buffer, x float32) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprFloat64(buf *bytes.Buffer, x float64) { fmt.Fprintf(buf, "%v", x) } +func FormatSExprString(buf *bytes.Buffer, x string) { fmt.Fprintf(buf, "%q", x) } + +func (x All) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(All") + + buf.WriteString(" B: ") + FormatSExprBool(buf, x.B()) + + buf.WriteString(" I8: ") + FormatSExprInt8(buf, x.I8()) + + buf.WriteString(" U8: ") + FormatSExprUint8(buf, x.U8()) + + buf.WriteString(" I16: ") + FormatSExprInt16(buf, x.I16()) + + buf.WriteString(" U16: ") + FormatSExprUint16(buf, x.U16()) + + buf.WriteString(" I32: ") + FormatSExprInt32(buf, x.I32()) + + buf.WriteString(" U32: ") + FormatSExprUint32(buf, x.U32()) + + buf.WriteString(" I64: ") + FormatSExprInt64(buf, x.I64()) + + buf.WriteString(" U64: ") + FormatSExprUint64(buf, x.U64()) + + buf.WriteString(" S: ") + FormatSExprString(buf, x.S()) + + buf.WriteString(" F32: ") + FormatSExprFloat32(buf, x.F32()) + + buf.WriteString(" F64: ") + FormatSExprFloat64(buf, x.F64()) + + buf.WriteByte(')') +} + +func (x SmallBefore) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(SmallBefore") + + buf.WriteString(" A: ") + FormatSExprBool(buf, x.A()) + + buf.WriteString(" B: ") + FormatSExprBool(buf, x.B()) + + buf.WriteString(" C: ") + FormatSExprUint8(buf, x.C()) + + buf.WriteString(" D: ") + FormatSExprUint8(buf, x.D()) + + buf.WriteString(" E: ") + FormatSExprUint8(buf, x.E()) + + buf.WriteString(" F: ") + FormatSExprUint16(buf, x.F()) + + buf.WriteString(" G: ") + FormatSExprUint16(buf, x.G()) + + buf.WriteString(" H: ") + FormatSExprUint32(buf, x.H()) + + buf.WriteString(" I: ") + FormatSExprUint64(buf, x.I()) + + buf.WriteByte(')') +} + +func (x BigBefore) FormatSExpr(buf *bytes.Buffer) { + buf.WriteString("(BigBefore") + + buf.WriteString(" A: ") + FormatSExprUint64(buf, x.A()) + + buf.WriteString(" B: ") + FormatSExprUint32(buf, x.B()) + + buf.WriteString(" C: ") + FormatSExprUint16(buf, x.C()) + + buf.WriteString(" D: ") + FormatSExprUint16(buf, x.D()) + + buf.WriteString(" E: ") + FormatSExprUint8(buf, x.E()) + + buf.WriteString(" F: ") + FormatSExprUint8(buf, x.F()) + + buf.WriteString(" G: ") + FormatSExprUint8(buf, x.G()) + + buf.WriteString(" H: ") + FormatSExprBool(buf, x.H()) + + buf.WriteString(" I: ") + FormatSExprBool(buf, x.I()) + + buf.WriteByte(')') +} + +// Codegen parameters: +// {NumNumericSlots:20 NumericSlotSize:16 NumRefSlots:2 NumStrSlots:1 Pack:true} +// diff --git a/pkg/sql/ir/tests/smallslots/smallslots_cfg_test.go b/pkg/sql/ir/tests/smallslots/smallslots_cfg_test.go new file mode 100644 index 000000000000..d49ca5a2ad26 --- /dev/null +++ b/pkg/sql/ir/tests/smallslots/smallslots_cfg_test.go @@ -0,0 +1,249 @@ +// Code generated by make. DO NOT EDIT. +// GENERATED FILE DO NOT EDIT +// Copyright 2017 The Cockroach Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. + +package smallslots + +import ( + "bytes" + "fmt" + "reflect" + "strconv" + "strings" + "testing" + + d "github.com/cockroachdb/cockroach/pkg/sql/ir/tests/smallslots/example/base" + p "github.com/cockroachdb/cockroach/pkg/sql/ir/tests/smallslots/prims/base" +) + +func makeSampleExpr(a *d.Allocator) d.Expr { + c1 := d.ConstExprValue{Datum: 1}.R(a).Expr() + c2 := d.ConstExprValue{Datum: 2}.R(a).Expr() + c3 := d.ConstExprValue{Datum: 3}.R(a).Expr() + b4 := d.BinExprValue{Left: c1, Op: d.BinOpAdd, Right: c2}.R(a).Expr() + b5 := d.BinExprValue{Left: c3, Op: d.BinOpMul, Right: b4}.R(a).Expr() + return b5 +} + +func assertEq(t *testing.T, n int, val interface{}, exp interface{}) { + if !reflect.DeepEqual(val, exp) { + t.Errorf("equal failed %d: expected %v, got %v", n, exp, val) + } +} + +func TestExprValues(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + b5 := e.MustBeBinExpr() + assertEq(t, 1, b5.Op(), d.BinOpMul) + assertEq(t, 2, b5.Left().MustBeConstExpr().Datum(), int64(3)) + b4 := b5.Right().MustBeBinExpr() + assertEq(t, 3, b4.Op(), d.BinOpAdd) + assertEq(t, 4, b4.Left().MustBeConstExpr().Datum(), int64(1)) + assertEq(t, 5, b4.Right().MustBeConstExpr().Datum(), int64(2)) +} + +func format(ref d.Expr) string { + switch ref.Tag() { + case d.ExprConstExpr: + c := ref.MustBeConstExpr() + return strconv.FormatInt(c.Datum(), 10) + case d.ExprBinExpr: + b := ref.MustBeBinExpr() + var op string + switch b.Op() { + case d.BinOpAdd: + op = "+" + case d.BinOpMul: + op = "*" + default: + panic("unknown BinOp") + } + return fmt.Sprintf("(%s %s %s)", format(b.Left()), op, format(b.Right())) + default: + panic("unknown Expr tag") + } +} + +func TestExprFormatSExpr(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + + var buf bytes.Buffer + e.FormatSExpr(&buf) + if buf.String() != "(BinExpr Left: (ConstExpr Datum: 3) Op: Mul Right: (BinExpr Left: (ConstExpr Datum: 1) Op: Add Right: (ConstExpr Datum: 2)))" { + t.Fatalf("unexpected: %q", buf.String()) + } +} + +func TestFormat(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + const expected = "(3 * (1 + 2))" + if got := format(e); got != expected { + t.Fatalf("expected %q but got %q", expected, got) + } +} + +func reverse(ref d.Expr, a *d.Allocator) d.Expr { + if ref.Tag() != d.ExprBinExpr { + return ref + } + b := ref.MustBeBinExpr() + revLeft := reverse(b.Left(), a) + revRight := reverse(b.Right(), a) + return b.V().WithLeft(revRight).WithRight(revLeft).R(a).Expr() +} + +func TestReverse(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + const expected = "((2 + 1) * 3)" + if got := format(reverse(e, a)); got != expected { + t.Fatalf("expected %q but got %q", expected, got) + } +} + +func TestDoubleReverse(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + if got0, got2 := format(e), format(reverse(reverse(e, a), a)); got0 != got2 { + t.Fatalf("reverse is not an involution: %q != %q", got0, got2) + } +} + +func deepEqual(ref1 d.Expr, ref2 d.Expr) bool { + if ref1.Tag() != ref2.Tag() { + return false + } + switch ref1.Tag() { + case d.ExprConstExpr: + return ref1.MustBeConstExpr().Datum() == ref2.MustBeConstExpr().Datum() + case d.ExprBinExpr: + b1 := ref1.MustBeBinExpr() + b2 := ref2.MustBeBinExpr() + return b1.Op() == b2.Op() && + deepEqual(b1.Left(), b2.Left()) && deepEqual(b1.Right(), b2.Right()) + default: + panic("unknown Expr tag") + } +} + +func TestDeepEqual(t *testing.T) { + a := d.NewAllocator() + e := makeSampleExpr(a) + if deepEqual(e, reverse(e, a)) { + t.Fatalf("expected expression not to be deepEqual to its reverse") + } + if !deepEqual(e, reverse(reverse(e, a), a)) { + t.Fatalf("expected expression to be deepEqual to the reverse of its reverse") + } +} + +func TestPrimValues(t *testing.T) { + a := p.NewAllocator() + all := p.AllValue{ + B: true, + I8: 'b', + U8: 'c', + I16: 0x1234, + U16: 0x4321, + I32: 0x12345678, + U32: 0x87654321, + I64: 0x123456789abcdef0, + U64: 0x0fedcba987654321, + S: "k", + F32: 1.234, + F64: 5.678, + }.R(a) + assertEq(t, 1, all.B(), true) + assertEq(t, 2, all.I8(), int8('b')) + assertEq(t, 3, all.U8(), uint8('c')) + assertEq(t, 4, all.I16(), int16(0x1234)) + assertEq(t, 5, all.U16(), uint16(0x4321)) + assertEq(t, 6, all.I32(), int32(0x12345678)) + assertEq(t, 7, all.U32(), uint32(0x87654321)) + assertEq(t, 8, all.I64(), int64(0x123456789abcdef0)) + assertEq(t, 9, all.U64(), uint64(0x0fedcba987654321)) + assertEq(t, 10, all.S(), "k") + assertEq(t, 11, all.F32(), float32(1.234)) + assertEq(t, 12, all.F64(), float64(5.678)) + + var buf bytes.Buffer + all.FormatSExpr(&buf) + assertEq(t, 100, buf.String(), strings.TrimSpace(` +(All B: true I8: 98 U8: 99 I16: 4660 U16: 17185 I32: 305419896 U32: 2271560481 I64: 1311768467463790320 U64: 1147797409030816545 S: "k" F32: 1.234 F64: 5.678) +`)) +} + +func TestPrimValues2(t *testing.T) { + a := p.NewAllocator() + v := p.SmallBeforeValue{ + A: true, + B: false, + C: 'c', + D: 'd', + E: 'e', + F: 0x1234, + G: 0x4321, + H: 0x12345678, + I: 0x123456789abcdef0, + }.R(a) + assertEq(t, 1, v.A(), true) + assertEq(t, 2, v.B(), false) + assertEq(t, 3, v.C(), uint8('c')) + assertEq(t, 4, v.D(), uint8('d')) + assertEq(t, 5, v.E(), uint8('e')) + assertEq(t, 6, v.F(), uint16(0x1234)) + assertEq(t, 7, v.G(), uint16(0x4321)) + assertEq(t, 8, v.H(), uint32(0x12345678)) + assertEq(t, 9, v.I(), uint64(0x123456789abcdef0)) + + var buf bytes.Buffer + v.FormatSExpr(&buf) + assertEq(t, 100, buf.String(), strings.TrimSpace(` +(SmallBefore A: true B: false C: 99 D: 100 E: 101 F: 4660 G: 17185 H: 305419896 I: 1311768467463790320) +`)) +} + +func TestPrimValues3(t *testing.T) { + a := p.NewAllocator() + v := p.BigBeforeValue{ + A: 0x123456789abcdef0, + B: 0x12345678, + C: 0x1234, + D: 0x4321, + E: 'e', + F: 'f', + G: 'g', + H: false, + I: true, + }.R(a) + assertEq(t, 1, v.A(), uint64(0x123456789abcdef0)) + assertEq(t, 2, v.B(), uint32(0x12345678)) + assertEq(t, 3, v.C(), uint16(0x1234)) + assertEq(t, 4, v.D(), uint16(0x4321)) + assertEq(t, 5, v.E(), uint8('e')) + assertEq(t, 6, v.F(), uint8('f')) + assertEq(t, 7, v.G(), uint8('g')) + assertEq(t, 8, v.H(), false) + assertEq(t, 9, v.I(), true) + + var buf bytes.Buffer + v.FormatSExpr(&buf) + assertEq(t, 100, buf.String(), strings.TrimSpace(` +(BigBefore A: 1311768467463790320 B: 305419896 C: 4660 D: 17185 E: 101 F: 102 G: 103 H: false I: true) +`)) +}