[m-rev.] for review: add builtin 8, 16 and 32 bit integer types -- Part 2

Julien Fischer jfischer at opturion.com
Sat Aug 19 22:25:05 AEST 2017


For review by anyone.

----------

Add builtin 8, 16 and 32 bit integer types -- Part 2.

Enable support for literals of the new types.

Begin implementing library support for 8, 16, and 32 bit types.

Update the compiler to use the new types.

library/int8.m:
library/int16.m:
library/int32.m:
library/uint8.m:
library/uint16.m:
library/uint32.m:
     Begin filling these modules out.

library/uint.m:
     Unrelated change: add the predicates plus/2, minus/2 and
     times/2 for uints.

library/integer.m:
     Add predicates for converting integer/0 values into values
     of the new types.

     Add functions for converting values of the new types into
     integer/0 values.

library/string.m:
     Add functions for converting values of the new types to strings.

library/private_builtin.m:
     Replace the placeholder definitions for the builtin unify and compare
     predicates for the new types with their actual definitions.

library/erlang_rtti_implementation.m:
library/rtti_implementation.m:
     Replace placeholder definitions for the new types with their
     actual definitions.

library/io.m:
     Add predicates for writing values of the new types to file streams.

library/stream.string_writer.m:
     Implement generic write and print for values of the new types.

library/string.to_string.m:
     Likewise for string/1.

library/term.m:
library/term_conversion.m:
     Add predicates and functions for converting the new types to
     and from terms.

compiler/builtin_ops.m:
compiler/elds.m:
compiler/hlds_data.m:
compiler/llds.m:
compiler/mlds.m:
compiler/prog_data.m:
     Replace placeholders for the new types with the new types.

compiler/superhomogeneous.m:
     Enable literals of the new types.

compiler/mlds_to_cs.m:
     Avoid a warning from the C# compiler for bitwise-or operators
     with sbyte operands.

compiler/c_util.m:
compiler/elds_to_erlang.m:
compiler/hlds_out_util.m:
compiler/llds_out_data.m:
compiler/lookup_switch.m:
compiler/mlds_to_c.m:
compiler/mlds_to_java.m:
compiler/opt_debug.m:
compiler/parse_tree_out_info.m:
compiler/parse_tree_to_term.m:
compiler/prog_out.m:
compiler/prog_rep.m:
compiler/prog_util.m:
     Replace placeholder code for the new types with code that uses the new
     types.

tests/invalid/invalid_int.m:
tests/invalid/invalid_int.err_exp2:
     Extend this test case to cover the fixed size integer types.

Julien.

diff --git a/compiler/builtin_ops.m b/compiler/builtin_ops.m
index f81552e8e..d09ecf2f4 100644
--- a/compiler/builtin_ops.m
+++ b/compiler/builtin_ops.m
@@ -2,6 +2,7 @@
  % vim: ft=mercury ts=4 sw=4 et
  %-----------------------------------------------------------------------------%
  % Copyright (C) 1999-2001, 2003-2006, 2009-2011 The University of Melbourne.
+% Copyright (C) 2014-2017 The Mercury team.
  % This file may only be copied under the terms of the GNU General
  % Public License - see the file COPYING in the Mercury distribution.
  %-----------------------------------------------------------------------------%
@@ -171,12 +172,12 @@
      --->    leaf(T)
      ;       int_const(int)
      ;       uint_const(uint)
-    ;       int8_const(int)     % XXX FIXED SIZE INTS
-    ;       uint8_const(int)    % XXX FIXED SIZE INTS
-    ;       int16_const(int)    % XXX FIXED SIZE INTS
-    ;       uint16_const(int)   % XXX FIXED SIZE INTS
-    ;       int32_const(int)    % XXX FIXED SIZE INTS
-    ;       uint32_const(int)   % XXX FIXED SIZE INTS
+    ;       int8_const(int8)
+    ;       uint8_const(uint8)
+    ;       int16_const(int16)
+    ;       uint16_const(uint16)
+    ;       int32_const(int32)
+    ;       uint32_const(uint32)
      ;       float_const(float)
      ;       unary(unary_op, simple_expr(T))
      ;       binary(binary_op, simple_expr(T), simple_expr(T)).
diff --git a/compiler/c_util.m b/compiler/c_util.m
index 48ea69617..052e24c4a 100644
--- a/compiler/c_util.m
+++ b/compiler/c_util.m
@@ -2,6 +2,7 @@
  % vim: ft=mercury ts=4 sw=4 et
  %---------------------------------------------------------------------------%
  % Copyright (C) 1999-2007, 2009-2012 The University of Melbourne.
+% Copyright (C) 2013-2017 The Mercury team.
  % This file may only be copied under the terms of the GNU General
  % Public License - see the file COPYING in the Mercury distribution.
  %---------------------------------------------------------------------------%
@@ -184,6 +185,42 @@
      io::di, io::uo) is det.
  :- pred output_uint_expr_cur_stream(uint::in, io::di, io::uo) is det.

+    % Write out an int8 as a C expression.
+    %
+:- pred output_int8_expr(io.text_output_stream::in, int8::in,
+    io::di, io::uo) is det.
+:- pred output_int8_expr_cur_stream(int8::in, io::di, io::uo) is det.
+
+    % Write out a uint8 as a C expression.
+    %
+:- pred output_uint8_expr(io.text_output_stream::in, uint8::in,
+    io::di, io::uo) is det.
+:- pred output_uint8_expr_cur_stream(uint8::in, io::di, io::uo) is det.
+
+    % Write out an int16 as a C expression.
+    %
+:- pred output_int16_expr(io.text_output_stream::in, int16::in,
+    io::di, io::uo) is det.
+:- pred output_int16_expr_cur_stream(int16::in, io::di, io::uo) is det.
+
+    % Write out a uint16 as a C expression.
+    %
+:- pred output_uint16_expr(io.text_output_stream::in, uint16::in,
+    io::di, io::uo) is det.
+:- pred output_uint16_expr_cur_stream(uint16::in, io::di, io::uo) is det.
+
+    % Write out an int32 as a C expression.
+    %
+:- pred output_int32_expr(io.text_output_stream::in, int32::in,
+    io::di, io::uo) is det.
+:- pred output_int32_expr_cur_stream(int32::in, io::di, io::uo) is det.
+
+    % Write out a uint32 as a C expression.
+    %
+:- pred output_uint32_expr(io.text_output_stream::in, uint32::in,
+    io::di, io::uo) is det.
+:- pred output_uint32_expr_cur_stream(uint32::in, io::di, io::uo) is det.
+
  %---------------------------------------------------------------------------%
  %
  % Float literals.
@@ -778,6 +815,65 @@ output_uint_expr_cur_stream(N, !IO) :-
      io.output_stream(Stream, !IO),
      output_uint_expr(Stream, N, !IO).

+%---------------------------------------------------------------------------%
+%
+% Fixed size integer literals.
+%
+
+output_int8_expr(Stream, N, !IO) :-
+    io.write_string(Stream, "INT8_C(", !IO),
+    io.write_int8(Stream, N, !IO),
+    io.write_string(Stream, ")", !IO).
+
+output_int8_expr_cur_stream(N, !IO) :-
+    io.output_stream(Stream, !IO),
+    output_int8_expr(Stream, N, !IO).
+
+output_uint8_expr(Stream, N, !IO) :-
+    io.write_string(Stream, "UINT8_C(", !IO),
+    io.write_uint8(Stream, N, !IO),
+    io.write_string(Stream, ")", !IO).
+
+output_uint8_expr_cur_stream(N, !IO) :-
+    io.output_stream(Stream, !IO),
+    output_uint8_expr(Stream, N, !IO).
+
+output_int16_expr(Stream, N, !IO) :-
+    io.write_string(Stream, "INT16_C(", !IO),
+    io.write_int16(Stream, N, !IO),
+    io.write_string(Stream, ")", !IO).
+
+output_int16_expr_cur_stream(N, !IO) :-
+    io.output_stream(Stream, !IO),
+    output_int16_expr(Stream, N, !IO).
+
+output_uint16_expr(Stream, N, !IO) :-
+    io.write_string(Stream, "UINT16_C(", !IO),
+    io.write_uint16(Stream, N, !IO),
+    io.write_string(Stream, ")", !IO).
+
+output_uint16_expr_cur_stream(N, !IO) :-
+    io.output_stream(Stream, !IO),
+    output_uint16_expr(Stream, N, !IO).
+
+output_int32_expr(Stream, N, !IO) :-
+    io.write_string(Stream, "INT32_C(", !IO),
+    io.write_int32(Stream, N, !IO),
+    io.write_string(Stream, ")", !IO).
+
+output_int32_expr_cur_stream(N, !IO) :-
+    io.output_stream(Stream, !IO),
+    output_int32_expr(Stream, N, !IO).
+
+output_uint32_expr(Stream, N, !IO) :-
+    io.write_string(Stream, "UINT32_C(", !IO),
+    io.write_uint32(Stream, N, !IO),
+    io.write_string(Stream, ")", !IO).
+
+output_uint32_expr_cur_stream(N, !IO) :-
+    io.output_stream(Stream, !IO),
+    output_uint32_expr(Stream, N, !IO).
+
  %---------------------------------------------------------------------------%
  %
  % Floating point literals.
diff --git a/compiler/elds.m b/compiler/elds.m
index 5248bd6d4..7dccebd0a 100644
--- a/compiler/elds.m
+++ b/compiler/elds.m
@@ -2,6 +2,7 @@
  % vim: ft=mercury ts=4 sw=4 et
  %-----------------------------------------------------------------------------%
  % Copyright (C) 2007, 2010-2011 The University of Melbourne.
+% Copyright (C) 2014-2017 The Mercury team.
  % This file may only be copied under the terms of the GNU General
  % Public License - see the file COPYING in the Mercury distribution.
  %-----------------------------------------------------------------------------%
@@ -215,12 +216,12 @@
      --->    elds_char(char)
      ;       elds_int(int)
      ;       elds_uint(uint)
-    ;       elds_int8(int)    % XXX FIXED SIZE INT
-    ;       elds_uint8(int)
-    ;       elds_int16(int)
-    ;       elds_uint16(int)
-    ;       elds_int32(int)
-    ;       elds_uint32(int)
+    ;       elds_int8(int8)
+    ;       elds_uint8(uint8)
+    ;       elds_int16(int16)
+    ;       elds_uint16(uint16)
+    ;       elds_int32(int32)
+    ;       elds_uint32(uint32)
      ;       elds_float(float)

      ;       elds_binary(string)
diff --git a/compiler/elds_to_erlang.m b/compiler/elds_to_erlang.m
index aea5e3552..6f22fc4d8 100644
--- a/compiler/elds_to_erlang.m
+++ b/compiler/elds_to_erlang.m
@@ -1,7 +1,8 @@
  %-----------------------------------------------------------------------------%
  % vim: ft=mercury ts=4 sw=4 et
  %-----------------------------------------------------------------------------%
-% Copyright (C) 2007-2011 The University of Melbourne.
+% Copyright (C) 2007-2012 The University of Melbourne.
+% Copyright (C) 2013-2017 The Mercury team.
  % This file may only be copied under the terms of the GNU General
  % Public License - see the file COPYING in the Mercury distribution.
  %-----------------------------------------------------------------------------%
@@ -782,29 +783,28 @@ output_term(ModuleInfo, VarSet, Indent, Term, !IO) :-
          io.write_uint(UInt, !IO),
          space(!IO)
      ;
-        % XXX FIXED SIZE INT
          Term = elds_int8(Int8),
-        io.write_int(Int8, !IO),
+        io.write_int8(Int8, !IO),
          space(!IO)
      ;
          Term = elds_uint8(UInt8),
-        io.write_int(UInt8, !IO),
+        io.write_uint8(UInt8, !IO),
          space(!IO)
      ;
          Term = elds_int16(Int16),
-        io.write_int(Int16, !IO),
+        io.write_int16(Int16, !IO),
          space(!IO)
      ;
          Term = elds_uint16(UInt16),
-        io.write_int(UInt16, !IO),
+        io.write_uint16(UInt16, !IO),
          space(!IO)
      ;
          Term = elds_int32(Int32),
-        io.write_int(Int32, !IO),
+        io.write_int32(Int32, !IO),
          space(!IO)
      ;
          Term = elds_uint32(UInt32),
-        io.write_int(UInt32, !IO),
+        io.write_uint32(UInt32, !IO),
          space(!IO)
      ;
          Term = elds_float(Float),
diff --git a/compiler/hlds_data.m b/compiler/hlds_data.m
index 8d56dba91..8c46ad77d 100644
--- a/compiler/hlds_data.m
+++ b/compiler/hlds_data.m
@@ -2,6 +2,7 @@
  % vim: ft=mercury ts=4 sw=4 et
  %---------------------------------------------------------------------------%
  % Copyright (C) 1996-2012 The University of Melbourne.
+% Copyright (C) 2014-2017 The Mercury team.
  % This file may only be copied under the terms of the GNU General
  % Public License - see the file COPYING in the Mercury distribution.
  %---------------------------------------------------------------------------%
@@ -705,13 +706,12 @@ cons_table_optimize(!ConsTable) :-
              % the specified unsigned integer value. This is used for uint
              % constants.

-            % XXX FIXED SIZE INT
-    ;       int_tag_int8(int)
-    ;       int_tag_uint8(int)
-    ;       int_tag_int16(int)
-    ;       int_tag_uint16(int)
-    ;       int_tag_int32(int)
-    ;       int_tag_uint32(int).
+    ;       int_tag_int8(int8)
+    ;       int_tag_uint8(uint8)
+    ;       int_tag_int16(int16)
+    ;       int_tag_uint16(uint16)
+    ;       int_tag_int32(int32)
+    ;       int_tag_uint32(uint32).

  :- type reserved_address
      --->    null_pointer
diff --git a/compiler/hlds_out_util.m b/compiler/hlds_out_util.m
index 0f303fd64..a3e02a57f 100644
--- a/compiler/hlds_out_util.m
+++ b/compiler/hlds_out_util.m
@@ -2,6 +2,7 @@
  % vim: ft=mercury ts=4 sw=4 et
  %-----------------------------------------------------------------------------%
  % Copyright (C) 2009-2012 The University of Melbourne.
+% Copyright (C) 2014-2017 The Mercury team.
  % This file may only be copied under the terms of the GNU General
  % Public License - see the file COPYING in the Mercury distribution.
  %-----------------------------------------------------------------------------%
@@ -681,32 +682,38 @@ functor_cons_id_to_string(ModuleInfo, VarSet, VarNamePrint, ConsId, ArgVars)
      ;
          ConsId = int8_const(Int8),
          Str = functor_to_string(VarSet, VarNamePrint,
-            term.integer(base_10, integer(Int8), signed, size_8_bit),
+            term.integer(base_10, integer.from_int8(Int8), signed,
+                size_8_bit),
              ArgVars)
      ;
          ConsId = uint8_const(UInt8),
          Str = functor_to_string(VarSet, VarNamePrint,
-            term.integer(base_10, integer(UInt8), unsigned, size_8_bit),
+            term.integer(base_10, integer.from_uint8(UInt8), unsigned,
+                size_8_bit),
              ArgVars)
      ;
          ConsId = int16_const(Int16),
          Str = functor_to_string(VarSet, VarNamePrint,
-            term.integer(base_10, integer(Int16), signed, size_16_bit),
+            term.integer(base_10, integer.from_int16(Int16), signed,
+                size_16_bit),
              ArgVars)
      ;
          ConsId = uint16_const(UInt16),
          Str = functor_to_string(VarSet, VarNamePrint,
-            term.integer(base_10, integer(UInt16), unsigned, size_16_bit),
+            term.integer(base_10, integer.from_uint16(UInt16), unsigned,
+                size_16_bit),
              ArgVars)
      ;
          ConsId = int32_const(Int32),
          Str = functor_to_string(VarSet, VarNamePrint,
-            term.integer(base_10, integer(Int32), signed, size_32_bit),
+            term.integer(base_10, integer.from_int32(Int32), signed,
+                size_32_bit),
              ArgVars)
      ;
          ConsId = uint32_const(UInt32),
          Str = functor_to_string(VarSet, VarNamePrint,
-            term.integer(base_10, integer(UInt32), unsigned, size_32_bit),
+            term.integer(base_10, integer.from_uint32(UInt32), unsigned,
+                size_32_bit),
              ArgVars)
      ;
          ConsId = float_const(Float),
@@ -867,22 +874,22 @@ cons_id_and_vars_or_arity_to_string(VarSet, Qual, ConsId, MaybeArgVars)
          String = uint_to_string(UInt) ++ "u"
      ;
          ConsId = int8_const(Int8),
-        string.int_to_string(Int8, String)
+        String = string.int8_to_string(Int8) ++ "i8"
      ;
          ConsId = uint8_const(UInt8),
-        string.int_to_string(UInt8, String)
+        String = string.uint8_to_string(UInt8) ++ "u8"
      ;
          ConsId = int16_const(Int16),
-        string.int_to_string(Int16, String)
+        String = string.int16_to_string(Int16) ++ "i16"
      ;
          ConsId = uint16_const(UInt16),
-        string.int_to_string(UInt16, String)
+        String = string.uint16_to_string(UInt16) ++ "u16"
      ;
          ConsId = int32_const(Int32),
-        string.int_to_string(Int32, String)
+        String = string.int32_to_string(Int32) ++ "i32"
      ;
          ConsId = uint32_const(UInt32),
-        string.int_to_string(UInt32, String)
+        String = string.uint32_to_string(UInt32) ++ "u32"
      ;
          ConsId = float_const(Float),
          String = float_to_string(Float)
diff --git a/compiler/llds.m b/compiler/llds.m
index 73a3fdec1..b794669e0 100644
--- a/compiler/llds.m
+++ b/compiler/llds.m
@@ -2,6 +2,7 @@
  % vim: ft=mercury ts=4 sw=4 et
  %-----------------------------------------------------------------------------%
  % Copyright (C) 1993-2012 The University of Melbourne.
+% Copyright (C) 2014-2017 The Mercury team.
  % This file may only be copied under the terms of the GNU General
  % Public License - see the file COPYING in the Mercury distribution.
  %-----------------------------------------------------------------------------%
@@ -1201,16 +1202,18 @@
  :- type rval_const
      --->    llconst_true
      ;       llconst_false
+
      ;       llconst_int(int)
      ;       llconst_uint(uint)

-            % XXX FIXED SIZE INT
-    ;       llconst_int8(int)
-    ;       llconst_uint8(int)
-    ;       llconst_int16(int)
-    ;       llconst_uint16(int)
-    ;       llconst_int32(int)
-    ;       llconst_uint32(int)
+    ;       llconst_int8(int8)
+    ;       llconst_uint8(uint8)
+
+    ;       llconst_int16(int16)
+    ;       llconst_uint16(uint16)
+
+    ;       llconst_int32(int32)
+    ;       llconst_uint32(uint32)

      ;       llconst_foreign(string, llds_type)
              % A constant in the target language.
diff --git a/compiler/llds_out_data.m b/compiler/llds_out_data.m
index dbe8acdaa..0e8342335 100644
--- a/compiler/llds_out_data.m
+++ b/compiler/llds_out_data.m
@@ -2,6 +2,7 @@
  % vim: ft=mercury ts=4 sw=4 et
  %----------------------------------------------------------------------------%
  % Copyright (C) 2009-2012 The University of Melbourne.
+% Copyright (C) 2013-2017 The Mercury team.
  % This file may only be copied under the terms of the GNU General
  % Public License - see the file COPYING in the Mercury distribution.
  %----------------------------------------------------------------------------%
@@ -1218,22 +1219,22 @@ output_rval_const(Info, Const, !IO) :-
          c_util.output_uint_expr_cur_stream(N, !IO)
      ;
          Const = llconst_int8(N),
-        c_util.output_int_expr_cur_stream(N, !IO)
+        c_util.output_int8_expr_cur_stream(N, !IO)
      ;
          Const = llconst_uint8(N),
-        c_util.output_int_expr_cur_stream(N, !IO)
+        c_util.output_uint8_expr_cur_stream(N, !IO)
      ;
          Const = llconst_int16(N),
-        c_util.output_int_expr_cur_stream(N, !IO)
+        c_util.output_int16_expr_cur_stream(N, !IO)
      ;
          Const = llconst_uint16(N),
-        c_util.output_int_expr_cur_stream(N, !IO)
+        c_util.output_uint16_expr_cur_stream(N, !IO)
      ;
          Const = llconst_int32(N),
-        c_util.output_int_expr_cur_stream(N, !IO)
+        c_util.output_int32_expr_cur_stream(N, !IO)
      ;
          Const = llconst_uint32(N),
-        c_util.output_int_expr_cur_stream(N, !IO)
+        c_util.output_uint32_expr_cur_stream(N, !IO)
      ;
          Const = llconst_foreign(Value, Type),
          io.write_char('(', !IO),
diff --git a/compiler/lookup_switch.m b/compiler/lookup_switch.m
index 0aba8ef26..62e60c9ed 100644
--- a/compiler/lookup_switch.m
+++ b/compiler/lookup_switch.m
@@ -2,6 +2,7 @@
  % vim: ft=mercury ts=4 sw=4 et
  %-----------------------------------------------------------------------------%
  % Copyright (C) 1996-2012 The University of Melbourne.
+% Copyright (C) 2015, 2017 The Mercury team.
  % This file may only be copied under the terms of the GNU General
  % Public License - see the file COPYING in the Mercury distribution.
  %-----------------------------------------------------------------------------%
@@ -943,6 +944,16 @@ generate_bit_vec_args([Word - Bits | Rest], Count, [Rval | Rvals]) :-

  %-----------------------------------------------------------------------------%

+    % XXX FIXED SIZE INTS
+    % These imports can be deleted once support for fixed size integer literals
+    % has bootstrapped.
+:- import_module int8.
+:- import_module uint8.
+:- import_module int16.
+:- import_module uint16.
+:- import_module int32.
+:- import_module uint32.
+
  default_value_for_type(lt_bool) = const(llconst_int(0)).
  default_value_for_type(lt_int_least8) = const(llconst_int(0)).
  default_value_for_type(lt_uint_least8) = const(llconst_int(0)).
@@ -952,13 +963,12 @@ default_value_for_type(lt_int_least32) = const(llconst_int(0)).
  default_value_for_type(lt_uint_least32) = const(llconst_int(0)).
  default_value_for_type(lt_int(int_type_int)) = const(llconst_int(0)).
  default_value_for_type(lt_int(int_type_uint)) = const(llconst_uint(0u)).
-% XXX FIXED SIZE INT.
-default_value_for_type(lt_int(int_type_int8)) = const(llconst_int8(0)).
-default_value_for_type(lt_int(int_type_uint8)) = const(llconst_uint8(0)).
-default_value_for_type(lt_int(int_type_int16)) = const(llconst_int16(0)).
-default_value_for_type(lt_int(int_type_uint16)) = const(llconst_uint16(0)).
-default_value_for_type(lt_int(int_type_int32)) = const(llconst_int32(0)).
-default_value_for_type(lt_int(int_type_uint32)) = const(llconst_uint32(0)).
+default_value_for_type(lt_int(int_type_int8)) = const(llconst_int8(cast_from_int(0))).
+default_value_for_type(lt_int(int_type_uint8)) = const(llconst_uint8(cast_from_int(0))).
+default_value_for_type(lt_int(int_type_int16)) = const(llconst_int16(cast_from_int(0))).
+default_value_for_type(lt_int(int_type_uint16)) = const(llconst_uint16(cast_from_int(0))).
+default_value_for_type(lt_int(int_type_int32)) = const(llconst_int32(cast_from_int(0))).
+default_value_for_type(lt_int(int_type_uint32)) = const(llconst_uint32(cast_from_int(0))).
  default_value_for_type(lt_float) = const(llconst_float(0.0)).
  default_value_for_type(lt_string) = const(llconst_string("")).
  default_value_for_type(lt_data_ptr) = const(llconst_int(0)).
diff --git a/compiler/mlds.m b/compiler/mlds.m
index 42801afa0..002f4e270 100644
--- a/compiler/mlds.m
+++ b/compiler/mlds.m
@@ -2,6 +2,7 @@
  % vim: ft=mercury ts=4 sw=4 et
  %---------------------------------------------------------------------------%
  % Copyright (C) 1999-2011 The University of Melbourne.
+% Copyright (C) 2013-2017 The Mercury team.
  % This file may only be copied under the terms of the GNU General
  % Public License - see the file COPYING in the Mercury distribution.
  %---------------------------------------------------------------------------%
@@ -1801,12 +1802,12 @@
      ;       mlconst_false
      ;       mlconst_int(int)
      ;       mlconst_uint(uint)
-    ;       mlconst_int8(int)
-    ;       mlconst_uint8(int)
-    ;       mlconst_int16(int)
-    ;       mlconst_uint16(int)
-    ;       mlconst_int32(int)
-    ;       mlconst_uint32(int)
+    ;       mlconst_int8(int8)
+    ;       mlconst_uint8(uint8)
+    ;       mlconst_int16(int16)
+    ;       mlconst_uint16(uint16)
+    ;       mlconst_int32(int32)
+    ;       mlconst_uint32(uint32)
      ;       mlconst_enum(int, mlds_type)
      ;       mlconst_char(int)
      ;       mlconst_float(float)
diff --git a/compiler/mlds_to_c.m b/compiler/mlds_to_c.m
index 4e7f183a3..34c5793e7 100644
--- a/compiler/mlds_to_c.m
+++ b/compiler/mlds_to_c.m
@@ -2,6 +2,7 @@
  % vim: ft=mercury ts=4 sw=4 et
  %---------------------------------------------------------------------------%
  % Copyright (C) 1999-2012 The University of Melbourne.
+% Copyright (C) 2013-2017 The Mercury team.
  % This file may only be copied under the terms of the GNU General
  % Public License - see the file COPYING in the Mercury distribution.
  %---------------------------------------------------------------------------%
@@ -5204,22 +5205,22 @@ mlds_output_rval_const(_Opts, Const, !IO) :-
          c_util.output_uint_expr_cur_stream(U, !IO)
      ;
          Const = mlconst_int8(N),
-        c_util.output_int_expr_cur_stream(N, !IO)
+        c_util.output_int8_expr_cur_stream(N, !IO)
      ;
          Const = mlconst_uint8(N),
-        c_util.output_int_expr_cur_stream(N, !IO)
+        c_util.output_uint8_expr_cur_stream(N, !IO)
      ;
          Const = mlconst_int16(N),
-        c_util.output_int_expr_cur_stream(N, !IO)
+        c_util.output_int16_expr_cur_stream(N, !IO)
      ;
          Const = mlconst_uint16(N),
-        c_util.output_int_expr_cur_stream(N, !IO)
+        c_util.output_uint16_expr_cur_stream(N, !IO)
      ;
          Const = mlconst_int32(N),
-        c_util.output_int_expr_cur_stream(N, !IO)
+        c_util.output_int32_expr_cur_stream(N, !IO)
      ;
          Const = mlconst_uint32(N),
-        c_util.output_int_expr_cur_stream(N, !IO)
+        c_util.output_uint32_expr_cur_stream(N, !IO)
      ;
          Const = mlconst_char(C),
          io.write_string("(MR_Char) ", !IO),
diff --git a/compiler/mlds_to_cs.m b/compiler/mlds_to_cs.m
index daea42e7b..f6f60abb8 100644
--- a/compiler/mlds_to_cs.m
+++ b/compiler/mlds_to_cs.m
@@ -2,6 +2,7 @@
  % vim: ft=mercury ts=4 sw=4 et
  %---------------------------------------------------------------------------%
  % Copyright (C) 2010-2012 The University of Melbourne.
+% Copyright (C) 2013-2017 The Mercury team.
  % This file may only be copied under the terms of the GNU General
  % Public License - see the file COPYING in the Mercury distribution.
  %---------------------------------------------------------------------------%
@@ -3460,7 +3461,6 @@ output_binop_for_csharp(Info, Op, X, Y, !IO) :-
          ; Op = int_div(int_type_int8)
          ; Op = int_mod(int_type_int8)
          ; Op = bitwise_and(int_type_int8)
-        ; Op = bitwise_or(int_type_int8)
          ; Op = bitwise_xor(int_type_int8)
          ; Op = unchecked_left_shift(int_type_int8)
          ; Op = unchecked_right_shift(int_type_int8)
@@ -3472,6 +3472,17 @@ output_binop_for_csharp(Info, Op, X, Y, !IO) :-
          io.write_string(" ", !IO),
          output_rval_for_csharp(Info, Y, !IO),
          io.write_string(")", !IO)
+    ;
+        % The special treatment of bitwise-or here is necessary to avoid
+        % warning CS0675 from the C# compiler.
+        Op = bitwise_or(int_type_int8),
+        io.write_string("(sbyte)((byte)", !IO),
+        output_rval_for_csharp(Info, X, !IO),
+        io.write_string(" ", !IO),
+        output_binary_op_for_csharp(Op, !IO),
+        io.write_string(" (byte)", !IO),
+        output_rval_for_csharp(Info, Y, !IO),
+        io.write_string(")", !IO)
      ;
          ( Op = int_add(int_type_uint8)
          ; Op = int_sub(int_type_uint8)
@@ -3607,22 +3618,22 @@ output_rval_const_for_csharp(Info, Const, !IO) :-
          output_uint_const_for_csharp(U, !IO)
      ;
          Const = mlconst_int8(N),
-        output_int_const_for_csharp(N, !IO)
+        output_int8_const_for_csharp(N, !IO)
      ;
          Const = mlconst_uint8(N),
-        output_int_const_for_csharp(N, !IO)
+        output_uint8_const_for_csharp(N, !IO)
      ;
          Const = mlconst_int16(N),
-        output_int_const_for_csharp(N, !IO)
+        output_int16_const_for_csharp(N, !IO)
      ;
          Const = mlconst_uint16(N),
-        output_int_const_for_csharp(N, !IO)
+        output_uint16_const_for_csharp(N, !IO)
      ;
          Const = mlconst_int32(N),
-        output_int_const_for_csharp(N, !IO)
+        output_int32_const_for_csharp(N, !IO)
      ;
          Const = mlconst_uint32(N),
-        output_int_const_for_csharp(N, !IO)
+        output_uint32_const_for_csharp(N, !IO)
      ;
          Const = mlconst_char(N),
          io.write_string("( ", !IO),
@@ -3730,6 +3741,37 @@ output_uint_const_for_csharp(U, !IO) :-
      io.write_uint(U, !IO),
      io.write_string("U", !IO).

+:- pred output_int8_const_for_csharp(int8::in, io::di, io::uo) is det.
+
+output_int8_const_for_csharp(I8, !IO) :-
+    io.write_int8(I8, !IO).
+
+:- pred output_uint8_const_for_csharp(uint8::in, io::di, io::uo) is det.
+
+output_uint8_const_for_csharp(U8, !IO) :-
+    io.write_uint8(U8, !IO).
+
+:- pred output_int16_const_for_csharp(int16::in, io::di, io::uo) is det.
+
+output_int16_const_for_csharp(I16, !IO) :-
+    io.write_int16(I16, !IO).
+
+:- pred output_uint16_const_for_csharp(uint16::in, io::di, io::uo) is det.
+
+output_uint16_const_for_csharp(U16, !IO) :-
+    io.write_uint16(U16, !IO).
+
+:- pred output_int32_const_for_csharp(int32::in, io::di, io::uo) is det.
+
+output_int32_const_for_csharp(I32, !IO) :-
+    io.write_int32(I32, !IO).
+
+:- pred output_uint32_const_for_csharp(uint32::in, io::di, io::uo) is det.
+
+output_uint32_const_for_csharp(U32, !IO) :-
+    io.write_uint32(U32, !IO),
+    io.write_string("U", !IO).
+
  %---------------------------------------------------------------------------%

  :- pred mlds_output_code_addr_for_csharp(csharp_out_info::in,
diff --git a/compiler/mlds_to_java.m b/compiler/mlds_to_java.m
index 525923d53..7f1aac371 100644
--- a/compiler/mlds_to_java.m
+++ b/compiler/mlds_to_java.m
@@ -1,8 +1,8 @@
  %---------------------------------------------------------------------------%
  % vim: ft=mercury ts=4 sw=4 et
  %---------------------------------------------------------------------------%
-% Copyright (C) 2000-2011 The University of Melbourne.
-% Copyright (C) 2013-2016 The Mercury team.
+% Copyright (C) 2000-2012 The University of Melbourne.
+% Copyright (C) 2013-2017 The Mercury team.
  % This file may only be copied under the terms of the GNU General
  % Public License - see the file COPYING in the Mercury distribution.
  %---------------------------------------------------------------------------%
@@ -119,6 +119,9 @@
  :- import_module cord.
  :- import_module digraph.
  :- import_module int.
+:- import_module int8.
+:- import_module int16.
+:- import_module int32.
  :- import_module list.
  :- import_module map.
  :- import_module maybe.
@@ -4628,22 +4631,22 @@ output_rval_const_for_java(Info, Const, !IO) :-
          output_int_const_for_java(uint.cast_to_int(U), !IO)
      ;
          Const = mlconst_int8(I8),
-        output_int_const_for_java(I8, !IO)
+        io.write_int8(I8, !IO)
      ;
          Const = mlconst_uint8(U8),
-        output_int_const_for_java(U8, !IO)
+        io.write_int8(int8.cast_from_uint8(U8), !IO)
      ;
          Const = mlconst_int16(I16),
-        output_int_const_for_java(I16, !IO)
+        io.write_int16(I16, !IO)
      ;
          Const = mlconst_uint16(U16),
-        output_int_const_for_java(U16, !IO)
+        io.write_int16(int16.cast_from_uint16(U16), !IO)
      ;
          Const = mlconst_int32(I32),
-        output_int_const_for_java(I32, !IO)
+        io.write_int32(I32, !IO)
      ;
          Const = mlconst_uint32(U32),
-        output_int_const_for_java(U32, !IO)
+        io.write_int32(int32.cast_from_uint32(U32), !IO)
      ;
          Const = mlconst_char(N),
          io.write_string("(", !IO),
diff --git a/compiler/opt_debug.m b/compiler/opt_debug.m
index 6fff4b72e..19c71b1f2 100644
--- a/compiler/opt_debug.m
+++ b/compiler/opt_debug.m
@@ -1,7 +1,8 @@
  %-----------------------------------------------------------------------------%
  % vim: ft=mercury ts=4 sw=4 et
  %-----------------------------------------------------------------------------%
-% Copyright (C) 1994-2011 The University of Melbourne.
+% Copyright (C) 1994-2012 The University of Melbourne.
+% Copyright (C) 2013-2017 The Mercury team.
  % This file may only be copied under the terms of the GNU General
  % Public License - see the file COPYING in the Mercury distribution.
  %-----------------------------------------------------------------------------%
@@ -445,22 +446,22 @@ dump_const(MaybeProcLabel, Const) = Str :-
          Str = uint_to_string(U)
      ;
          Const = llconst_int8(I8),
-        Str = int_to_string(I8)
+        Str = int8_to_string(I8)
      ;
          Const = llconst_uint8(U8),
-        Str = int_to_string(U8)
+        Str = uint8_to_string(U8)
      ;
          Const = llconst_int16(I16),
-        Str = int_to_string(I16)
+        Str = int16_to_string(I16)
      ;
          Const = llconst_uint16(U16),
-        Str = int_to_string(U16)
+        Str = uint16_to_string(U16)
      ;
          Const = llconst_int32(I32),
-        Str = int_to_string(I32)
+        Str = int32_to_string(I32)
      ;
          Const = llconst_uint32(U32),
-        Str = int_to_string(U32)
+        Str = uint32_to_string(U32)
      ;
          Const = llconst_foreign(F, _),
          Str = F
diff --git a/compiler/parse_tree_out_info.m b/compiler/parse_tree_out_info.m
index abd088fc4..78738992f 100644
--- a/compiler/parse_tree_out_info.m
+++ b/compiler/parse_tree_out_info.m
@@ -1,7 +1,7 @@
  %---------------------------------------------------------------------------%
  % vim: ft=mercury ts=4 sw=4 et
  %---------------------------------------------------------------------------%
-% Copyright (C) 2015 The Mercury team.
+% Copyright (C) 2015-2017 The Mercury team.
  % This file may only be copied under the terms of the GNU General
  % Public License - see the file COPYING in the Mercury distribution.
  %---------------------------------------------------------------------------%
@@ -107,13 +107,12 @@
      pred add_char(char::in, U::di, U::uo) is det,
      pred add_int(int::in, U::di, U::uo) is det,
      pred add_uint(uint::in, U::di, U::uo) is det,
-    % XXX FIXED SIZE INT
-    pred add_int8(int::in, U::di, U::uo) is det,
-    pred add_uint8(int::in, U::di, U::uo) is det,
-    pred add_int16(int::in, U::di, U::uo) is det,
-    pred add_uint16(int::in, U::di, U::uo) is det,
-    pred add_int32(int::in, U::di, U::uo) is det,
-    pred add_uint32(int::in, U::di, U::uo) is det,
+    pred add_int8(int8::in, U::di, U::uo) is det,
+    pred add_uint8(uint8::in, U::di, U::uo) is det,
+    pred add_int16(int16::in, U::di, U::uo) is det,
+    pred add_uint16(uint16::in, U::di, U::uo) is det,
+    pred add_int32(int32::in, U::di, U::uo) is det,
+    pred add_uint32(uint32::in, U::di, U::uo) is det,
      pred add_float(float::in, U::di, U::uo) is det,
      pred add_purity_prefix(purity::in, U::di, U::uo) is det,
      pred add_quoted_atom(string::in, U::di, U::uo) is det,
@@ -199,12 +198,12 @@ maybe_unqualify_sym_name(Info, SymName, OutSymName) :-
      pred(add_char/3) is io.write_char,
      pred(add_int/3) is io.write_int,
      pred(add_uint/3) is write_uint_literal,
-    pred(add_int8/3) is io.write_int,
-    pred(add_uint8/3) is io.write_int,
-    pred(add_int16/3) is io.write_int,
-    pred(add_uint16/3) is io.write_int,
-    pred(add_int32/3) is io.write_int,
-    pred(add_uint32/3) is io.write_int,
+    pred(add_int8/3) is write_int8_literal,
+    pred(add_uint8/3) is write_uint8_literal,
+    pred(add_int16/3) is write_int16_literal,
+    pred(add_uint16/3) is write_uint16_literal,
+    pred(add_int32/3) is write_int32_literal,
+    pred(add_uint32/3) is write_uint32_literal,
      pred(add_float/3) is io.write_float,
      pred(add_purity_prefix/3) is prog_out.write_purity_prefix,
      pred(add_quoted_atom/3) is term_io.quote_atom,
@@ -249,6 +248,42 @@ write_uint_literal(UInt, !IO) :-
      io.write_uint(UInt, !IO),
      io.write_char('u', !IO).

+:- pred write_int8_literal(int8::in, io::di, io::uo) is det.
+
+write_int8_literal(Int8, !IO) :-
+    io.write_int8(Int8, !IO),
+    io.write_string("i8", !IO).
+
+:- pred write_uint8_literal(uint8::in, io::di, io::uo) is det.
+
+write_uint8_literal(UInt8, !IO) :-
+    io.write_uint8(UInt8, !IO),
+    io.write_string("u8", !IO).
+
+:- pred write_int16_literal(int16::in, io::di, io::uo) is det.
+
+write_int16_literal(Int16, !IO) :-
+    io.write_int16(Int16, !IO),
+    io.write_string("i16", !IO).
+
+:- pred write_uint16_literal(uint16::in, io::di, io::uo) is det.
+
+write_uint16_literal(UInt16, !IO) :-
+    io.write_uint16(UInt16, !IO),
+    io.write_string("u16", !IO).
+
+:- pred write_int32_literal(int32::in, io::di, io::uo) is det.
+
+write_int32_literal(Int32, !IO) :-
+    io.write_int32(Int32, !IO),
+    io.write_string("i32", !IO).
+
+:- pred write_uint32_literal(uint32::in, io::di, io::uo) is det.
+
+write_uint32_literal(UInt32, !IO) :-
+    io.write_uint32(UInt32, !IO),
+    io.write_string("u32", !IO).
+
  %---------------------------------------------------------------------------%

  :- pred write_eval_eval_method(eval_method::in, io::di, io::uo) is det.
@@ -294,41 +329,40 @@ output_uint(U, Str0, Str) :-
      S = uint_to_string(U) ++ "u",
      string.append(Str0, S, Str).

-% XXX FIXED SIZE INT
-:- pred output_int8(int::in, string::di, string::uo) is det.
+:- pred output_int8(int8::in, string::di, string::uo) is det.

-output_int8(I, Str0, Str) :-
-    string.int_to_string(I, S),
+output_int8(I8, Str0, Str) :-
+    S = string.int8_to_string(I8),
      string.append(Str0, S, Str).

-:- pred output_uint8(int::in, string::di, string::uo) is det.
+:- pred output_uint8(uint8::in, string::di, string::uo) is det.

-output_uint8(I, Str0, Str) :-
-    string.int_to_string(I, S),
+output_uint8(U8, Str0, Str) :-
+    S = string.uint8_to_string(U8),
      string.append(Str0, S, Str).

-:- pred output_int16(int::in, string::di, string::uo) is det.
+:- pred output_int16(int16::in, string::di, string::uo) is det.

-output_int16(I, Str0, Str) :-
-    string.int_to_string(I, S),
+output_int16(I16, Str0, Str) :-
+    S = string.int16_to_string(I16),
      string.append(Str0, S, Str).

-:- pred output_uint16(int::in, string::di, string::uo) is det.
+:- pred output_uint16(uint16::in, string::di, string::uo) is det.

-output_uint16(I, Str0, Str) :-
-    string.int_to_string(I, S),
+output_uint16(U16, Str0, Str) :-
+    S = string.uint16_to_string(U16),
      string.append(Str0, S, Str).

-:- pred output_int32(int::in, string::di, string::uo) is det.
+:- pred output_int32(int32::in, string::di, string::uo) is det.

-output_int32(I, Str0, Str) :-
-    string.int_to_string(I, S),
+output_int32(I32, Str0, Str) :-
+    S = string.int32_to_string(I32),
      string.append(Str0, S, Str).

-:- pred output_uint32(int::in, string::di, string::uo) is det.
+:- pred output_uint32(uint32::in, string::di, string::uo) is det.

-output_uint32(I, Str0, Str) :-
-    string.int_to_string(I, S),
+output_uint32(U32, Str0, Str) :-
+    S = string.uint32_to_string(U32),
      string.append(Str0, S, Str).

  :- pred output_float(float::in, string::di, string::uo) is det.
diff --git a/compiler/parse_tree_to_term.m b/compiler/parse_tree_to_term.m
index 8cfb45ec7..a24357a29 100644
--- a/compiler/parse_tree_to_term.m
+++ b/compiler/parse_tree_to_term.m
@@ -2,7 +2,7 @@
  % vim: ft=mercury ts=4 sw=4 et
  %---------------------------------------------------------------------------%
  % Copyright (C) 2009-2012 The University of Melbourne.
-% Copyright (C) 2015-2016 The Mercury team.
+% Copyright (C) 2015-2017 The Mercury team.
  % This file may only be copied under the terms of the GNU General
  % Public License - see the file COPYING in the Mercury distribution.
  %---------------------------------------------------------------------------%
@@ -654,27 +654,27 @@ cons_id_and_args_to_term_full(ConsId, ArgTerms, Term) :-
      ;
          ConsId = int8_const(Int8),
          term.context_init(Context),
-        Term = int_to_decimal_term(Int8, Context)
+        Term = int8_to_decimal_term(Int8, Context)
      ;
          ConsId = uint8_const(UInt8),
          term.context_init(Context),
-        Term = int_to_decimal_term(UInt8, Context)
+        Term = uint8_to_decimal_term(UInt8, Context)
      ;
          ConsId = int16_const(Int16),
          term.context_init(Context),
-        Term = int_to_decimal_term(Int16, Context)
+        Term = int16_to_decimal_term(Int16, Context)
      ;
          ConsId = uint16_const(UInt16),
          term.context_init(Context),
-        Term = int_to_decimal_term(UInt16, Context)
+        Term = uint16_to_decimal_term(UInt16, Context)
      ;
          ConsId = int32_const(Int32),
          term.context_init(Context),
-        Term = int_to_decimal_term(Int32, Context)
+        Term = int32_to_decimal_term(Int32, Context)
      ;
          ConsId = uint32_const(UInt32),
          term.context_init(Context),
-        Term = int_to_decimal_term(UInt32, Context)
+        Term = uint32_to_decimal_term(UInt32, Context)
      ;
          ConsId = float_const(Float),
          term.context_init(Context),
diff --git a/compiler/prog_data.m b/compiler/prog_data.m
index dd62cfb7b..db44d2ef7 100644
--- a/compiler/prog_data.m
+++ b/compiler/prog_data.m
@@ -2,7 +2,7 @@
  % vim: ft=mercury ts=4 sw=4 et
  %---------------------------------------------------------------------------%
  % Copyright (C) 1996-2012 The University of Melbourne.
-% Copyright (C) 2015 The Mercury team.
+% Copyright (C) 2014-2017 The Mercury team.
  % This file may only be copied under the terms of the GNU General
  % Public License - see the file COPYING in the Mercury distribution.
  %---------------------------------------------------------------------------%
@@ -107,12 +107,12 @@

      ;       int_const(int)
      ;       uint_const(uint)
-    ;       int8_const(int)     % XXX FIXED SIZE INT
-    ;       uint8_const(int)    % XXX FIXED SIZE INT
-    ;       int16_const(int)    % XXX FIXED SIZE INT
-    ;       uint16_const(int)   % XXX FIXED SIZE INT
-    ;       int32_const(int)    % XXX FIXED SIZE INT
-    ;       uint32_const(int)   % XXX FIXED SIZE INT
+    ;       int8_const(int8)
+    ;       uint8_const(uint8)
+    ;       int16_const(int16)
+    ;       uint16_const(uint16)
+    ;       int32_const(int32)
+    ;       uint32_const(uint32)
      ;       float_const(float)
      ;       char_const(char)
      ;       string_const(string)
diff --git a/compiler/prog_out.m b/compiler/prog_out.m
index 923ff5908..1443147ff 100644
--- a/compiler/prog_out.m
+++ b/compiler/prog_out.m
@@ -2,6 +2,7 @@
  % vim: ft=mercury ts=4 sw=4 et
  %-----------------------------------------------------------------------------%
  % Copyright (C) 1993-2011 The University of Melbourne.
+% Copyright (C) 2014-2017 The Mercury team.
  % This file may only be copied under the terms of the GNU General
  % Public License - see the file COPYING in the Mercury distribution.
  %-----------------------------------------------------------------------------%
@@ -371,29 +372,23 @@ cons_id_and_arity_to_string_maybe_quoted(MangleCons, QuoteCons, ConsId)
          ConsId = uint_const(UInt),
          String = uint_to_string(UInt)
      ;
-        % XXX FIXED SIZE INT
          ConsId = int8_const(Int8),
-        string.int_to_string(Int8, String)
+        String = string.int8_to_string(Int8)
      ;
-        % XXX FIXED SIZE INT
          ConsId = uint8_const(UInt8),
-        string.int_to_string(UInt8, String)
+        String = string.uint8_to_string(UInt8)
      ;
-        % XXX FIXED SIZE INT
          ConsId = int16_const(Int16),
-        string.int_to_string(Int16, String)
+        String = string.int16_to_string(Int16)
      ;
-        % XXX FIXED SIZE INT
          ConsId = uint16_const(UInt16),
-        string.int_to_string(UInt16, String)
+        String = string.uint16_to_string(UInt16)
      ;
-        % XXX FIXED SIZE INT
          ConsId = int32_const(Int32),
-        string.int_to_string(Int32, String)
+        String = string.int32_to_string(Int32)
      ;
-        % XXX FIXED SIZE INT
          ConsId = uint32_const(UInt32),
-        string.int_to_string(UInt32, String)
+        String = string.uint32_to_string(UInt32)
      ;
          ConsId = float_const(Float),
          String = float_to_string(Float)
diff --git a/compiler/prog_rep.m b/compiler/prog_rep.m
index 46758c9bb..50c2ffcae 100644
--- a/compiler/prog_rep.m
+++ b/compiler/prog_rep.m
@@ -2,7 +2,7 @@
  % vim: ft=mercury ts=4 sw=4 et
  %---------------------------------------------------------------------------%
  % Copyright (C) 2000-2012 University of Melbourne.
-% Copyright (C) 2015 The Mercury team.
+% Copyright (C) 2015-2017 The Mercury team.
  % This file may only be copied under the terms of the GNU General
  % Public License - see the file COPYING in the Mercury distribution.
  %-----------------------------------------------------------------------------%
@@ -868,12 +868,12 @@ cons_id_rep(cons(SymName, _, _)) =
  cons_id_rep(tuple_cons(_)) = "{}".
  cons_id_rep(int_const(Int)) = string.int_to_string(Int).
  cons_id_rep(uint_const(UInt)) = string.uint_to_string(UInt).
-cons_id_rep(int8_const(Int8)) = string.int_to_string(Int8).
-cons_id_rep(uint8_const(UInt8)) = string.int_to_string(UInt8).
-cons_id_rep(int16_const(Int16)) = string.int_to_string(Int16).
-cons_id_rep(uint16_const(UInt16)) = string.int_to_string(UInt16).
-cons_id_rep(int32_const(Int32)) = string.int_to_string(Int32).
-cons_id_rep(uint32_const(UInt32)) = string.int_to_string(UInt32).
+cons_id_rep(int8_const(Int8)) = string.int8_to_string(Int8).
+cons_id_rep(uint8_const(UInt8)) = string.uint8_to_string(UInt8).
+cons_id_rep(int16_const(Int16)) = string.int16_to_string(Int16).
+cons_id_rep(uint16_const(UInt16)) = string.uint16_to_string(UInt16).
+cons_id_rep(int32_const(Int32)) = string.int32_to_string(Int32).
+cons_id_rep(uint32_const(UInt32)) = string.uint32_to_string(UInt32).
  cons_id_rep(float_const(Float)) = string.float_to_string(Float).
  cons_id_rep(char_const(Char)) = string.char_to_string(Char).
  cons_id_rep(string_const(String)) = """" ++ String ++ """".
diff --git a/compiler/prog_util.m b/compiler/prog_util.m
index ca74d6350..fd3512e3e 100644
--- a/compiler/prog_util.m
+++ b/compiler/prog_util.m
@@ -2,6 +2,7 @@
  % vim: ft=mercury ts=4 sw=4 et
  %-----------------------------------------------------------------------------%
  % Copyright (C) 1994-2001, 2003-2012 The University of Melbourne.
+% Copyright (C) 2014-2017 The Mercury team.
  % This file may only be copied under the terms of the GNU General
  % Public License - see the file COPYING in the Mercury distribution.
  %-----------------------------------------------------------------------------%
@@ -728,15 +729,45 @@ make_functor_cons_id(Functor, Arity, ConsId) :-
          Functor = term.atom(Name),
          ConsId = cons(unqualified(Name), Arity, cons_id_dummy_type_ctor)
      ;
-        Functor = term.integer(Base, Integer, Signedness, size_word),
+        Functor = term.integer(Base, Integer, Signedness, Size),
          (
              Signedness = signed,
-            source_integer_to_int(Base, Integer, Int),
-            ConsId = int_const(Int)
+            (
+                Size = size_word,
+                source_integer_to_int(Base, Integer, Int),
+                ConsId = int_const(Int)
+            ;
+                Size = size_8_bit,
+                integer.to_int8(Integer, Int8),
+                ConsId = int8_const(Int8)
+            ;
+                Size = size_16_bit,
+                integer.to_int16(Integer, Int16),
+                ConsId = int16_const(Int16)
+            ;
+                Size = size_32_bit,
+                integer.to_int32(Integer, Int32),
+                ConsId = int32_const(Int32)
+            )
          ;
              Signedness = unsigned,
-            integer.to_uint(Integer, UInt),
-            ConsId = uint_const(UInt)
+            (
+                Size = size_word,
+                integer.to_uint(Integer, UInt),
+                ConsId = uint_const(UInt)
+            ;
+                Size = size_8_bit,
+                integer.to_uint8(Integer, UInt8),
+                ConsId = uint8_const(UInt8)
+            ;
+                Size = size_16_bit,
+                integer.to_uint16(Integer, UInt16),
+                ConsId = uint16_const(UInt16)
+            ;
+                Size = size_32_bit,
+                integer.to_uint32(Integer, UInt32),
+                ConsId = uint32_const(UInt32)
+            )
          )
      ;
          Functor = term.string(String),
diff --git a/compiler/superhomogeneous.m b/compiler/superhomogeneous.m
index 79533007d..9dfa15a4f 100644
--- a/compiler/superhomogeneous.m
+++ b/compiler/superhomogeneous.m
@@ -1,7 +1,8 @@
  %-----------------------------------------------------------------------------%
  % vim: ft=mercury ts=4 sw=4 et
  %-----------------------------------------------------------------------------%
-% Copyright (C) 2005-2012,2014 The University of Melbourne.
+% Copyright (C) 2005-2012 The University of Melbourne.
+% Copyright (C) 2014-2017 The Mercury team.
  % This file may only be copied under the terms of the GNU General
  % Public License - see the file COPYING in the Mercury distribution.
  %-----------------------------------------------------------------------------%
@@ -739,50 +740,57 @@ parse_ordinary_cons_id(Functor, ArgTerms, Context, ConsId, !Specs) :-
              Size = size_word,
              (
                  Signedness = signed,
-                ( if source_integer_to_int(Base, Integer, Int) then
-                    ConsId = int_const(Int)
-                else
-                    BasePrefix = integer_base_prefix(Base),
-                    IntString = integer.to_base_string(Integer,
-                        integer_base_int(Base)),
-                    Pieces = [words("Error: the integer literal"),
-                        quote(BasePrefix ++ IntString),
-                        words("is too big to be represented on this machine."),
-                        nl],
-                    Msg = simple_msg(Context, [always(Pieces)]),
-                    Spec = error_spec(severity_error, phase_parse_tree_to_hlds,
-                        [Msg]),
-                    !:Specs = [Spec | !.Specs],
-                    % This is a dummy.
-                    ConsId = int_const(0)
-                )
+                parse_integer_cons_id(Context, Base, Integer, "", "",
+                    source_integer_to_int(Base), (func(I) = int_const(I)),
+                    ConsId, !Specs)
              ;
                  Signedness = unsigned,
-                ( if integer.to_uint(Integer, UInt) then
-                    ConsId = uint_const(UInt)
-                else
-                    BasePrefix = integer_base_prefix(Base),
-                    IntString = integer.to_base_string(Integer,
-                        integer_base_int(Base)),
-                    Pieces = [words("Error: the unsigned integer literal"),
-                        quote(BasePrefix ++ IntString ++ "u"),
-                        words("is too big to be represented on this machine."),
-                        nl],
-                    Msg = simple_msg(Context, [always(Pieces)]),
-                    Spec = error_spec(severity_error, phase_parse_tree_to_hlds,
-                        [Msg]),
-                    !:Specs = [Spec | !.Specs],
-                    % This is a dummy.
-                    ConsId = int_const(0)
-                )
+                parse_integer_cons_id(Context, Base, Integer, "unsigned", "u",
+                    integer.to_uint, (func(I) = uint_const(I)),
+                    ConsId, !Specs)
              )
          ;
-            ( Size = size_8_bit
-            ; Size = size_16_bit
-            ; Size = size_32_bit
-            ; Size = size_64_bit
-            ),
-            Pieces = [words("Error: fixed size integers"),
+            Size = size_8_bit,
+            (
+                Signedness = signed,
+                parse_integer_cons_id(Context, Base, Integer, "8-bit", "i8",
+                    integer.to_int8, (func(I) = int8_const(I)),
+                    ConsId, !Specs)
+            ;
+                Signedness = unsigned,
+                parse_integer_cons_id(Context, Base, Integer, "unsigned 8-bit",
+                    "u8", integer.to_uint8, (func(I) = uint8_const(I)),
+                    ConsId, !Specs)
+            )
+        ;
+            Size = size_16_bit,
+            (
+                Signedness = signed,
+                parse_integer_cons_id(Context, Base, Integer, "16-bit", "i16",
+                    integer.to_int16, (func(I) = int16_const(I)),
+                    ConsId, !Specs)
+            ;
+                Signedness = unsigned,
+                parse_integer_cons_id(Context, Base, Integer, "unsigned 16-bit",
+                    "u16", integer.to_uint16, (func(I) = uint16_const(I)),
+                    ConsId, !Specs)
+            )
+        ;
+            Size = size_32_bit,
+            (
+                Signedness = signed,
+                parse_integer_cons_id(Context, Base, Integer, "32-bit", "i32",
+                    integer.to_int32, (func(I) = int32_const(I)),
+                    ConsId, !Specs)
+            ;
+                Signedness = unsigned,
+                parse_integer_cons_id(Context, Base, Integer, "unsigned 32-bit",
+                    "u32", integer.to_uint32, (func(I) = uint32_const(I)),
+                    ConsId, !Specs)
+            )
+        ;
+            Size = size_64_bit,
+            Pieces = [words("Error: 64-bit integer types"),
                  words("are not (yet) supported.")],
              Msg = simple_msg(Context, [always(Pieces)]),
              Spec = error_spec(severity_error, phase_parse_tree_to_hlds,
@@ -802,6 +810,31 @@ parse_ordinary_cons_id(Functor, ArgTerms, Context, ConsId, !Specs) :-
          ConsId = impl_defined_const(Name)
      ).

+:- pred parse_integer_cons_id(term.context::in, integer_base::in, integer::in, string::in,
+    string::in, pred(integer, T)::in(pred(in, out) is semidet),
+    (func(T) = cons_id)::in, cons_id::out,
+    list(error_spec)::in, list(error_spec)::out) is det.
+
+parse_integer_cons_id(Context, Base, Integer, IntDesc, IntSuffixStr, ConvPred,
+        ToConsIdPred, ConsId, !Specs) :-
+    ( if ConvPred(Integer, Int) then
+        ConsId = ToConsIdPred(Int)
+    else
+        BasePrefix = integer_base_prefix(Base),
+        IntString = integer.to_base_string(Integer,
+            integer_base_int(Base)),
+        Pieces = [words("Error: the"), words(IntDesc), words("integer literal"),
+            quote(BasePrefix ++ IntString ++ IntSuffixStr),
+            words("is outside the range of that type."),
+            nl],
+        Msg = simple_msg(Context, [always(Pieces)]),
+        Spec = error_spec(severity_error, phase_parse_tree_to_hlds,
+            [Msg]),
+        !:Specs = [Spec | !.Specs],
+        % This is a dummy.
+        ConsId = int_const(0)
+    ).
+
      % See whether Atom indicates a term with special syntax.
      %
  :- pred maybe_unravel_special_var_functor_unification(prog_var::in,
diff --git a/library/erlang_rtti_implementation.m b/library/erlang_rtti_implementation.m
index db60cad76..ac8652f09 100644
--- a/library/erlang_rtti_implementation.m
+++ b/library/erlang_rtti_implementation.m
@@ -1,7 +1,8 @@
  %---------------------------------------------------------------------------%
  % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
  %---------------------------------------------------------------------------%
-% Copyright (C) 2007, 2011 The University of Melbourne.
+% Copyright (C) 2007, 2009-2012 The University of Melbourne.
+% Copyright (C) 2014-2017 The Mercury team.
  % This file may only be copied under the terms of the GNU Library General
  % Public License - see the file COPYING.LIB in the Mercury distribution.
  %---------------------------------------------------------------------------%
@@ -843,37 +844,43 @@ deconstruct_2(Term, TypeInfo, TypeCtorInfo, TypeCtorRep, NonCanon,
          Arguments = []
      ;
          TypeCtorRep = etcr_int8,
-        Functor = "<<int8>>",   % XXX FIXED SIZE INT
+        det_dynamic_cast(Term, Int8),
+        Functor = string.int8_to_string(Int8) ++ "i8",
          FunctorNumber = 0,
          Arity = 0,
          Arguments = []
      ;
          TypeCtorRep = etcr_uint8,
-        Functor = "<<uint8>>",  % XXX FIXED SIZE INT
+        det_dynamic_cast(Term, UInt8),
+        Functor = string.uint8_to_string(UInt8) ++ "u8",
          FunctorNumber = 0,
          Arity = 0,
          Arguments = []
      ;
          TypeCtorRep = etcr_int16,
-        Functor = "<<int16>>",   % XXX FIXED SIZE INT
+        det_dynamic_cast(Term, Int16),
+        Functor = string.int16_to_string(Int16) ++ "i16",
          FunctorNumber = 0,
          Arity = 0,
          Arguments = []
      ;
          TypeCtorRep = etcr_uint16,
-        Functor = "<<uint16>>",  % XXX FIXED SIZE INT
+        det_dynamic_cast(Term, UInt16),
+        Functor = string.uint16_to_string(UInt16) ++ "u16",
          FunctorNumber = 0,
          Arity = 0,
          Arguments = []
      ;
          TypeCtorRep = etcr_int32,
-        Functor = "<<int32>>",   % XXX FIXED SIZE INT
+        det_dynamic_cast(Term, Int32),
+        Functor = string.int32_to_string(Int32) ++ "i32",
          FunctorNumber = 0,
          Arity = 0,
          Arguments = []
      ;
          TypeCtorRep = etcr_uint32,
-        Functor = "<<uint32>>",  % XXX FIXED SIZE INT
+        det_dynamic_cast(Term, UInt32),
+        Functor = string.uint32_to_string(UInt32) ++ "u32",
          FunctorNumber = 0,
          Arity = 0,
          Arguments = []
diff --git a/library/int16.m b/library/int16.m
index a0e1499f8..4325c9c02 100644
--- a/library/int16.m
+++ b/library/int16.m
@@ -5,16 +5,391 @@
  % This file may only be copied under the terms of the GNU Library General
  % Public License - see the file COPYING.LIB in the Mercury distribution.
  %---------------------------------------------------------------------------%
+%
+% File: int16.m
+% Main author: juliensf
+% Stability: low.
+%
+% Predicates and functions for dealing with signed 16-bit integer numbers.
+%
+%---------------------------------------------------------------------------%

  :- module int16.
  :- interface.

-    % int16s are NYI -- this module is just a placeholder for their
-    % library support.
+:- import_module pretty_printer.
+
+%---------------------------------------------------------------------------%
+
+    % from_int(I, I16):
+    % Convert an int to an int16.
+    % Fails if I is not in [-32768, 32767].
      %
-:- type placeholder_int16 ---> placeholder_int16.
+:- pred from_int(int::in, int16::out) is semidet.
+
+    % As above, but throw an exception instead of failing.
+    %
+:- func det_from_int(int) = int16.
+
+:- func cast_from_int(int) = int16.
+
+:- func cast_from_uint16(uint16) = int16.
+
+:- func to_int(int16) = int.

  %---------------------------------------------------------------------------%
-:- end_module int16.
+
+    % Less than.
+    %
+:- pred (int16::in) < (int16::in) is semidet.
+
+    % Greater than.
+    %
+:- pred (int16::in) > (int16::in) is semidet.
+
+    % Less than or equal.
+    %
+:- pred (int16::in) =< (int16::in) is semidet.
+
+    % Greater than or equal.
+    %
+:- pred (int16::in) >= (int16::in) is semidet.
+
+%---------------------------------------------------------------------------%
+
+    % Maximum.
+    %
+:- func max(int16, int16) = int16.
+
+    % Minimum.
+    %
+:- func min(int16, int16) = int16.
+
+%---------------------------------------------------------------------------%
+
+    % Unary plus.
+    %
+:- func + (int16::in) = (int16::uo) is det.
+
+    % Unary minus.
+    %
+:- func - (int16::in) = (int16::uo) is det.
+
+    % Addition.
+    %
+:- func int16 + int16 = int16.
+:- mode in   + in  = uo is det.
+:- mode uo   + in  = in is det.
+:- mode in   + uo  = in is det.
+
+:- func plus(int16, int16) = int16.
+
+    % Subtraction.
+    %
+:- func int16 - int16 = int16.
+:- mode in   - in   = uo is det.
+:- mode uo   - in   = in is det.
+:- mode in   - uo   = in is det.
+
+:- func minus(int16, int16) = int16.
+
+    % Multiplication.
+    %
+:- func (int16::in) * (int16::in) = (int16::uo) is det.
+:- func times(int16, int16) = int16.
+
+    % Flooring integer division.
+    % Truncates towards minus infinity, e.g. (-10_i16) div 3_i16 = (-4_i16).
+    %
+    % Throws a `math.domain_error' exception if the right operand is zero.
+    %
+:- func (int16::in) div (int16::in) = (int16::uo) is det.
+
+    % Truncating integer division.
+    % Truncates towards zero, e.g. (-10_i16) // 3_i16 = (-3_i16).
+    % `div' has nicer mathematical properties for negative operands,
+    % but `//' is typically more efficient.
+    %
+    % Throws a `math.domain_error' exception if the right operand is zero.
+    %
+:- func (int16::in) // (int16::in) = (int16::uo) is det.
+
+    % (/)/2 is a synonym for (//)/2.
+    %
+:- func (int16::in) / (int16::in) = (int16::uo) is det.
+
+    % unchecked_quotient(X, Y) is the same as X // Y, but the behaviour
+    % is undefined if the right operand is zero.
+    %
+:- func unchecked_quotient(int16::in, int16::in) = (int16::uo) is det.
+
+    % Modulus.
+    % X mod Y = X - (X div Y) * Y
+    %
+    % Throws a `math.domain_error' exception if the right operand is zero.
+    %
+:- func (int16::in) mod (int16::in) = (int16::uo) is det.
+
+    % Remainder.
+    % X rem Y = X - (X // Y) * Y.
+    %
+    % Throws a `math.domain_error/` exception if the right operand is zero.
+    %
+:- func (int16::in) rem (int16::in) = (int16::uo) is det.
+
+    % unchecked_rem(X, Y) is the same as X rem Y, but the behaviour is
+    % undefined if the right operand is zero.
+    %
+:- func unchecked_rem(int16::in, int16::in) = (int16::uo) is det.
+
+    % Left shift.
+    % X << Y returns X "left shifted" by Y bits.
+    % The bit positions vacated by the shift are filled by zeros.
+    % Throws an exception if Y is not in [0, 16).
+    %
+:- func (int16::in) << (int::in) = (int16::uo) is det.
+
+    % unchecked_lift_shift(X, Y) is the same as X << Y except that the
+    % behaviour is undefined if Y is not in [0, 16).
+    % It will typically be be implemented more efficiently than X << Y.
+    %
+:- func unchecked_left_shift(int16::in, int::in) = (int16::uo) is det.
+
+    % Right shift.
+    % X >> Y returns X "right shifted" by Y bits.
+    % The bit positions vacated by the shift are filled by the sign bit.
+    % Throws an exception if Y is not in [0, 16).
+    %
+:- func (int16::in) >> (int::in) = (int16::uo) is det.
+
+    % unchecked_right_shift(X, Y) is the same as X >> Y except that the
+    % behaviour is undefined if Y is not in [0, 16).
+    % It will typically be implemented more efficiently than X >> Y.
+    %
+:- func unchecked_right_shift(int16::in, int::in) = (int16::uo) is det.
+
+    % even(X) is equivalent to (X mod 2i16 = 0i16).
+    %
+:- pred even(int16::in) is semidet.
+
+    % odd(X) is equivalent to (not even(X)), i.e. (X mod 2i16 = 1i16).
+    %
+:- pred odd(int16::in) is semidet.
+
+    % Bitwise and.
+    %
+:- func (int16::in) /\ (int16::in) = (int16::uo) is det.
+
+    % Bitwise or.
+    %
+:- func (int16::in) \/ (int16::in) = (int16::uo) is det.
+
+    % Bitwise exclusive or (xor).
+    %
+:- func xor(int16, int16) = int16.
+:- mode xor(in, in) = uo is det.
+:- mode xor(in, uo) = in is det.
+:- mode xor(uo, in) = in is det.
+
+    % Bitwise complement.
+    %
+:- func \ (int16::in) = (int16::uo) is det.
+
+:- func min_int16 = int16.
+
+:- func max_int16 = int16.
+
+    % Convert an int16 to a pretty_printer.doc for formatting.
+    %
+:- func int16_to_doc(int16) = pretty_printer.doc.
+
+%---------------------------------------------------------------------------%
+%---------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module exception.
+:- import_module int.
+:- import_module math.
+:- import_module require.
+:- import_module string.
+:- import_module uint.
+
  %---------------------------------------------------------------------------%

+from_int(I, I16) :-
+    I >= -32_768,
+    I =< 32_767,
+    I16 = cast_from_int(I).
+
+det_from_int(I) = I16 :-
+    ( if from_int(I, I16Prime) then
+        I16 = I16Prime
+    else
+        error("int16.det_from_int: cannot convert int to int16")
+    ).
+
+%---------------------------------------------------------------------------%
+
+:- pragma foreign_proc("C",
+    cast_from_int(I::in) = (I16::out),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
+        does_not_affect_liveness],
+"
+    I16 = (int16_t) I;
+").
+
+:- pragma foreign_proc("C#",
+    cast_from_int(I::in) = (I16::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I16 = (short) I;
+").
+
+:- pragma foreign_proc("Java",
+    cast_from_int(I::in) = (I16::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I16 = (short) I;
+").
+
+:- pragma no_determinism_warning(cast_from_int/1).
+cast_from_int(_) = _ :-
+    sorry($module, "int16.cast_from_int/1 NYI for Erlang").
+
+%---------------------------------------------------------------------------%
+
+:- pragma foreign_proc("C",
+    cast_from_uint16(U16::in) = (I16::out),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
+        does_not_affect_liveness],
+"
+    I16 = U16;
+").
+
+:- pragma foreign_proc("C#",
+    cast_from_uint16(U16::in) = (I16::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I16 = (short) U16;
+").
+
+:- pragma foreign_proc("Java",
+    cast_from_uint16(U16::in) = (I16::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I16 = U16;
+").
+
+:- pragma no_determinism_warning(cast_from_uint16/1).
+cast_from_uint16(_) = _ :-
+    sorry($module, "int16.cast_from_uint16/1 NYI for Erlang").
+
+%---------------------------------------------------------------------------%
+
+:- pragma foreign_proc("C",
+    to_int(I16::in) = (I::out),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
+"
+    I = I16;
+").
+
+:- pragma foreign_proc("C#",
+    to_int(I16::in) = (I::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I = I16;
+").
+
+:- pragma foreign_proc("Java",
+    to_int(I16::in) = (I::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I = I16;
+").
+
+%---------------------------------------------------------------------------%
+
+max(X, Y) =
+    ( if X > Y then X else Y ).
+
+min(X, Y) =
+    ( if X < Y then X else Y ).
+
+%---------------------------------------------------------------------------%
+
+X div Y = Div :-
+    Trunc = X // Y,
+    ( if
+        ( X >= cast_from_int(0), Y >= cast_from_int(0)
+        ; X < cast_from_int(0), Y < cast_from_int(0)
+        ; X rem Y = cast_from_int(0)
+        )
+    then
+        Div = Trunc
+    else
+        Div = Trunc - cast_from_int(1)
+    ).
+
+:- pragma inline('//'/2).
+X // Y = Div :-
+    ( if Y = cast_from_int(0) then
+        throw(math.domain_error("int16.'//': division by zero"))
+    else
+        Div = unchecked_quotient(X, Y)
+    ).
+
+:- pragma inline('/'/2).
+X / Y = X // Y.
+
+X mod Y = X - (X div Y) * Y.
+
+:- pragma inline(rem/2).
+X rem Y = Rem :-
+    ( if Y = cast_from_int(0) then
+        throw(math.domain_error("int16.rem: division by zero"))
+    else
+        Rem = unchecked_rem(X, Y)
+    ).
+
+%---------------------------------------------------------------------------%
+
+X << Y = Result :-
+    ( if cast_from_int(Y) < 16u then
+        Result = unchecked_left_shift(X, Y)
+    else
+        Msg = "int16.(<<): second operand is out of range",
+        throw(math.domain_error(Msg))
+    ).
+
+X >> Y = Result :-
+    ( if cast_from_int(Y) < 16u then
+        Result = unchecked_right_shift(X, Y)
+    else
+        Msg = "int16.(>>): second operand is out of range",
+        throw(math.domain_error(Msg))
+    ).
+
+%---------------------------------------------------------------------------%
+
+:- pragma inline(even/1).
+even(X) :-
+    (X /\ cast_from_int(1)) = cast_from_int(0).
+
+:- pragma inline(odd/1).
+odd(X) :-
+    (X /\ cast_from_int(1)) \= cast_from_int(0).
+
+%---------------------------------------------------------------------------%
+
+min_int16 = cast_from_int(-32_768).
+
+max_int16 = cast_from_int(32_767).
+
+%---------------------------------------------------------------------------%
+
+int16_to_doc(X) = str(string.int16_to_string(X)).
+
+%---------------------------------------------------------------------------%
+:- end_module int16.
+%---------------------------------------------------------------------------%
diff --git a/library/int32.m b/library/int32.m
index da40d0290..84a072b19 100644
--- a/library/int32.m
+++ b/library/int32.m
@@ -5,16 +5,407 @@
  % This file may only be copied under the terms of the GNU Library General
  % Public License - see the file COPYING.LIB in the Mercury distribution.
  %---------------------------------------------------------------------------%
+%
+% File: int32.m
+% Main author: juliensf
+% Stability: low.
+%
+% Predicates and functions for dealing with signed 32-bit integer numbers.
+%
+%---------------------------------------------------------------------------%

  :- module int32.
  :- interface.

-    % int32s are NYI -- this module is just a placeholder for their
-    % library support.
+:- import_module pretty_printer.
+
+%---------------------------------------------------------------------------%
+
+    % from_int(I, I32):
+    % Convert an int to an int32.
+    % Fails if not in [-2147483648, 2147483647].
      %
-:- type placeholder_int32 ---> placeholder_int32.
+:- pred from_int(int::in, int32::out) is semidet.
+
+    % As above, but throw an exception instead of failing.
+    %
+:- func det_from_int(int) = int32.
+
+:- func cast_from_int(int) = int32.
+
+:- func cast_from_uint32(uint32) = int32.
+
+:- func to_int(int32) = int.

  %---------------------------------------------------------------------------%
-:- end_module int32.
+
+    % Less than.
+    %
+:- pred (int32::in) < (int32::in) is semidet.
+
+    % Greater than.
+    %
+:- pred (int32::in) > (int32::in) is semidet.
+
+    % Less than or equal.
+    %
+:- pred (int32::in) =< (int32::in) is semidet.
+
+    % Greater than or equal.
+    %
+:- pred (int32::in) >= (int32::in) is semidet.
+
  %---------------------------------------------------------------------------%

+    % Unary plus.
+    %
+:- func + (int32::in) = (int32::uo) is det.
+
+    % Unary minus.
+    %
+:- func - (int32::in) = (int32::uo) is det.
+
+    % Addition.
+    %
+:- func int32 + int32 = int32.
+:- mode in   + in  = uo is det.
+:- mode uo   + in  = in is det.
+:- mode in   + uo  = in is det.
+
+:- func plus(int32, int32) = int32.
+
+    % Subtraction.
+    %
+:- func int32 - int32 = int32.
+:- mode in   - in   = uo is det.
+:- mode uo   - in   = in is det.
+:- mode in   - uo   = in is det.
+
+:- func minus(int32, int32) = int32.
+
+    % Multiplication.
+    %
+:- func (int32::in) * (int32::in) = (int32::uo) is det.
+:- func times(int32, int32) = int32.
+
+    % Maximum.
+    %
+:- func max(int32, int32) = int32.
+
+    % Minimum.
+    %
+:- func min(int32, int32) = int32.
+
+    % Flooring integer division.
+    % Truncates towards minus infinity, e.g. (-10_i32) div 3_i32 = (-4_i32).
+    %
+    % Throws a `math.domain_error' exception if the right operand is zero.
+    %
+:- func (int32::in) div (int32::in) = (int32::uo) is det.
+
+    % Truncating integer division.
+    % Truncates towards zero, e.g. (-10_i32) // 3_i32 = (-3_i32).
+    % `div' has nicer mathematical properties for negative operands,
+    % but `//' is typically more efficient.
+    %
+    % Throws a `math.domain_error' exception if the right operand is zero.
+    %
+:- func (int32::in) // (int32::in) = (int32::uo) is det.
+
+    % (/)/2 is a synonym for (//)/2.
+    %
+:- func (int32::in) / (int32::in) = (int32::uo) is det.
+
+    % unchecked_quotient(X, Y) is the same as X // Y, but the behaviour
+    % is undefined if the right operand is zero.
+    %
+:- func unchecked_quotient(int32::in, int32::in) = (int32::uo) is det.
+
+    % Modulus.
+    % X mod Y = X - (X div Y) * Y
+    %
+    % Throws a `math.domain_error' exception if the right operand is zero.
+    %
+:- func (int32::in) mod (int32::in) = (int32::uo) is det.
+
+    % Remainder.
+    % X rem Y = X - (X // Y) * Y.
+    %
+    % Throws a `math.domain_error/` exception if the right operand is zero.
+    %
+:- func (int32::in) rem (int32::in) = (int32::uo) is det.
+
+    % unchecked_rem(X, Y) is the same as X rem Y, but the behaviour is
+    % undefined if the right operand is zero.
+    %
+:- func unchecked_rem(int32::in, int32::in) = (int32::uo) is det.
+
+    % Left shift.
+    % X << Y returns X "left shifted" by Y bits.
+    % The bit positions vacated by the shift are filled by zeros.
+    % Throws an exception if Y is not in [0, 32).
+    %
+:- func (int32::in) << (int::in) = (int32::uo) is det.
+
+    % unchecked_lift_shift(X, Y) is the same as X << Y except that the
+    % behaviour is undefined if Y is not in [0, 32).
+    % It will typically be be implemented more efficiently than X << Y.
+    %
+:- func unchecked_left_shift(int32::in, int::in) = (int32::uo) is det.
+
+    % Right shift.
+    % X >> Y returns X "right shifted" by Y bits.
+    % The bit positions vacated by the shift are filled by the sign bit.
+    % Throws an exception if Y is not in [0, 32).
+    %
+:- func (int32::in) >> (int::in) = (int32::uo) is det.
+
+    % unchecked_right_shift(X, Y) is the same as X >> Y except that the
+    % behaviour is undefined if Y is not in [0, bits_per_int32).
+    % It will typically be implemented more efficiently than X >> Y.
+    %
+:- func unchecked_right_shift(int32::in, int::in) = (int32::uo) is det.
+
+    % even(X) is equivalent to (X mod 2 = 0).
+    %
+:- pred even(int32::in) is semidet.
+
+    % odd(X) is equivalent to (not even(X)), i.e. (X mod 2 = 1).
+    %
+:- pred odd(int32::in) is semidet.
+
+    % Bitwise and.
+    %
+:- func (int32::in) /\ (int32::in) = (int32::uo) is det.
+
+    % Bitwise or.
+    %
+:- func (int32::in) \/ (int32::in) = (int32::uo) is det.
+
+    % Bitwise exclusive or (xor).
+    %
+:- func xor(int32, int32) = int32.
+:- mode xor(in, in) = uo is det.
+:- mode xor(in, uo) = in is det.
+:- mode xor(uo, in) = in is det.
+
+    % Bitwise complement.
+    %
+:- func \ (int32::in) = (int32::uo) is det.
+
+    % Convert a int32 to a pretty_printer.doc for formatting.
+    %
+:- func int32_to_doc(int32) = pretty_printer.doc.
+
+%---------------------------------------------------------------------------%
+%---------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module exception.
+:- import_module math.
+:- import_module require.
+:- import_module string.
+:- import_module uint.
+
+%---------------------------------------------------------------------------%
+
+:- pragma foreign_proc("C",
+    from_int(A::in, B::out),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
+"
+    if (A > (MR_Integer) INT32_MAX) {
+        SUCCESS_INDICATOR = MR_FALSE;
+    } else if (A < (MR_Integer) INT32_MIN) {
+        SUCCESS_INDICATOR = MR_FALSE;
+    } else {
+        B = (int32_t) A;
+        SUCCESS_INDICATOR = MR_TRUE;
+    }
+").
+
+:- pragma foreign_proc("C#",
+    from_int(A::in, B::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    B = A; // Mercury's 'int' type in the C# grade is 32-bits.
+    SUCCESS_INDICATOR = true;
+").
+
+:- pragma foreign_proc("Java",
+    from_int(A::in, B::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    B = A; // Mercury's 'int' type in the Java grade is 32-bits.
+    SUCCESS_INDICATOR = true;
+").
+
+det_from_int(I) = U :-
+    ( if from_int(I, U0) then
+        U = U0
+    else
+        error("int32.det_from_int: cannot convert int to int32")
+    ).
+
+%---------------------------------------------------------------------------%
+
+:- pragma foreign_proc("C",
+    cast_from_int(I::in) = (I32::out),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
+        does_not_affect_liveness],
+"
+    I32 = (int32_t) I;
+").
+
+:- pragma foreign_proc("C#",
+    cast_from_int(I::in) = (I32::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I32 = I;
+").
+
+:- pragma foreign_proc("Java",
+    cast_from_int(I::in) = (I32::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I32 = I;
+").
+
+:- pragma no_determinism_warning(cast_from_int/1).
+cast_from_int(_) = _ :-
+    sorry($module, "int32.cast_from_int/1 NYI for Erlang").
+
+%---------------------------------------------------------------------------%
+
+:- pragma foreign_proc("C",
+    cast_from_uint32(U32::in) = (I32::out),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
+        does_not_affect_liveness],
+"
+    I32 = U32;
+").
+
+:- pragma foreign_proc("C#",
+    cast_from_uint32(U32::in) = (I32::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I32 = (int) U32;
+").
+
+:- pragma foreign_proc("Java",
+    cast_from_uint32(U32::in) = (I32::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I32 = U32;
+").
+
+:- pragma no_determinism_warning(cast_from_uint32/1).
+cast_from_uint32(_) = _ :-
+    sorry($module, "int32.cast_from_uint32/1 NYI for Erlang").
+
+%---------------------------------------------------------------------------%
+
+:- pragma foreign_proc("C",
+    to_int(I32::in) = (I::out),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
+"
+    I = I32;
+").
+
+:- pragma foreign_proc("C#",
+    to_int(I32::in) = (I::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I = I32;
+").
+
+:- pragma foreign_proc("Java",
+    to_int(I32::in) = (I::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I = I32;
+").
+
+:- pragma no_determinism_warning(to_int/1).
+to_int(_) = _ :-
+    sorry($module, "int32.to_int/1 NYI for Erlang").
+
+%---------------------------------------------------------------------------%
+
+X div Y = Div :-
+    Trunc = X // Y,
+    ( if
+        ( X >= cast_from_int(0), Y >= cast_from_int(0)
+        ; X < cast_from_int(0), Y < cast_from_int(0)
+        ; X rem Y = cast_from_int(0)
+        )
+    then
+        Div = Trunc
+    else
+        Div = Trunc - cast_from_int(1)
+    ).
+
+:- pragma inline('//'/2).
+X // Y = Div :-
+    ( if Y = cast_from_int(0) then
+        throw(math.domain_error("int32.'//': division by zero"))
+    else
+        Div = unchecked_quotient(X, Y)
+    ).
+
+:- pragma inline('/'/2).
+X / Y = X // Y.
+
+X mod Y = X  - (X div Y) * Y.
+
+:- pragma inline(rem/2).
+X rem Y = Rem :-
+    ( if Y = cast_from_int(0) then
+        throw(math.domain_error("int32.rem: division by zero"))
+    else
+        Rem = unchecked_rem(X, Y)
+    ).
+
+%---------------------------------------------------------------------------%
+
+X << Y = Result :-
+    ( if cast_from_int(Y) < 32u then
+        Result = unchecked_left_shift(X, Y)
+    else
+        Msg = "uint.(<<): second operand is out of range",
+        throw(math.domain_error(Msg))
+    ).
+
+X >> Y = Result :-
+    ( if cast_from_int(Y) < 32u then
+        Result = unchecked_right_shift(X, Y)
+    else
+        Msg = "uint.(>>): second operand is out of range",
+        throw(math.domain_error(Msg))
+    ).
+
+%---------------------------------------------------------------------------%
+
+max(X, Y) =
+    ( if X > Y then X else Y ).
+
+min(X, Y) =
+    ( if X < Y then X else Y ).
+
+%---------------------------------------------------------------------------%
+
+:- pragma inline(even/1).
+even(X) :-
+    (X /\ cast_from_int(1)) = cast_from_int(0).
+
+:- pragma inline(odd/1).
+odd(X) :-
+    (X /\ cast_from_int(1)) \= cast_from_int(0).
+
+%---------------------------------------------------------------------------%
+
+int32_to_doc(X) = str(string.int32_to_string(X)).
+
+%---------------------------------------------------------------------------%
+:- end_module int32.
+%---------------------------------------------------------------------------%
diff --git a/library/int8.m b/library/int8.m
index 4144652ca..292cce277 100644
--- a/library/int8.m
+++ b/library/int8.m
@@ -5,16 +5,396 @@
  % This file may only be copied under the terms of the GNU Library General
  % Public License - see the file COPYING.LIB in the Mercury distribution.
  %---------------------------------------------------------------------------%
+%
+% File: int8.m
+% Main author: juliensf
+% Stability: low.
+%
+% Predicates and functions for dealing with signed 8-bit integer numbers.
+%
+%---------------------------------------------------------------------------%

  :- module int8.
  :- interface.

-    % int8s are NYI -- this module is just a placeholder for their
-    % library support.
+:- import_module pretty_printer.
+
+%---------------------------------------------------------------------------%
+
+    % from_int(I, I8):
+    % Convert an int to an int8.
+    % Fails if I is not in [-128, 127].
      %
-:- type placeholder_int8 ---> placeholder_int8.
+:- pred from_int(int::in, int8::out) is semidet.
+
+    % As above, but throw an exception instead of failing.
+    %
+:- func det_from_int(int) = int8.
+
+:- func cast_from_int(int) = int8.
+:- func cast_from_uint8(uint8) = int8.
+
+:- func to_int(int8) = int.

  %---------------------------------------------------------------------------%
-:- end_module int8.
+
+    % Less than.
+    %
+:- pred (int8::in) < (int8::in) is semidet.
+
+    % Greater than.
+    %
+:- pred (int8::in) > (int8::in) is semidet.
+
+    % Less than or equal.
+    %
+:- pred (int8::in) =< (int8::in) is semidet.
+
+    % Greater than or equal.
+    %
+:- pred (int8::in) >= (int8::in) is semidet.
+
+%---------------------------------------------------------------------------%
+
+    % Maximum.
+    %
+:- func max(int8, int8) = int8.
+
+    % Minimum.
+    %
+:- func min(int8, int8) = int8.
+
+%---------------------------------------------------------------------------%
+
+    % Unary plus.
+    %
+:- func + (int8::in) = (int8::uo) is det.
+
+    % Unary minus.
+    %
+:- func - (int8::in) = (int8::uo) is det.
+
+    % Addition.
+    %
+:- func int8 + int8 = int8.
+:- mode in   + in  = uo is det.
+:- mode uo   + in  = in is det.
+:- mode in   + uo  = in is det.
+
+:- func plus(int8, int8) = int8.
+
+    % Subtraction.
+    %
+:- func int8 - int8 = int8.
+:- mode in   - in   = uo is det.
+:- mode uo   - in   = in is det.
+:- mode in   - uo   = in is det.
+
+:- func minus(int8, int8) = int8.
+
+    % Multiplication.
+    %
+:- func (int8::in) * (int8::in) = (int8::uo) is det.
+:- func times(int8, int8) = int8.
+
+    % Flooring integer division.
+    % Truncates towards minus infinity, e.g. (-10_i8) div 3_i8 = (-4_i8).
+    %
+    % Throws a `math.domain_error' exception if the right operand is zero.
+    %
+:- func (int8::in) div (int8::in) = (int8::uo) is det.
+
+    % Truncating integer division.
+    % Truncates towards zero, e.g. (-10_i8) // 3_i8 = (-3_i8).
+    % `div' has nicer mathematical properties for negative operands,
+    % but `//' is typically more efficient.
+    %
+    % Throws a `math.domain_error' exception if the right operand is zero.
+    %
+:- func (int8::in) // (int8::in) = (int8::uo) is det.
+
+    % (/)/2 is a synonym for (//)/2.
+    %
+:- func (int8::in) / (int8::in) = (int8::uo) is det.
+
+    % unchecked_quotient(X, Y) is the same as X // Y, but the behaviour
+    % is undefined if the right operand is zero.
+    %
+:- func unchecked_quotient(int8::in, int8::in) = (int8::uo) is det.
+
+    % Modulus.
+    % X mod Y = X - (X div Y) * Y
+    %
+    % Throws a `math.domain_error' exception if the right operand is zero.
+    %
+:- func (int8::in) mod (int8::in) = (int8::uo) is det.
+
+    % Remainder.
+    % X rem Y = X - (X // Y) * Y.
+    %
+    % Throws a `math.domain_error/` exception if the right operand is zero.
+    %
+:- func (int8::in) rem (int8::in) = (int8::uo) is det.
+
+    % unchecked_rem(X, Y) is the same as X rem Y, but the behaviour is
+    % undefined if the right operand is zero.
+    %
+:- func unchecked_rem(int8::in, int8::in) = (int8::uo) is det.
+
+    % Left shift.
+    % X << Y returns X "left shifted" by Y bits.
+    % The bit positions vacated by the shift are filled by zeros.
+    % Throws an exception if Y is not in [0, 8).
+    %
+:- func (int8::in) << (int::in) = (int8::uo) is det.
+
+    % unchecked_lift_shift(X, Y) is the same as X << Y except that the
+    % behaviour is undefined if Y is not in [0, 8).
+    % It will typically be be implemented more efficiently than X << Y.
+    %
+:- func unchecked_left_shift(int8::in, int::in) = (int8::uo) is det.
+
+    % Right shift.
+    % X >> Y returns X "right shifted" by Y bits.
+    % The bit positions vacated by the shift are filled by the sign bit.
+    % Throws an exception if Y is not in [0, 8).
+    %
+:- func (int8::in) >> (int::in) = (int8::uo) is det.
+
+    % unchecked_right_shift(X, Y) is the same as X >> Y except that the
+    % behaviour is undefined if Y is not in [0, 8).
+    % It will typically be implemented more efficiently than X >> Y.
+    %
+:- func unchecked_right_shift(int8::in, int::in) = (int8::uo) is det.
+
+    % even(X) is equivalent to (X mod 2i8 = 0i8).
+    %
+:- pred even(int8::in) is semidet.
+
+    % odd(X) is equivalent to (not even(X)), i.e. (X mod 2i8 = 1i8).
+    %
+:- pred odd(int8::in) is semidet.
+
  %---------------------------------------------------------------------------%

+    % Bitwise complement.
+    %
+:- func \ (int8::in) = (int8::uo) is det.
+
+    % Bitwise and.
+    %
+:- func (int8::in) /\ (int8::in) = (int8::uo) is det.
+
+    % Bitwise or.
+    %
+:- func (int8::in) \/ (int8::in) = (int8::uo) is det.
+
+    % Bitwise exclusive or (xor).
+    %
+:- func xor(int8, int8) = int8.
+:- mode xor(in, in) = uo is det.
+:- mode xor(in, uo) = in is det.
+:- mode xor(uo, in) = in is det.
+
+%---------------------------------------------------------------------------%
+
+:- func min_int8 = int8.
+
+:- func max_int8 = int8.
+
+%---------------------------------------------------------------------------%
+
+    % Convert an int8 to a pretty_printer.doc for formatting.
+    %
+:- func int8_to_doc(int8) = pretty_printer.doc.
+
+%---------------------------------------------------------------------------%
+%---------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module exception.
+:- import_module int.
+:- import_module math.
+:- import_module require.
+:- import_module string.
+:- import_module uint.
+
+%---------------------------------------------------------------------------%
+
+from_int(I, I8) :-
+    I >= -128,
+    I =< 127,
+    I8 = cast_from_int(I).
+
+det_from_int(I) = I8 :-
+    ( if from_int(I, I8Prime) then
+        I8 = I8Prime
+    else
+        error("int8.det_from_int: cannot convert int to int8")
+    ).
+
+%---------------------------------------------------------------------------%
+
+:- pragma foreign_proc("C",
+    cast_from_int(I::in) = (I8::out),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
+        does_not_affect_liveness],
+"
+    I8 = (int8_t) I;
+").
+
+:- pragma foreign_proc("C#",
+    cast_from_int(I::in) = (I8::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I8 = (sbyte) I;
+").
+
+:- pragma foreign_proc("Java",
+    cast_from_int(I::in) = (I8::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I8 = (byte) I;
+").
+
+:- pragma no_determinism_warning(cast_from_int/1).
+cast_from_int(_) = _ :-
+    sorry($module, "int8.cast_from_int/1 NYI for Erlang").
+
+%---------------------------------------------------------------------------%
+
+:- pragma foreign_proc("C",
+    cast_from_uint8(U8::in) = (I8::out),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
+        does_not_affect_liveness],
+"
+    I8 = U8;
+").
+
+:- pragma foreign_proc("C#",
+    cast_from_uint8(U8::in) = (I8::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I8 = (sbyte) U8;
+").
+
+:- pragma foreign_proc("Java",
+    cast_from_uint8(U8::in) = (I8::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I8 = U8;
+").
+
+:- pragma no_determinism_warning(cast_from_uint8/1).
+cast_from_uint8(_) = _ :-
+    sorry($module, "int8.cast_from_uint8/1 NYI for Erlang").
+
+%---------------------------------------------------------------------------%
+
+:- pragma foreign_proc("C",
+    to_int(I8::in) = (I::out),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
+"
+    I = I8;
+").
+
+:- pragma foreign_proc("C#",
+    to_int(I8::in) = (I::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I = I8;
+").
+
+:- pragma foreign_proc("Java",
+    to_int(I8::in) = (I::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I = I8;
+").
+
+%---------------------------------------------------------------------------%
+
+X div Y = Div :-
+    Trunc = X // Y,
+    ( if
+        ( X >= cast_from_int(0), Y >= cast_from_int(0)
+        ; X < cast_from_int(0), Y < cast_from_int(0)
+        ; X rem Y = cast_from_int(0)
+        )
+    then
+        Div = Trunc
+    else
+        Div = Trunc - cast_from_int(1)
+    ).
+
+:- pragma inline('//'/2).
+X // Y = Div :-
+    ( if Y = cast_from_int(0) then
+        throw(math.domain_error("int8.'//': division by zero"))
+    else
+        Div = unchecked_quotient(X, Y)
+    ).
+
+:- pragma inline('/'/2).
+X / Y = X // Y.
+
+X mod Y = X - (X div Y) * Y.
+
+:- pragma inline(rem/2).
+X rem Y = Rem :-
+    ( if Y = cast_from_int(0) then
+        throw(math.domain_error("int8.rem: division by zero"))
+    else
+        Rem = unchecked_rem(X, Y)
+    ).
+
+%---------------------------------------------------------------------------%
+
+X << Y = Result :-
+    ( if cast_from_int(Y) < 8u then
+        Result = unchecked_left_shift(X, Y)
+    else
+        Msg = "int8.(<<): second operand is out of range",
+        throw(math.domain_error(Msg))
+    ).
+
+X >> Y = Result :-
+    ( if cast_from_int(Y) < 8u then
+        Result = unchecked_right_shift(X, Y)
+    else
+        Msg = "int8.(>>): second operand is out of range",
+        throw(math.domain_error(Msg))
+    ).
+
+%---------------------------------------------------------------------------%
+
+max(X, Y) =
+    ( if X > Y then X else Y ).
+
+min(X, Y) =
+    ( if X < Y then X else Y ).
+
+%---------------------------------------------------------------------------%
+
+:- pragma inline(even/1).
+even(X) :-
+    (X /\ cast_from_int(1)) = cast_from_int(0).
+
+:- pragma inline(odd/1).
+odd(X) :-
+    (X /\ cast_from_int(1)) \= cast_from_int(0).
+
+%---------------------------------------------------------------------------%
+
+min_int8 = cast_from_int(-128).
+
+max_int8 = cast_from_int(127).
+
+%---------------------------------------------------------------------------%
+
+int8_to_doc(X) = str(string.int8_to_string(X)).
+
+%---------------------------------------------------------------------------%
+:- end_module int8.
+%---------------------------------------------------------------------------%
diff --git a/library/integer.m b/library/integer.m
index 630067a1f..5209fab61 100644
--- a/library/integer.m
+++ b/library/integer.m
@@ -191,6 +191,60 @@
      %
  :- func det_to_uint(integer) = uint.

+    % Convert an integer to an int8.
+    % Fails if the integer is not in the range [-128, 127].
+    %
+:- pred to_int8(integer::in, int8::out) is semidet.
+
+    % As above, but throws an exception rather than failing.
+    %
+:- func det_to_int8(integer) = int8.
+
+    % Convert an integer to a uint8.
+    % Fails if the integer is not in the range [0, 255].
+    %
+:- pred to_uint8(integer::in, uint8::out) is semidet.
+
+    % As above, but throws an exception rather than failing.
+    %
+:- func det_to_uint8(integer) = uint8.
+
+    % Convert an integer to an int16.
+    % Fails if the integer is not in the range [-32768, 32767].
+    %
+:- pred to_int16(integer::in, int16::out) is semidet.
+
+    % As above, but throws an exception rather than failing.
+    %
+:- func det_to_int16(integer) = int16.
+
+    % Convert an integer to a uint16.
+    % Fails if the integer is not in the range [0, 65535].
+    %
+:- pred to_uint16(integer::in, uint16::out) is semidet.
+
+    % As above, but throws an exception rather than failing.
+    %
+:- func det_to_uint16(integer) = uint16.
+
+    % Convert an integer to an int32.
+    % Fails if the integer is not in the range [-2147483648, 2147483647].
+    %
+:- pred to_int32(integer::in, int32::out) is semidet.
+
+    % As above, but throws an exception rather than failing.
+    %
+:- func det_to_int32(integer) = int32.
+
+    % Convert an integer to a uint32.
+    % Fails if the integer is not in range [0, 4294967295].
+    %
+:- pred to_uint32(integer::in, uint32::out) is semidet.
+
+    % As above, but throws an exception rather than failing.
+    %
+:- func det_to_uint32(integer) = uint32.
+
  %---------------------%

      % Convert an integer to a float.
@@ -214,7 +268,7 @@

  %---------------------------------------------------------------------------%

-    % Convert int to integer.
+    % Convert an int to integer.
      %
  :- func integer(int) = integer.

@@ -222,6 +276,30 @@
      %
  :- func from_uint(uint) = integer.

+    % Convert an int8 to an integer.
+    %
+:- func from_int8(int8) = integer.
+
+    % Convert a uint8 to an integer.
+    %
+:- func from_uint8(uint8) = integer.
+
+    % Convert an int16 to an integer.
+    %
+:- func from_int16(int16) = integer.
+
+    % Convert a uint16 to an integer.
+    %
+:- func from_uint16(uint16) = integer.
+
+    % Convert an int32 to an integer.
+    %
+:- func from_int32(int32) = integer.
+
+    % Convert a uint32 to an integer.
+    %
+:- func from_uint32(uint32) = integer.
+
      % Convert a string to an integer. The string must contain only digits
      % [0-9], optionally preceded by a plus or minus sign. If the string does
      % not match this syntax, then the predicate fails.
@@ -257,11 +335,17 @@
  :- import_module exception.
  :- import_module float.
  :- import_module int.
+:- import_module int8.
+:- import_module int16.
+:- import_module int32.
  :- import_module list.
  :- import_module math.
  :- import_module require.
  :- import_module string.
  :- import_module uint.
+:- import_module uint8.
+:- import_module uint16.
+:- import_module uint32.

  %---------------------------------------------------------------------------%

@@ -406,6 +490,13 @@ chop_uint(N, Div, Mod) :-
      Div = N `uint.unchecked_right_shift` log2base,
      Mod = N /\ cast_from_int(basemask).

+:- pred chop_uint32(uint32::in, uint32::out, uint32::out) is det.
+
+chop_uint32(N, Div, Mod) :-
+    % See the comments in chop/3.
+    Div = N `uint32.unchecked_right_shift` log2base,
+    Mod = N /\ cast_from_int(basemask).
+
  %---------------------%

  :- func det_first(integer) = digit.
@@ -1320,6 +1411,98 @@ det_to_uint(Integer) = UInt :-

  %---------------------------------------------------------------------------%

+to_int8(Integer, Int8) :-
+    Integer = i(_Sign, [Digit]),
+    int8.from_int(Digit, Int8).
+
+det_to_int8(Integer) = Int8 :-
+    ( if integer.to_int8(Integer, Int8Prime) then
+        Int8 = Int8Prime
+    else
+        throw(math.domain_error(
+            "integer.det_to_int8: domain error (conversion would overflow)"))
+    ).
+
+%---------------------------------------------------------------------------%
+
+to_uint8(Integer, UInt8) :-
+    Integer = i(_Sign, [Digit]),
+    uint8.from_int(Digit, UInt8).
+
+det_to_uint8(Integer) = UInt8 :-
+    ( if integer.to_uint8(Integer, UInt8Prime) then
+        UInt8 = UInt8Prime
+    else
+        throw(math.domain_error(
+            "integer.det_to_uint8: domain error (conversion would overflow)"))
+    ).
+
+%---------------------------------------------------------------------------%
+
+to_int16(Integer, Int16) :-
+    integer.to_int(Integer, Int),
+    int16.from_int(Int, Int16).
+
+det_to_int16(Integer) = Int16 :-
+    ( if integer.to_int16(Integer, Int16Prime) then
+        Int16 = Int16Prime
+    else
+        throw(math.domain_error(
+            "integer.det_to_int16: domain error (conversion would overflow)"))
+    ).
+
+%---------------------------------------------------------------------------%
+
+to_uint16(Integer, UInt16) :-
+    integer.to_int(Integer, Int),
+    uint16.from_int(Int, UInt16).
+
+det_to_uint16(Integer) = UInt16 :-
+    ( if integer.to_uint16(Integer, UInt16Prime) then
+        UInt16 = UInt16Prime
+    else
+        throw(math.domain_error(
+            "integer.det_to_uint16: domain error (conversion would overflow)"))
+    ).
+
+%---------------------------------------------------------------------------%
+
+to_int32(Integer, Int32) :-
+    integer.to_int(Integer, Int),
+    int32.from_int(Int, Int32).
+
+det_to_int32(Integer) = Int32 :-
+    ( if integer.to_int32(Integer, Int32Prime) then
+        Int32 = Int32Prime
+    else
+        throw(math.domain_error(
+            "integer.det_to_int32: domain error (conversion would overflow"))
+    ).
+
+%---------------------------------------------------------------------------%
+
+to_uint32(Integer, UInt32) :-
+    Integer >= integer.zero,
+    Integer =< integer.from_uint32(uint32.max_uint32),
+    Integer = i(_Sign, Digits),
+    UInt32 = uint32_list(Digits, uint32.cast_from_int(0)).
+
+:- func uint32_list(list(int), uint32) = uint32.
+
+uint32_list([], Accum) = Accum.
+uint32_list([H | T], Accum) =
+    uint32_list(T, Accum * cast_from_int(base) + cast_from_int(H)).
+
+det_to_uint32(Integer) = UInt32 :-
+    ( if integer.to_uint32(Integer, UInt32Prime) then
+        UInt32 = UInt32Prime
+    else
+        throw(math.domain_error(
+            "integer.det_to_uint32: domain error (conversion would overflow"))
+    ).
+
+%---------------------------------------------------------------------------%
+
  float(i(_, List)) = float_list(float.float(base), 0.0, List).

  :- func float_list(float, float, list(int)) = float.
@@ -1588,6 +1771,53 @@ uint_to_digits_2(U, Tail) = Result :-
              i(Length + 1, [cast_to_int(Mod) | Digits]))
      ).

+%---------------------------------------------------------------------------%
+
+from_int8(I8) = Integer :-
+    I = int8.to_int(I8),
+    Integer = integer(I).
+
+from_uint8(U8) = Integer :-
+    I = uint8.to_int(U8),
+    Integer = integer(I).
+
+from_int16(I16) = Integer :-
+    I = int16.to_int(I16),
+    Integer = integer(I).
+
+from_uint16(U16) = Integer :-
+    I = uint16.to_int(U16),
+    Integer = integer(I).
+
+from_int32(I32) = Integer :-
+    I = int32.to_int(I32),
+    Integer = integer(I).
+
+from_uint32(U32) = Integer :-
+    ( if U32 = cast_from_int(0) then
+        Integer = integer.zero
+    else if U32 < cast_from_int(base) then
+        Integer = i(1, [cast_to_int(U32)])
+    else
+        Integer = uint32_to_digits(U32)
+    ).
+
+:- func uint32_to_digits(uint32) = integer.
+
+uint32_to_digits(U) = uint32_to_digits_2(U, integer.zero).
+
+:- func uint32_to_digits_2(uint32, integer) = integer.
+
+uint32_to_digits_2(U, Tail) = Result :-
+    ( if U = cast_from_int(0) then
+        Result = Tail
+    else
+        Tail = i(Length, Digits),
+        chop_uint32(U, Div, Mod),
+        Result = uint32_to_digits_2(Div,
+            i(Length + 1, [cast_to_int(Mod) | Digits]))
+    ).
+
  %---------------------------------------------------------------------------%
  %
  % Converting strings to integers.
diff --git a/library/io.m b/library/io.m
index 243b611ac..51260413c 100644
--- a/library/io.m
+++ b/library/io.m
@@ -2,7 +2,7 @@
  % vim: ft=mercury ts=4 sw=4 et
  %---------------------------------------------------------------------------%
  % Copyright (C) 1993-2012 The University of Melbourne.
-% Copyright (C) 2013-2016 The Mercury team.
+% Copyright (C) 2013-2017 The Mercury team.
  % This file may only be copied under the terms of the GNU Library General
  % Public License - see the file COPYING.LIB in the Mercury distribution.
  %---------------------------------------------------------------------------%
@@ -498,12 +498,30 @@
  :- pred write_int(int::in, io::di, io::uo) is det.
  :- pred write_int(io.text_output_stream::in, int::in, io::di, io::uo) is det.

+:- pred write_int8(int8::in, io::di, io::uo) is det.
+:- pred write_int8(io.text_output_stream::in, int8::in, io::di, io::uo) is det.
+
+:- pred write_int16(int16::in, io::di, io::uo) is det.
+:- pred write_int16(io.text_output_stream::in, int16::in, io::di, io::uo) is det.
+
+:- pred write_int32(int32::in, io::di, io::uo) is det.
+:- pred write_int32(io.text_output_stream::in, int32::in, io::di, io::uo) is det.
+
      % Writes an unsigned integer to the current output stream
      % or to the specified output stream.
      %
  :- pred write_uint(uint::in, io::di, io::uo) is det.
  :- pred write_uint(io.text_output_stream::in, uint::in, io::di, io::uo) is det.

+:- pred write_uint8(uint8::in, io::di, io::uo) is det.
+:- pred write_uint8(io.text_output_stream::in, uint8::in, io::di, io::uo) is det.
+
+:- pred write_uint16(uint16::in, io::di, io::uo) is det.
+:- pred write_uint16(io.text_output_stream::in, uint16::in, io::di, io::uo) is det.
+
+:- pred write_uint32(uint32::in, io::di, io::uo) is det.
+:- pred write_uint32(io.text_output_stream::in, uint32::in, io::di, io::uo) is det.
+
      % Writes a floating point number to the current output stream
      % or to the specified output stream.
      %
@@ -1523,7 +1541,13 @@
  :- instance stream.writer(text_output_stream, char,   io).
  :- instance stream.writer(text_output_stream, float,  io).
  :- instance stream.writer(text_output_stream, int,    io).
+:- instance stream.writer(text_output_stream, int8,   io).
+:- instance stream.writer(text_output_stream, int16,  io).
+:- instance stream.writer(text_output_stream, int32,  io).
  :- instance stream.writer(text_output_stream, uint,   io).
+:- instance stream.writer(text_output_stream, uint8,  io).
+:- instance stream.writer(text_output_stream, uint16, io).
+:- instance stream.writer(text_output_stream, uint8,  io).
  :- instance stream.writer(text_output_stream, string, io).
  :- instance stream.writer(text_output_stream, univ,   io).
  :- instance stream.line_oriented(text_output_stream, io).
@@ -7762,10 +7786,34 @@ write_int(Val, !IO) :-
      output_stream(Stream, !IO),
      write_int(Stream, Val, !IO).

+write_int8(Val, !IO) :-
+    output_stream(Stream, !IO),
+    write_int8(Stream, Val, !IO).
+
+write_int16(Val, !IO) :-
+    output_stream(Stream, !IO),
+    write_int16(Stream, Val, !IO).
+
+write_int32(Val, !IO) :-
+    output_stream(Stream, !IO),
+    write_int32(Stream, Val, !IO).
+
  write_uint(Val, !IO) :-
      output_stream(Stream, !IO),
      write_uint(Stream, Val, !IO).

+write_uint8(Val, !IO) :-
+    output_stream(Stream, !IO),
+    write_uint8(Stream, Val, !IO).
+
+write_uint16(Val, !IO) :-
+    output_stream(Stream, !IO),
+    write_uint16(Stream, Val, !IO).
+
+write_uint32(Val, !IO) :-
+    output_stream(Stream, !IO),
+    write_uint32(Stream, Val, !IO).
+
  write_float(Val, !IO) :-
      output_stream(Stream, !IO),
      write_float(Stream, Val, !IO).
@@ -7942,6 +7990,60 @@ write_int(output_stream(Stream), Val, !IO) :-
      }
  ").

+write_int8(output_stream(Stream), Val, !IO) :-
+    write_int8_2(Stream, Val, Error, !IO),
+    throw_on_output_error(Error, !IO).
+
+:- pred write_int8_2(stream::in, int8::in, system_error::out, io::di, io::uo)
+    is det.
+:- pragma foreign_proc("C",
+    write_int8_2(Stream::in, Val::in, Error::out, _IO0::di, _IO::uo),
+    [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe,
+        does_not_affect_liveness, no_sharing],
+"
+    if (ML_fprintf(Stream, ""%d"", Val) < 0) {
+        Error = errno;
+    } else {
+        Error = 0;
+    }
+").
+
+write_int16(output_stream(Stream), Val, !IO) :-
+    write_int16_2(Stream, Val, Error, !IO),
+    throw_on_output_error(Error, !IO).
+
+:- pred write_int16_2(stream::in, int16::in, system_error::out, io::di, io::uo)
+    is det.
+:- pragma foreign_proc("C",
+    write_int16_2(Stream::in, Val::in, Error::out, _IO0::di, _IO::uo),
+    [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe,
+        does_not_affect_liveness, no_sharing],
+"
+    if (ML_fprintf(Stream, ""%d"", Val) < 0) {
+        Error = errno;
+    } else {
+        Error = 0;
+    }
+").
+
+write_int32(output_stream(Stream), Val, !IO) :-
+    write_int32_2(Stream, Val, Error, !IO),
+    throw_on_output_error(Error, !IO).
+
+:- pred write_int32_2(stream::in, int32::in, system_error::out, io::di, io::uo)
+    is det.
+:- pragma foreign_proc("C",
+    write_int32_2(Stream::in, Val::in, Error::out, _IO0::di, _IO::uo),
+    [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe,
+        does_not_affect_liveness, no_sharing],
+"
+    if (ML_fprintf(Stream, ""%d"", Val) < 0) {
+        Error = errno;
+    } else {
+        Error = 0;
+    }
+").
+
  write_uint(output_stream(Stream), Val, !IO) :-
      write_uint_2(Stream, Val, Error, !IO),
      throw_on_output_error(Error, !IO).
@@ -7960,6 +8062,60 @@ write_uint(output_stream(Stream), Val, !IO) :-
      }
  ").

+write_uint8(output_stream(Stream), Val, !IO) :-
+    write_uint8_2(Stream, Val, Error, !IO),
+    throw_on_output_error(Error, !IO).
+
+:- pred write_uint8_2(stream::in, uint8::in, system_error::out, io::di, io::uo)
+    is det.
+:- pragma foreign_proc("C",
+    write_uint8_2(Stream::in, Val::in, Error::out, _IO0::di, _IO::uo),
+    [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe,
+        does_not_affect_liveness, no_sharing],
+"
+    if (ML_fprintf(Stream, ""%u"", Val) < 0) {
+        Error = errno;
+    } else {
+        Error = 0;
+    }
+").
+
+write_uint16(output_stream(Stream), Val, !IO) :-
+    write_uint16_2(Stream, Val, Error, !IO),
+    throw_on_output_error(Error, !IO).
+
+:- pred write_uint16_2(stream::in, uint16::in, system_error::out, io::di, io::uo)
+    is det.
+:- pragma foreign_proc("C",
+    write_uint16_2(Stream::in, Val::in, Error::out, _IO0::di, _IO::uo),
+    [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe,
+        does_not_affect_liveness, no_sharing],
+"
+    if (ML_fprintf(Stream, ""%u"", Val) < 0) {
+        Error = errno;
+    } else {
+        Error = 0;
+    }
+").
+
+write_uint32(output_stream(Stream), Val, !IO) :-
+    write_uint32_2(Stream, Val, Error, !IO),
+    throw_on_output_error(Error, !IO).
+
+:- pred write_uint32_2(stream::in, uint32::in, system_error::out, io::di, io::uo)
+    is det.
+:- pragma foreign_proc("C",
+    write_uint32_2(Stream::in, Val::in, Error::out, _IO0::di, _IO::uo),
+    [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe,
+        does_not_affect_liveness, no_sharing],
+"
+    if (ML_fprintf(Stream, ""%u"", Val) < 0) {
+        Error = errno;
+    } else {
+        Error = 0;
+    }
+").
+
  write_float(output_stream(Stream), Val, !IO) :-
      write_float_2(Stream, Val, Error, !IO),
      throw_on_output_error(Error, !IO).
@@ -8189,6 +8345,78 @@ flush_binary_output(binary_output_stream(Stream), !IO) :-
      }
  ").

+:- pragma foreign_proc("C#",
+    write_int8_2(Stream::in, Val::in, Error::out, _IO0::di, _IO::uo),
+    [will_not_call_mercury, promise_pure, thread_safe, tabled_for_io],
+"
+    try {
+        io.mercury_print_string(Stream, Val.ToString());
+        Error = null;
+    } catch (System.SystemException e) {
+        Error = e;
+    }
+").
+
+:- pragma foreign_proc("C#",
+    write_int16_2(Stream::in, Val::in, Error::out, _IO0::di, _IO::uo),
+    [will_not_call_mercury, promise_pure, thread_safe, tabled_for_io],
+"
+    try {
+        io.mercury_print_string(Stream, Val.ToString());
+        Error = null;
+    } catch (System.SystemException e) {
+        Error = e;
+    }
+").
+
+:- pragma foreign_proc("C#",
+    write_int32_2(Stream::in, Val::in, Error::out, _IO0::di, _IO::uo),
+    [will_not_call_mercury, promise_pure, thread_safe, tabled_for_io],
+"
+    try {
+        io.mercury_print_string(Stream, Val.ToString());
+        Error = null;
+    } catch (System.SystemException e) {
+        Error = e;
+    }
+").
+
+:- pragma foreign_proc("C#",
+    write_uint8_2(Stream::in, Val::in, Error::out, _IO0::di, _IO::uo),
+    [will_not_call_mercury, promise_pure, thread_safe, tabled_for_io],
+"
+    try {
+        io.mercury_print_string(Stream, Val.ToString());
+        Error = null;
+    } catch (System.SystemException e) {
+        Error = e;
+    }
+").
+
+:- pragma foreign_proc("C#",
+    write_uint16_2(Stream::in, Val::in, Error::out, _IO0::di, _IO::uo),
+    [will_not_call_mercury, promise_pure, thread_safe, tabled_for_io],
+"
+    try {
+        io.mercury_print_string(Stream, Val.ToString());
+        Error = null;
+    } catch (System.SystemException e) {
+        Error = e;
+    }
+").
+
+:- pragma foreign_proc("C#",
+    write_uint32_2(Stream::in, Val::in, Error::out, _IO0::di, _IO::uo),
+    [will_not_call_mercury, promise_pure, thread_safe, tabled_for_io],
+"
+    try {
+        io.mercury_print_string(Stream, Val.ToString());
+        Error = null;
+    } catch (System.SystemException e) {
+        Error = e;
+    }
+").
+
  :- pragma foreign_proc("C#",
      write_byte_2(Stream::in, Byte::in, Error::out, _IO0::di, _IO::uo),
      [will_not_call_mercury, promise_pure, thread_safe, tabled_for_io],
@@ -8292,7 +8520,69 @@ flush_binary_output(binary_output_stream(Stream), !IO) :-
  ").

  :- pragma foreign_proc("Java",
-    write_uint_2(Stream::in, Val::in, Error::out, _IO0::di, _IO::uo),
+    write_int8_2(Stream::in, Val::in, Error::out, _IO0::di, _IO::uo),
+    [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
+"
+    try {
+        ((io.MR_TextOutputFile) Stream).write(String.valueOf(Val));
+        Error = null;
+    } catch (java.io.IOException e) {
+        Error = e;
+    }
+").
+
+:- pragma foreign_proc("Java",
+    write_int16_2(Stream::in, Val::in, Error::out, _IO0::di, _IO::uo),
+    [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
+"
+    try {
+        ((io.MR_TextOutputFile) Stream).write(String.valueOf(Val));
+        Error = null;
+    } catch (java.io.IOException e) {
+        Error = e;
+    }
+").
+
+:- pragma foreign_proc("Java",
+    write_int32_2(Stream::in, Val::in, Error::out, _IO0::di, _IO::uo),
+    [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
+"
+    try {
+        ((io.MR_TextOutputFile) Stream).write(String.valueOf(Val));
+        Error = null;
+    } catch (java.io.IOException e) {
+        Error = e;
+    }
+").
+
+:- pragma foreign_proc("Java",
+    write_uint8_2(Stream::in, Val::in, Error::out, _IO0::di, _IO::uo),
+    [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
+"
+    try {
+        ((io.MR_TextOutputFile) Stream).write(
+            java.lang.Integer.toString(Val & 0xff));
+        Error = null;
+    } catch (java.io.IOException e) {
+        Error = e;
+    }
+").
+
+:- pragma foreign_proc("Java",
+    write_uint16_2(Stream::in, Val::in, Error::out, _IO0::di, _IO::uo),
+    [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
+"
+    try {
+        ((io.MR_TextOutputFile) Stream).write(
+            java.lang.Integer.toString(Val & 0xffff));
+        Error = null;
+    } catch (java.io.IOException e) {
+        Error = e;
+    }
+").
+
+:- pragma foreign_proc("Java",
+    write_uint32_2(Stream::in, Val::in, Error::out, _IO0::di, _IO::uo),
      [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
  "
      try {
@@ -8424,6 +8714,60 @@ flush_binary_output(binary_output_stream(Stream), !IO) :-
      Error = ok
  ").

+:- pragma foreign_proc("Erlang",
+    write_int8_2(Stream::in, Val::in, Error::out, _IO0::di, _IO::uo),
+    [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
+"
+    mercury__io:mercury_write_int(Stream, Val),
+    % mercury_write_int does not return errors yet.
+    Error = ok
+").
+
+:- pragma foreign_proc("Erlang",
+    write_int16_2(Stream::in, Val::in, Error::out, _IO0::di, _IO::uo),
+    [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
+"
+    mercury__io:mercury_write_int(Stream, Val),
+    % mercury_write_int does not return errors yet.
+    Error = ok
+").
+
+:- pragma foreign_proc("Erlang",
+    write_int32_2(Stream::in, Val::in, Error::out, _IO0::di, _IO::uo),
+    [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
+"
+    mercury__io:mercury_write_int(Stream, Val),
+    % mercury_write_int does not return errors yet.
+    Error = ok
+").
+
+:- pragma foreign_proc("Erlang",
+    write_uint8_2(Stream::in, Val::in, Error::out, _IO0::di, _IO::uo),
+    [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
+"
+    mercury__io:mercury_write_int(Stream, Val),
+    % mercury_write_int does not return errors yet.
+    Error = ok
+").
+
+:- pragma foreign_proc("Erlang",
+    write_uint16_2(Stream::in, Val::in, Error::out, _IO0::di, _IO::uo),
+    [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
+"
+    mercury__io:mercury_write_int(Stream, Val),
+    % mercury_write_int does not return errors yet.
+    Error = ok
+").
+
+:- pragma foreign_proc("Erlang",
+    write_uint32_2(Stream::in, Val::in, Error::out, _IO0::di, _IO::uo),
+    [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
+"
+    mercury__io:mercury_write_int(Stream, Val),
+    % mercury_write_int does not return errors yet.
+    Error = ok
+").
+
  :- pragma foreign_proc("Erlang",
      write_string_2(Stream::in, Message::in, Error::out, _IO0::di, _IO::uo),
      [will_not_call_mercury, promise_pure, thread_safe, tabled_for_io],
@@ -11243,12 +11587,48 @@ result_to_stream_result(error(Error)) = error(Error).
      pred(put/4) is write_int
  ].

+:- instance stream.writer(output_stream, int8, io)
+    where
+[
+    pred(put/4) is write_int8
+].
+
+:- instance stream.writer(output_stream, int16, io)
+    where
+[
+    pred(put/4) is write_int16
+].
+
+:- instance stream.writer(output_stream, int32, io)
+    where
+[
+    pred(put/4) is write_int32
+].
+
  :- instance stream.writer(output_stream, uint, io)
      where
  [
      pred(put/4) is write_uint
  ].

+:- instance stream.writer(output_stream, uint8, io)
+    where
+[
+    pred(put/4) is write_uint8
+].
+
+:- instance stream.writer(output_stream, uint16, io)
+    where
+[
+    pred(put/4) is write_uint16
+].
+
+:- instance stream.writer(output_stream, uint32, io)
+    where
+[
+    pred(put/4) is write_uint32
+].
+
  :- instance stream.writer(output_stream, string, io)
      where
  [
diff --git a/library/pprint.m b/library/pprint.m
index 8424353d3..b2897d3f9 100644
--- a/library/pprint.m
+++ b/library/pprint.m
@@ -2,6 +2,7 @@
  % vim:ts=4 sw=4 expandtab tw=0 wm=0 ft=mercury
  %---------------------------------------------------------------------------%
  % Copyright (C) 2000-2007, 2010-2011 The University of Melbourne
+% Copyright (C) 2014-2017 The Mercury team.
  % This file may only be copied under the terms of the GNU Library General
  % Public License - see the file COPYING.LIB in the Mercury distribution.
  %---------------------------------------------------------------------------%
@@ -187,7 +188,12 @@
  :- instance doc(doc).
  :- instance doc(string).
  :- instance doc(int).
+:- instance doc(int8).
+:- instance doc(int16).
+:- instance doc(int32).
  :- instance doc(uint).
+:- instance doc(uint8).
+:- instance doc(uint16).
  :- instance doc(float).
  :- instance doc(char).

@@ -414,12 +420,19 @@ doc(X) = doc(int.max_int, X).

  %---------------------------------------------------------------------------%

-:- instance doc(doc)     where [ doc(_, Doc)    = Doc            ].
-:- instance doc(string)  where [ doc(_, String) = text(String)   ].
-:- instance doc(uint)    where [ doc(_, UInt) = text(uint_to_string(UInt))].
-:- instance doc(int)     where [ doc(_, Int)    = poly(i(Int))   ].
-:- instance doc(float)   where [ doc(_, Float)  = poly(f(Float)) ].
-:- instance doc(char)    where [ doc(_, Char)   = poly(c(Char))  ].
+:- instance doc(doc)    where [ doc(_, Doc)    = Doc            ].
+:- instance doc(string) where [ doc(_, String) = text(String)   ].
+:- instance doc(int)    where [ doc(_, Int)    = poly(i(Int))   ].
+:- instance doc(int8)   where [ doc(_, Int8) = text(int8_to_string(Int8))].
+:- instance doc(int16) where [ doc(_, Int16) = text(int16_to_string(Int16))].
+:- instance doc(int32) where [ doc(_, Int32) = text(int32_to_string(Int32))].
+:- instance doc(uint)   where [ doc(_, UInt) = text(uint_to_string(UInt))].
+:- instance doc(uint8)  where [ doc(_, UInt8) = text(uint8_to_string(UInt8))].
+:- instance doc(uint16) where [
+    doc(_, UInt16) = text(uint16_to_string(UInt16))
+].
+:- instance doc(float)  where [ doc(_, Float)  = poly(f(Float)) ].
+:- instance doc(char)   where [ doc(_, Char)   = poly(c(Char))  ].

  %---------------------------------------------------------------------------%

diff --git a/library/private_builtin.m b/library/private_builtin.m
index 390a5287a..04fa67103 100644
--- a/library/private_builtin.m
+++ b/library/private_builtin.m
@@ -2,6 +2,7 @@
  % vim: ft=mercury ts=4 sw=4 et
  %---------------------------------------------------------------------------%
  % Copyright (C) 1994-2007, 2012 The University of Melbourne.
+% Copyright (C) 2013-2017 The Mercury team.
  % This file may only be copied under the terms of the GNU Library General
  % Public License - see the file COPYING.LIB in the Mercury distribution.
  %---------------------------------------------------------------------------%
@@ -51,23 +52,23 @@
  :- pred builtin_unify_uint(uint::in, uint::in) is semidet.
  :- pred builtin_compare_uint(comparison_result::uo, uint::in, uint::in) is det.

-:- pred builtin_unify_int8(T::in, T::in) is semidet.
-:- pred builtin_compare_int8(comparison_result::uo, T::in, T::in) is det.
+:- pred builtin_unify_int8(int8::in, int8::in) is semidet.
+:- pred builtin_compare_int8(comparison_result::uo, int8::in, int8::in) is det.

-:- pred builtin_unify_uint8(T::in, T::in) is semidet.
-:- pred builtin_compare_uint8(comparison_result::uo, T::in, T::in) is det.
+:- pred builtin_unify_uint8(uint8::in, uint8::in) is semidet.
+:- pred builtin_compare_uint8(comparison_result::uo, uint8::in, uint8::in) is det.

-:- pred builtin_unify_int16(T::in, T::in) is semidet.
-:- pred builtin_compare_int16(comparison_result::uo, T::in, T::in) is det.
+:- pred builtin_unify_int16(int16::in, int16::in) is semidet.
+:- pred builtin_compare_int16(comparison_result::uo, int16::in, int16::in) is det.

-:- pred builtin_unify_uint16(T::in, T::in) is semidet.
-:- pred builtin_compare_uint16(comparison_result::uo, T::in, T::in) is det.
+:- pred builtin_unify_uint16(uint16::in, uint16::in) is semidet.
+:- pred builtin_compare_uint16(comparison_result::uo, uint16::in, uint16::in) is det.

-:- pred builtin_unify_int32(T::in, T::in) is semidet.
-:- pred builtin_compare_int32(comparison_result::uo, T::in, T::in) is det.
+:- pred builtin_unify_int32(int32::in, int32::in) is semidet.
+:- pred builtin_compare_int32(comparison_result::uo, int32::in, int32::in) is det.

-:- pred builtin_unify_uint32(T::in, T::in) is semidet.
-:- pred builtin_compare_uint32(comparison_result::uo, T::in, T::in) is det.
+:- pred builtin_unify_uint32(uint32::in, uint32::in) is semidet.
+:- pred builtin_compare_uint32(comparison_result::uo, uint32::in, uint32::in) is det.

  :- pred builtin_unify_character(character::in, character::in) is semidet.
  :- pred builtin_compare_character(comparison_result::uo, character::in,
@@ -154,13 +155,25 @@
  :- import_module char.
  :- import_module float.
  :- import_module int.
+:- import_module int8.
+:- import_module int16.
+:- import_module int32.
  :- import_module uint.
+:- import_module uint8.
+:- import_module uint16.
+:- import_module uint32.
  :- import_module require.
  :- import_module string.
  :- import_module type_desc.

  :- pragma inline(builtin_compare_int/3).
  :- pragma inline(builtin_compare_uint/3).
+:- pragma inline(builtin_compare_int8/3).
+:- pragma inline(builtin_compare_uint8/3).
+:- pragma inline(builtin_compare_int16/3).
+:- pragma inline(builtin_compare_uint16/3).
+:- pragma inline(builtin_compare_int32/3).
+:- pragma inline(builtin_compare_uint32/3).
  :- pragma inline(builtin_compare_character/3).
  :- pragma inline(builtin_compare_string/3).
  :- pragma inline(builtin_compare_float/3).
@@ -187,88 +200,70 @@ builtin_compare_uint(R, X, Y) :-
          R = (>)
      ).

-builtin_unify_int8(_, _) :-
-    ( if semidet_succeed then
-        sorry("unify for int8")
-    else
-        semidet_succeed
-    ).
+builtin_unify_int8(X, X).

-builtin_compare_int8(R, _, _) :-
-    ( if semidet_succeed then
-        sorry("compare for int8")
-    else
+builtin_compare_int8(R, X, Y) :-
+    ( if X < Y then
+        R = (<)
+    else if X = Y then
          R = (=)
-    ).
-
-builtin_unify_uint8(_, _) :-
-    ( if semidet_succeed then
-        sorry("unify for uint8")
      else
-        semidet_succeed
+        R = (>)
      ).

-builtin_compare_uint8(R, _, _) :-
-    ( if semidet_succeed then
-        sorry("compare for uint8")
-    else
-        R = (=)
-    ).
+builtin_unify_uint8(X, X).

-builtin_unify_int16(_, _) :-
-    ( if semidet_succeed then
-        sorry("unify for int16")
+builtin_compare_uint8(R, X, Y) :-
+    ( if X < Y then
+        R = (<)
+    else if X = Y then
+        R = (=)
      else
-        semidet_succeed
+        R = (>)
      ).

-builtin_compare_int16(R, _, _) :-
-    ( if semidet_succeed then
-        sorry("compare for int16")
-    else
-        R = (=)
-    ).
+builtin_unify_int16(X, X).

-builtin_unify_uint16(_, _) :-
-    ( if semidet_succeed then
-        sorry("unify for uint16")
+builtin_compare_int16(R, X, Y) :-
+    ( if X < Y then
+        R = (<)
+    else if X = Y then
+        R = (=)
      else
-        semidet_succeed
+        R = (>)
      ).

-builtin_compare_uint16(R, _, _) :-
-    ( if semidet_succeed then
-        sorry("compare for uint16")
-    else
-        R = (=)
-    ).
+builtin_unify_uint16(X, X).

-builtin_unify_int32(_, _) :-
-    ( if semidet_succeed then
-        sorry("unify for int32")
+builtin_compare_uint16(R, X, Y) :-
+    ( if X < Y then
+        R = (<)
+    else if X = Y then
+        R = (=)
      else
-        semidet_succeed
+        R = (>)
      ).

-builtin_compare_int32(R, _, _) :-
-    ( if semidet_succeed then
-        sorry("compare for int32")
-    else
-        R = (=)
-    ).
+builtin_unify_int32(X, X).

-builtin_unify_uint32(_, _) :-
-    ( if semidet_succeed then
-        sorry("unify for uint32")
+builtin_compare_int32(R, X, Y) :-
+    ( if X < Y then
+        R = (<)
+    else if X = Y then
+        R = (=)
      else
-        semidet_succeed
+        R = (>)
      ).

-builtin_compare_uint32(R, _, _) :-
-    ( if semidet_succeed then
-        sorry("compare for uint32")
-    else
+builtin_unify_uint32(X, X).
+
+builtin_compare_uint32(R, X, Y) :-
+    ( if X < Y then
+        R = (<)
+    else if X = Y then
          R = (=)
+    else
+        R = (>)
      ).

  builtin_unify_character(C, C).
diff --git a/library/rtti_implementation.m b/library/rtti_implementation.m
index 2c5ea04c3..eeea7e186 100644
--- a/library/rtti_implementation.m
+++ b/library/rtti_implementation.m
@@ -1,7 +1,8 @@
  %---------------------------------------------------------------------------%
  % vim: ft=mercury ts=4 sw=4 et
  %---------------------------------------------------------------------------%
-% Copyright (C) 2001-2007, 2009-2010 The University of Melbourne.
+% Copyright (C) 2001-2007, 2009-2011 The University of Melbourne.
+% Copyright (C) 2014-2016 The Mercury team.
  % This file may only be copied under the terms of the GNU Library General
  % Public License - see the file COPYING.LIB in the Mercury distribution.
  %---------------------------------------------------------------------------%
@@ -2741,37 +2742,43 @@ deconstruct_2(Term, TypeInfo, TypeCtorInfo, TypeCtorRep, NonCanon,
          Arguments = []
      ;
          TypeCtorRep = tcr_int8,
-        Functor = "<<int8>>",
+        det_dynamic_cast(Term, Int8),
+        Functor = string.int8_to_string(Int8) ++ "i8",
          Ordinal = -1,
          Arity = 0,
          Arguments = []
      ;
          TypeCtorRep = tcr_uint8,
-        Functor = "<<uint8>>",
+        det_dynamic_cast(Term, UInt8),
+        Functor = string.uint8_to_string(UInt8) ++ "u8",
          Ordinal = -1,
          Arity = 0,
          Arguments = []
      ;
          TypeCtorRep = tcr_int16,
-        Functor = "<<int16>>",
+        det_dynamic_cast(Term, Int16),
+        Functor = string.int16_to_string(Int16) ++ "i16",
          Ordinal = -1,
          Arity = 0,
          Arguments = []
      ;
          TypeCtorRep = tcr_uint16,
-        Functor = "<<uint16>>",
+        det_dynamic_cast(Term, UInt16),
+        Functor = string.uint16_to_string(UInt16) ++ "u16",
          Ordinal = -1,
          Arity = 0,
          Arguments = []
      ;
          TypeCtorRep = tcr_int32,
-        Functor = "<<int32>>",
+        det_dynamic_cast(Term, Int32),
+        Functor = string.int32_to_string(Int32) ++ "i32",
          Ordinal = -1,
          Arity = 0,
          Arguments = []
      ;
          TypeCtorRep = tcr_uint32,
-        Functor = "<<uint32>>",
+        det_dynamic_cast(Term, UInt32),
+        Functor = string.uint32_to_string(UInt32) ++ "u32",
          Ordinal = -1,
          Arity = 0,
          Arguments = []
diff --git a/library/stream.string_writer.m b/library/stream.string_writer.m
index 337fe951f..3b158b249 100644
--- a/library/stream.string_writer.m
+++ b/library/stream.string_writer.m
@@ -2,6 +2,7 @@
  % vim: ft=mercury ts=4 sw=4 et
  %---------------------------------------------------------------------------%
  % Copyright (C) 2006-2007, 2011 The University of Melbourne.
+% Copyright (C) 2014-2017 The Mercury team.
  % This file may only be copied under the terms of the GNU Library General
  % Public License - see the file COPYING.LIB in the Mercury distribution.
  %---------------------------------------------------------------------------%
@@ -32,6 +33,24 @@
  :- pred put_uint(Stream::in, uint::in, State::di, State::uo) is det
      <= stream.writer(Stream, string, State).

+:- pred put_int8(Stream::in, int8::in, State::di, State::uo) is det
+    <= stream.writer(Stream, string, State).
+
+:- pred put_uint8(Stream::in, uint8::in, State::di, State::uo) is det
+    <= stream.writer(Stream, string, State).
+
+:- pred put_int16(Stream::in, int16::in, State::di, State::uo) is det
+    <= stream.writer(Stream, string, State).
+
+:- pred put_uint16(Stream::in, uint16::in, State::di, State::uo) is det
+    <= stream.writer(Stream, string, State).
+
+:- pred put_int32(Stream::in, int32::in, State::di, State::uo) is det
+    <= stream.writer(Stream, string, State).
+
+:- pred put_uint32(Stream::in, uint32::in, State::di, State::uo) is det
+    <= stream.writer(Stream, string, State).
+
  :- pred put_float(Stream::in, float::in, State::di, State::uo) is det
      <= stream.writer(Stream, string, State).

@@ -234,6 +253,105 @@ put_uint(Stream, UInt, !State) :-
          put(Stream, string.uint_to_string(UInt), !State)
      ).

+put_int8(Stream, Int8, !State) :-
+    ( if
+        % Handle the common I/O case more efficiently.
+        dynamic_cast(!.State, IOState0),
+        dynamic_cast(Stream, IOStream)
+    then
+        io.write_int8(IOStream, Int8, unsafe_promise_unique(IOState0), IOState),
+        ( if dynamic_cast(IOState, !:State) then
+            !:State = unsafe_promise_unique(!.State)
+        else
+            error("stream.string_writer.put_int8: unexpected type error")
+        )
+    else
+        put(Stream, string.int8_to_string(Int8), !State)
+    ).
+
+put_uint8(Stream, UInt8, !State) :-
+    ( if
+        % Handle the common I/O case more efficiently.
+        dynamic_cast(!.State, IOState0),
+        dynamic_cast(Stream, IOStream)
+    then
+        io.write_uint8(IOStream, UInt8,
+            unsafe_promise_unique(IOState0), IOState),
+        ( if dynamic_cast(IOState, !:State) then
+            !:State = unsafe_promise_unique(!.State)
+        else
+            error("stream.string_writer.put_uint8: unexpected type error")
+        )
+    else
+        put(Stream, string.uint8_to_string(UInt8), !State)
+    ).
+
+put_int16(Stream, Int16, !State) :-
+    ( if
+        % Handle the common I/O case more efficiently.
+        dynamic_cast(!.State, IOState0),
+        dynamic_cast(Stream, IOStream)
+    then
+        io.write_int16(IOStream, Int16, unsafe_promise_unique(IOState0), IOState),
+        ( if dynamic_cast(IOState, !:State) then
+            !:State = unsafe_promise_unique(!.State)
+        else
+            error("stream.string_writer.put_int16: unexpected type error")
+        )
+    else
+        put(Stream, string.int16_to_string(Int16), !State)
+    ).
+
+put_uint16(Stream, UInt16, !State) :-
+    ( if
+        % Handle the common I/O case more efficiently.
+        dynamic_cast(!.State, IOState0),
+        dynamic_cast(Stream, IOStream)
+    then
+        io.write_uint16(IOStream, UInt16,
+            unsafe_promise_unique(IOState0), IOState),
+        ( if dynamic_cast(IOState, !:State) then
+            !:State = unsafe_promise_unique(!.State)
+        else
+            error("stream.string_writer.put_uint16: unexpected type error")
+        )
+    else
+        put(Stream, string.uint16_to_string(UInt16), !State)
+    ).
+
+put_int32(Stream, Int32, !State) :-
+    ( if
+        % Handle the common I/O case more efficiently.
+        dynamic_cast(!.State, IOState0),
+        dynamic_cast(Stream, IOStream)
+    then
+        io.write_int32(IOStream, Int32, unsafe_promise_unique(IOState0), IOState),
+        ( if dynamic_cast(IOState, !:State) then
+            !:State = unsafe_promise_unique(!.State)
+        else
+            error("stream.string_writer.put_int32: unexpected type error")
+        )
+    else
+        put(Stream, string.int32_to_string(Int32), !State)
+    ).
+
+put_uint32(Stream, UInt32, !State) :-
+    ( if
+        % Handle the common I/O case more efficiently.
+        dynamic_cast(!.State, IOState0),
+        dynamic_cast(Stream, IOStream)
+    then
+        io.write_uint32(IOStream, UInt32,
+            unsafe_promise_unique(IOState0), IOState),
+        ( if dynamic_cast(IOState, !:State) then
+            !:State = unsafe_promise_unique(!.State)
+        else
+            error("stream.string_writer.put_uint32: unexpected type error")
+        )
+    else
+        put(Stream, string.uint32_to_string(UInt32), !State)
+    ).
+
  put_float(Stream, Float, !State) :-
      ( if
          % Handle the common I/O case more efficiently.
@@ -294,6 +412,18 @@ print(Stream, NonCanon, Term, !State) :-
          put(Stream, Char, !State)
      else if dynamic_cast(Term, UInt : uint) then
          put(Stream, uint_to_string(UInt), !State)
+    else if dynamic_cast(Term, Int8 : int8) then
+        put(Stream, int8_to_string(Int8), !State)
+    else if dynamic_cast(Term, UInt8 : uint8) then
+        put(Stream, uint8_to_string(UInt8), !State)
+    else if dynamic_cast(Term, Int16 : int16) then
+        put(Stream, int16_to_string(Int16), !State)
+    else if dynamic_cast(Term, UInt16 : uint16) then
+        put(Stream, uint16_to_string(UInt16), !State)
+    else if dynamic_cast(Term, Int32 : int32) then
+        put(Stream, int32_to_string(Int32), !State)
+    else if dynamic_cast(Term, UInt32 : uint32) then
+        put(Stream, uint32_to_string(UInt32), !State)
      else if dynamic_cast(Term, OrigUniv) then
          write_univ(Stream, OrigUniv, !State)
      else if dynamic_cast(Term, BigInt) then
@@ -397,6 +527,24 @@ do_write_univ_prio(Stream, NonCanon, Univ, Priority, !State) :-
      else if univ_to_type(Univ, UInt) then
          put_uint(Stream, UInt, !State),
          put_char(Stream, 'u', !State)
+    else if univ_to_type(Univ, Int8) then
+        put_int8(Stream, Int8, !State),
+        put(Stream, "i8", !State)
+    else if univ_to_type(Univ, UInt8) then
+        put_uint8(Stream, UInt8, !State),
+        put(Stream, "u8", !State)
+    else if univ_to_type(Univ, Int16) then
+        put_int16(Stream, Int16, !State),
+        put(Stream, "i16", !State)
+    else if univ_to_type(Univ, UInt16) then
+        put_uint16(Stream, UInt16, !State),
+        put(Stream, "u16", !State)
+    else if univ_to_type(Univ, Int32)then
+        put_int32(Stream, Int32, !State),
+        put(Stream, "i32", !State)
+    else if univ_to_type(Univ, UInt32) then
+        put_uint32(Stream, UInt32, !State),
+        put(Stream, "u32", !State)
      else if univ_to_type(Univ, Float) then
          put_float(Stream, Float, !State)
      else if univ_to_type(Univ, Bitmap) then
diff --git a/library/string.m b/library/string.m
index 7f809d139..fae3c7af4 100644
--- a/library/string.m
+++ b/library/string.m
@@ -2,6 +2,7 @@
  % vim: ts=4 sw=4 et ft=mercury
  %---------------------------------------------------------------------------%
  % Copyright (C) 1993-2012 The University of Melbourne.
+% Copyright (C) 2013-2017 The Mercury team.
  % This file may only be copied under the terms of the GNU Library General
  % Public License - see the file COPYING.LIB in the Mercury distribution.
  %---------------------------------------------------------------------------%
@@ -1232,8 +1233,34 @@
  :- func int_to_base_string_group(int, int, int, string) = string.
  :- mode int_to_base_string_group(in, in, in, in) = uo is det.

+    % Convert an unsigned integer to a string.
+    %
  :- func uint_to_string(uint::in) = (string::uo) is det.

+    % Convert an 8-bit integer to a string.
+    %
+:- func int8_to_string(int8::in) = (string::uo) is det.
+
+    % Convert an unsigned 8-bit integer to a string.
+    %
+:- func uint8_to_string(uint8::in) = (string::uo) is det.
+
+    % Convert an 16-bit integer to a string.
+    %
+:- func int16_to_string(int16::in) = (string::uo) is det.
+
+    % Convert an unsigned 16-bit integer to a string.
+    %
+:- func uint16_to_string(uint16::in) = (string::uo) is det.
+
+    % Convert a 32-bit integer to a string.
+    %
+:- func int32_to_string(int32::in) = (string::uo) is det.
+
+    % Convert an unsigned 32-bit integer to a string.
+    %
+:- func uint32_to_string(uint32::in) = (string::uo) is det.
+
      % Convert a float to a string.
      % In the current implementation, the resulting float will be in the form
      % that it was printed using the format string "%#.<prec>g".
@@ -1408,6 +1435,7 @@
  #include <ctype.h>
  #include <string.h>
  #include <stdio.h>
+#include <inttypes.h>

  #include ""mercury_string.h""   /* for MR_allocate_aligned_string*() etc. */
  #include ""mercury_tags.h""     /* for MR_list_cons*() */
@@ -5867,6 +5895,180 @@ uint_to_string(_) = _ :-

  %---------------------%

+:- pragma foreign_proc("C",
+    int8_to_string(I8::in) = (S::uo),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
+"
+    char buffer[5];
+    sprintf(buffer, ""%"" PRId8, I8);
+    MR_allocate_aligned_string_msg(S, strlen(buffer), MR_ALLOC_ID);
+    strcpy(S, buffer);
+").
+
+:- pragma foreign_proc("C#",
+    int_to_string(I8::in) = (S::uo),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    S = I8.ToString();
+").
+
+:- pragma foreign_proc("Java",
+    int8_to_string(I8::in) = (S::uo),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    S = java.lang.Integer.toString(I8);
+").
+
+int8_to_string(_) = _ :-
+    sorry($module, "string.int8_to_string/1").
+
+%---------------------%
+
+:- pragma foreign_proc("C",
+    uint8_to_string(U8::in) = (S::uo),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
+"
+    char buffer[4];
+    sprintf(buffer, ""%"" PRIu8, U8);
+    MR_allocate_aligned_string_msg(S, strlen(buffer), MR_ALLOC_ID);
+    strcpy(S, buffer);
+").
+
+:- pragma foreign_proc("C#",
+    uint8_to_string(U8::in) = (S::uo),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    S = U8.ToString();
+").
+
+:- pragma foreign_proc("Java",
+    uint8_to_string(U8::in) = (S::uo),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    S = java.lang.Integer.toString(U8 & 0xff);
+").
+
+uint8_to_string(_) = _ :-
+    sorry($module, "string.uint8_to_string/1").
+
+%---------------------%
+
+:- pragma foreign_proc("C",
+    int16_to_string(I16::in) = (S::uo),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
+"
+    char buffer[7];
+    sprintf(buffer, ""%"" PRId16, I16);
+    MR_allocate_aligned_string_msg(S, strlen(buffer), MR_ALLOC_ID);
+    strcpy(S, buffer);
+").
+
+:- pragma foreign_proc("C#",
+    int16_to_string(I16::in) = (S::uo),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    S = I16.ToString();
+").
+
+:- pragma foreign_proc("Java",
+    int16_to_string(I16::in) = (S::uo),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    S = java.lang.Integer.toString(I16);
+").
+
+int16_to_string(_) = _ :-
+    sorry($module, "string.int16_to_string/1").
+
+%---------------------%
+
+:- pragma foreign_proc("C",
+    uint16_to_string(U16::in) = (S::uo),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
+"
+    char buffer[6];
+    sprintf(buffer, ""%"" PRIu16, (MR_Unsigned)U16);
+    MR_allocate_aligned_string_msg(S, strlen(buffer), MR_ALLOC_ID);
+    strcpy(S, buffer);
+").
+
+:- pragma foreign_proc("C#",
+    uint16_to_string(U16::in) = (S::uo),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    S = U16.ToString();
+").
+
+:- pragma foreign_proc("Java",
+    uint16_to_string(U16::in) = (S::uo),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    S = java.lang.Integer.toString(U16 & 0xffff);
+").
+
+uint16_to_string(_) = _ :-
+    sorry($module, "string.uint16_to_string/1").
+
+%---------------------%
+
+:- pragma foreign_proc("C",
+    int32_to_string(I32::in) = (S::uo),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
+"
+    char buffer[11];
+    sprintf(buffer, ""%"" PRId32, I32);
+    MR_allocate_aligned_string_msg(S, strlen(buffer), MR_ALLOC_ID);
+    strcpy(S, buffer);
+").
+
+:- pragma foreign_proc("C#",
+    int32_to_string(I32::in) = (S::uo),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    S = I32.ToString();
+").
+
+:- pragma foreign_proc("Java",
+    int32_to_string(I32::in) = (S::uo),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    S = java.lang.Integer.toString(I32);
+").
+
+int32_to_string(_) = _ :-
+    sorry($module, "string.int32_to_string/1").
+
+%---------------------%
+
+:- pragma foreign_proc("C",
+    uint32_to_string(U32::in) = (S::uo),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
+"
+    char buffer[10];
+    sprintf(buffer, ""%"" PRIu32, U32);
+    MR_allocate_aligned_string_msg(S, strlen(buffer), MR_ALLOC_ID);
+    strcpy(S, buffer);
+").
+
+:- pragma foreign_proc("C#",
+    uint32_to_string(U32::in) = (S::uo),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    S = U32.ToString();
+").
+
+:- pragma foreign_proc("Java",
+    uint32_to_string(U32::in) = (S::uo),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    S = java.lang.Long.toString(U32 & 0xffffffffL);
+").
+
+uint32_to_string(_) = _ :-
+    sorry($module, "string.uint32_to_string/1").
+
+%---------------------%
+
  float_to_string(Float) = S2 :-
      float_to_string(Float, S2).

diff --git a/library/string.to_string.m b/library/string.to_string.m
index 0a9d0f731..c1e917849 100644
--- a/library/string.to_string.m
+++ b/library/string.to_string.m
@@ -104,7 +104,8 @@ value_to_revstrings(NonCanon, OpsTable, X, !Rs) :-

  value_to_revstrings_prio(NonCanon, OpsTable, Priority, X, !Rs) :-
      % We need to special-case the builtin types:
-    %   int, uint, char, float, string
+    %   int, uint, int8, uint8, int16, uint16, int32, uint32
+    %   char, float, string
      %   type_info, univ, c_pointer, array
      %   and private_builtin.type_info

@@ -116,6 +117,18 @@ value_to_revstrings_prio(NonCanon, OpsTable, Priority, X, !Rs) :-
          add_revstring(string.int_to_string(Int), !Rs)
      else if dynamic_cast(X, UInt) then
          add_revstring(string.uint_to_string(UInt) ++ "u", !Rs)
+    else if dynamic_cast(X, Int8) then
+        add_revstring(string.int8_to_string(Int8) ++ "i8", !Rs)
+    else if dynamic_cast(X, UInt8) then
+        add_revstring(string.uint8_to_string(UInt8) ++ "u8", !Rs)
+    else if dynamic_cast(X, Int16) then
+        add_revstring(string.int16_to_string(Int16) ++ "i16", !Rs)
+    else if dynamic_cast(X, UInt16) then
+        add_revstring(string.uint16_to_string(UInt16) ++ "u16", !Rs)
+    else if dynamic_cast(X, Int32) then
+        add_revstring(string.int32_to_string(Int32) ++ "i32", !Rs)
+    else if dynamic_cast(X, UInt32) then
+        add_revstring(string.uint32_to_string(UInt32) ++ "u32", !Rs)
      else if dynamic_cast(X, Float) then
          add_revstring(string.float_to_string(Float), !Rs)
      else if dynamic_cast(X, Bitmap) then
diff --git a/library/term.m b/library/term.m
index 3a2211608..4c286f4f0 100644
--- a/library/term.m
+++ b/library/term.m
@@ -2,7 +2,7 @@
  % vim: ts=4 sw=4 et ft=mercury
  %---------------------------------------------------------------------------%
  % Copyright (C) 1993-2000,2003-2009,2011-2012 The University of Melbourne.
-% Copyright (C) 2015-2017 The Mercury team.
+% Copyright (C) 2014-2017 The Mercury team.
  % This file may only be copied under the terms of the GNU Library General
  % Public License - see the file COPYING.LIB in the Mercury distribution.
  %---------------------------------------------------------------------------%
@@ -149,14 +149,38 @@

  :- pred term_to_int(term(T)::in, int::out) is semidet.

+:- pred term_to_int8(term(T)::in, int8::out) is semidet.
+
+:- pred term_to_int16(term(T)::in, int16::out) is semidet.
+
+:- pred term_to_int32(term(T)::in, int32::out) is semidet.
+
  :- pred term_to_uint(term(T)::in, uint::out) is semidet.

+:- pred term_to_uint8(term(T)::in, uint8::out) is semidet.
+
+:- pred term_to_uint16(term(T)::in, uint16::out) is semidet.
+
+:- pred term_to_uint32(term(T)::in, uint32::out) is semidet.
+
  :- pred decimal_term_to_int(term(T)::in, int::out) is semidet.

  :- func int_to_decimal_term(int, context) = term(T).

  :- func uint_to_decimal_term(uint, context) = term(T).

+:- func int8_to_decimal_term(int8, context) = term(T).
+
+:- func uint8_to_decimal_term(uint8, context) = term(T).
+
+:- func int16_to_decimal_term(int16, context) = term(T).
+
+:- func uint16_to_decimal_term(uint16, context) = term(T).
+
+:- func int32_to_decimal_term(int32, context) = term(T).
+
+:- func uint32_to_decimal_term(uint32, context) = term(T).
+
  %---------------------------------------------------------------------------%
  %
  % Predicates to unify terms.
@@ -794,11 +818,41 @@ term_to_int(Term, Int) :-
      Const = integer(_Base, Integer, signed, size_word),
      integer.to_int(Integer, Int).

+term_to_int8(Term, Int8) :-
+    Term = functor(Const, [], _Context),
+    Const = integer(_Base, Integer, signed, size_8_bit),
+    integer.to_int8(Integer, Int8).
+
+term_to_int16(Term, Int16) :-
+    Term = functor(Const, [], _Context),
+    Const = integer(_Base, Integer, signed, size_16_bit),
+    integer.to_int16(Integer, Int16).
+
+term_to_int32(Term, Int32) :-
+    Term = functor(Const, [], _Context),
+    Const = integer(_Base, Integer, signed, size_32_bit),
+    integer.to_int32(Integer, Int32).
+
  term_to_uint(Term, UInt) :-
      Term = functor(Const, [], _Context),
      Const = integer(_Base, Integer, unsigned, size_word),
      integer.to_uint(Integer, UInt).

+term_to_uint8(Term, UInt8) :-
+    Term = functor(Const, [], _Context),
+    Const = integer(_Base, Integer, unsigned, size_8_bit),
+    integer.to_uint8(Integer, UInt8).
+
+term_to_uint16(Term, UInt16) :-
+    Term = functor(Const, [], _Context),
+    Const = integer(_Base, Integer, unsigned, size_16_bit),
+    integer.to_uint16(Integer, UInt16).
+
+term_to_uint32(Term, UInt32) :-
+    Term = functor(Const, [], _Context),
+    Const = integer(_Base, Integer, unsigned, size_32_bit),
+    integer.to_uint32(Integer, UInt32).
+
  decimal_term_to_int(Term, Int) :-
      Term = functor(Const, [], _Context),
      Const = integer(base_10, Integer, signed, size_word),
@@ -812,6 +866,36 @@ uint_to_decimal_term(UInt, Context) = Term :-
      Const = integer(base_10, integer.from_uint(UInt), unsigned, size_word),
      Term = functor(Const, [], Context).

+int8_to_decimal_term(Int8, Context) = Term :-
+    Const = integer(base_10, integer.from_int8(Int8), signed,
+        size_8_bit),
+    Term = functor(Const, [], Context).
+
+uint8_to_decimal_term(UInt8, Context) = Term :-
+    Const = integer(base_10, integer.from_uint8(UInt8), unsigned,
+        size_8_bit),
+    Term = functor(Const, [], Context).
+
+int16_to_decimal_term(Int16, Context) = Term :-
+    Const = integer(base_10, integer.from_int16(Int16), signed,
+        size_16_bit),
+    Term = functor(Const, [], Context).
+
+uint16_to_decimal_term(UInt16, Context) = Term :-
+    Const = integer(base_10, integer.from_uint16(UInt16), unsigned,
+        size_16_bit),
+    Term = functor(Const, [], Context).
+
+int32_to_decimal_term(Int32, Context) = Term :-
+    Const = integer(base_10, integer.from_int32(Int32), signed,
+        size_32_bit),
+    Term = functor(Const, [], Context).
+
+uint32_to_decimal_term(UInt32, Context) = Term :-
+    Const = integer(base_10, integer.from_uint32(UInt32), unsigned,
+        size_32_bit),
+    Term = functor(Const, [], Context).
+
  %---------------------------------------------------------------------------%

  unify_term(TermX, TermY, !Subst) :-
diff --git a/library/term_conversion.m b/library/term_conversion.m
index db2bdd3e1..f318f28bb 100644
--- a/library/term_conversion.m
+++ b/library/term_conversion.m
@@ -218,6 +218,36 @@ term_to_univ_special_case(ModuleName, TypeCtorName, TypeArgs, Term,
              Functor = integer(_Base, Integer, unsigned, size_word),
              integer.to_uint(Integer, UInt),
              type_to_univ(UInt, Univ)
+        ;
+            TypeCtorName = "int8",
+            Functor = integer(_Base, Integer, signed, size_8_bit),
+            integer.to_int8(Integer, Int8),
+            type_to_univ(Int8, Univ)
+        ;
+            TypeCtorName = "uint8",
+            Functor = integer(_Base, Integer, unsigned, size_8_bit),
+            integer.to_uint8(Integer, UInt8),
+            type_to_univ(UInt8, Univ)
+        ;
+            TypeCtorName = "int16",
+            Functor = integer(_Base, Integer, signed, size_16_bit),
+            integer.to_int16(Integer, Int16),
+            type_to_univ(Int16, Univ)
+        ;
+            TypeCtorName = "uint16",
+            Functor = integer(_Base, Integer, unsigned, size_16_bit),
+            integer.to_uint16(Integer, UInt16),
+            type_to_univ(UInt16, Univ)
+        ;
+            TypeCtorName = "int32",
+            Functor = integer(_Base, Integer, signed, size_32_bit),
+            integer.to_int32(Integer, Int32),
+            type_to_univ(Int32, Univ)
+        ;
+            TypeCtorName = "uint32",
+            Functor = integer(_Base, Integer, unsigned, size_32_bit),
+            integer.to_uint32(Integer, UInt32),
+            type_to_univ(UInt32, Univ)
          ;
              TypeCtorName = "float",
              Functor = float(Float),
@@ -299,6 +329,30 @@ term_to_univ_special_case(ModuleName, TypeCtorName, TypeArgs, Term,
              TypeTerm = functor(atom("uint"), [], _),
              term_to_uint(ValueTerm, UInt),
              Univ = univ(UInt)
+        ;
+            TypeTerm = functor(atom("int8"), [], _),
+            term_to_int8(ValueTerm, Int8),
+            Univ = univ(Int8)
+        ;
+            TypeTerm = functor(atom("uint8"), [], _),
+            term_to_uint8(ValueTerm, UInt8),
+            Univ = univ(UInt8)
+        ;
+            TypeTerm = functor(atom("int16"), [], _),
+            term_to_int16(ValueTerm, Int16),
+            Univ = univ(Int16)
+        ;
+            TypeTerm = functor(atom("uint16"), [], _),
+            term_to_uint16(ValueTerm, UInt16),
+            Univ = univ(UInt16)
+        ;
+            TypeTerm = functor(atom("int32"), [], _),
+            term_to_int32(ValueTerm, Int32),
+            Univ = univ(Int32)
+        ;
+            TypeTerm = functor(atom("uint32"), [], _),
+            term_to_uint32(ValueTerm, UInt32),
+            Univ = univ(UInt32)
          ;
              TypeTerm = functor(atom("string"), [], _),
              ValueTerm = functor(string(String), [], _),
diff --git a/library/uint.m b/library/uint.m
index 4074bc120..229e37ef7 100644
--- a/library/uint.m
+++ b/library/uint.m
@@ -58,6 +58,8 @@
  :- mode uo   + in  = in is det.
  :- mode in   + uo  = in is det.

+:- func plus(uint, uint) = uint.
+
      % Subtraction.
      %
  :- func uint - uint = uint.
@@ -65,9 +67,12 @@
  :- mode uo   - in   = in is det.
  :- mode in   - uo   = in is det.

+:- func minus(uint, uint) = uint.
+
      % Multiplication.
      %
  :- func (uint::in) * (uint::in) = (uint::uo) is det.
+:- func times(uint, uint) = uint.

      % Maximum.
      %
@@ -253,6 +258,7 @@ det_from_int(I) = U :-
      U = I;
  ").

+%---------------------------------------------------------------------------%

  cast_from_int(_) = _ :-
      sorry($module, "uint.cast_from_int/1 NYI for Erlang").
diff --git a/library/uint16.m b/library/uint16.m
index 703026221..7ff0c9a4e 100644
--- a/library/uint16.m
+++ b/library/uint16.m
@@ -5,16 +5,327 @@
  % This file may only be copied under the terms of the GNU Library General
  % Public License - see the file COPYING.LIB in the Mercury distribution.
  %---------------------------------------------------------------------------%
+%
+% File: uint16.m
+% Main author: juliensf
+% Stability: low.
+%
+% Predicates and functions for dealing with unsigned 16-bit integer numbers.
+%
+%---------------------------------------------------------------------------%

  :- module uint16.
  :- interface.

-    % uint16s are NYI -- this module is just a placeholder for their
-    % library support.
+:- import_module pretty_printer.
+
+%--------------------------------------------------------------------------%
+
+    % from_int(I, U16):
+    % Convert an int into a uint16.
+    % Fails if I is not in [0, 65535].
+    %
+:- pred from_int(int::in, uint16::out) is semidet.
+
+    % As above, but throw an exception instead of failing.
+    %
+:- func det_from_int(int) = uint16.
+
+:- func cast_from_int(int) = uint16.
+
+:- func to_int(uint16) = int.
+
+    % Less than.
+    %
+:- pred (uint16::in) < (uint16::in) is semidet.
+
+    % Greater than.
+    %
+:- pred (uint16::in) > (uint16::in) is semidet.
+
+    % Less than or equal.
+    %
+:- pred (uint16::in) =< (uint16::in) is semidet.
+
+    % Greater than or equal.
+    %
+:- pred (uint16::in) >= (uint16::in) is semidet.
+
+    % Addition.
+    %
+:- func uint16 + uint16 = uint16.
+:- mode in   + in  = uo is det.
+:- mode uo   + in  = in is det.
+:- mode in   + uo  = in is det.
+
+:- func plus(uint16, uint16) = uint16.
+
+    % Subtraction.
+    %
+:- func uint16 - uint16 = uint16.
+:- mode in   - in   = uo is det.
+:- mode uo   - in   = in is det.
+:- mode in   - uo   = in is det.
+
+:- func minus(uint16, uint16) = uint16.
+
+    % Multiplication.
+    %
+:- func (uint16::in) * (uint16::in) = (uint16::uo) is det.
+:- func times(uint16, uint16) = uint16.
+
+    % Maximum.
+    %
+:- func max(uint16, uint16) = uint16.
+
+    % Minimum.
+    %
+:- func min(uint16, uint16) = uint16.
+
+    % Truncating integer division.
+    %
+    % Throws a `math.domain_error' exception if the right operand is zero.
+    %
+:- func (uint16::in) div (uint16::in) = (uint16::uo) is det.
+
+    % Truncating integer division.
+    %
+    % Throws a `math.domain_error' exception if the right operand is zero.
+    %
+:- func (uint16::in) // (uint16::in) = (uint16::uo) is det.
+
+    % (/)/2 is a synonym for (//)/2.
+    %
+:- func (uint16::in) / (uint16::in) = (uint16::uo) is det.
+
+    % unchecked_quotient(X, Y) is the same as X // Y, but the behaviour
+    % is undefined if the right operand is zero.
+    %
+:- func unchecked_quotient(uint16::in, uint16::in) = (uint16::uo) is det.
+
+    % Modulus.
+    % X mod Y = X - (X div Y) * Y
+    %
+    % Throws a `math.domain_error' exception if the right operand is zero.
+    %
+:- func (uint16::in) mod (uint16::in) = (uint16::uo) is det.
+
+    % Remainder.
+    % X rem Y = X - (X // Y) * Y.
      %
-:- type placeholder_uint16 ---> placeholder_uint16.
+    % Throws a `math.domain_error/` exception if the right operand is zero.
+    %
+:- func (uint16::in) rem (uint16::in) = (uint16::uo) is det.
+
+    % unchecked_rem(X, Y) is the same as X rem Y, but the behaviour is
+    % undefined if the right operand is zero.
+    %
+:- func unchecked_rem(uint16::in, uint16::in) = (uint16::uo) is det.
+
+    % Left shift.
+    % X << Y returns X "left shifted" by Y bits.
+    % The bit positions vacated by the shift are filled by zeros.
+    % Throws an exception if Y is not in [0, 16).
+    %
+:- func (uint16::in) << (int::in) = (uint16::uo) is det.
+
+    % unchecked_lift_shift(X, Y) is the same as X << Y except that the
+    % behaviour is undefined if Y is not in [0, 16).
+    % It will typically be be implemented more efficiently than X << Y.
+    %
+:- func unchecked_left_shift(uint16::in, int::in) = (uint16::uo) is det.
+
+    % Right shift.
+    % X >> Y returns X "right shifted" by Y bits.
+    % The bit positions vacated by the shift are filled by zeros.
+    % Throws an exception if Y is not in [0, 16).
+    %
+:- func (uint16::in) >> (int::in) = (uint16::uo) is det.
+
+    % unchecked_right_shift(X, Y) is the same as X >> Y except that the
+    % behaviour is undefined if Y is not in [0, 16).
+    % It will typically be implemented more efficiently than X >> Y.
+    %
+:- func unchecked_right_shift(uint16::in, int::in) = (uint16::uo) is det.
+
+    % even(X) is equivalent to (X mod 2 = 0).
+    %
+:- pred even(uint16::in) is semidet.
+
+    % odd(X) is equivalent to (not even(X)), i.e. (X mod 2 = 1).
+    %
+:- pred odd(uint16::in) is semidet.
+
+    % Bitwise and.
+    %
+:- func (uint16::in) /\ (uint16::in) = (uint16::uo) is det.
+
+    % Bitwise or.
+    %
+:- func (uint16::in) \/ (uint16::in) = (uint16::uo) is det.
+
+    % Bitwise exclusive or (xor).
+    %
+:- func xor(uint16, uint16) = uint16.
+:- mode xor(in, in) = uo is det.
+:- mode xor(in, uo) = in is det.
+:- mode xor(uo, in) = in is det.
+
+    % Bitwise complement.
+    %
+:- func \ (uint16::in) = (uint16::uo) is det.
+
+    % Convert a uint16 to a pretty_printer.doc for formatting.
+    %
+:- func uint16_to_doc(uint16) = pretty_printer.doc.

  %---------------------------------------------------------------------------%
-:- end_module uint16.
  %---------------------------------------------------------------------------%

+:- implementation.
+
+:- import_module exception.
+:- import_module int.
+:- import_module math.
+:- import_module require.
+:- import_module string.
+:- import_module uint.
+
+%---------------------------------------------------------------------------%
+
+from_int(I, U8) :-
+    I >= 0,
+    I =< 65_535,
+    U8 = cast_from_int(I).
+
+det_from_int(I) = U16 :-
+    ( if from_int(I, U16Prime) then
+        U16 = U16Prime
+    else
+        error("uint16.det_from_int: cannot convert int to uint16")
+    ).
+
+%---------------------------------------------------------------------------%
+
+:- pragma foreign_proc("C",
+    cast_from_int(I::in) = (U16::out),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
+        does_not_affect_liveness],
+"
+    U16 = (uint16_t) I;
+").
+
+:- pragma foreign_proc("C#",
+    cast_from_int(I::in) = (U16::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    U16 = (ushort) I;
+").
+
+:- pragma foreign_proc("Java",
+    cast_from_int(I::in) = (U16::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    U16 = (short) I;
+").
+
+:- pragma no_determinism_warning(cast_from_int/1).
+cast_from_int(_) = _ :-
+    sorry($module, "uint16.cast_from_int/1 NYI for Erlang").
+
+%---------------------------------------------------------------------------%
+
+:- pragma foreign_proc("C",
+    to_int(U16::in) = (I::out),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
+        does_not_affect_liveness],
+"
+    I = U16;
+").
+
+:- pragma foreign_proc("C#",
+    to_int(U16::in) = (I::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I = U16;
+").
+
+:- pragma foreign_proc("Java",
+    to_int(U16::in) = (I::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I = U16 & 0xffff;
+").
+
+:- pragma no_determinism_warning(to_int/1).
+to_int(_) = _ :-
+    sorry($module, "uint16.to_int/1 NYI for Erlang").
+
+%---------------------------------------------------------------------------%
+
+X div Y = X // Y.
+
+:- pragma inline('//'/2).
+X // Y = Div :-
+    ( if Y = cast_from_int(0) then
+        throw(math.domain_error("uint16.'//': division by zero"))
+    else
+        Div = unchecked_quotient(X, Y)
+    ).
+
+:- pragma inline('/'/2).
+X / Y = X // Y.
+
+X mod Y = X rem Y.
+
+:- pragma inline(rem/2).
+X rem Y = Rem :-
+    ( if Y = cast_from_int(0) then
+        throw(math.domain_error("uint16.rem: division by zero"))
+    else
+        Rem = unchecked_rem(X, Y)
+    ).
+
+%---------------------------------------------------------------------------%
+
+X << Y = Result :-
+    ( if cast_from_int(Y) < 16u then
+        Result = unchecked_left_shift(X, Y)
+    else
+        Msg = "uint16.(<<): second operand is out of range",
+        throw(math.domain_error(Msg))
+    ).
+
+X >> Y = Result :-
+    ( if cast_from_int(Y) < 16u then
+        Result = unchecked_right_shift(X, Y)
+    else
+        Msg = "uint16.(>>): second operand is out of range",
+        throw(math.domain_error(Msg))
+    ).
+
+%---------------------------------------------------------------------------%
+
+max(X, Y) =
+    ( if X > Y then X else Y ).
+
+min(X, Y) =
+    ( if X < Y then X else Y ).
+
+%---------------------------------------------------------------------------%
+
+:- pragma inline(even/1).
+even(X) :-
+    (X /\ cast_from_int(1)) = cast_from_int(0).
+
+:- pragma inline(odd/1).
+odd(X) :-
+    (X /\ cast_from_int(1)) \= cast_from_int(0).
+
+%---------------------------------------------------------------------------%
+
+uint16_to_doc(X) = str(string.uint16_to_string(X)).
+
+%---------------------------------------------------------------------------%
+:- end_module uint16.
+%---------------------------------------------------------------------------%
diff --git a/library/uint32.m b/library/uint32.m
index 4409db83a..7eb1dbd8e 100644
--- a/library/uint32.m
+++ b/library/uint32.m
@@ -5,16 +5,381 @@
  % This file may only be copied under the terms of the GNU Library General
  % Public License - see the file COPYING.LIB in the Mercury distribution.
  %---------------------------------------------------------------------------%
+%
+% File: uint32.m
+% Main author: juliensf
+% Stability: low.
+%
+% Predicates and functions for dealing with unsigned 32-bit integer numbers.
+%
+%---------------------------------------------------------------------------%

  :- module uint32.
  :- interface.

-    % uint32s are NYI -- this module is just a placeholder for their
-    % library support.
+:- import_module pretty_printer.
+
+%---------------------------------------------------------------------------%
+
+    % from_int(I, U32):
+    % Convert an int into a uint32.
+    % Fails if I is not in [0, 2147483647].
+    %
+:- pred from_int(int::in, uint32::out) is semidet.
+
+:- func det_from_int(int) = uint32.
+
+:- func cast_from_int(int) = uint32.
+
+:- func cast_to_int(uint32) = int.
+
+    % Less than.
+    %
+:- pred (uint32::in) < (uint32::in) is semidet.
+
+    % Greater than.
+    %
+:- pred (uint32::in) > (uint32::in) is semidet.
+
+    % Less than or equal.
+    %
+:- pred (uint32::in) =< (uint32::in) is semidet.
+
+    % Greater than or equal.
+    %
+:- pred (uint32::in) >= (uint32::in) is semidet.
+
+    % Addition.
+    %
+:- func uint32 + uint32 = uint32.
+:- mode in   + in  = uo is det.
+:- mode uo   + in  = in is det.
+:- mode in   + uo  = in is det.
+
+:- func plus(uint32, uint32) = uint32.
+
+    % Subtraction.
+    %
+:- func uint32 - uint32 = uint32.
+:- mode in   - in   = uo is det.
+:- mode uo   - in   = in is det.
+:- mode in   - uo   = in is det.
+
+:- func minus(uint32, uint32) = uint32.
+
+    % Multiplication.
+    %
+:- func (uint32::in) * (uint32::in) = (uint32::uo) is det.
+:- func times(uint32, uint32) = uint32.
+
+    % Maximum.
+    %
+:- func max(uint32, uint32) = uint32.
+
+    % Minimum.
+    %
+:- func min(uint32, uint32) = uint32.
+
+    % Truncating integer division.
+    %
+    % Throws a `math.domain_error' exception if the right operand is zero.
+    %
+:- func (uint32::in) div (uint32::in) = (uint32::uo) is det.
+
+    % Truncating integer division.
+    %
+    % Throws a `math.domain_error' exception if the right operand is zero.
+    %
+:- func (uint32::in) // (uint32::in) = (uint32::uo) is det.
+
+    % (/)/2 is a synonym for (//)/2.
+    %
+:- func (uint32::in) / (uint32::in) = (uint32::uo) is det.
+
+    % unchecked_quotient(X, Y) is the same as X // Y, but the behaviour
+    % is undefined if the right operand is zero.
+    %
+:- func unchecked_quotient(uint32::in, uint32::in) = (uint32::uo) is det.
+
+    % Modulus.
+    % X mod Y = X - (X div Y) * Y
+    %
+    % Throws a `math.domain_error' exception if the right operand is zero.
+    %
+:- func (uint32::in) mod (uint32::in) = (uint32::uo) is det.
+
+    % Remainder.
+    % X rem Y = X - (X // Y) * Y.
+    %
+    % Throws a `math.domain_error/` exception if the right operand is zero.
+    %
+:- func (uint32::in) rem (uint32::in) = (uint32::uo) is det.
+
+    % unchecked_rem(X, Y) is the same as X rem Y, but the behaviour is
+    % undefined if the right operand is zero.
+    %
+:- func unchecked_rem(uint32::in, uint32::in) = (uint32::uo) is det.
+
+    % Left shift.
+    % X << Y returns X "left shifted" by Y bits.
+    % The bit positions vacated by the shift are filled by zeros.
+    % Throws an exception if Y is not in [0, 32).
+    %
+:- func (uint32::in) << (int::in) = (uint32::uo) is det.
+
+    % unchecked_lift_shift(X, Y) is the same as X << Y except that the
+    % behaviour is undefined if Y is not in [0, 32).
+    % It will typically be be implemented more efficiently than X << Y.
+    %
+:- func unchecked_left_shift(uint32::in, int::in) = (uint32::uo) is det.
+
+    % Right shift.
+    % X >> Y returns X "right shifted" by Y bits.
+    % The bit positions vacated by the shift are filled by zeros.
+    % Throws an exception if Y is not in [0, 32).
+    %
+:- func (uint32::in) >> (int::in) = (uint32::uo) is det.
+
+    % unchecked_right_shift(X, Y) is the same as X >> Y except that the
+    % behaviour is undefined if Y is not in [0, 32).
+    % It will typically be implemented more efficiently than X >> Y.
+    %
+:- func unchecked_right_shift(uint32::in, int::in) = (uint32::uo) is det.
+
+    % even(X) is equivalent to (X mod 2 = 0).
+    %
+:- pred even(uint32::in) is semidet.
+
+    % odd(X) is equivalent to (not even(X)), i.e. (X mod 2 = 1).
+    %
+:- pred odd(uint32::in) is semidet.
+
+    % Bitwise and.
+    %
+:- func (uint32::in) /\ (uint32::in) = (uint32::uo) is det.
+
+    % Bitwise or.
      %
-:- type placeholder_uint32 ---> placeholder_uint32.
+:- func (uint32::in) \/ (uint32::in) = (uint32::uo) is det.
+
+    % Bitwise exclusive or (xor).
+    %
+:- func xor(uint32, uint32) = uint32.
+:- mode xor(in, in) = uo is det.
+:- mode xor(in, uo) = in is det.
+:- mode xor(uo, in) = in is det.
+
+    % Bitwise complement.
+    %
+:- func \ (uint32::in) = (uint32::uo) is det.
+
+:- func max_uint32 = uint32.
+
+    % Convert a uint32 to a pretty_printer.doc for formatting.
+    %
+:- func uint32_to_doc(uint32) = pretty_printer.doc.

  %---------------------------------------------------------------------------%
-:- end_module uint32.
  %---------------------------------------------------------------------------%

+:- implementation.
+
+:- import_module exception.
+:- import_module math.
+:- import_module require.
+:- import_module string.
+:- import_module uint.
+
+%---------------------------------------------------------------------------%
+
+:- pragma foreign_proc("C",
+    from_int(I::in, U::out),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
+"
+    if (I < 0) {
+        SUCCESS_INDICATOR = MR_FALSE;
+    } else if (I > (MR_Integer) INT32_MAX) {
+        SUCCESS_INDICATOR = MR_FALSE;
+    } else {
+        U = (uint32_t) I;
+        SUCCESS_INDICATOR = MR_TRUE;
+    }
+").
+
+:- pragma foreign_proc("C#",
+    from_int(I::in, U::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    U = (uint) I;
+    SUCCESS_INDICATOR = (I < 0) ? false : true;
+").
+
+:- pragma foreign_proc("Java",
+    from_int(I::in, U::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    U = I;
+    SUCCESS_INDICATOR = (I < 0) ? false : true;
+").
+
+:- pragma no_determinism_warning(from_int/2).
+from_int(_, _) :-
+    sorry($module, "uint32.from_int NYI for Erlang").
+
+det_from_int(I) = U :-
+    ( if from_int(I, U0)
+    then U = U0
+    else error("uint32.det_from_int: cannot convert int to uint32")
+    ).
+
+%---------------------------------------------------------------------------%
+
+:- pragma foreign_proc("C",
+    cast_from_int(I::in) = (U32::out),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
+        does_not_affect_liveness],
+"
+    U32 = (uint32_t) I;
+").
+
+:- pragma foreign_proc("C#",
+    cast_from_int(I::in) = (U32::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    U32 = (uint) I;
+").
+
+:- pragma foreign_proc("Java",
+    cast_from_int(I::in) = (U32::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    U32 = I;
+").
+
+:- pragma no_determinism_warning(cast_from_int/1).
+cast_from_int(_) = _ :-
+    sorry($module, "uint32.cast_from_int/1 NYI for Erlang").
+
+%---------------------------------------------------------------------------%
+
+:- pragma foreign_proc("C",
+    cast_to_int(U32::in) = (I::out),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
+        does_not_affect_liveness],
+"
+    I = (MR_Integer) U32;
+").
+
+:- pragma foreign_proc("C#",
+    cast_to_int(U32::in) = (I::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I = (int) U32;
+").
+
+:- pragma foreign_proc("Java",
+    cast_to_int(U32::in) = (I::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I = U32;
+").
+
+:- pragma no_determinism_warning(cast_to_int/1).
+cast_to_int(_) = _ :-
+    sorry($module, "uint32.cast_to_int/1 NYI for Erlang").
+
+%---------------------------------------------------------------------------%
+
+X div Y = X // Y.
+
+:- pragma inline('//'/2).
+X // Y = Div :-
+    ( if Y = cast_from_int(0) then
+        throw(math.domain_error("uint32.'//': division by zero"))
+    else
+        Div = unchecked_quotient(X, Y)
+    ).
+
+:- pragma inline('/'/2).
+X / Y = X // Y.
+
+X mod Y = X rem Y.
+
+:- pragma inline(rem/2).
+X rem Y = Rem :-
+    ( if Y = cast_from_int(0) then
+        throw(math.domain_error("uint32.rem: division by zero"))
+    else
+        Rem = unchecked_rem(X, Y)
+    ).
+
+%---------------------------------------------------------------------------%
+
+X << Y = Result :-
+    ( if cast_from_int(Y) < 32u then
+        Result = unchecked_left_shift(X, Y)
+    else
+        Msg = "uint32.(<<): second operand is out of range",
+        throw(math.domain_error(Msg))
+    ).
+
+X >> Y = Result :-
+    ( if cast_from_int(Y) < 32u then
+        Result = unchecked_right_shift(X, Y)
+    else
+        Msg = "uint32.(>>): second operand is out of range",
+        throw(math.domain_error(Msg))
+    ).
+
+%---------------------------------------------------------------------------%
+
+max(X, Y) =
+    ( if X > Y then X else Y ).
+
+min(X, Y) =
+    ( if X < Y then X else Y ).
+
+%---------------------------------------------------------------------------%
+
+:- pragma inline(even/1).
+even(X) :-
+    (X /\ cast_from_int(1)) = cast_from_int(0).
+
+:- pragma inline(odd/1).
+odd(X) :-
+    (X /\ cast_from_int(1)) \= cast_from_int(0).
+
+%---------------------------------------------------------------------------%
+
+:- pragma foreign_proc("C",
+    max_uint32 = (U::out),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
+"
+    U = UINT32_MAX;
+").
+
+:- pragma foreign_proc("C#",
+    max_uint32 = (U::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    U = uint.MaxValue;
+").
+
+:- pragma foreign_proc("Java",
+    max_uint32 = (U::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    U = 0xffffffff;
+").
+
+:- pragma no_determinism_warning(max_uint32/0).
+max_uint32 = _ :-
+    sorry($module, "uint32.max_uint32/0 NYI for Erlang").
+
+%---------------------------------------------------------------------------%
+
+uint32_to_doc(X) = str(string.uint32_to_string(X)).
+
+%---------------------------------------------------------------------------%
+:- end_module uint32.
+%---------------------------------------------------------------------------%
diff --git a/library/uint8.m b/library/uint8.m
index d640fb587..e3d0c055f 100644
--- a/library/uint8.m
+++ b/library/uint8.m
@@ -5,16 +5,327 @@
  % This file may only be copied under the terms of the GNU Library General
  % Public License - see the file COPYING.LIB in the Mercury distribution.
  %---------------------------------------------------------------------------%
+%
+% File: uint8.m
+% Main author: juliensf
+% Stability: low.
+%
+% Predicates and functions for dealing with unsigned 8-bit integer numbers.
+%
+%---------------------------------------------------------------------------%

  :- module uint8.
  :- interface.

-    % uint8s are NYI -- this module is just a placeholder for their
-    % library support.
+:- import_module pretty_printer.
+
+%---------------------------------------------------------------------------%
+
+    % from_int(I, U8):
+    % Convert an int to a uint8.
+    % Fails if I is not in [0, 255].
+    %
+:- pred from_int(int::in, uint8::out) is semidet.
+
+    % As above, but throw an exception instead of failing.
+    %
+:- func det_from_int(int) = uint8.
+
+:- func cast_from_int(int) = uint8.
+
+:- func to_int(uint8) = int.
+
+    % Less than.
+    %
+:- pred (uint8::in) < (uint8::in) is semidet.
+
+    % Greater than.
+    %
+:- pred (uint8::in) > (uint8::in) is semidet.
+
+    % Less than or equal.
+    %
+:- pred (uint8::in) =< (uint8::in) is semidet.
+
+    % Greater than or equal.
+    %
+:- pred (uint8::in) >= (uint8::in) is semidet.
+
+    % Addition.
+    %
+:- func uint8 + uint8 = uint8.
+:- mode in   + in  = uo is det.
+:- mode uo   + in  = in is det.
+:- mode in   + uo  = in is det.
+
+:- func plus(uint8, uint8) = uint8.
+
+    % Subtraction.
+    %
+:- func uint8 - uint8 = uint8.
+:- mode in   - in   = uo is det.
+:- mode uo   - in   = in is det.
+:- mode in   - uo   = in is det.
+
+:- func minus(uint8, uint8) = uint8.
+
+    % Multiplication.
+    %
+:- func (uint8::in) * (uint8::in) = (uint8::uo) is det.
+:- func times(uint8, uint8) = uint8.
+
+    % Maximum.
+    %
+:- func max(uint8, uint8) = uint8.
+
+    % Minimum.
+    %
+:- func min(uint8, uint8) = uint8.
+
+    % Truncating integer division.
+    %
+    % Throws a `math.domain_error' exception if the right operand is zero.
+    %
+:- func (uint8::in) div (uint8::in) = (uint8::uo) is det.
+
+    % Truncating integer division.
+    %
+    % Throws a `math.domain_error' exception if the right operand is zero.
+    %
+:- func (uint8::in) // (uint8::in) = (uint8::uo) is det.
+
+    % (/)/2 is a synonym for (//)/2.
+    %
+:- func (uint8::in) / (uint8::in) = (uint8::uo) is det.
+
+    % unchecked_quotient(X, Y) is the same as X // Y, but the behaviour
+    % is undefined if the right operand is zero.
+    %
+:- func unchecked_quotient(uint8::in, uint8::in) = (uint8::uo) is det.
+
+    % Modulus.
+    % X mod Y = X - (X div Y) * Y
+    %
+    % Throws a `math.domain_error' exception if the right operand is zero.
+    %
+:- func (uint8::in) mod (uint8::in) = (uint8::uo) is det.
+
+    % Remainder.
+    % X rem Y = X - (X // Y) * Y.
+    %
+    % Throws a `math.domain_error/` exception if the right operand is zero.
+    %
+:- func (uint8::in) rem (uint8::in) = (uint8::uo) is det.
+
+    % unchecked_rem(X, Y) is the same as X rem Y, but the behaviour is
+    % undefined if the right operand is zero.
+    %
+:- func unchecked_rem(uint8::in, uint8::in) = (uint8::uo) is det.
+
+    % Left shift.
+    % X << Y returns X "left shifted" by Y bits.
+    % The bit positions vacated by the shift are filled by zeros.
+    % Throws an exception if Y is not in [0, 8).
+    %
+:- func (uint8::in) << (int::in) = (uint8::uo) is det.
+
+    % unchecked_lift_shift(X, Y) is the same as X << Y except that the
+    % behaviour is undefined if Y is not in [0, 8).
+    % It will typically be be implemented more efficiently than X << Y.
+    %
+:- func unchecked_left_shift(uint8::in, int::in) = (uint8::uo) is det.
+
+    % Right shift.
+    % X >> Y returns X "right shifted" by Y bits.
+    % The bit positions vacated by the shift are filled by zeros.
+    % Throws an exception if Y is not in [0, 8).
+    %
+:- func (uint8::in) >> (int::in) = (uint8::uo) is det.
+
+    % unchecked_right_shift(X, Y) is the same as X >> Y except that the
+    % behaviour is undefined if Y is not in [0, 8).
+    % It will typically be implemented more efficiently than X >> Y.
+    %
+:- func unchecked_right_shift(uint8::in, int::in) = (uint8::uo) is det.
+
+    % even(X) is equivalent to (X mod 2i8 = 0i8).
      %
-:- type placeholder_uint8 ---> placeholder_uint8.
+:- pred even(uint8::in) is semidet.
+
+    % odd(X) is equivalent to (not even(X)), i.e. (X mod 2i8 = 1i8).
+    %
+:- pred odd(uint8::in) is semidet.
+
+    % Bitwise and.
+    %
+:- func (uint8::in) /\ (uint8::in) = (uint8::uo) is det.
+
+    % Bitwise or.
+    %
+:- func (uint8::in) \/ (uint8::in) = (uint8::uo) is det.
+
+    % Bitwise exclusive or (xor).
+    %
+:- func xor(uint8, uint8) = uint8.
+:- mode xor(in, in) = uo is det.
+:- mode xor(in, uo) = in is det.
+:- mode xor(uo, in) = in is det.
+
+    % Bitwise complement.
+    %
+:- func \ (uint8::in) = (uint8::uo) is det.
+
+    % Convert an uint8 to a pretty_printer.doc for formatting.
+    %
+:- func uint8_to_doc(uint8) = pretty_printer.doc.

  %---------------------------------------------------------------------------%
-:- end_module uint8.
  %---------------------------------------------------------------------------%

+:- implementation.
+
+:- import_module exception.
+:- import_module int.
+:- import_module math.
+:- import_module require.
+:- import_module string.
+:- import_module uint.
+
+%---------------------------------------------------------------------------%
+
+from_int(I, U8) :-
+    I >= 0,
+    I =< 255,
+    U8 = cast_from_int(I).
+
+det_from_int(I) = U8 :-
+    ( if from_int(I, U8Prime) then
+        U8 = U8Prime
+    else
+        error("uint8.det_from_int: cannot convert int to uint8")
+    ).
+
+%---------------------------------------------------------------------------%
+
+:- pragma foreign_proc("C",
+    cast_from_int(I::in) = (U8::out),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
+        does_not_affect_liveness],
+"
+    U8 = (uint8_t) I;
+").
+
+:- pragma foreign_proc("C#",
+    cast_from_int(I::in) = (U8::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    U8 = (byte) I;
+").
+
+:- pragma foreign_proc("Java",
+    cast_from_int(I::in) = (U8::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    U8 = (byte) I;
+").
+
+:- pragma no_determinism_warning(cast_from_int/1).
+cast_from_int(_) = _ :-
+    sorry($module, "uint8.cast_from_int/1 NYI for Erlang").
+
+%---------------------------------------------------------------------------%
+
+:- pragma foreign_proc("C",
+    to_int(U8::in) = (I::out),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
+        does_not_affect_liveness],
+"
+    I = U8;
+").
+
+:- pragma foreign_proc("C#",
+    to_int(U8::in) = (I::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I = U8;
+").
+
+:- pragma foreign_proc("Java",
+    to_int(U8::in) = (I::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I = U8 & 0xff;
+").
+
+:- pragma no_determinism_warning(to_int/1).
+to_int(_) = _ :-
+    sorry($module, "uint8.to_int/1 NYI for Erlang").
+
+%---------------------------------------------------------------------------%
+
+X div Y = X // Y.
+
+:- pragma inline('//'/2).
+X // Y = Div :-
+    ( if Y = cast_from_int(0) then
+        throw(math.domain_error("uint.'//': division by zero"))
+    else
+        Div = unchecked_quotient(X, Y)
+    ).
+
+:- pragma inline('/'/2).
+X / Y = X // Y.
+
+X mod Y = X rem Y.
+
+:- pragma inline(rem/2).
+X rem Y = Rem :-
+    ( if Y = cast_from_int(0) then
+        throw(math.domain_error("uint8.rem: division by zero"))
+    else
+        Rem = unchecked_rem(X, Y)
+    ).
+
+%---------------------------------------------------------------------------%
+
+X << Y = Result :-
+    ( if cast_from_int(Y) < 8u then
+        Result = unchecked_left_shift(X, Y)
+    else
+        Msg = "uint8.(<<): second operand is out of range",
+        throw(math.domain_error(Msg))
+    ).
+
+X >> Y = Result :-
+    ( if cast_from_int(Y) < 8u then
+        Result = unchecked_right_shift(X, Y)
+    else
+        Msg = "uint8.(>>): second operand is out of range",
+        throw(math.domain_error(Msg))
+    ).
+
+%---------------------------------------------------------------------------%
+
+max(X, Y) =
+    ( if X > Y then X else Y ).
+
+min(X, Y) =
+    ( if X < Y then X else Y ).
+
+%---------------------------------------------------------------------------%
+
+:- pragma inline(even/1).
+even(X) :-
+    (X /\ cast_from_int(1)) = cast_from_int(0).
+
+:- pragma inline(odd/1).
+odd(X) :-
+    (X /\ cast_from_int(1)) \= cast_from_int(0).
+
+%---------------------------------------------------------------------------%
+
+uint8_to_doc(X) = str(string.uint8_to_string(X)).
+
+%---------------------------------------------------------------------------%
+:- end_module uint8.
+%---------------------------------------------------------------------------%
diff --git a/tests/invalid/invalid_int.err_exp2 b/tests/invalid/invalid_int.err_exp2
index ee90634fa..8985b3922 100644
--- a/tests/invalid/invalid_int.err_exp2
+++ b/tests/invalid/invalid_int.err_exp2
@@ -1,9 +1,29 @@
  invalid_int.m:019: Error: the integer literal
  invalid_int.m:019:   `0b10000000000000000000000000000000000000000000000000000000000000000'
-invalid_int.m:019:   is too big to be represented on this machine.
-invalid_int.m:024: Error: the integer literal `0o2000000000000000000000' is too
-invalid_int.m:024:   big to be represented on this machine.
-invalid_int.m:030: Error: the integer literal `0x10000000000000000' is too big
-invalid_int.m:030:   to be represented on this machine.
-invalid_int.m:035: Error: the integer literal `9223372036854775808' is too big
-invalid_int.m:035:   to be represented on this machine.
+invalid_int.m:019:   is outside the range of that type.
+invalid_int.m:024: Error: the integer literal `0o2000000000000000000000' is
+invalid_int.m:024:   outside the range of that type.
+invalid_int.m:030: Error: the integer literal `0x10000000000000000' is outside
+invalid_int.m:030:   the range of that type.
+invalid_int.m:035: Error: the integer literal `9223372036854775808' is outside
+invalid_int.m:035:   the range of that type.
+invalid_int.m:040: Error: the 8-bit integer literal `-129i8' is outside the
+invalid_int.m:040:   range of that type.
+invalid_int.m:043: Error: the 8-bit integer literal `128i8' is outside the
+invalid_int.m:043:   range of that type.
+invalid_int.m:048: Error: the unsigned 8-bit integer literal `256u8' is outside
+invalid_int.m:048:   the range of that type.
+invalid_int.m:049: Error: the unsigned 8-bit integer literal `257u8' is outside
+invalid_int.m:049:   the range of that type.
+invalid_int.m:054: Error: the 16-bit integer literal `-32769i16' is outside the
+invalid_int.m:054:   range of that type.
+invalid_int.m:057: Error: the 16-bit integer literal `32768i16' is outside the
+invalid_int.m:057:   range of that type.
+invalid_int.m:063: Error: the unsigned 16-bit integer literal `65536u16' is
+invalid_int.m:063:   outside the range of that type.
+invalid_int.m:068: Error: the 32-bit integer literal `-2147483649i32' is
+invalid_int.m:068:   outside the range of that type.
+invalid_int.m:071: Error: the 32-bit integer literal `2147483648i32' is outside
+invalid_int.m:071:   the range of that type.
+invalid_int.m:077: Error: the unsigned 32-bit integer literal `4294967296u32'
+invalid_int.m:077:   is outside the range of that type.
diff --git a/tests/invalid/invalid_int.m b/tests/invalid/invalid_int.m
index 8a99191cf..88ecdd502 100644
--- a/tests/invalid/invalid_int.m
+++ b/tests/invalid/invalid_int.m
@@ -34,4 +34,46 @@ main(!IO) :-
          9223372036854775807,
          9223372036854775808
      },
-    io.write(X, !IO).
+    io.write(X, !IO),
+
+    I8 = {
+        -129_i8,
+        -128_i8,
+         127_i8,
+         128_i8
+    },
+    io.write(I8, !IO),
+
+    U8 = {
+        256_u8,
+        257_u8
+    },
+    io.write(U8, !IO),
+
+    I16 = {
+        -32_769_i16,
+        -32_768_i16,
+         32_767_i16,
+         32_768_i16
+    },
+    io.write(I16, !IO),
+
+    U16 = {
+         65_535_u16,
+         65_536_u16
+    },
+    io.write(U16, !IO),
+
+    I32 = {
+        -2_147_483_649_i32,
+        -2_147_483_648_i32,
+         2_147_483_647_i32,
+         2_147_483_648_i32
+    },
+    io.write(I32, !IO),
+
+    U32 = {
+         4_294_967_295_u32,
+         4_294_967_296_u32
+    },
+    io.write(U32, !IO).


More information about the reviews mailing list