diff --git a/docs/cton_lexer.py b/docs/cton_lexer.py index c12db5aea7..0139de337c 100644 --- a/docs/cton_lexer.py +++ b/docs/cton_lexer.py @@ -30,7 +30,7 @@ class CretonneLexer(RegexLexer): # Known attributes. (keywords('align', 'aligntrap', 'uext', 'sext', 'inreg'), Name.Attribute), # Well known value types. - (r'\b(bool|i\d+|f32|f64)(x\d+)?\b', Keyword.Type), + (r'\b(b\d+|i\d+|f32|f64)(x\d+)?\b', Keyword.Type), # v = value # ss = stack slot (r'(v|ss)\d+', Name.Variable), diff --git a/docs/langref.rst b/docs/langref.rst index 47f7fa8833..df0e19b20a 100644 --- a/docs/langref.rst +++ b/docs/langref.rst @@ -87,7 +87,36 @@ All SSA values have a type which determines the size and shape (for SIMD vectors) of the value. Many instructions are polymorphic -- they can operate on different types. -.. autoctontype:: bool +Boolean types +------------- + +Boolean values are either true or false. While this only requires a single bit +to represent, more bits are often used when holding a boolean value in a +register or in memory. The :type:`b1` type represents an abstract boolean +value. It can only exist as an SSA value, it can't be stored in memory or +converted to another type. The larger boolean types can be stored in memory. + +.. todo:: Clarify the representation of larger boolean types. + + The multi-bit boolean types can be interpreted in different ways. We could + declare that zero means false and non-zero means true. This may require + unwanted normalization code in some places. + + We could specify a fixed encoding like all ones for true. This would then + lead to undefined behavior if untrusted code uses the multibit booleans + incorrectly. + + Something like this: + + - External code is not allowed to load/store multi-bit booleans or + otherwise expose the representation. + - Each target specifies the exact representation of a multi-bit boolean. + +.. autoctontype:: b1 +.. autoctontype:: b8 +.. autoctontype:: b16 +.. autoctontype:: b32 +.. autoctontype:: b64 Integer types ------------- @@ -115,7 +144,7 @@ SIMD vector types ----------------- A SIMD vector type represents a vector of values from one of the scalar types -(:type:`bool`, integer, and floating point). Each scalar value in a SIMD type is +(boolean, integer, and floating point). Each scalar value in a SIMD type is called a *lane*. The number of lanes must be a power of two in the range 2-256. .. type:: i%Bx%N @@ -146,14 +175,14 @@ called a *lane*. The number of lanes must be a power of two in the range 2-256. The size of a :type:`f64` vector in memory is :math:`8N` bytes. -.. type:: boolx%N +.. type:: b1x%N A boolean SIMD vector. Boolean vectors are used when comparing SIMD vectors. For example, - comparing two :type:`i32x4` values would produce a :type:`boolx4` result. + comparing two :type:`i32x4` values would produce a :type:`b1x4` result. - Like the :type:`bool` type, a boolean vector cannot be stored in memory. + Like the :type:`b1` type, a boolean vector cannot be stored in memory. Pseudo-types and type classes ----------------------------- @@ -194,11 +223,11 @@ in this reference. .. type:: Logic - Either :type:`bool` or :type:`boolxN`. + Either :type:`b1` or :type:`b1xN`. .. type:: Testable - Either :type:`bool` or :type:`iN`. + Either :type:`b1` or :type:`iN`. Immediate operand types ----------------------- @@ -291,7 +320,7 @@ instruction in the EBB. Branch when zero. - If ``x`` is a :type:`bool` value, take the branch when ``x`` is false. If + If ``x`` is a :type:`b1` value, take the branch when ``x`` is false. If ``x`` is an integer value, take the branch when ``x = 0``. :arg Testable x: Value to test. @@ -303,7 +332,7 @@ instruction in the EBB. Branch when non-zero. - If ``x`` is a :type:`bool` value, take the branch when ``x`` is true. If + If ``x`` is a :type:`b1` value, take the branch when ``x`` is true. If ``x`` is an integer value, take the branch when ``x != 0``. :arg Testable x: Value to test. @@ -479,8 +508,7 @@ Cretonne also provides more restricted memory operations that are always safe. Load from memory at ``p + Offset``. This is a polymorphic instruction that can load any value type which has a - memory representation (i.e., everything except :type:`bool` and boolean - vectors). + memory representation. :arg iPtr p: Base address. :arg Offset: Immediate signed offset. @@ -692,7 +720,7 @@ load a constant into an SSA value. Conditional select. - :arg bool c: Controlling flag. + :arg b1 c: Controlling flag. :arg T x: Value to return when ``c`` is true. :arg T y: Value to return when ``c`` is false. Must be same type as ``x``. :result T a: Same type as ``x`` and ``y``. @@ -710,7 +738,7 @@ Vector operations Select lanes from ``x`` or ``y`` controlled by the lanes of the boolean vector ``c``. - :arg boolxN c: Controlling flag vector. + :arg b1xN c: Controlling flag vector. :arg TxN x: Vector with lanes selected by the true lanes of ``c``. Must be a vector type with the same number of lanes as ``c``. :arg TxN y: Vector with lanes selected by the false lanes of ``c``. @@ -872,7 +900,7 @@ These operations generally follow IEEE 754-2008 semantics. :arg Cond: Condition code determining how ``x`` and ``y`` are compared. :arg x,y: Floating point scalar or vector values of the same type. - :rtype: :type:`bool` or :type:`boolxN` with the same number of lanes as + :rtype: :type:`b1` or :type:`b1xN` with the same number of lanes as ``x`` and ``y``. An 'ordered' condition code yields ``false`` if either operand is Nan. diff --git a/meta/cretonne/__init__.py b/meta/cretonne/__init__.py index fd0c4664dd..bbf0e74063 100644 --- a/meta/cretonne/__init__.py +++ b/meta/cretonne/__init__.py @@ -95,6 +95,20 @@ class FloatType(ScalarType): def __repr__(self): return 'FloatType(bits={})'.format(self.bits) +class BoolType(ScalarType): + """A concrete scalar boolean type.""" + + def __init__(self, bits): + assert bits > 0, 'BoolType must have positive number of bits' + super(BoolType, self).__init__( + name='b{:d}'.format(bits), + membytes=bits/8, + doc="A boolean type with {} bits.".format(bits)) + self.bits = bits + + def __repr__(self): + return 'BoolType(bits={})'.format(self.bits) + # # Parametric polymorphism. # diff --git a/meta/cretonne/types.py b/meta/cretonne/types.py index 3d369a60e4..c639d89050 100644 --- a/meta/cretonne/types.py +++ b/meta/cretonne/types.py @@ -2,14 +2,19 @@ The cretonne.types module predefines all the Cretonne scalar types. """ -from . import ScalarType, IntType, FloatType +from . import ScalarType, IntType, FloatType, BoolType #: Boolean. -bool = ScalarType('bool', 0, +b1 = ScalarType('b1', 0, """ A boolean value that is either true or false. """) +b8 = BoolType(8) #: 8-bit bool. +b16 = BoolType(16) #: 16-bit bool. +b32 = BoolType(32) #: 32-bit bool. +b64 = BoolType(64) #: 64-bit bool. + i8 = IntType(8) #: 8-bit int. i16 = IntType(16) #: 16-bit int. i32 = IntType(32) #: 32-bit int.