mirror of
https://github.com/vlang/v.git
synced 2025-09-13 22:42:26 +03:00
Merge c5579c426c
into a8d200ac0e
This commit is contained in:
commit
ee38b34ec9
17 changed files with 143 additions and 13 deletions
|
@ -193,7 +193,7 @@ by using any of the following commands in a terminal:
|
||||||
* [Trace](#trace)
|
* [Trace](#trace)
|
||||||
* [Memory-unsafe code](#memory-unsafe-code)
|
* [Memory-unsafe code](#memory-unsafe-code)
|
||||||
* [Structs with reference fields](#structs-with-reference-fields)
|
* [Structs with reference fields](#structs-with-reference-fields)
|
||||||
* [sizeof and __offsetof](#sizeof-and-__offsetof)
|
* [sizeof, alignof and __offsetof](#sizeof-alignof-and-__offsetof)
|
||||||
* [Limited operator overloading](#limited-operator-overloading)
|
* [Limited operator overloading](#limited-operator-overloading)
|
||||||
* [Performance tuning](#performance-tuning)
|
* [Performance tuning](#performance-tuning)
|
||||||
* [Atomics](#atomics)
|
* [Atomics](#atomics)
|
||||||
|
@ -6980,9 +6980,10 @@ println(baz)
|
||||||
println(qux)
|
println(qux)
|
||||||
```
|
```
|
||||||
|
|
||||||
## sizeof and __offsetof
|
## sizeof, alignof and __offsetof
|
||||||
|
|
||||||
* `sizeof(Type)` gives the size of a type in bytes.
|
* `sizeof(Type)` gives the size of a type in bytes.
|
||||||
|
* `alignof(Type)` gives the alignment of a type in bytes.
|
||||||
* `__offsetof(Struct, field_name)` gives the offset in bytes of a struct field.
|
* `__offsetof(Struct, field_name)` gives the offset in bytes of a struct field.
|
||||||
|
|
||||||
```v
|
```v
|
||||||
|
@ -6992,6 +6993,7 @@ struct Foo {
|
||||||
}
|
}
|
||||||
|
|
||||||
assert sizeof(Foo) == 8
|
assert sizeof(Foo) == 8
|
||||||
|
assert alignof[Foo]() == 4
|
||||||
assert __offsetof(Foo, a) == 0
|
assert __offsetof(Foo, a) == 0
|
||||||
assert __offsetof(Foo, b) == 4
|
assert __offsetof(Foo, b) == 4
|
||||||
```
|
```
|
||||||
|
|
|
@ -33,6 +33,7 @@ pub const int_type_name = $if new_int ? {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Expr = NodeError
|
pub type Expr = NodeError
|
||||||
|
| AlignOf
|
||||||
| AnonFn
|
| AnonFn
|
||||||
| ArrayDecompose
|
| ArrayDecompose
|
||||||
| ArrayInit
|
| ArrayInit
|
||||||
|
@ -1956,6 +1957,16 @@ pub mut:
|
||||||
scope &Scope = unsafe { nil }
|
scope &Scope = unsafe { nil }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct AlignOf {
|
||||||
|
pub:
|
||||||
|
guessed_type bool // a legacy `alignof( GuessedType )` => a deprecation notice, suggesting `v fmt -w .` => `alignof[ Type ]()`
|
||||||
|
is_type bool
|
||||||
|
pos token.Pos
|
||||||
|
pub mut:
|
||||||
|
expr Expr // checker uses this to set typ, when !is_type
|
||||||
|
typ Type
|
||||||
|
}
|
||||||
|
|
||||||
pub struct SizeOf {
|
pub struct SizeOf {
|
||||||
pub:
|
pub:
|
||||||
guessed_type bool // a legacy `sizeof( GuessedType )` => a deprecation notice, suggesting `v fmt -w .` => `sizeof[ Type ]()`
|
guessed_type bool // a legacy `sizeof( GuessedType )` => a deprecation notice, suggesting `v fmt -w .` => `sizeof[ Type ]()`
|
||||||
|
@ -2275,11 +2286,11 @@ pub fn (expr Expr) pos() token.Pos {
|
||||||
// println('compiler bug, unhandled EmptyExpr pos()')
|
// println('compiler bug, unhandled EmptyExpr pos()')
|
||||||
token.Pos{}
|
token.Pos{}
|
||||||
}
|
}
|
||||||
NodeError, ArrayDecompose, ArrayInit, AsCast, Assoc, AtExpr, BoolLiteral, CallExpr,
|
NodeError, AlignOf, ArrayDecompose, ArrayInit, AsCast, Assoc, AtExpr, BoolLiteral,
|
||||||
CastExpr, ChanInit, CharLiteral, ConcatExpr, Comment, ComptimeCall, ComptimeSelector,
|
CallExpr, CastExpr, ChanInit, CharLiteral, ConcatExpr, Comment, ComptimeCall,
|
||||||
EnumVal, DumpExpr, FloatLiteral, GoExpr, SpawnExpr, Ident, IfExpr, IntegerLiteral,
|
ComptimeSelector, EnumVal, DumpExpr, FloatLiteral, GoExpr, SpawnExpr, Ident, IfExpr,
|
||||||
IsRefType, Likely, LockExpr, MapInit, MatchExpr, None, OffsetOf, OrExpr, ParExpr,
|
IntegerLiteral, IsRefType, Likely, LockExpr, MapInit, MatchExpr, None, OffsetOf, OrExpr,
|
||||||
PostfixExpr, PrefixExpr, RangeExpr, SelectExpr, SelectorExpr, SizeOf, SqlExpr,
|
ParExpr, PostfixExpr, PrefixExpr, RangeExpr, SelectExpr, SelectorExpr, SizeOf, SqlExpr,
|
||||||
StringInterLiteral, StringLiteral, StructInit, TypeNode, TypeOf, UnsafeExpr, ComptimeType,
|
StringInterLiteral, StringLiteral, StructInit, TypeNode, TypeOf, UnsafeExpr, ComptimeType,
|
||||||
LambdaExpr, Nil {
|
LambdaExpr, Nil {
|
||||||
expr.pos
|
expr.pos
|
||||||
|
@ -2817,7 +2828,7 @@ pub fn (expr Expr) is_literal() bool {
|
||||||
!expr.has_arg && expr.expr.is_literal() && (expr.typ.is_any_kind_of_pointer()
|
!expr.has_arg && expr.expr.is_literal() && (expr.typ.is_any_kind_of_pointer()
|
||||||
|| expr.typ in [i8_type, i16_type, int_type, i64_type, u8_type, u16_type, u32_type, u64_type, f32_type, f64_type, char_type, bool_type, rune_type])
|
|| expr.typ in [i8_type, i16_type, int_type, i64_type, u8_type, u16_type, u32_type, u64_type, f32_type, f64_type, char_type, bool_type, rune_type])
|
||||||
}
|
}
|
||||||
SizeOf, IsRefType {
|
AlignOf, SizeOf, IsRefType {
|
||||||
expr.is_type || expr.expr.is_literal()
|
expr.is_type || expr.expr.is_literal()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -413,6 +413,12 @@ pub fn (x Expr) str() string {
|
||||||
stdatomic.sub_i64(&nested_expr_str_calls, 1)
|
stdatomic.sub_i64(&nested_expr_str_calls, 1)
|
||||||
}
|
}
|
||||||
match x {
|
match x {
|
||||||
|
AlignOf {
|
||||||
|
if x.is_type {
|
||||||
|
return 'alignof(${global_table.type_to_str(x.typ)})'
|
||||||
|
}
|
||||||
|
return 'alignof(${x.expr.str()})'
|
||||||
|
}
|
||||||
AnonFn {
|
AnonFn {
|
||||||
return 'anon_fn'
|
return 'anon_fn'
|
||||||
}
|
}
|
||||||
|
|
|
@ -1310,6 +1310,13 @@ pub fn (t &Table) type_size(typ Type) (int, int) {
|
||||||
return size, align
|
return size, align
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// type_align returns the alignment (in bytes) of `typ`, just like C's alignof().
|
||||||
|
pub fn (t &Table) type_align(typ Type) int {
|
||||||
|
// we only care about the second (alignment) return value
|
||||||
|
_, align := t.type_size(typ)
|
||||||
|
return align
|
||||||
|
}
|
||||||
|
|
||||||
// round_up rounds the number `n` up to the next multiple `multiple`.
|
// round_up rounds the number `n` up to the next multiple `multiple`.
|
||||||
// Note: `multiple` must be a power of 2.
|
// Note: `multiple` must be a power of 2.
|
||||||
@[inline]
|
@[inline]
|
||||||
|
|
|
@ -3288,7 +3288,7 @@ pub fn (mut c Checker) expr(mut node ast.Expr) ast.Type {
|
||||||
}
|
}
|
||||||
return ret_type
|
return ret_type
|
||||||
}
|
}
|
||||||
ast.SizeOf {
|
ast.AlignOf, ast.SizeOf {
|
||||||
if !node.is_type {
|
if !node.is_type {
|
||||||
node.typ = c.expr(mut node.expr)
|
node.typ = c.expr(mut node.expr)
|
||||||
}
|
}
|
||||||
|
|
|
@ -435,6 +435,10 @@ fn (mut c Checker) eval_comptime_const_expr(expr ast.Expr, nlevel int) ?ast.Comp
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ast.AlignOf {
|
||||||
|
a := c.table.type_align(expr.typ)
|
||||||
|
return i64(a)
|
||||||
|
}
|
||||||
ast.SizeOf {
|
ast.SizeOf {
|
||||||
s, _ := c.table.type_size(c.unwrap_generic(expr.typ))
|
s, _ := c.table.type_size(c.unwrap_generic(expr.typ))
|
||||||
return i64(s)
|
return i64(s)
|
||||||
|
|
|
@ -491,6 +491,9 @@ pub fn (mut e Eval) expr(expr ast.Expr, expecting ast.Type) Object {
|
||||||
// eprintln('unhandled struct init at line $expr.pos.line_nr')
|
// eprintln('unhandled struct init at line $expr.pos.line_nr')
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
ast.AlignOf {
|
||||||
|
return Uint{e.type_to_align(expr.typ), 64}
|
||||||
|
}
|
||||||
ast.SizeOf {
|
ast.SizeOf {
|
||||||
return Uint{e.type_to_size(expr.typ), 64}
|
return Uint{e.type_to_size(expr.typ), 64}
|
||||||
}
|
}
|
||||||
|
@ -635,6 +638,12 @@ fn (e &Eval) type_to_size(typ ast.Type) u64 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// type_to_align returns the natural alignment (in bits) of `typ`.
|
||||||
|
fn (e &Eval) type_to_align(typ ast.Type) u64 {
|
||||||
|
// on most ABIs the alignment of a type == its size
|
||||||
|
return e.type_to_size(typ)
|
||||||
|
}
|
||||||
|
|
||||||
fn (e &Eval) get_escape(r rune) rune {
|
fn (e &Eval) get_escape(r rune) rune {
|
||||||
res := match r {
|
res := match r {
|
||||||
`\\` {
|
`\\` {
|
||||||
|
|
|
@ -572,6 +572,9 @@ pub fn (mut f Fmt) expr(node_ ast.Expr) {
|
||||||
match mut node {
|
match mut node {
|
||||||
ast.NodeError {}
|
ast.NodeError {}
|
||||||
ast.EmptyExpr {}
|
ast.EmptyExpr {}
|
||||||
|
ast.AlignOf {
|
||||||
|
f.align_of(node)
|
||||||
|
}
|
||||||
ast.AnonFn {
|
ast.AnonFn {
|
||||||
f.anon_fn(node)
|
f.anon_fn(node)
|
||||||
}
|
}
|
||||||
|
@ -2996,6 +2999,20 @@ pub fn (mut f Fmt) selector_expr(node ast.SelectorExpr) {
|
||||||
f.or_expr(node.or_block)
|
f.or_expr(node.or_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (mut f Fmt) align_of(node ast.AlignOf) {
|
||||||
|
f.write('alignof')
|
||||||
|
if node.is_type {
|
||||||
|
f.write('[')
|
||||||
|
f.write(f.table.type_to_str_using_aliases(node.typ, f.mod2alias))
|
||||||
|
f.write(']()')
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
f.write('(')
|
||||||
|
f.expr(node.expr)
|
||||||
|
f.write(')')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn (mut f Fmt) size_of(node ast.SizeOf) {
|
pub fn (mut f Fmt) size_of(node ast.SizeOf) {
|
||||||
f.write('sizeof')
|
f.write('sizeof')
|
||||||
if node.is_type && !node.guessed_type {
|
if node.is_type && !node.guessed_type {
|
||||||
|
|
|
@ -3624,6 +3624,9 @@ fn (mut g Gen) expr(node_ ast.Expr) {
|
||||||
ast.EmptyExpr {
|
ast.EmptyExpr {
|
||||||
g.error('g.expr(): unhandled EmptyExpr', token.Pos{})
|
g.error('g.expr(): unhandled EmptyExpr', token.Pos{})
|
||||||
}
|
}
|
||||||
|
ast.AlignOf {
|
||||||
|
g.align_of(node)
|
||||||
|
}
|
||||||
ast.AnonFn {
|
ast.AnonFn {
|
||||||
g.gen_anon_fn(mut node)
|
g.gen_anon_fn(mut node)
|
||||||
}
|
}
|
||||||
|
@ -7738,6 +7741,17 @@ fn (mut g Gen) get_type(typ ast.Type) ast.Type {
|
||||||
return if typ == g.field_data_type { g.comptime.comptime_for_field_value.typ } else { typ }
|
return if typ == g.field_data_type { g.comptime.comptime_for_field_value.typ } else { typ }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) align_of(node ast.AlignOf) {
|
||||||
|
typ := g.type_resolver.typeof_type(node.expr, g.get_type(node.typ))
|
||||||
|
node_typ := g.unwrap_generic(typ)
|
||||||
|
sym := g.table.sym(node_typ)
|
||||||
|
if sym.language == .v && sym.kind in [.placeholder, .any] {
|
||||||
|
g.error('unknown type `${sym.name}`', node.pos)
|
||||||
|
}
|
||||||
|
styp := g.styp(node_typ)
|
||||||
|
g.write('alignof(${util.no_dots(styp)})')
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut g Gen) size_of(node ast.SizeOf) {
|
fn (mut g Gen) size_of(node ast.SizeOf) {
|
||||||
typ := g.type_resolver.typeof_type(node.expr, g.get_type(node.typ))
|
typ := g.type_resolver.typeof_type(node.expr, g.get_type(node.typ))
|
||||||
node_typ := g.unwrap_generic(typ)
|
node_typ := g.unwrap_generic(typ)
|
||||||
|
|
|
@ -339,6 +339,7 @@ typedef int (*qsort_callback_func)(const void*, const void*);
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <stdarg.h> // for va_list
|
#include <stdarg.h> // for va_list
|
||||||
|
#include <stdalign.h> // for alignof
|
||||||
|
|
||||||
#ifdef __TERMUX__
|
#ifdef __TERMUX__
|
||||||
#if defined __BIONIC_AVAILABILITY_GUARD && __BIONIC_AVAILABILITY_GUARD(28)
|
#if defined __BIONIC_AVAILABILITY_GUARD && __BIONIC_AVAILABILITY_GUARD(28)
|
||||||
|
|
|
@ -633,6 +633,9 @@ pub fn (mut f Gen) expr(node_ ast.Expr) {
|
||||||
ast.SelectorExpr {
|
ast.SelectorExpr {
|
||||||
f.selector_expr(node)
|
f.selector_expr(node)
|
||||||
}
|
}
|
||||||
|
ast.AlignOf {
|
||||||
|
f.align_of(node)
|
||||||
|
}
|
||||||
ast.SizeOf {
|
ast.SizeOf {
|
||||||
f.size_of(node)
|
f.size_of(node)
|
||||||
}
|
}
|
||||||
|
@ -2147,6 +2150,16 @@ pub fn (mut f Gen) selector_expr(node ast.SelectorExpr) {
|
||||||
f.write(node.field_name)
|
f.write(node.field_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (mut f Gen) align_of(node ast.AlignOf) {
|
||||||
|
f.write('alignof(')
|
||||||
|
if node.is_type {
|
||||||
|
f.write(f.table.type_to_str_using_aliases(node.typ, f.mod2alias))
|
||||||
|
} else {
|
||||||
|
f.expr(node.expr)
|
||||||
|
}
|
||||||
|
f.write(')')
|
||||||
|
}
|
||||||
|
|
||||||
pub fn (mut f Gen) size_of(node ast.SizeOf) {
|
pub fn (mut f Gen) size_of(node ast.SizeOf) {
|
||||||
f.write('sizeof(')
|
f.write('sizeof(')
|
||||||
if node.is_type {
|
if node.is_type {
|
||||||
|
|
|
@ -1032,7 +1032,7 @@ fn (mut g JsGen) expr(node_ ast.Expr) {
|
||||||
ast.SelectorExpr {
|
ast.SelectorExpr {
|
||||||
g.gen_selector_expr(node)
|
g.gen_selector_expr(node)
|
||||||
}
|
}
|
||||||
ast.SizeOf, ast.IsRefType {
|
ast.AlignOf, ast.SizeOf, ast.IsRefType {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
ast.OffsetOf {
|
ast.OffsetOf {
|
||||||
|
|
|
@ -782,7 +782,7 @@ fn (mut w Walker) expr(node_ ast.Expr) {
|
||||||
w.expr(node.high)
|
w.expr(node.high)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.SizeOf, ast.IsRefType {
|
ast.AlignOf, ast.SizeOf, ast.IsRefType {
|
||||||
w.expr(node.expr)
|
w.expr(node.expr)
|
||||||
w.mark_by_type(node.typ)
|
w.mark_by_type(node.typ)
|
||||||
}
|
}
|
||||||
|
|
|
@ -332,8 +332,9 @@ fn (mut p Parser) check_expr(precedence int) !ast.Expr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.key_sizeof, .key_isreftype {
|
.key_alignof, .key_sizeof, .key_isreftype {
|
||||||
is_reftype := p.tok.kind == .key_isreftype
|
is_reftype := p.tok.kind == .key_isreftype
|
||||||
|
is_alignof := p.tok.kind == .key_alignof
|
||||||
p.next() // sizeof
|
p.next() // sizeof
|
||||||
|
|
||||||
if p.tok.kind == .lsbr {
|
if p.tok.kind == .lsbr {
|
||||||
|
@ -351,6 +352,12 @@ fn (mut p Parser) check_expr(precedence int) !ast.Expr {
|
||||||
typ: typ
|
typ: typ
|
||||||
pos: type_pos
|
pos: type_pos
|
||||||
}
|
}
|
||||||
|
} else if is_alignof {
|
||||||
|
node = ast.AlignOf{
|
||||||
|
is_type: true
|
||||||
|
typ: typ
|
||||||
|
pos: type_pos
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
node = ast.SizeOf{
|
node = ast.SizeOf{
|
||||||
is_type: true
|
is_type: true
|
||||||
|
@ -381,6 +388,12 @@ fn (mut p Parser) check_expr(precedence int) !ast.Expr {
|
||||||
expr: expr
|
expr: expr
|
||||||
pos: pos
|
pos: pos
|
||||||
}
|
}
|
||||||
|
} else if is_alignof {
|
||||||
|
node = ast.AlignOf{
|
||||||
|
is_type: false
|
||||||
|
expr: expr
|
||||||
|
pos: pos
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
node = ast.SizeOf{
|
node = ast.SizeOf{
|
||||||
is_type: false
|
is_type: false
|
||||||
|
@ -403,6 +416,13 @@ fn (mut p Parser) check_expr(precedence int) !ast.Expr {
|
||||||
typ: arg_type
|
typ: arg_type
|
||||||
pos: pos
|
pos: pos
|
||||||
}
|
}
|
||||||
|
} else if is_alignof {
|
||||||
|
node = ast.AlignOf{
|
||||||
|
guessed_type: true
|
||||||
|
is_type: true
|
||||||
|
typ: arg_type
|
||||||
|
pos: pos
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
node = ast.SizeOf{
|
node = ast.SizeOf{
|
||||||
guessed_type: true
|
guessed_type: true
|
||||||
|
|
|
@ -2670,7 +2670,7 @@ fn (mut p Parser) global_decl() ast.GlobalDecl {
|
||||||
ast.FloatLiteral {
|
ast.FloatLiteral {
|
||||||
typ = ast.f64_type
|
typ = ast.f64_type
|
||||||
}
|
}
|
||||||
ast.IntegerLiteral, ast.SizeOf {
|
ast.AlignOf, ast.IntegerLiteral, ast.SizeOf {
|
||||||
typ = ast.int_type
|
typ = ast.int_type
|
||||||
}
|
}
|
||||||
ast.StringLiteral, ast.StringInterLiteral {
|
ast.StringLiteral, ast.StringInterLiteral {
|
||||||
|
|
23
vlib/v/tests/alignof_test.v
Normal file
23
vlib/v/tests/alignof_test.v
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
struct S1 {
|
||||||
|
p voidptr
|
||||||
|
}
|
||||||
|
|
||||||
|
struct S2 {
|
||||||
|
i int
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_alignof() {
|
||||||
|
assert alignof[rune]() == 4
|
||||||
|
assert alignof[[44]u8]() == 1
|
||||||
|
assert alignof(`€`) == 4
|
||||||
|
// depends on -m32/64
|
||||||
|
assert alignof[S1]() in [u32(4), 8]
|
||||||
|
s := S2{}
|
||||||
|
assert alignof(s.i) == 4
|
||||||
|
|
||||||
|
assert alignof('hello') == $if x64 {
|
||||||
|
8
|
||||||
|
} $else {
|
||||||
|
4
|
||||||
|
}
|
||||||
|
}
|
|
@ -121,6 +121,7 @@ pub enum Kind {
|
||||||
key_select
|
key_select
|
||||||
key_like
|
key_like
|
||||||
key_ilike
|
key_ilike
|
||||||
|
key_alignof
|
||||||
key_sizeof
|
key_sizeof
|
||||||
key_isreftype
|
key_isreftype
|
||||||
key_likely
|
key_likely
|
||||||
|
@ -305,6 +306,7 @@ fn build_token_str() []string {
|
||||||
s[Kind.key_asm] = 'asm'
|
s[Kind.key_asm] = 'asm'
|
||||||
s[Kind.key_return] = 'return'
|
s[Kind.key_return] = 'return'
|
||||||
s[Kind.key_module] = 'module'
|
s[Kind.key_module] = 'module'
|
||||||
|
s[Kind.key_alignof] = 'alignof'
|
||||||
s[Kind.key_sizeof] = 'sizeof'
|
s[Kind.key_sizeof] = 'sizeof'
|
||||||
s[Kind.key_isreftype] = 'isreftype'
|
s[Kind.key_isreftype] = 'isreftype'
|
||||||
s[Kind.key_likely] = '_likely_'
|
s[Kind.key_likely] = '_likely_'
|
||||||
|
@ -657,6 +659,7 @@ pub fn kind_to_string(k Kind) string {
|
||||||
.key_select { 'key_select' }
|
.key_select { 'key_select' }
|
||||||
.key_like { 'key_like' }
|
.key_like { 'key_like' }
|
||||||
.key_ilike { 'key_ilike' }
|
.key_ilike { 'key_ilike' }
|
||||||
|
.key_alignof { 'key_alignof' }
|
||||||
.key_sizeof { 'key_sizeof' }
|
.key_sizeof { 'key_sizeof' }
|
||||||
.key_isreftype { 'key_isreftype' }
|
.key_isreftype { 'key_isreftype' }
|
||||||
.key_likely { 'key_likely' }
|
.key_likely { 'key_likely' }
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue