public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* proposal to make SIZE_TYPE more flexible
@ 2013-10-30  4:28 DJ Delorie
  2013-10-30 15:53 ` Joseph S. Myers
  0 siblings, 1 reply; 47+ messages in thread
From: DJ Delorie @ 2013-10-30  4:28 UTC (permalink / raw)
  To: gcc


There are a couple of places in gcc where wierd-sized pointers are an
issue.  While you can use a partial-integer mode for pointers, the
pointer *math* is still done in standard C types, which usually don't
match the modes of pointers and often result in suboptimal code.

My proposal is to allow the target to define its own type for
pointers, sizeof_t, and ptrdiff_t to use, so that gcc can adapt to
weird pointer sizes instead of the target having to use power-of-two
pointer math.

This means the target would somehow have to register its new types
(int20_t and uint20_t in the MSP430 case, for example), as well as
specify that type to the rest of gcc.  There are some problems with
the naive approach, though, and the changes are somewhat pervasive.

So my question is, would this approach be acceptable?  Most of the
cases where new code would be added, have gcc_unreachable() at the
moment anyway.

Specific issues follow...

SIZE_TYPE is used...

	tree.c: build_common_tree_nodes()
		compares against fixed strings; if no match it
		gcc_unreachable()'s - instead, look up type in
		language core.

	c-family/c-common.c
		just makes a string macro, it's up to the target to
		provide a legitimate value for it.

	lto/lto-lang.c
		compares against fixed strings to define THREE related
		types, including intmax_type_node and
		uintmax_type_node.  IMHO it should not be using
		pointer sizes to determine integer sizes.

PTRDIFF_TYPE is used...

	c-family/c-common.c
	fortran/iso-c-binding.def
	fortran/trans-types.c

		These all use lookups; however fortran's
		get_typenode_from_name only supports "standard" type
		names.

POINTER_SIZE is used...

	I have found in the past that gcc has issues if POINTER_SIZE
	is not a power of two.  IIRC BLKmode was used to copy pointer
	values.  Other examples:

  assemble_align (POINTER_SIZE);

	can't align to non-power-of-two bits

   assemble_integer (XEXP (DECL_RTL (src), 0),
	             POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);

	need to round up, not truncate

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-10-30  4:28 proposal to make SIZE_TYPE more flexible DJ Delorie
@ 2013-10-30 15:53 ` Joseph S. Myers
  2013-10-30 19:18   ` DJ Delorie
  0 siblings, 1 reply; 47+ messages in thread
From: Joseph S. Myers @ 2013-10-30 15:53 UTC (permalink / raw)
  To: DJ Delorie; +Cc: gcc

On Wed, 30 Oct 2013, DJ Delorie wrote:

> My proposal is to allow the target to define its own type for
> pointers, sizeof_t, and ptrdiff_t to use, so that gcc can adapt to
> weird pointer sizes instead of the target having to use power-of-two
> pointer math.
> 
> This means the target would somehow have to register its new types
> (int20_t and uint20_t in the MSP430 case, for example), as well as
> specify that type to the rest of gcc.  There are some problems with
> the naive approach, though, and the changes are somewhat pervasive.

It is a deficiency that SIZE_TYPE is defined to be a string at all (and 
likewise for all the other target macros for standard typedefs including 
all those for <stdint.h>).  Separately, it's a deficiency that these 
things are target macros rather than target hooks.

I've previously suggested making these into enum values instead of strings 
(probably first making the target macros into such values, then later 
converting them into hooks that return such values).  Specifically, I 
suggested that the values should come from enum integer_type_kind, as an 
existing enumeration of relevant standard integer types, and in 
<http://gcc.gnu.org/ml/gcc-patches/2010-11/msg02900.html> suggested a 
possible division into hooks.  The thread starting at 
<http://gcc.gnu.org/ml/gcc-patches/2010-12/msg00964.html> had such a 
conversion for stdint.h macros into enum-valued macros.

This doesn't help you with your 20-bit types.  I don't think the principle 
is wrong, though; it's just that the integer_type_kind enumeration should 
be extensible by targets in some way.  Instead of having references to 
int128 hardcoded in various places in the core compiler, the information 
about the existence of such a type should go in some config/ file or files 
only used by those targets that actually support such a type for at least 
some multilibs (64-bit targets, typically).  Regarding that, see various 
messages of mine to gcc-patches on 1 July 2011 in response to Bernd's 
40-bit integer support changes.  All the generic fixes (making 
FRACTIONAL_INT_MODEs work more reliably) went in, but not the changes that 
would have hardcoded references to 40-bit types in various places in the 
target-independent compiler.  Instead of having an __int128 keyword 
(target-independent) targets would be able to define a set of N for which 
there are __intN keywords and for which everything handling __int128 will 
equally handle __intN.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-10-30 15:53 ` Joseph S. Myers
@ 2013-10-30 19:18   ` DJ Delorie
  2013-10-30 20:49     ` Joseph S. Myers
  0 siblings, 1 reply; 47+ messages in thread
From: DJ Delorie @ 2013-10-30 19:18 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: gcc


> It is a deficiency that SIZE_TYPE is defined to be a string at all (and 
> likewise for all the other target macros for standard typedefs including 
> all those for <stdint.h>).  Separately, it's a deficiency that these 
> things are target macros rather than target hooks.

My thought was that there'd be a set of target hooks that returned a
TREE for various types.  But as an interim solution, the checks that
use strcmp() should fail into a type lookup-by-name.  I.e. replace the
gcc_unreachables with expensive table lookups.

I think there's an advantage in newlib to having a macro that expands
to the type-as-a-string needed for various types.  Of course, if gcc
had a typedef for those types, that would be better, but slightly
harder to autodetect.

> Instead of having an __int128 keyword (target-independent) targets
> would be able to define a set of N for which there are __intN
> keywords and for which everything handling __int128 will equally
> handle __intN.

That sounds great, and would elide the problem of a target needing to
register their own types for those.  I hadn't considered simplifying
the intN_t problem, since you *can* register custom types, I was
mostly just thinking about how to *use* those types for size_t et al.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-10-30 19:18   ` DJ Delorie
@ 2013-10-30 20:49     ` Joseph S. Myers
  2013-10-30 22:19       ` DJ Delorie
  0 siblings, 1 reply; 47+ messages in thread
From: Joseph S. Myers @ 2013-10-30 20:49 UTC (permalink / raw)
  To: DJ Delorie; +Cc: gcc

On Wed, 30 Oct 2013, DJ Delorie wrote:

> 
> > It is a deficiency that SIZE_TYPE is defined to be a string at all (and 
> > likewise for all the other target macros for standard typedefs including 
> > all those for <stdint.h>).  Separately, it's a deficiency that these 
> > things are target macros rather than target hooks.
> 
> My thought was that there'd be a set of target hooks that returned a
> TREE for various types.  But as an interim solution, the checks that
> use strcmp() should fail into a type lookup-by-name.  I.e. replace the
> gcc_unreachables with expensive table lookups.

My reasoning is:

* You need to have strings as the expansions of macros such as 
__SIZE_TYPE__.

* You also need to have trees for the types, including in places such as 
the Fortran front end where converting a C type name into a tree may not 
be particularly convenient.

* So the hook should return a type identifier that can be converted both 
to strings where those are needed and meaningful (in c-cppbuiltin.c) and 
into trees where those are needed (somewhere in the language-independent 
compiler).  enum integer_type_kind is, if extended in some way to cover 
target-specific types, pretty much exactly what's wanted here.

* If you do that, you eliminate the fragility of multiple orderings of 
type specifiers being valid in C but the exact ordering "long unsigned 
int" being needed in SIZE_TYPE.  I hope it might be possible to eliminate 
the long sequence of record_builtin_type calls with such names, or at 
least simplify it, given some investigation of how they are used - there's 
a comment "Define `int' and `char' first so that dbx will output them 
first.", but since some of the calls use NULL as a type name they can't 
all be needed in order to provide names for debug info.

> > Instead of having an __int128 keyword (target-independent) targets
> > would be able to define a set of N for which there are __intN
> > keywords and for which everything handling __int128 will equally
> > handle __intN.
> 
> That sounds great, and would elide the problem of a target needing to
> register their own types for those.  I hadn't considered simplifying
> the intN_t problem, since you *can* register custom types, I was
> mostly just thinking about how to *use* those types for size_t et al.

Having a keyword is better than having a built-in typedef registered by 
the back end (or by c-common.c, in the case of __int128_t and 
__uint128_t), because a keyword can be used together with "_Complex" and 
"unsigned" in the same ways you could use "int" or "long", but you can't 
use a typedef with "_Complex" or "unsigned".

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-10-30 20:49     ` Joseph S. Myers
@ 2013-10-30 22:19       ` DJ Delorie
  2013-10-30 22:51         ` Joseph S. Myers
  0 siblings, 1 reply; 47+ messages in thread
From: DJ Delorie @ 2013-10-30 22:19 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: gcc


So, given all that, is there any way to add the "target-specific
size_t" portion without waiting for-who-knows-how-long for the intN_t
and enum-size-type projects to finish?  Some form of interim API that
we can put in, so that we can start working on finding all the
assumptions about size_t, while waiting for the rest to finish?

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-10-30 22:19       ` DJ Delorie
@ 2013-10-30 22:51         ` Joseph S. Myers
  2013-11-14  1:58           ` DJ Delorie
  0 siblings, 1 reply; 47+ messages in thread
From: Joseph S. Myers @ 2013-10-30 22:51 UTC (permalink / raw)
  To: DJ Delorie; +Cc: gcc

On Wed, 30 Oct 2013, DJ Delorie wrote:

> So, given all that, is there any way to add the "target-specific
> size_t" portion without waiting for-who-knows-how-long for the intN_t
> and enum-size-type projects to finish?  Some form of interim API that
> we can put in, so that we can start working on finding all the
> assumptions about size_t, while waiting for the rest to finish?

I have no idea how ugly something supporting target-specific strings would 
be, since supporting such strings for these standard typedefs never seemed 
to be a direction we wanted to go in.

(Obviously it's possible to convert only a subset of macros to use enums 
rather than strings, or to be hooks rather than macros.)

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-10-30 22:51         ` Joseph S. Myers
@ 2013-11-14  1:58           ` DJ Delorie
  2013-11-14 13:26             ` Joseph S. Myers
  0 siblings, 1 reply; 47+ messages in thread
From: DJ Delorie @ 2013-11-14  1:58 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: gcc


> > So, given all that, is there any way to add the "target-specific
> > size_t" portion without waiting for-who-knows-how-long for the intN_t
> > and enum-size-type projects to finish?  Some form of interim API that
> > we can put in, so that we can start working on finding all the
> > assumptions about size_t, while waiting for the rest to finish?
> 
> I have no idea how ugly something supporting target-specific strings would 
> be, since supporting such strings for these standard typedefs never seemed 
> to be a direction we wanted to go in.

I tried to hack in support for intN_t in a backend, and it was a maze
of initialization sequence nightmares.  So I guess we need to do the
intN_t part first.  Is someone working on this?  If not, is there a
spec I could use to get started on it?

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-11-14  1:58           ` DJ Delorie
@ 2013-11-14 13:26             ` Joseph S. Myers
  2013-11-14 18:12               ` DJ Delorie
  2013-11-15 23:38               ` DJ Delorie
  0 siblings, 2 replies; 47+ messages in thread
From: Joseph S. Myers @ 2013-11-14 13:26 UTC (permalink / raw)
  To: DJ Delorie; +Cc: gcc

On Wed, 13 Nov 2013, DJ Delorie wrote:

> I tried to hack in support for intN_t in a backend, and it was a maze
> of initialization sequence nightmares.  So I guess we need to do the
> intN_t part first.  Is someone working on this?  If not, is there a
> spec I could use to get started on it?

Instead of a target-independent __int128 keyword, there would be a set 
(possibly empty) of __intN keywords, determined by a target hook.  
Everything handling __int128 would be updated to work with a 
target-determined set of types instead.

Preferably, the number of such keywords would be arbitrary (so I suppose 
there would be a single RID_INTN for them) - that seems cleaner than the 
system for address space keywords with a fixed block from RID_ADDR_SPACE_0 
to RID_ADDR_SPACE_15.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-11-14 13:26             ` Joseph S. Myers
@ 2013-11-14 18:12               ` DJ Delorie
  2013-11-14 18:37                 ` Joseph S. Myers
  2013-11-15 23:38               ` DJ Delorie
  1 sibling, 1 reply; 47+ messages in thread
From: DJ Delorie @ 2013-11-14 18:12 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: gcc


> Instead of a target-independent __int128 keyword, there would be a set 
> (possibly empty) of __intN keywords, determined by a target hook.  

Or *-modes.def ?

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-11-14 18:12               ` DJ Delorie
@ 2013-11-14 18:37                 ` Joseph S. Myers
  2013-11-14 18:48                   ` DJ Delorie
  0 siblings, 1 reply; 47+ messages in thread
From: Joseph S. Myers @ 2013-11-14 18:37 UTC (permalink / raw)
  To: DJ Delorie; +Cc: gcc

On Thu, 14 Nov 2013, DJ Delorie wrote:

> > Instead of a target-independent __int128 keyword, there would be a set 
> > (possibly empty) of __intN keywords, determined by a target hook.  
> 
> Or *-modes.def ?

That would be one possibility - if the idea is to define __intN for all 
integer modes not matching a standard type (and passing 
targetm.scalar_mode_supported_p), I advise posting details of what effect 
this would have for all targets so we can see how many such types would 
get added.

(I don't advise having __intN when there are matching standard integer 
types as that would introduce unnecessary complications regarding whether 
__intN is the same type, or a distinct one needing its own name mangling 
and rank for promotion.  Draft TS 18661-3 does have _Float32 etc. as 
always distinct types from float etc., but I don't see any use for that 
for integer types for now.)

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-11-14 18:37                 ` Joseph S. Myers
@ 2013-11-14 18:48                   ` DJ Delorie
  2013-11-14 21:40                     ` Joseph S. Myers
  0 siblings, 1 reply; 47+ messages in thread
From: DJ Delorie @ 2013-11-14 18:48 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: gcc


> That would be one possibility - if the idea is to define __intN for all 
> integer modes not matching a standard type (and passing 
> targetm.scalar_mode_supported_p), I advise posting details of what effect 
> this would have for all targets so we can see how many such types would 
> get added.

I was thinking of using the existing PARTIAL/FRACTIONAL_INT_MODE macros.

avr/avr-modes.def:FRACTIONAL_INT_MODE (PSI, 24, 3);
bfin/bfin-modes.def:PARTIAL_INT_MODE (DI, 40, PDI);
m32c/m32c-modes.def:PARTIAL_INT_MODE (SI, 24, PSI);
msp430/msp430-modes.def:PARTIAL_INT_MODE (SI, 20, PSI);
rs6000/rs6000-modes.def:PARTIAL_INT_MODE (TI, 128, PTI);
sh/sh-modes.def:PARTIAL_INT_MODE (SI, 22, PSI);
sh/sh-modes.def:PARTIAL_INT_MODE (DI, 64, PDI);

I suspect we'd have to filter out the power-of-two PSI ones though, leaving:

avr/avr-modes.def:FRACTIONAL_INT_MODE (PSI, 24, 3);
bfin/bfin-modes.def:PARTIAL_INT_MODE (DI, 40, PDI);
m32c/m32c-modes.def:PARTIAL_INT_MODE (SI, 24, PSI);
msp430/msp430-modes.def:PARTIAL_INT_MODE (SI, 20, PSI);
sh/sh-modes.def:PARTIAL_INT_MODE (SI, 22, PSI);

I'm assuming we need a mode to go with any type we create?  Otherwise,
we could add a FRACTIONAL_INT_TYPE(wrapper-mode, bits) macro to add
yet more.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-11-14 18:48                   ` DJ Delorie
@ 2013-11-14 21:40                     ` Joseph S. Myers
  2013-11-15  1:47                       ` DJ Delorie
  0 siblings, 1 reply; 47+ messages in thread
From: Joseph S. Myers @ 2013-11-14 21:40 UTC (permalink / raw)
  To: DJ Delorie; +Cc: gcc

On Thu, 14 Nov 2013, DJ Delorie wrote:

> > That would be one possibility - if the idea is to define __intN for all 
> > integer modes not matching a standard type (and passing 
> > targetm.scalar_mode_supported_p), I advise posting details of what effect 
> > this would have for all targets so we can see how many such types would 
> > get added.
> 
> I was thinking of using the existing PARTIAL/FRACTIONAL_INT_MODE macros.

FRACTIONAL_INT_MODEs probably work more reliably as integer types than 
PARTIAL_INT_MODEs, given Bernd's fixes a couple of years ago (I'm not 
clear on why we actually need both).  But I was imagining something that 
would cover TImode as well, so replacing the existing logic around 
__int128.

> I suspect we'd have to filter out the power-of-two PSI ones though, leaving:

I think the filter should be based on being the same number of bits as a 
standard type (char / short / int / long / long long) rather than being 
power-of-two.

> I'm assuming we need a mode to go with any type we create?  Otherwise,

Actually, no - bit-fields have funny-sized types that work without their 
own modes (they should automatically get the next larger integer mode, 
with padding bits).  If you don't have a mode, presumably arithmetic on a 
larger mode and masking the results is the best way of doing arithmetic on 
your special type.  But this may not be well-optimized (as far as I know 
the lowering of such operations to use modes the target supports still 
takes place entirely at RTL expansion time, when it might be better to do 
it on GIMPLE and let GIMPLE optimizers work on the larger-type 
arithmetic).

If you do want types without corresponding modes, that goes back to having 
a hook to list the relevant type sizes.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-11-14 21:40                     ` Joseph S. Myers
@ 2013-11-15  1:47                       ` DJ Delorie
  2013-11-15  1:56                         ` Joseph S. Myers
  0 siblings, 1 reply; 47+ messages in thread
From: DJ Delorie @ 2013-11-15  1:47 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: gcc


> If you do want types without corresponding modes, that goes back to
> having a hook to list the relevant type sizes.

Perhaps a FRACTIONAL_INT_TYPE() macro then, for when there's no
machine mode to go with it?  Although I'm struggling to imagine a case
where a target would need to define a bit-sized type that doesn't
correspond to any machine mode.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-11-15  1:47                       ` DJ Delorie
@ 2013-11-15  1:56                         ` Joseph S. Myers
  0 siblings, 0 replies; 47+ messages in thread
From: Joseph S. Myers @ 2013-11-15  1:56 UTC (permalink / raw)
  To: DJ Delorie; +Cc: gcc

On Thu, 14 Nov 2013, DJ Delorie wrote:

> > If you do want types without corresponding modes, that goes back to
> > having a hook to list the relevant type sizes.
> 
> Perhaps a FRACTIONAL_INT_TYPE() macro then, for when there's no
> machine mode to go with it?  Although I'm struggling to imagine a case
> where a target would need to define a bit-sized type that doesn't
> correspond to any machine mode.

Whatever you do, there needs to be a runtime iteration to decide which 
modes get types, given that whether a mode is supported can depend on 
command-line options (TImode only being supported for -m64, for example).

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-11-14 13:26             ` Joseph S. Myers
  2013-11-14 18:12               ` DJ Delorie
@ 2013-11-15 23:38               ` DJ Delorie
  2013-11-16 11:23                 ` Richard Biener
  1 sibling, 1 reply; 47+ messages in thread
From: DJ Delorie @ 2013-11-15 23:38 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: gcc


> Everything handling __int128 would be updated to work with a 
> target-determined set of types instead.
> 
> Preferably, the number of such keywords would be arbitrary (so I suppose 
> there would be a single RID_INTN for them) - that seems cleaner than the 
> system for address space keywords with a fixed block from RID_ADDR_SPACE_0 
> to RID_ADDR_SPACE_15.

I did a scan through the gcc source tree trying to track down all the
implications of this, and there were a lot of them, and not just the
RID_* stuff.  There's also the integer_types[] array (indexed by
itk_*, which is its own mess) and c_common_reswords[] array, for
example.

I think it might not be possible to have one RID_* map to multiple
actual keywords, as there are few cases that need to know *which* intN
is used *and* have access to the original string of the token, and
many cases where code assumes a 1:1 relation between RID_*, a type,
and a keyword string.

IMHO the key design choices come down to:

* Do we change a few global const arrays to be dynamic arrays?

* We need to consider that "position in array" is no longer a suitable
  sort key for these arrays.  itk_* comes to mind here, but RID_* are
  abused sometimes too.  (note: I've seen this before, where PSImode
  isn't included in "find smallest mode" logic, for example, because
  it's no in the array in the same place as SImode)

* Need to dynamically map keywords/bitsizes/tokens to types in all the
  cases where we explicitly check for int128.  Some of these places
  have explicit "check types in the right order" logic hard-coded that
  may need to be changed to a data-search logic.

* The C++ mangler needs to know what to do with these new types.

I'll attach my notes from the scan for reference...

----------------------------------------
Search for in128 ...
Search for c_common_reswords ...
Search for itk_ ...

--- . ---

tree-core.h

	enum integer_type_kind is used to map all integer types "in
	order" so we need an alternate way to map them.  Currently hard-codes
	the itk_int128 types.

tree.h

	defines int128_unsigned_type_node and int128_integer_type_node

	uses itk_int128 and itk_unsigned_int128 - int128_*_type_node
	is an [itk_*] array reference.

builtin-types.def

	defines BT_INT182 but nothing uses it yet.

gimple.c

	gimple_signed_or_unsigned_type maps types to their signed or
	unsigned variant.  Two cases: one checks for int128
	explicitly, the other checks for compatibility with int128.

tree.c

	make_or_reuse_type maps size/signed to a
	int128_integer_type_node etc.

	build_common_tree_nodes makes int128_*_type_node if the target
	supports TImode.

tree-streamer.c

	preload_common_nodes() records one node per itk_*

--- LTO ---

lto.c

	read_cgraph_and_symbols() reads one node per integer_types[itk_*]

--- C-FAMILY ---

c-lex.c

	intepret_integer scans itk_* to find the best (smallest) type
	for integers.

	narrowest_unsigned_type assumes integer_types[itk_*] in
	bit-size order, and assumes [N*2] is signed/unsigned pairs.

	narrowest_signed_type: same.

c-cppbuiltin.c

	__SIZEOF_INTn__ for each intN

c-pretty-print.c

	prints I128 suffix for int128-sized integer literals.

c-common.c

	int128_* has an entry in c_global_trees[]

	c_common_reswords[] has an entry for __int128 -> RID_INT128

	c_common_type_for_size maps int:128 to  int128_*_type_node

	c_common_type_for_mode: same.

	c_common_signed_or_unsigned_type - checks for int128 types.
	same as igmple_signed_or_unsigned_type?()

	c_build_bitfield_integer_type assigns int128_*_type_node for
	:128 fields.

	c_common_nodes_and_builtins maps int128_*_type_node to
	RID_INT128 and "__int128".  Also maps to decl __int128_t

	keyword_begins_type_specifier() checks for RID_INT128

--- C ---

c-tree.h

	adds cts_int128 to c_typespec_keyword[]

c-parser.c

	c_parse_init() reads c_common_reswords[] which has __int128,
	maps one id to each RID_* code.

	c_token_starts_typename() checks for RID_INT128

	c_token_starts_declspecs() checks for RID_INT128

	c_parser_declspecs() checks for RID_INT128

	c_parser_attribute_any_word() checks for RID_INT128

	c_parser_objc_selector() checks for RID_INT128

c-decl.c

	error for "long __int128" etc throughout

	declspecs_add_type() checks for RID_INT128

	finish_declspecs() checks for cts_int128

--- FORTRAN ---

ico-c-binding.def

	maps int128_t to c_int128_t via get_int_kind_from_width(

--- C++ ---

class.c

	layout_class_types uses itk_* to find the best (smallest)
	integer type for overlarge bitfields.

lex.c

	init_reswords() reads c_common_reswords[], which includes __int128

rtti.c

	emit_support_tinfos has a dummy list of types fundamentals[]
	that hardcodes int128_*_type_node in it.

decl.c

	checks for __int128 in declspecs to report if it's not supported.

	finish_enum_value_list() uses itk_* to find the right type for enums.

	build_enumerator() also.

parser.c

	all RID_INTN need to be in
	cp_lexer_next_token_is_decl_specifier_keyword() (simple
	true/false)

	cp_parser_simple_type_specifier uses __intN as type selector
	in a decl. (has token->keyword available, token->u.value is a tree?)

mangle.c

	'n',  /* itk_int128 */
	'o',  /* itk_unsigned_int128  */

typeck.c

	cp_common_type() needs to know about intN compatibility with
	other integer types.

cp-tree.h

	cp_decl_specifier_seq needs a bool for each intN specified.
	(else, what about "__int8 __int16 foo;" ?

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-11-15 23:38               ` DJ Delorie
@ 2013-11-16 11:23                 ` Richard Biener
  2013-11-16 12:26                   ` Joseph S. Myers
  0 siblings, 1 reply; 47+ messages in thread
From: Richard Biener @ 2013-11-16 11:23 UTC (permalink / raw)
  To: DJ Delorie, Joseph S. Myers; +Cc: gcc

DJ Delorie <dj@redhat.com> wrote:
>
>> Everything handling __int128 would be updated to work with a 
>> target-determined set of types instead.
>> 
>> Preferably, the number of such keywords would be arbitrary (so I
>suppose 
>> there would be a single RID_INTN for them) - that seems cleaner than
>the 
>> system for address space keywords with a fixed block from
>RID_ADDR_SPACE_0 
>> to RID_ADDR_SPACE_15.
>
>I did a scan through the gcc source tree trying to track down all the
>implications of this, and there were a lot of them, and not just the
>RID_* stuff.  There's also the integer_types[] array (indexed by
>itk_*, which is its own mess)

I don't think we need this. It shoul be split into frontend parts and what we consider part of the C ABI of the target.

 and c_common_reswords[] array, for
>example.
>
>I think it might not be possible to have one RID_* map to multiple
>actual keywords, as there are few cases that need to know *which* intN
>is used *and* have access to the original string of the token, and
>many cases where code assumes a 1:1 relation between RID_*, a type,
>and a keyword string.
>
>IMHO the key design choices come down to:
>
>* Do we change a few global const arrays to be dynamic arrays?
>
>* We need to consider that "position in array" is no longer a suitable
>  sort key for these arrays.  itk_* comes to mind here, but RID_* are
>  abused sometimes too.  (note: I've seen this before, where PSImode
>  isn't included in "find smallest mode" logic, for example, because
>  it's no in the array in the same place as SImode)
>
>* Need to dynamically map keywords/bitsizes/tokens to types in all the
>  cases where we explicitly check for int128.  Some of these places
>  have explicit "check types in the right order" logic hard-coded that
>  may need to be changed to a data-search logic.
>
>* The C++ mangler needs to know what to do with these new types.
>
>I'll attach my notes from the scan for reference...
>
>----------------------------------------
>Search for in128 ...
>Search for c_common_reswords ...
>Search for itk_ ...
>
>--- . ---
>
>tree-core.h
>
>	enum integer_type_kind is used to map all integer types "in
>	order" so we need an alternate way to map them.  Currently hard-codes
>	the itk_int128 types.
>
>tree.h
>
>	defines int128_unsigned_type_node and int128_integer_type_node
>
>	uses itk_int128 and itk_unsigned_int128 - int128_*_type_node
>	is an [itk_*] array reference.
>
>builtin-types.def
>
>	defines BT_INT182 but nothing uses it yet.
>
>gimple.c
>
>	gimple_signed_or_unsigned_type maps types to their signed or
>	unsigned variant.  Two cases: one checks for int128
>	explicitly, the other checks for compatibility with int128.
>
>tree.c
>
>	make_or_reuse_type maps size/signed to a
>	int128_integer_type_node etc.
>
>	build_common_tree_nodes makes int128_*_type_node if the target
>	supports TImode.
>
>tree-streamer.c
>
>	preload_common_nodes() records one node per itk_*
>
>--- LTO ---
>
>lto.c
>
>	read_cgraph_and_symbols() reads one node per integer_types[itk_*]
>
>--- C-FAMILY ---
>
>c-lex.c
>
>	intepret_integer scans itk_* to find the best (smallest) type
>	for integers.
>
>	narrowest_unsigned_type assumes integer_types[itk_*] in
>	bit-size order, and assumes [N*2] is signed/unsigned pairs.
>
>	narrowest_signed_type: same.
>
>c-cppbuiltin.c
>
>	__SIZEOF_INTn__ for each intN
>
>c-pretty-print.c
>
>	prints I128 suffix for int128-sized integer literals.
>
>c-common.c
>
>	int128_* has an entry in c_global_trees[]
>
>	c_common_reswords[] has an entry for __int128 -> RID_INT128
>
>	c_common_type_for_size maps int:128 to  int128_*_type_node
>
>	c_common_type_for_mode: same.
>
>	c_common_signed_or_unsigned_type - checks for int128 types.
>	same as igmple_signed_or_unsigned_type?()
>
>	c_build_bitfield_integer_type assigns int128_*_type_node for
>	:128 fields.
>
>	c_common_nodes_and_builtins maps int128_*_type_node to
>	RID_INT128 and "__int128".  Also maps to decl __int128_t
>
>	keyword_begins_type_specifier() checks for RID_INT128
>
>--- C ---
>
>c-tree.h
>
>	adds cts_int128 to c_typespec_keyword[]
>
>c-parser.c
>
>	c_parse_init() reads c_common_reswords[] which has __int128,
>	maps one id to each RID_* code.
>
>	c_token_starts_typename() checks for RID_INT128
>
>	c_token_starts_declspecs() checks for RID_INT128
>
>	c_parser_declspecs() checks for RID_INT128
>
>	c_parser_attribute_any_word() checks for RID_INT128
>
>	c_parser_objc_selector() checks for RID_INT128
>
>c-decl.c
>
>	error for "long __int128" etc throughout
>
>	declspecs_add_type() checks for RID_INT128
>
>	finish_declspecs() checks for cts_int128
>
>--- FORTRAN ---
>
>ico-c-binding.def
>
>	maps int128_t to c_int128_t via get_int_kind_from_width(
>
>--- C++ ---
>
>class.c
>
>	layout_class_types uses itk_* to find the best (smallest)
>	integer type for overlarge bitfields.
>
>lex.c
>
>	init_reswords() reads c_common_reswords[], which includes __int128
>
>rtti.c
>
>	emit_support_tinfos has a dummy list of types fundamentals[]
>	that hardcodes int128_*_type_node in it.
>
>decl.c
>
>	checks for __int128 in declspecs to report if it's not supported.
>
>	finish_enum_value_list() uses itk_* to find the right type for enums.
>
>	build_enumerator() also.
>
>parser.c
>
>	all RID_INTN need to be in
>	cp_lexer_next_token_is_decl_specifier_keyword() (simple
>	true/false)
>
>	cp_parser_simple_type_specifier uses __intN as type selector
>	in a decl. (has token->keyword available, token->u.value is a tree?)
>
>mangle.c
>
>	'n',  /* itk_int128 */
>	'o',  /* itk_unsigned_int128  */
>
>typeck.c
>
>	cp_common_type() needs to know about intN compatibility with
>	other integer types.
>
>cp-tree.h
>
>	cp_decl_specifier_seq needs a bool for each intN specified.
>	(else, what about "__int8 __int16 foo;" ?


^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-11-16 11:23                 ` Richard Biener
@ 2013-11-16 12:26                   ` Joseph S. Myers
  2013-11-21 22:41                     ` DJ Delorie
  0 siblings, 1 reply; 47+ messages in thread
From: Joseph S. Myers @ 2013-11-16 12:26 UTC (permalink / raw)
  To: Richard Biener; +Cc: DJ Delorie, gcc

On Sat, 16 Nov 2013, Richard Biener wrote:

> >I did a scan through the gcc source tree trying to track down all the
> >implications of this, and there were a lot of them, and not just the
> >RID_* stuff.  There's also the integer_types[] array (indexed by
> >itk_*, which is its own mess)
> 
> I don't think we need this. It shoul be split into frontend parts and 
> what we consider part of the C ABI of the target.

Indeed, most middle-end references to particular C types are suspect (and 
likewise references to particular modes such as SImode, other than QImode 
which is always the target byte of BITS_PER_UNIT bits).  As regards the 
ABI, I've previously suggested a hook taking a subset of itk_* values are 
a replacement for target macros such as INT_TYPE_SIZE (cf Joern's patches, 
Nov/Dec 2010, and note that in various places it may be better to use 
TYPE_PRECISION (integer_type_node) etc. if the type nodes have been 
initialized by then).  But such a hook doesn't need to handle __intN types 
since it's part of the definition of __intN that it takes N bits.

I suppose global type nodes may be needed outside front ends for dealing 
with built-in function interfaces if nothing else, but for __intN you 
might get an interface "return the signed / unsigned __intN type" rather 
than macros like int128_integer_type_node.

(Looking at some examples of middle-end code inappropriately using 
particular C ABI types: the code in tree-ssa-loop-ivopts.c needs some way 
to iterate over "integer types that are efficient on the target"; what 
types the ABI says are int / long / long long should be irrelevant.  Code 
in convert.c is an example of a trickier case, where the enums for 
built-in functions embed information about the integer and floating-point 
types involved and a better way would be needed to extract the underlying 
operation for a built-in function and identify the function, if any, for 
an arbitrary type or pair of types.)

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-11-16 12:26                   ` Joseph S. Myers
@ 2013-11-21 22:41                     ` DJ Delorie
  2013-11-21 22:59                       ` Joseph S. Myers
  0 siblings, 1 reply; 47+ messages in thread
From: DJ Delorie @ 2013-11-21 22:41 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: richard.guenther, gcc


I did an audit of the core files for "integer_type_node" and didn't
see much beyond what was already noted (i.e. mostly builtins and
constants).

Since core builtins shouldn't be using intN types anyway, I don't
think there are many cases left where the core needs to "know" about
all the types, once the types are initialized.  It's mostly the FE
that need to know about the new intN types.

(my personal worry is how much of the core assumes that types are
powers-of-two)

So where can we begin on all this?

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-11-21 22:41                     ` DJ Delorie
@ 2013-11-21 22:59                       ` Joseph S. Myers
  2013-11-22  8:29                         ` DJ Delorie
  0 siblings, 1 reply; 47+ messages in thread
From: Joseph S. Myers @ 2013-11-21 22:59 UTC (permalink / raw)
  To: DJ Delorie; +Cc: richard.guenther, gcc

On Thu, 21 Nov 2013, DJ Delorie wrote:

> So where can we begin on all this?

As noted, make the existing int128 handling more generic (bearing in mind 
that quite likely much of the language-independent compiler doesn't 
actually need to know about int128, even if it does at present).

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-11-21 22:59                       ` Joseph S. Myers
@ 2013-11-22  8:29                         ` DJ Delorie
  2013-11-22 12:43                           ` Joseph S. Myers
  0 siblings, 1 reply; 47+ messages in thread
From: DJ Delorie @ 2013-11-22  8:29 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: richard.guenther, gcc


> > So where can we begin on all this?
> 
> As noted, make the existing int128 handling more generic (bearing in mind 
> that quite likely much of the language-independent compiler doesn't 
> actually need to know about int128, even if it does at present).

I recall that, but that led to the whole
moving-integer-type-kind-out-of-MI proposal, which led to the
MI-knows-too-much-about-C-types comment.

If I come up with some table-driven API to register
"integer-like-types" and search/sort/choose from them, would that be a
good starting point?  Then we can #define *_type_node to a function
call perhaps.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-11-22  8:29                         ` DJ Delorie
@ 2013-11-22 12:43                           ` Joseph S. Myers
  2013-11-22 19:33                             ` DJ Delorie
  0 siblings, 1 reply; 47+ messages in thread
From: Joseph S. Myers @ 2013-11-22 12:43 UTC (permalink / raw)
  To: DJ Delorie; +Cc: richard.guenther, gcc

On Fri, 22 Nov 2013, DJ Delorie wrote:

> If I come up with some table-driven API to register
> "integer-like-types" and search/sort/choose from them, would that be a
> good starting point?  Then we can #define *_type_node to a function
> call perhaps.

I am doubtful that it's appropriate for e.g. integer_type_node to be a 
function call.  I can believe it makes sense for int128_integer_type_node 
to be such a call (more precisely, for int128_integer_type_node to cease 
to exist and for any front-end places needing it to call a function, with 
a type size that should not be a constant 128).  I can also believe it's 
appropriate for the global nodes for trees reflecting C ABI types to go 
somewhere other than tree.h.

I've no idea whether a table-driven API for anything would be a good 
starting point.  That depends on a detailed analysis of the current 
situation and its deficiencies for whatever you are proposing replacing 
with such an API.

I *am* reasonably confident that the places handling hardcoded lists of 
intQI_type_node, intHI_type_node, ... would better iterate over whatever 
supported integer modes may be present in the particular compiler 
configuration (and have some set of signed / unsigned / atomic types 
associated with integer modes) rather than hardcoding a list.

It would not surprise me if some of the global type nodes either aren't 
needed at all or, being only used for built-in functions, should actually 
be defined in builtin-types.def rather than tree.[ch].  For example, 
complex_integer_type_node and float_ptr_type_node.  But I don't think 
cleaning up those would actually help in any way towards your goal; it 
would be a completely orthogonal cleanup.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-11-22 12:43                           ` Joseph S. Myers
@ 2013-11-22 19:33                             ` DJ Delorie
  2013-11-22 21:00                               ` Joseph S. Myers
  0 siblings, 1 reply; 47+ messages in thread
From: DJ Delorie @ 2013-11-22 19:33 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: richard.guenther, gcc


> (more precisely, for int128_integer_type_node to cease to exist and
> for any front-end places needing it to call a function, with a type
> size that should not be a constant 128).

The complications I've seen there is, for example, when you're
iterating through types looking for a "best" type, where some of the
types are fixed foo_type_node's and others are dynamic
intN_type_nodes.  Perhaps we sould use a hybrid list-plus-table
approach?  So we check for the standard types explicitly, then iterate
through the list of intN types?

> I can also believe it's appropriate for the global nodes for trees
> reflecting C ABI types to go somewhere other than tree.h.

Which are those?  Why isn't "int" one of those?

> I've no idea whether a table-driven API for anything would be a good 
> starting point.  That depends on a detailed analysis of the current 
> situation and its deficiencies for whatever you are proposing replacing 
> with such an API.

If you want to support more than one intN at a time, IMHO you need
more than just one intN object, hence a table of some sort.

Or are you assuming that any given backend would only be allowed to
define one intN type?  That's already not going to work, as I need
int20_t in addition to the "now standard" int128_t.

> I *am* reasonably confident that the places handling hardcoded lists
> of intQI_type_node, intHI_type_node, ... would better iterate over
> whatever supported integer modes may be present in the particular
> compiler configuration (and have some set of signed / unsigned /
> atomic types associated with integer modes) rather than hardcoding a
> list.

How is this different than the places handling hardcoded lists of
integer_type_node et al?

> It would not surprise me if some of the global type nodes either aren't 
> needed at all or, being only used for built-in functions, should actually 
> be defined in builtin-types.def rather than tree.[ch].  For example, 
> complex_integer_type_node and float_ptr_type_node.  But I don't think 
> cleaning up those would actually help in any way towards your goal; it 
> would be a completely orthogonal cleanup.

Yeah, I'm not trying to take on more work, just trying to hit the
prereqs for my own project.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-11-22 19:33                             ` DJ Delorie
@ 2013-11-22 21:00                               ` Joseph S. Myers
  2013-11-22 21:19                                 ` DJ Delorie
  0 siblings, 1 reply; 47+ messages in thread
From: Joseph S. Myers @ 2013-11-22 21:00 UTC (permalink / raw)
  To: DJ Delorie; +Cc: richard.guenther, gcc

On Fri, 22 Nov 2013, DJ Delorie wrote:

> > (more precisely, for int128_integer_type_node to cease to exist and
> > for any front-end places needing it to call a function, with a type
> > size that should not be a constant 128).
> 
> The complications I've seen there is, for example, when you're
> iterating through types looking for a "best" type, where some of the
> types are fixed foo_type_node's and others are dynamic
> intN_type_nodes.  Perhaps we sould use a hybrid list-plus-table
> approach?  So we check for the standard types explicitly, then iterate
> through the list of intN types?

In general you need to analyze each such case individually to produce a 
reasoned argument for what it should logically be doing.  Given such 
analyses, maybe then you can identify particular tables of types in 
particular orders (for example) that should be set up to iterate through.

> > I can also believe it's appropriate for the global nodes for trees
> > reflecting C ABI types to go somewhere other than tree.h.
> 
> Which are those?  Why isn't "int" one of those?

I think "int" is one of them.  Those files that have a need for C ABI 
types would include tree-c-abi.h.  Optimizers that aren't e.g. generating 
calls to built-in functions where the C ABI is involved wouldn't include 
that header.  As this should be orthogonal to your project it could just 
as well be part of the tree.h cleanup project.

> > I've no idea whether a table-driven API for anything would be a good 
> > starting point.  That depends on a detailed analysis of the current 
> > situation and its deficiencies for whatever you are proposing replacing 
> > with such an API.
> 
> If you want to support more than one intN at a time, IMHO you need
> more than just one intN object, hence a table of some sort.
> 
> Or are you assuming that any given backend would only be allowed to
> define one intN type?  That's already not going to work, as I need
> int20_t in addition to the "now standard" int128_t.

I am saying that the starting point is understanding what is logically 
correct in the various different places dealing with integer types, and an 
analysis of that is what must drive any API design.

Does the target with __int20 actually have __int128 (i.e. pass 
targetm.scalar_mode_supported_p (TImode))?  But you should indeed be able 
to have an arbitrary number of such types.

> > I *am* reasonably confident that the places handling hardcoded lists
> > of intQI_type_node, intHI_type_node, ... would better iterate over
> > whatever supported integer modes may be present in the particular
> > compiler configuration (and have some set of signed / unsigned /
> > atomic types associated with integer modes) rather than hardcoding a
> > list.
> 
> How is this different than the places handling hardcoded lists of
> integer_type_node et al?

(a) We already have the system for an arbitrary set of integer modes to be 
defined and iterated over, whereas the set of standard C types is 
target-independent.

(b) This sort of thing tends to be more readily addressed through a series 
of small cleanup patches that clearly isolate anything that might possibly 
change behavior at all than through one huge patch.  So any small obvious 
things are naturally separated out.

(c) Iteration over C types has other complications such as preferences 
between different types (e.g. int and long) with the same middle-end 
properties.

(d) I don't think the standard C types are particularly relevant to your 
project.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-11-22 21:00                               ` Joseph S. Myers
@ 2013-11-22 21:19                                 ` DJ Delorie
  2013-11-23  0:41                                   ` Joseph S. Myers
  0 siblings, 1 reply; 47+ messages in thread
From: DJ Delorie @ 2013-11-22 21:19 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: richard.guenther, gcc


> In general you need to analyze each such case individually to produce a 
> reasoned argument for what it should logically be doing.  Given such 
> analyses, maybe then you can identify particular tables of types in 
> particular orders (for example) that should be set up to iterate through.

Ok, I'll do this next, except it's what I did first... and we still
haven't decided how to handle some of those cases.  I'll re-analyze.

> Does the target with __int20 actually have __int128 (i.e. pass 
> targetm.scalar_mode_supported_p (TImode))?  But you should indeed be able 
> to have an arbitrary number of such types.

It doesn't support it, but it does *have* it.  In that the compiler
correcly parses the __int128 keyword and knows to tell you it isn't
supported.  So, it needs at least two keywords.  Which implies "it
needs two..." in other places.

And it's reasonable to expect that *someone* will want int16, int32,
etc types once a general solution is in place.

> (d) I don't think the standard C types are particularly relevant to your 
> project.

Should we be pulling the int128 support out of the integer_types[]
list and put it in the global_trees[] (or some table) list?  Because
most of the int128 support is tied in with the standard C type
handling, not the target-specific handling.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-11-22 21:19                                 ` DJ Delorie
@ 2013-11-23  0:41                                   ` Joseph S. Myers
  2013-12-10  3:35                                     ` DJ Delorie
  0 siblings, 1 reply; 47+ messages in thread
From: Joseph S. Myers @ 2013-11-23  0:41 UTC (permalink / raw)
  To: DJ Delorie; +Cc: richard.guenther, gcc

On Fri, 22 Nov 2013, DJ Delorie wrote:

> > Does the target with __int20 actually have __int128 (i.e. pass 
> > targetm.scalar_mode_supported_p (TImode))?  But you should indeed be able 
> > to have an arbitrary number of such types.
> 
> It doesn't support it, but it does *have* it.  In that the compiler
> correcly parses the __int128 keyword and knows to tell you it isn't
> supported.  So, it needs at least two keywords.  Which implies "it
> needs two..." in other places.

Making __int20 and __int128 exactly similar indicates __int128 *not* being 
a keyword on targets not supporting it.

> And it's reasonable to expect that *someone* will want int16, int32,
> etc types once a general solution is in place.

As previously noted, it's best only to define such types where (a) there 
is an integer mode passing targetm.scalar_mode_supported_p and (b) no 
standard C type matches, to avoid issues with whether __int32 is the same 
as int or not.

> > (d) I don't think the standard C types are particularly relevant to your 
> > project.
> 
> Should we be pulling the int128 support out of the integer_types[]
> list and put it in the global_trees[] (or some table) list?  Because
> most of the int128 support is tied in with the standard C type
> handling, not the target-specific handling.

My guess is that the int128 support doesn't belong in any of the existing 
global arrays, but in some new arrays supporting whatever set of intN 
types the target has.  That's just a guess; whether you follow or don't 
follow it, your analysis of the code needs to justify your choice.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-11-23  0:41                                   ` Joseph S. Myers
@ 2013-12-10  3:35                                     ` DJ Delorie
  2013-12-10 17:17                                       ` Joseph S. Myers
  0 siblings, 1 reply; 47+ messages in thread
From: DJ Delorie @ 2013-12-10  3:35 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: richard.guenther, gcc


First pass at actual code.  I took the path of using a new macro in
TARGET-modes.def and having genmodes build the relevent tables.  Part
of the table is created by genmodes, the rest is created at runtime.

genmodes: bitsize, mode.

runtime: signed/unsigned type trees
  (eventually, flag for "target supports this, for this run")

I ended up making a range of RID_* codes as it seemed too difficult to
have one code map to more than one token.  I only added four, though,
and they're mapped to the table entries so each target can (at the
moment) define up to four __intN types.  insn-modes.h has a define
that says how many codes are actually used.

I also have not yet removed the int128 code, although my patch shows a
128-bit __intN definition being added the new way.  This patch is
mostly just to get an OK on my methods.



Index: machmode.h
===================================================================
--- machmode.h	(revision 205719)
+++ machmode.h	(working copy)
@@ -322,7 +322,16 @@ extern void init_adjust_machine_modes (v
 			 GET_MODE_PRECISION (MODE2))
 
 #define HWI_COMPUTABLE_MODE_P(MODE) \
   (SCALAR_INT_MODE_P (MODE) \
    && GET_MODE_PRECISION (MODE) <= HOST_BITS_PER_WIDE_INT)
 
+typedef struct {
+  /* These parts are initailized by genmodes output */
+  int bitsize;
+  enum machine_mode m;
+  /* RID_* is RID_INTN_BASE + index into this array */
+} int_n_data_t;
+
+extern const int_n_data_t int_n_data[NUM_INT_N_ENTS];
+
 #endif /* not HAVE_MACHINE_MODES */
Index: c-family/c-common.c
===================================================================
--- c-family/c-common.c	(revision 205719)
+++ c-family/c-common.c	(working copy)
@@ -5285,12 +5285,13 @@ c_common_nodes_and_builtins (void)
   int char16_type_size;
   int char32_type_size;
   int wchar_type_size;
   tree array_domain_type;
   tree va_list_ref_type_node;
   tree va_list_arg_type_node;
+  int i;
 
   build_common_tree_nodes (flag_signed_char, flag_short_double);
 
   /* Define `int' and `char' first so that dbx will output them first.  */
   record_builtin_type (RID_INT, NULL, integer_type_node);
   record_builtin_type (RID_CHAR, "char", char_type_node);
@@ -5308,12 +5309,24 @@ c_common_nodes_and_builtins (void)
     {
       record_builtin_type (RID_INT128, "__int128",
 			   int128_integer_type_node);
       record_builtin_type (RID_MAX, "__int128 unsigned",
 			   int128_unsigned_type_node);
     }
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    {
+      char name[25];
+      sprintf (name, "__int%d", int_n_data[i].bitsize);
+      record_builtin_type ((enum rid)(RID_FIRST_INT_N + i), name,
+			   int_n_trees[i].signed_type);
+      sprintf (name, "__int%d unsigned", int_n_data[i].bitsize);
+      record_builtin_type (RID_MAX, name,
+			   int_n_trees[i].unsigned_type);
+    }
+
   if (c_dialect_cxx ())
     record_builtin_type (RID_MAX, "unsigned long", long_unsigned_type_node);
   record_builtin_type (RID_MAX, "long long int",
 		       long_long_integer_type_node);
   record_builtin_type (RID_MAX, "long long unsigned int",
 		       long_long_unsigned_type_node);
@@ -11576,12 +11589,15 @@ keyword_begins_type_specifier (enum rid 
     case RID_STRUCT:
     case RID_CLASS:
     case RID_UNION:
     case RID_ENUM:
       return true;
     default:
+      if (keyword >= RID_FIRST_INT_N
+	  && keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS)
+	return true;
       return false;
     }
 }
 
 /* Return true if KEYWORD names a type qualifier.  */
 
Index: c-family/c-common.h
===================================================================
--- c-family/c-common.h	(revision 205719)
+++ c-family/c-common.h	(working copy)
@@ -185,12 +185,29 @@ enum rid
   RID_ADDR_SPACE_14,
   RID_ADDR_SPACE_15,
 
   RID_FIRST_ADDR_SPACE = RID_ADDR_SPACE_0,
   RID_LAST_ADDR_SPACE = RID_ADDR_SPACE_15,
 
+  /* __intN_t keywords.  The _N_M here doesn't correspond to the intN
+     in the keyword; use the bitsize in int_n_t_data_t[M] for that.
+     For example, if int_n_t_data_t[0].bitsize is 13, then RID_INT_N_0
+     is for __int13_t.  */
+
+  /* Note that the range to use is RID_FIRST_INT_N through
+     RID_FIRST_INT_N + NUM_INT_N_ENTS - 1 and c-parser.c has a list of
+     all RID_INT_N_* in a case statement.  */
+
+  RID_INT_N_0,
+  RID_INT_N_1,
+  RID_INT_N_2,
+  RID_INT_N_3,
+
+  RID_FIRST_INT_N = RID_INT_N_0,
+  RID_LAST_INT_N = RID_INT_N_3,
+
   RID_MAX,
 
   RID_FIRST_MODIFIER = RID_STATIC,
   RID_LAST_MODIFIER = RID_ONEWAY,
 
   RID_FIRST_CXX0X = RID_CONSTEXPR,
Index: c/c-parser.c
===================================================================
--- c/c-parser.c	(revision 205719)
+++ c/c-parser.c	(working copy)
@@ -109,12 +109,21 @@ c_parse_init (void)
 
       id = get_identifier (c_common_reswords[i].word);
       C_SET_RID_CODE (id, c_common_reswords[i].rid);
       C_IS_RESERVED_WORD (id) = 1;
       ridpointers [(int) c_common_reswords[i].rid] = id;
     }
+
+  for (i = 0; i < NUM_INT_N_ENTS; i++)
+    {
+      char name[50];
+      sprintf (name, "__int%d", int_n_data[i].bitsize);
+      id = get_identifier (name);
+      C_SET_RID_CODE (id, RID_FIRST_INT_N + i);
+      C_IS_RESERVED_WORD (id) = 1;
+    }
 }
 \f
 /* The C lexer intermediates between the lexer in cpplib and c-lex.c
    and the C parser.  Unlike the C++ lexer, the parser structure
    stores the lexer information instead of using a separate structure.
    Identifiers are separated into ordinary identifiers, type names,
@@ -506,12 +515,15 @@ c_token_starts_typename (c_token *token)
 	case RID_FRACT:
 	case RID_ACCUM:
 	case RID_SAT:
 	case RID_AUTO_TYPE:
 	  return true;
 	default:
+	  if (token->keyword >= RID_FIRST_INT_N
+	      && token->keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS)
+	    return true;
 	  return false;
 	}
     case CPP_LESS:
       if (c_dialect_objc ())
 	return true;
       return false;
@@ -665,12 +677,15 @@ c_token_starts_declspecs (c_token *token
 	case RID_SAT:
 	case RID_ALIGNAS:
 	case RID_ATOMIC:
 	case RID_AUTO_TYPE:
 	  return true;
 	default:
+	  if (token->keyword >= RID_FIRST_INT_N
+	      && token->keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS)
+	    return true;
 	  return false;
 	}
     case CPP_LESS:
       if (c_dialect_objc ())
 	return true;
       return false;
@@ -2294,12 +2309,16 @@ c_parser_declspecs (c_parser *parser, st
 	case RID_DFLOAT64:
 	case RID_DFLOAT128:
 	case RID_BOOL:
 	case RID_FRACT:
 	case RID_ACCUM:
 	case RID_SAT:
+	case RID_INT_N_0:
+	case RID_INT_N_1:
+	case RID_INT_N_2:
+	case RID_INT_N_3:
 	  if (!typespec_ok)
 	    goto out;
 	  attrs_ok = true;
 	  seen_type = true;
 	  if (c_dialect_objc ())
 	    parser->objc_need_raw_identifier = true;
@@ -3744,12 +3763,16 @@ c_parser_attribute_any_word (c_parser *p
 	case RID_ACCUM:
 	case RID_SAT:
 	case RID_TRANSACTION_ATOMIC:
 	case RID_TRANSACTION_CANCEL:
 	case RID_ATOMIC:
 	case RID_AUTO_TYPE:
+	case RID_INT_N_0:
+	case RID_INT_N_1:
+	case RID_INT_N_2:
+	case RID_INT_N_3:
 	  ok = true;
 	  break;
 	default:
 	  ok = false;
 	  break;
 	}
@@ -8807,12 +8830,16 @@ c_parser_objc_selector (c_parser *parser
     case RID_FLOAT:
     case RID_DOUBLE:
     case RID_VOID:
     case RID_BOOL:
     case RID_ATOMIC:
     case RID_AUTO_TYPE:
+    case RID_INT_N_0:
+    case RID_INT_N_1:
+    case RID_INT_N_2:
+    case RID_INT_N_3:
       c_parser_consume_token (parser);
       return value;
     default:
       return NULL_TREE;
     }
 }
Index: c/c-tree.h
===================================================================
--- c/c-tree.h	(revision 205719)
+++ c/c-tree.h	(working copy)
@@ -206,12 +206,13 @@ enum c_typespec_keyword {
   cts_void,
   cts_bool,
   cts_char,
   cts_int,
   cts_float,
   cts_int128,
+  cts_int_n,
   cts_double,
   cts_dfloat32,
   cts_dfloat64,
   cts_dfloat128,
   cts_fract,
   cts_accum,
@@ -272,12 +273,14 @@ struct c_declspecs {
      separately.  */
   tree attrs;
   /* The base-2 log of the greatest alignment required by an _Alignas
      specifier, in bytes, or -1 if no such specifiers with nonzero
      alignment.  */
   int align_log;
+  /* For the __intN declspec, this stores the index into the int_n_* arrays.  */
+  int int_n_idx;
   /* The storage class specifier, or csc_none if none.  */
   enum c_storage_class storage_class;
   /* Any type specifier keyword used such as "int", not reflecting
      modifiers such as "short", or cts_none if none.  */
   ENUM_BITFIELD (c_typespec_keyword) typespec_word : 8;
   /* The kind of type specifier if one has been seen, ctsk_none
Index: c/c-decl.c
===================================================================
--- c/c-decl.c	(revision 205719)
+++ c/c-decl.c	(working copy)
@@ -9508,12 +9508,39 @@ declspecs_add_type (location_t loc, stru
 	      else
 		{
 		  specs->typespec_word = cts_int128;
 		  specs->locations[cdw_typespec] = loc;
 		}
 	      return specs;
+	    case RID_INT_N_0:
+	    case RID_INT_N_1:
+	    case RID_INT_N_2:
+	    case RID_INT_N_3:
+	      if (!in_system_header_at (input_location))
+		pedwarn (loc, OPT_Wpedantic,
+			 "ISO C does not support %<__intN%> types");
+
+	      if (specs->long_p)
+		error_at (loc,
+			  ("both %<__intN%> and %<long%> in "
+			   "declaration specifiers"));
+	      else if (specs->saturating_p)
+		error_at (loc,
+			  ("both %<_Sat%> and %<__intN%> in "
+			   "declaration specifiers"));
+	      else if (specs->short_p)
+		error_at (loc,
+			  ("both %<__intN%> and %<short%> in "
+			   "declaration specifiers"));
+	      else
+		{
+		  specs->typespec_word = cts_int_n;
+		  specs->int_n_idx = i - RID_INT_N_0;
+		  specs->locations[cdw_typespec] = loc;
+		}
+	      return specs;
 	    case RID_VOID:
 	      if (specs->long_p)
 		error_at (loc,
 			  ("both %<long%> and %<void%> in "
 			   "declaration specifiers"));
 	      else if (specs->short_p)
@@ -10082,12 +10109,25 @@ finish_declspecs (struct c_declspecs *sp
 	{
 	  pedwarn (specs->locations[cdw_complex], OPT_Wpedantic,
 		   "ISO C does not support complex integer types");
 	  specs->type = build_complex_type (specs->type);
 	}
       break;
+    case cts_int_n:
+      gcc_assert (!specs->long_p && !specs->short_p && !specs->long_long_p);
+      gcc_assert (!(specs->signed_p && specs->unsigned_p));
+      specs->type = (specs->unsigned_p
+		     ? int_n_trees[specs->int_n_idx].unsigned_type
+		     : int_n_trees[specs->int_n_idx].signed_type);
+      if (specs->complex_p)
+	{
+	  pedwarn (specs->locations[cdw_complex], OPT_Wpedantic,
+		   "ISO C does not support complex integer types");
+	  specs->type = build_complex_type (specs->type);
+	}
+      break;
     case cts_int:
       gcc_assert (!(specs->long_p && specs->short_p));
       gcc_assert (!(specs->signed_p && specs->unsigned_p));
       if (specs->long_long_p)
 	specs->type = (specs->unsigned_p
 		       ? long_long_unsigned_type_node
Index: tree.c
===================================================================
--- tree.c	(revision 205719)
+++ tree.c	(working copy)
@@ -236,12 +236,14 @@ static unsigned int type_hash_list (cons
 static unsigned int attribute_hash_list (const_tree, hashval_t);
 static bool decls_same_for_odr (tree decl1, tree decl2);
 
 tree global_trees[TI_MAX];
 tree integer_types[itk_none];
 
+int_n_trees_t int_n_trees[NUM_INT_N_ENTS];
+
 unsigned char tree_contains_struct[MAX_TREE_CODES][64];
 
 /* Number of operands for each OpenMP clause.  */
 unsigned const char omp_clause_num_ops[] =
 {
   0, /* OMP_CLAUSE_ERROR  */
@@ -9447,12 +9449,14 @@ make_vector_type (tree innertype, int nu
   return t;
 }
 
 static tree
 make_or_reuse_type (unsigned size, int unsignedp)
 {
+  int i;
+
   if (size == INT_TYPE_SIZE)
     return unsignedp ? unsigned_type_node : integer_type_node;
   if (size == CHAR_TYPE_SIZE)
     return unsignedp ? unsigned_char_type_node : signed_char_type_node;
   if (size == SHORT_TYPE_SIZE)
     return unsignedp ? short_unsigned_type_node : short_integer_type_node;
@@ -9462,12 +9466,17 @@ make_or_reuse_type (unsigned size, int u
     return (unsignedp ? long_long_unsigned_type_node
             : long_long_integer_type_node);
   if (size == 128 && int128_integer_type_node)
     return (unsignedp ? int128_unsigned_type_node
             : int128_integer_type_node);
 
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (size == int_n_data[i].bitsize)
+      return (unsignedp ? int_n_trees[i].unsigned_type
+	      : int_n_trees[i].signed_type);
+
   if (unsignedp)
     return make_unsigned_type (size);
   else
     return make_signed_type (size);
 }
 
@@ -9576,12 +9585,14 @@ build_atomic_base (tree type, unsigned i
    SHORT_DOUBLE specifies whether double should be of the same precision
    as float.  */
 
 void
 build_common_tree_nodes (bool signed_char, bool short_double)
 {
+  int i;
+
   error_mark_node = make_node (ERROR_MARK);
   TREE_TYPE (error_mark_node) = error_mark_node;
 
   initialize_sizetypes ();
 
   /* Define both `signed char' and `unsigned char'.  */
@@ -9615,12 +9626,20 @@ build_common_tree_nodes (bool signed_cha
       {
         int128_integer_type_node = make_signed_type (128);
         int128_unsigned_type_node = make_unsigned_type (128);
       }
 #endif
 
+    for (i = 0; i < NUM_INT_N_ENTS; i ++)
+      {
+	int_n_trees[i].signed_type = make_signed_type (int_n_data[i].bitsize);
+	int_n_trees[i].unsigned_type = make_unsigned_type (int_n_data[i].bitsize);
+	TYPE_SIZE (int_n_trees[i].signed_type) = bitsize_int (int_n_data[i].bitsize);
+	TYPE_SIZE (int_n_trees[i].unsigned_type) = bitsize_int (int_n_data[i].bitsize);
+      }
+
   /* Define a boolean type.  This type only represents boolean values but
      may be larger than char depending on the value of BOOL_TYPE_SIZE.
      Front ends which want to override this size (i.e. Java) can redefine
      boolean_type_node before calling build_common_tree_nodes_2.  */
   boolean_type_node = make_unsigned_type (BOOL_TYPE_SIZE);
   TREE_SET_CODE (boolean_type_node, BOOLEAN_TYPE);
Index: tree.h
===================================================================
--- tree.h	(revision 205719)
+++ tree.h	(working copy)
@@ -4552,7 +4552,16 @@ extern unsigned int get_pointer_alignmen
 extern tree fold_call_stmt (gimple, bool);
 extern tree gimple_fold_builtin_snprintf_chk (gimple, tree, enum built_in_function);
 extern void set_builtin_user_assembler_name (tree decl, const char *asmspec);
 extern bool is_simple_builtin (tree);
 extern bool is_inexpensive_builtin (tree);
 
+
+typedef struct {
+  /* These parts are initialized at runtime */
+  tree signed_type;
+  tree unsigned_type;
+} int_n_trees_t;
+
+extern int_n_trees_t int_n_trees[NUM_INT_N_ENTS];
+
 #endif  /* GCC_TREE_H  */
Index: stor-layout.c
===================================================================
--- stor-layout.c	(revision 205719)
+++ stor-layout.c	(working copy)
@@ -310,22 +310,28 @@ finalize_size_functions (void)
    than MAX_FIXED_MODE_SIZE will not be used.  */
 
 enum machine_mode
 mode_for_size (unsigned int size, enum mode_class mclass, int limit)
 {
   enum machine_mode mode;
+  int i;
 
   if (limit && size > MAX_FIXED_MODE_SIZE)
     return BLKmode;
 
   /* Get the first mode which has this size, in the specified class.  */
   for (mode = GET_CLASS_NARROWEST_MODE (mclass); mode != VOIDmode;
        mode = GET_MODE_WIDER_MODE (mode))
     if (GET_MODE_PRECISION (mode) == size)
       return mode;
 
+  if (mclass == MODE_INT && mode == BLKmode)
+    for (i = 0; i < NUM_INT_N_ENTS; i ++)
+      if (int_n_data[i].bitsize == size)
+	return int_n_data[i].m;
+
   return BLKmode;
 }
 
 /* Similar, except passed a tree node.  */
 
 enum machine_mode
@@ -346,22 +352,32 @@ mode_for_size_tree (const_tree size, enu
 /* Similar, but never return BLKmode; return the narrowest mode that
    contains at least the requested number of value bits.  */
 
 enum machine_mode
 smallest_mode_for_size (unsigned int size, enum mode_class mclass)
 {
-  enum machine_mode mode;
+  enum machine_mode mode = VOIDmode;
+  int i;
 
   /* Get the first mode which has at least this size, in the
      specified class.  */
   for (mode = GET_CLASS_NARROWEST_MODE (mclass); mode != VOIDmode;
        mode = GET_MODE_WIDER_MODE (mode))
     if (GET_MODE_PRECISION (mode) >= size)
-      return mode;
+      break;
 
-  gcc_unreachable ();
+  if (mclass == MODE_INT)
+    for (i = 0; i < NUM_INT_N_ENTS; i ++)
+      if (int_n_data[i].bitsize >= size
+	  && int_n_data[i].bitsize < GET_MODE_PRECISION (mode))
+	mode = int_n_data[i].m;
+
+  if (mode == VOIDmode)
+    gcc_unreachable ();
+
+  return mode;
 }
 
 /* Find an integer mode of the exact same size, or BLKmode on failure.  */
 
 enum machine_mode
 int_mode_for_mode (enum machine_mode mode)
Index: genmodes.c
===================================================================
--- genmodes.c	(revision 205719)
+++ genmodes.c	(working copy)
@@ -69,23 +69,25 @@ struct mode_data
 
   const char *file;		/* file and line of definition, */
   unsigned int line;		/* for error reporting */
   unsigned int counter;		/* Rank ordering of modes */
   unsigned int ibit;		/* the number of integral bits */
   unsigned int fbit;		/* the number of fractional bits */
+
+  unsigned int int_n;		/* If nonzero, then __int<INT_N> will be defined */
 };
 
 static struct mode_data *modes[MAX_MODE_CLASS];
 static unsigned int n_modes[MAX_MODE_CLASS];
 static struct mode_data *void_mode;
 
 static const struct mode_data blank_mode = {
   0, "<unknown>", MAX_MODE_CLASS,
   -1U, -1U, -1U, -1U,
   0, 0, 0, 0, 0,
-  "<unknown>", 0, 0, 0, 0
+  "<unknown>", 0, 0, 0, 0, 0
 };
 
 static htab_t modes_by_name;
 
 /* Data structure for recording target-specified runtime adjustments
    to a particular mode.  We support varying the byte size, the
@@ -627,12 +629,40 @@ reset_float_format (const char *name, co
       error ("%s:%d: mode \"%s\" is not a FLOAT class", file, line, name);
       return;
     }
   m->format = format;
 }
 
+/* __intN support.  */
+#define INT_N(PREC,M) \
+  make_int_n (PREC, #M, __FILE__, __LINE__)
+static void ATTRIBUTE_UNUSED
+make_int_n (int bitsize, const char *m,
+            const char *file, unsigned int line)
+{
+  struct mode_data *component = find_mode (m);
+  if (!component)
+    {
+      error ("%s:%d: no mode \"%s\"", file, line, m);
+      return;
+    }
+  if (component->cl != MODE_INT
+      && component->cl != MODE_PARTIAL_INT)
+    {
+      error ("%s:%d: mode \"%s\" is not class INT or PARTIAL_INT", file, line, m);
+      return;
+    }
+  if (component->int_n != 0)
+    {
+      error ("%s:%d: mode \"%s\" already has an intN", file, line, m);
+      return;
+    }
+
+  component->int_n = bitsize;
+}
+
 /* Partial integer modes are specified by relation to a full integer
    mode.  */
 #define PARTIAL_INT_MODE(M,PREC,NAME)				\
   make_partial_integer_mode (#M, #NAME, PREC, __FILE__, __LINE__)
 static void ATTRIBUTE_UNUSED
 make_partial_integer_mode (const char *base, const char *name,
@@ -881,12 +911,13 @@ emit_max_int (void)
 
 static void
 emit_insn_modes_h (void)
 {
   int c;
   struct mode_data *m, *first, *last;
+  int n_int_n_ents = 0;
 
   printf ("/* Generated automatically from machmode.def%s%s\n",
 	   HAVE_EXTRA_MODES ? " and " : "",
 	   EXTRA_MODES_FILE);
 
   puts ("\
@@ -941,12 +972,19 @@ enum machine_mode\n{");
 #if 0 /* disabled for backward compatibility, temporary */
   printf ("#define CONST_REAL_FORMAT_FOR_MODE%s\n", adj_format ? "" :" const");
 #endif
   printf ("#define CONST_MODE_IBIT%s\n", adj_ibit ? "" : " const");
   printf ("#define CONST_MODE_FBIT%s\n", adj_fbit ? "" : " const");
   emit_max_int ();
+
+  for_all_modes (c, m)
+    if (m->int_n)
+      n_int_n_ents ++;
+
+  printf ("#define NUM_INT_N_ENTS %d\n", n_int_n_ents);
+
   puts ("\
 \n\
 #endif /* insn-modes.h */");
 }
 
 static void
@@ -1384,12 +1422,34 @@ emit_mode_fbit (void)
   for_all_modes (c, m)
     tagged_printf ("%u", m->fbit, m->name);
 
   print_closer ();
 }
 
+/* Emit __intN for all modes.  */
+
+static void
+emit_mode_int_n (void)
+{
+  int c;
+  struct mode_data *m;
+
+  print_decl ("int_n_data_t", "int_n_data", "");
+
+  for_all_modes (c, m)
+    if (m->int_n)
+      {
+	printf(" {\n");
+	tagged_printf ("%u", m->int_n, m->name);
+	printf ("%smode,", m->name);
+	printf(" },\n");
+      }
+
+  print_closer ();
+}
+
 
 static void
 emit_insn_modes_c (void)
 {
   emit_insn_modes_c_header ();
   emit_mode_name ();
@@ -1403,12 +1463,13 @@ emit_insn_modes_c (void)
   emit_mode_base_align ();
   emit_class_narrowest_mode ();
   emit_real_format_for_mode ();
   emit_mode_adjustments ();
   emit_mode_ibit ();
   emit_mode_fbit ();
+  emit_mode_int_n ();
 }
 
 static void
 emit_min_insn_modes_c (void)
 {
   emit_min_insn_modes_c_header ();
Index: gimple.c
===================================================================
--- gimple.c	(revision 205719)
+++ gimple.c	(working copy)
@@ -2091,12 +2091,13 @@ gimple_compare_field_offset (tree f1, tr
    signed according to UNSIGNEDP.  */
 
 static tree
 gimple_signed_or_unsigned_type (bool unsignedp, tree type)
 {
   tree type1;
+  int i;
 
   type1 = TYPE_MAIN_VARIANT (type);
   if (type1 == signed_char_type_node
       || type1 == char_type_node
       || type1 == unsigned_char_type_node)
     return unsignedp ? unsigned_char_type_node : signed_char_type_node;
@@ -2112,12 +2113,20 @@ gimple_signed_or_unsigned_type (bool uns
            ? long_long_unsigned_type_node
 	   : long_long_integer_type_node;
   if (int128_integer_type_node && (type1 == int128_integer_type_node || type1 == int128_unsigned_type_node))
     return unsignedp
            ? int128_unsigned_type_node
 	   : int128_integer_type_node;
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+      if (type1 == int_n_trees[i].unsigned_type
+	  || type1 == int_n_trees[i].signed_type)
+	return unsignedp
+	  ? int_n_trees[i].unsigned_type
+	  : int_n_trees[i].signed_type;
+
 #if HOST_BITS_PER_WIDE_INT >= 64
   if (type1 == intTI_type_node || type1 == unsigned_intTI_type_node)
     return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
 #endif
   if (type1 == intDI_type_node || type1 == unsigned_intDI_type_node)
     return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
@@ -2229,12 +2238,18 @@ gimple_signed_or_unsigned_type (bool uns
 	    : long_long_integer_type_node);
   if (int128_integer_type_node && TYPE_OK (int128_integer_type_node))
     return (unsignedp
 	    ? int128_unsigned_type_node
 	    : int128_integer_type_node);
 
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (TYPE_MODE (type) == int_n_data[i].m && TYPE_PRECISION (type) == int_n_data[i].bitsize)
+	return unsignedp
+	  ? int_n_trees[i].unsigned_type
+	  : int_n_trees[i].signed_type;
+
 #if HOST_BITS_PER_WIDE_INT >= 64
   if (TYPE_OK (intTI_type_node))
     return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
 #endif
   if (TYPE_OK (intDI_type_node))
     return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
Index: config/msp430/msp430-modes.def
===================================================================
--- config/msp430/msp430-modes.def	(revision 205719)
+++ config/msp430/msp430-modes.def	(working copy)
@@ -1,3 +1,5 @@
 /* 20-bit address */
 PARTIAL_INT_MODE (SI, 20, PSI);
 
+INT_N (20, PSI);
+INT_N (64, TI);

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-12-10  3:35                                     ` DJ Delorie
@ 2013-12-10 17:17                                       ` Joseph S. Myers
  2013-12-10 18:10                                         ` DJ Delorie
                                                           ` (2 more replies)
  0 siblings, 3 replies; 47+ messages in thread
From: Joseph S. Myers @ 2013-12-10 17:17 UTC (permalink / raw)
  To: DJ Delorie; +Cc: richard.guenther, gcc

On Mon, 9 Dec 2013, DJ Delorie wrote:

> First pass at actual code.  I took the path of using a new macro in
> TARGET-modes.def and having genmodes build the relevent tables.  Part
> of the table is created by genmodes, the rest is created at runtime.

This seems mostly plausible, though I don't see anything to ensure that 
__intN does not exist at all if the size matches one of the standard C 
types, or if the mode fails targetm.scalar_mode_supported_p.  (To move 
__int128 to this system, given that its availability will depend on the 
options passed to the compiler, I suppose the macro call to create the 
type will be in machmode.def alongside the definition of TImode, but 
whether it does in fact end up creating a type will depend on such 
conditionals in the compiler - and code will need to check for NULL tree 
nodes for types not supported with the given options passed to the 
compiler.)

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-12-10 17:17                                       ` Joseph S. Myers
@ 2013-12-10 18:10                                         ` DJ Delorie
  2013-12-10 18:38                                           ` Joseph S. Myers
  2013-12-20  4:58                                         ` DJ Delorie
  2013-12-20 19:47                                         ` DJ Delorie
  2 siblings, 1 reply; 47+ messages in thread
From: DJ Delorie @ 2013-12-10 18:10 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: richard.guenther, gcc


> This seems mostly plausible, though I don't see anything to ensure that 
> __intN does not exist at all if the size matches one of the standard C 
> types,

My thought here was that, since each __intN is specified by the
target, they'd know to only do so if it doesn't match an existing (for
that target) type.  But what if it does?  What if the standard types
changed based on command line options, and the target wanted to offer
an __intN as a "this will always work" alternative to standard types?

I did code it such that standard types are preferred over __intN types
in the searches.

> or if the mode fails targetm.scalar_mode_supported_p.

As I mentioned, I haven't added that part yet.  My though there is to
add a runtime flag to the int_n_trees[] array and have each loop over
that data check the flag.  I suppose I could check for the types being
NULL but IIRC there are cases that only use the genmodes data and not
the types.  For aesthetic reasons I wanted to keep the flag separate.

> (To move __int128 to this system, given that its availability will

I put all the new code alongside the __int128 code, so the __int128
code can just be cut out after the new code is in place, but that's
down the road a bit.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-12-10 18:10                                         ` DJ Delorie
@ 2013-12-10 18:38                                           ` Joseph S. Myers
  2013-12-10 18:42                                             ` DJ Delorie
  0 siblings, 1 reply; 47+ messages in thread
From: Joseph S. Myers @ 2013-12-10 18:38 UTC (permalink / raw)
  To: DJ Delorie; +Cc: richard.guenther, gcc

On Tue, 10 Dec 2013, DJ Delorie wrote:

> > This seems mostly plausible, though I don't see anything to ensure that 
> > __intN does not exist at all if the size matches one of the standard C 
> > types,
> 
> My thought here was that, since each __intN is specified by the
> target, they'd know to only do so if it doesn't match an existing (for
> that target) type.  But what if it does?  What if the standard types
> changed based on command line options, and the target wanted to offer
> an __intN as a "this will always work" alternative to standard types?

If you have such alternative types, you have extra complications: either 
they are the same as a standard type (and you need to define what the 
order of preference is and keep it constant, to avoid __intN changing from 
int to long at random), or they are distinct (and you need to define 
integer promotion ranks and ensure the front end code handles promotions 
for types the same size as int correctly).  Not having such alternatives 
avoids such complications.  Thus, I'd rather any possibility of such types 
came later after the basic support for types not matching the standard 
types.

(For the types you do have, there's a need to define C++ name mangling.  
There are various other issues for such extended types - see PR 50441 
comment 3, and PR 43622 - but you can safely ignore such issues for now as 
pre-existing problems with __int128.  Whereas __int128 does have mangling 
defined in cp/mangle.c, and targets can already define their own mangling 
for target-specific types through a hook.)

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-12-10 18:38                                           ` Joseph S. Myers
@ 2013-12-10 18:42                                             ` DJ Delorie
  2013-12-11  9:27                                               ` Richard Biener
  0 siblings, 1 reply; 47+ messages in thread
From: DJ Delorie @ 2013-12-10 18:42 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: richard.guenther, gcc


> (For the types you do have, there's a need to define C++ name mangling.  

I mentioned this before, and I don't have a good solution for it.
Both C++ and LTO need a mangled form of __intN types.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-12-10 18:42                                             ` DJ Delorie
@ 2013-12-11  9:27                                               ` Richard Biener
  0 siblings, 0 replies; 47+ messages in thread
From: Richard Biener @ 2013-12-11  9:27 UTC (permalink / raw)
  To: DJ Delorie; +Cc: Joseph S. Myers, GCC Development

On Tue, Dec 10, 2013 at 7:42 PM, DJ Delorie <dj@redhat.com> wrote:
>
>> (For the types you do have, there's a need to define C++ name mangling.
>
> I mentioned this before, and I don't have a good solution for it.
> Both C++ and LTO need a mangled form of __intN types.

LTO shouldn't need any of this.  Ideally we'd reduce the number of
middle-end visible global trees down to the set that is fully defined
by the target C ABI.  All extra standard types relevant for frontends
would simply be streamed (you can as well stream all trees, including
the global ones - we chose to not stream them as optimization though
and because of pointer comparisons with them throughout the middle-end,
notably for va_list stuff).

Richard.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-12-10 17:17                                       ` Joseph S. Myers
  2013-12-10 18:10                                         ` DJ Delorie
@ 2013-12-20  4:58                                         ` DJ Delorie
  2013-12-20 12:42                                           ` Joseph S. Myers
  2013-12-20 19:47                                         ` DJ Delorie
  2 siblings, 1 reply; 47+ messages in thread
From: DJ Delorie @ 2013-12-20  4:58 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: richard.guenther, gcc


Where is the right place to set the array of "this __intN mode is
enabled" flags?  I initially set it in tree.c where __int128 is set
up, but that happens *after* c_parse_init() needs the flag to set up
the RID_* keywords for them.

Alternately, should I be calling targetm.scalar_mode_supported_p() all
over the place?  We'd need to be careful to not call that too early
too...

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-12-20  4:58                                         ` DJ Delorie
@ 2013-12-20 12:42                                           ` Joseph S. Myers
  0 siblings, 0 replies; 47+ messages in thread
From: Joseph S. Myers @ 2013-12-20 12:42 UTC (permalink / raw)
  To: DJ Delorie; +Cc: richard.guenther, gcc

On Thu, 19 Dec 2013, DJ Delorie wrote:

> Where is the right place to set the array of "this __intN mode is
> enabled" flags?  I initially set it in tree.c where __int128 is set
> up, but that happens *after* c_parse_init() needs the flag to set up
> the RID_* keywords for them.

Maybe immediately after the call to init_adjust_machine_modes from 
do_compile?  (It can't actually be inside backend_init, since it needs to 
happen even if just preprocessing - whether __SIZEOF_INT128__ gets defined 
depends on __int128 availability, and presumably you'll have such 
__SIZEOF_INT<N>__ macros for whichever such types are available - in which 
case no_backend is true.)

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-12-10 17:17                                       ` Joseph S. Myers
  2013-12-10 18:10                                         ` DJ Delorie
  2013-12-20  4:58                                         ` DJ Delorie
@ 2013-12-20 19:47                                         ` DJ Delorie
  2013-12-20 21:53                                           ` Joseph S. Myers
  2 siblings, 1 reply; 47+ messages in thread
From: DJ Delorie @ 2013-12-20 19:47 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: richard.guenther, gcc


> This seems mostly plausible, though I don't see anything to ensure that 
> __intN does not exist at all if the size matches one of the standard C 
> types, or if the mode fails targetm.scalar_mode_supported_p.

What do we check against for this?  Is there some table of standard
types we can read the bitsize of in toplev.c, or should we use the
macros as below?  What about float/vector/complex types?  I assume we
don't check those since the __intN types are integer types.

Also, should we special-case the int128 case so we always get __int128
if the backend supports TImode?

static bool
standard_type_bitsize (int bitsize)
{
  if (bitsize == 128)
    return false;
  if (bitsize == CHAR_TYPE_SIZE
      || bitsize == SHORT_TYPE_SIZE
      || bitsize == INT_TYPE_SIZE
      || bitsize == LONG_TYPE_SIZE
      || bitsize == LONG_LONG_TYPE_SIZE)
    return true;
  return false;
}

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-12-20 19:47                                         ` DJ Delorie
@ 2013-12-20 21:53                                           ` Joseph S. Myers
  2013-12-20 21:59                                             ` DJ Delorie
  0 siblings, 1 reply; 47+ messages in thread
From: Joseph S. Myers @ 2013-12-20 21:53 UTC (permalink / raw)
  To: DJ Delorie; +Cc: richard.guenther, gcc

On Fri, 20 Dec 2013, DJ Delorie wrote:

> > This seems mostly plausible, though I don't see anything to ensure that 
> > __intN does not exist at all if the size matches one of the standard C 
> > types, or if the mode fails targetm.scalar_mode_supported_p.
> 
> What do we check against for this?  Is there some table of standard
> types we can read the bitsize of in toplev.c, or should we use the
> macros as below?  What about float/vector/complex types?  I assume we
> don't check those since the __intN types are integer types.

I think using the macros for type sizes is fine, and float / vector / 
complex types are completely irrelevant to this (so standard_type_bitsize 
should maybe be standard_integer_type_bitsize).

> Also, should we special-case the int128 case so we always get __int128
> if the backend supports TImode?

No, the (TImode, __int128) pair should be handled the same way as all the 
other __intN types rather than special-cased (of course you should ensure 
the patch does not end up changing the set of configurations for which 
__int128 is available).

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-12-20 21:53                                           ` Joseph S. Myers
@ 2013-12-20 21:59                                             ` DJ Delorie
  2013-12-20 22:15                                               ` Joseph S. Myers
  0 siblings, 1 reply; 47+ messages in thread
From: DJ Delorie @ 2013-12-20 21:59 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: richard.guenther, gcc


> I think using the macros for type sizes is fine, and float / vector / 
> complex types are completely irrelevant to this (so standard_type_bitsize 
> should maybe be standard_integer_type_bitsize).

Whew.  Am I missing any in the previous code snippet (char, short,
int, long, long long) ?  Those were the ones documented in tm.texi.

> No, the (TImode, __int128) pair should be handled the same way as all the 
> other __intN types rather than special-cased (of course you should ensure 
> the patch does not end up changing the set of configurations for which 
> __int128 is available).

So if a target happened to set "long long" to TImode, it wouldn't have
__int128 any more?  I'm wondering if any ILP64 target would be
affected (x86-64 isn't, I don't think any others are).

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-12-20 21:59                                             ` DJ Delorie
@ 2013-12-20 22:15                                               ` Joseph S. Myers
  2013-12-20 22:40                                                 ` DJ Delorie
  0 siblings, 1 reply; 47+ messages in thread
From: Joseph S. Myers @ 2013-12-20 22:15 UTC (permalink / raw)
  To: DJ Delorie; +Cc: richard.guenther, gcc

On Fri, 20 Dec 2013, DJ Delorie wrote:

> > I think using the macros for type sizes is fine, and float / vector / 
> > complex types are completely irrelevant to this (so standard_type_bitsize 
> > should maybe be standard_integer_type_bitsize).
> 
> Whew.  Am I missing any in the previous code snippet (char, short,
> int, long, long long) ?  Those were the ones documented in tm.texi.

That's the correct list.

> > No, the (TImode, __int128) pair should be handled the same way as all the 
> > other __intN types rather than special-cased (of course you should ensure 
> > the patch does not end up changing the set of configurations for which 
> > __int128 is available).
> 
> So if a target happened to set "long long" to TImode, it wouldn't have
> __int128 any more?  I'm wondering if any ILP64 target would be
> affected (x86-64 isn't, I don't think any others are).

No existing target defines LONG_LONG_TYPE_SIZE to more than 64.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-12-20 22:15                                               ` Joseph S. Myers
@ 2013-12-20 22:40                                                 ` DJ Delorie
  2013-12-21  1:01                                                   ` Joseph S. Myers
  0 siblings, 1 reply; 47+ messages in thread
From: DJ Delorie @ 2013-12-20 22:40 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: richard.guenther, gcc


Ok, so I've got it checking for existing types and checking the target
for supported modes.  Any other features, or is it time for a second
patch?  Should I cut out the __int128 parts yet, or do you just want
to see the new code still?

To-Do: C++ parser, C++ mangling.  Still no idea what to do about
mangling.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-12-20 22:40                                                 ` DJ Delorie
@ 2013-12-21  1:01                                                   ` Joseph S. Myers
  2014-01-09  2:31                                                     ` DJ Delorie
  0 siblings, 1 reply; 47+ messages in thread
From: Joseph S. Myers @ 2013-12-21  1:01 UTC (permalink / raw)
  To: DJ Delorie; +Cc: richard.guenther, gcc

On Fri, 20 Dec 2013, DJ Delorie wrote:

> Ok, so I've got it checking for existing types and checking the target
> for supported modes.  Any other features, or is it time for a second
> patch?  Should I cut out the __int128 parts yet, or do you just want
> to see the new code still?

I think a patch is more useful once believe feature-complete, which means 
replacing the __int128 support with the new mechanism.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2013-12-21  1:01                                                   ` Joseph S. Myers
@ 2014-01-09  2:31                                                     ` DJ Delorie
  2014-01-09  3:23                                                       ` Joseph S. Myers
  0 siblings, 1 reply; 47+ messages in thread
From: DJ Delorie @ 2014-01-09  2:31 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: richard.guenther, gcc


> I think a patch is more useful once believe feature-complete, which
> means replacing the __int128 support with the new mechanism.

One of the side-effects of taking out the existing __int128 support is
that __int128 isn't in the integer_type_kind list, so isn't a type
that is usable for constants.  This breaks int128-4.C, which assumes a
128-bit integer constant.  If I add generic support for intN types in
i_t_k[], then we'll get (for example) 20-bit constants, which might
not be what we want.  The only other option is to special-case
__int128 if we find it in the __intN list.

Thoughts?

Also, I noted a few tests check for the int128-specific error message
when the type is not supported, but as per our previous discussion,
the __int128 keyword just doesn't exist if the type isn't supported.
Do we need to discern between "not supported with these options" and
"not supported ever" ?

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2014-01-09  2:31                                                     ` DJ Delorie
@ 2014-01-09  3:23                                                       ` Joseph S. Myers
  2014-01-09  7:02                                                         ` DJ Delorie
  0 siblings, 1 reply; 47+ messages in thread
From: Joseph S. Myers @ 2014-01-09  3:23 UTC (permalink / raw)
  To: DJ Delorie; +Cc: richard.guenther, gcc

On Wed, 8 Jan 2014, DJ Delorie wrote:

> > I think a patch is more useful once believe feature-complete, which
> > means replacing the __int128 support with the new mechanism.
> 
> One of the side-effects of taking out the existing __int128 support is
> that __int128 isn't in the integer_type_kind list, so isn't a type
> that is usable for constants.  This breaks int128-4.C, which assumes a
> 128-bit integer constant.  If I add generic support for intN types in

I don't see constants in that test.

It's not possible to write constants of type __int128 anyway.  It *is* 
possible to build them up using expressions casting narrower constants to 
__int128.  If you write a constant with a large value (with or without a 
suffix) that won't fit in target intmax_t / uintmax_t (or target long / 
unsigned long for C90), then you should get a pedwarn (and some larger 
type, maybe widest_integer_literal_type_node / 
widest_unsigned_literal_type_node, will be used if available).

> i_t_k[], then we'll get (for example) 20-bit constants, which might
> not be what we want.  The only other option is to special-case
> __int128 if we find it in the __intN list.

Integer constant types should be taken from the int / long / long long 
(and unsigned variants) list.  If a constant can't fit in any type ISO C 
allows for it, then it's reasonable to go on the extended types wider than 
long long, in increasing order of size, but __int20 is never relevant for 
constants as it's always narrower than long.

> Thoughts?

It's desirable anyway to have a way of representing what might be a 
standard type from integer_type_kind, or an extended type, given that it 
would be good for macros such as SIZE_TYPE to evaluate to enumerated 
values not magic strings.  Maybe a reserved space of itk_* values just 
like reserving RID_* values?

> Also, I noted a few tests check for the int128-specific error message
> when the type is not supported, but as per our previous discussion,
> the __int128 keyword just doesn't exist if the type isn't supported.
> Do we need to discern between "not supported with these options" and
> "not supported ever" ?

I don't think there's a need to distinguish, although I don't think it 
would be particularly harmful to have an __int128 keyword present without 
a corresponding type for targets not supporting __int128, if that helps 
diagnostics, as long as nothing else special-cases __int128.

(Draft TS 18661-3 has the interesting peculiarity that the keywords 
_FloatN for N = 16, 32, 64 or >= 128 and a multiple of 32, _DecimalN for N 
>= 32 and a multiple of 32, and _Float32x, _Float64x, _Float128x, 
_Decimal64x, _Decimal128x always exist as keywords whether or not the 
corresponding types are supported.  Implementing that would I suppose 
require special checks to handle arbitrary _FloatN and _DecimalN (for 
valid N) as keywords - an infinite number of keywords - much as we handle 
_Imaginary as a keyword without otherwise implementing it.)

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2014-01-09  3:23                                                       ` Joseph S. Myers
@ 2014-01-09  7:02                                                         ` DJ Delorie
  2014-01-09 16:22                                                           ` Joseph S. Myers
  0 siblings, 1 reply; 47+ messages in thread
From: DJ Delorie @ 2014-01-09  7:02 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: richard.guenther, gcc


> I don't see constants in that test.

// Test for int128 enums.
// { dg-do compile { target int128 } }
// { dg-options "" }

enum E {
  e1 = 0xffffffffffffffff,
  e2, e3
} e = e3;

#define SA(I,X) int a##I[(X)? 1 : -1]

SA(1, sizeof(E) == sizeof(__int128));

> Integer constant types should be taken from the int / long / long long 
> (and unsigned variants) list.  If a constant can't fit in any type ISO C 
> allows for it, then it's reasonable to go on the extended types wider than 
> long long, in increasing order of size, but __int20 is never relevant for 
> constants as it's always narrower than long.
> 
> > Thoughts?
> 
> It's desirable anyway to have a way of representing what might be a 
> standard type from integer_type_kind, or an extended type, given that it 
> would be good for macros such as SIZE_TYPE to evaluate to enumerated 
> values not magic strings.  Maybe a reserved space of itk_* values just 
> like reserving RID_* values?

It would have to be (1) sorted, and (2) kept in signed/unsigned pairs,
unless we take out the logic that uses it and replace it with
something that doesn't need that pattern.  The table exists only for
finding "smallest matching type" etc.

> I don't think there's a need to distinguish, although I don't think it 
> would be particularly harmful to have an __int128 keyword present without 
> a corresponding type for targets not supporting __int128, if that helps 
> diagnostics, as long as nothing else special-cases __int128.

So... OK if __int20 and __int128 keywords exist always (for ports that
request them, which for __int128 would be all of them), but still be
"unsupported" if for some reason the port doesn't support them because
of command line options?

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2014-01-09  7:02                                                         ` DJ Delorie
@ 2014-01-09 16:22                                                           ` Joseph S. Myers
  2014-01-15 12:48                                                             ` DJ Delorie
  0 siblings, 1 reply; 47+ messages in thread
From: Joseph S. Myers @ 2014-01-09 16:22 UTC (permalink / raw)
  To: DJ Delorie; +Cc: richard.guenther, gcc

On Wed, 8 Jan 2014, DJ Delorie wrote:

> So... OK if __int20 and __int128 keywords exist always (for ports that
> request them, which for __int128 would be all of them), but still be
> "unsupported" if for some reason the port doesn't support them because
> of command line options?

That seems reasonable.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2014-01-09 16:22                                                           ` Joseph S. Myers
@ 2014-01-15 12:48                                                             ` DJ Delorie
  2014-01-28 21:52                                                               ` DJ Delorie
  0 siblings, 1 reply; 47+ messages in thread
From: DJ Delorie @ 2014-01-15 12:48 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: richard.guenther, gcc


Ok, I think I got all the features in and all the backwards
compatibility working.  Big patch attached, including sample support
for msp430-elf.  Tested for x86-64 and msp430.

gcc/

	* machmode.h (int_n_data_t): New.
	(int_n_enabled_p): New.
	(int_n_data): New.
	* tree.c (int_n_enabled_p): New.
	(int_n_trees): New.
	(make_or_reuse_type): Check for all __intN types, not just
	__int128.
	(build_common_tree_nodes): Likewise.  Also fill in integer_typs[]
	entries.
	* tree.h (int128_integer_type_node): Remove.
	(int128_unsigned_type_node): Remove.
	(int_n_trees_t): New.
	(int_n_enabled_p): New.
	(int_n_trees): New.
	* toplev.c (standard_type_bitsize): New.
	(do_compile): Check which __intN types are enabled for the current
	run.
	* builtin-types.def (BT_INT128): Remove.
	(BT_UINT128): Remove.
	* machmode.def: Add macro to create __intN for all targets.
	* stor-layout.c (mode_for_size): Support __intN types.
	(smallest_mode_for_size): Likewise.
	* genmodes.c (struct mode_data): Add int_n field.
	(blank_mode): Likewise.
	(INT_N): New.
	(make_int_n): New.
	(emit_insn_modes_h): Count __intN entries and define
	NUM_INT_N_ENTS.
	(emit_mode_int_n): New.
	(emit_insn_modes_c): Call it.
	* gimple.c (gimple_signed_or_unsigned_type): Check for all __intN
	types, not just __int128.
	* tree-core.h (integer_type_kind): Remove __int128-specific
	entries, reserve spots for __intN entries.

	* config/msp430/msp430.c (msp430_scalar_mode_supported_p): New.
	* config/msp430/msp430-modes.def: Add __int20 macro.

gcc/c-family/

	* c-pretty-print.c (pp_c_integer_constant): Check for all __intN
	types, not just __int128.
	* c-cppbuiltin.c (c_cpp_builtins): Add builtins for all __intN
	types, not just __int128.
	* c-common.c (c_common_reswords): Remove __int128 special case.
	(c_common_type_for_size): Check for all __intN types, not just
	__int128.
	(c_common_type_for_mode): Likewise.
	(c_common_signed_or_unsigned_type): Likewise.
	(c_build_bitfield_integer_type): Likewise.
	(c_common_nodes_and_builtins): Likewise.
	(keyword_begins_type_specifier): Likewise.
	* c-common.h (rid): Remove RID_INT128 and add RID_INT_N_* for all
	__intN variants.

gcc/c/

	* c-parser.c (c_parse_init): Add RID entries for each __intN.
	(c_token_starts_typename): Check all __intN, not just __int128.
	(c_token_starts_declspecs): Likewise.
	(c_parser_declspecs): Likewise.
	(c_parser_attribute_any_word): Likewise.
	(c_parser_objc_selector): Likewise.
	* c-tree.h (c_typespec_keyword): cts_int128 -> cts_int_n.
	(struct c_declspecs): Add int_n_idx field to record *which* __intN
	is specified.
	* c-decl.c (declspecs_add_type): Check for all __intN, not just
	__int128.
	(finish_declspecs): Likewise.

gcc/cp/
	* typeck.c (cp_common_type): Check for all __intN types, not just
	__int128.
	* decl.c (grokdeclarator): Likewise.
	* rtti.c (emit_support_tinfos): Remove __int128-specific entries.
	* parser.c (cp_lexer_next_token_is_decl_specifier_keyword): Check
	for all __intN types, not just __int128.
	(cp_parser_simple_type_specifier): Likewise.
	* mangle.c (integer_type_codes): Remove int128-specific codes.
	* cp-tree.h (cp_decl_specifier_seq): Add int_n_idx to store which
	__intN was specified.
	* lex.c (init_reswords): Reserve all __intN keywords.


Index: machmode.h
===================================================================
--- machmode.h	(revision 206609)
+++ machmode.h	(working copy)
@@ -322,7 +322,19 @@ extern void init_adjust_machine_modes (v
 			 GET_MODE_PRECISION (MODE2))
 
 #define HWI_COMPUTABLE_MODE_P(MODE) \
   (SCALAR_INT_MODE_P (MODE) \
    && GET_MODE_PRECISION (MODE) <= HOST_BITS_PER_WIDE_INT)
 
+typedef struct {
+  /* These parts are initailized by genmodes output */
+  unsigned int bitsize;
+  enum machine_mode m;
+  /* RID_* is RID_INTN_BASE + index into this array */
+} int_n_data_t;
+
+/* This is also in tree.h.  genmodes.c guarantees the're sorted from
+   smallest bitsize to largest bitsize. */
+extern bool int_n_enabled_p[NUM_INT_N_ENTS];
+extern const int_n_data_t int_n_data[NUM_INT_N_ENTS];
+
 #endif /* not HAVE_MACHINE_MODES */
Index: c-family/c-pretty-print.c
===================================================================
--- c-family/c-pretty-print.c	(revision 206609)
+++ c-family/c-pretty-print.c	(working copy)
@@ -907,12 +907,14 @@ pp_c_string_literal (c_pretty_printer *p
 
 /* Pretty-print an INTEGER literal.  */
 
 static void
 pp_c_integer_constant (c_pretty_printer *pp, tree i)
 {
+  int idx;
+
   /* We are going to compare the type of I to other types using
      pointer comparison so we need to use its canonical type.  */
   tree type =
     TYPE_CANONICAL (TREE_TYPE (i))
     ? TYPE_CANONICAL (TREE_TYPE (i))
     : TREE_TYPE (i);
@@ -939,15 +941,23 @@ pp_c_integer_constant (c_pretty_printer 
     pp_character (pp, 'u');
   if (type == long_integer_type_node || type == long_unsigned_type_node)
     pp_character (pp, 'l');
   else if (type == long_long_integer_type_node
 	   || type == long_long_unsigned_type_node)
     pp_string (pp, "ll");
-  else if (type == int128_integer_type_node
-           || type == int128_unsigned_type_node)
-    pp_string (pp, "I128");
+  else for (idx = 0; idx < NUM_INT_N_ENTS; idx ++)
+    if (int_n_enabled_p[idx])
+      {
+	char buf[2+20];
+	if (type == int_n_trees[idx].signed_type
+	    || type == int_n_trees[idx].unsigned_type)
+	  {
+	    sprintf (buf, "I%d", int_n_data[idx].bitsize);
+	    pp_string (pp, buf);
+	  }
+      }
 }
 
 /* Print out a CHARACTER literal.  */
 
 static void
 pp_c_character_constant (c_pretty_printer *pp, tree c)
Index: c-family/c-cppbuiltin.c
===================================================================
--- c-family/c-cppbuiltin.c	(revision 206609)
+++ c-family/c-cppbuiltin.c	(working copy)
@@ -775,12 +775,14 @@ cpp_iec_559_complex_value (void)
 }
 
 /* Hook that registers front end and target-specific built-ins.  */
 void
 c_cpp_builtins (cpp_reader *pfile)
 {
+  int i;
+
   /* -undef turns off target-specific built-ins.  */
   if (flag_undef)
     return;
 
   define_language_independent_builtin_macros (pfile);
 
@@ -993,15 +995,20 @@ c_cpp_builtins (cpp_reader *pfile)
   else if (flag_stack_protect == 1)
     cpp_define (pfile, "__SSP__=1");
 
   if (flag_openmp)
     cpp_define (pfile, "_OPENMP=201307");
 
-  if (int128_integer_type_node != NULL_TREE)
-    builtin_define_type_sizeof ("__SIZEOF_INT128__",
-			        int128_integer_type_node);
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i])
+      {
+	char buf[15+20];
+	sprintf(buf, "__SIZEOF_INT%d__", int_n_data[i].bitsize);
+	builtin_define_type_sizeof (buf,
+				    int_n_trees[i].signed_type);
+      }
   builtin_define_type_sizeof ("__SIZEOF_WCHAR_T__", wchar_type_node);
   builtin_define_type_sizeof ("__SIZEOF_WINT_T__", wint_type_node);
   builtin_define_type_sizeof ("__SIZEOF_PTRDIFF_T__",
 			      unsigned_ptrdiff_type_node);
 
   /* A straightforward target hook doesn't work, because of problems
Index: c-family/c-common.c
===================================================================
--- c-family/c-common.c	(revision 206609)
+++ c-family/c-common.c	(working copy)
@@ -57,18 +57,16 @@ cpp_reader *parse_in;		/* Declared in c-
 
    INTEGER_TYPE and REAL_TYPE nodes for the standard data types.
 
 	tree short_integer_type_node;
 	tree long_integer_type_node;
 	tree long_long_integer_type_node;
-	tree int128_integer_type_node;
 
 	tree short_unsigned_type_node;
 	tree long_unsigned_type_node;
 	tree long_long_unsigned_type_node;
-	tree int128_unsigned_type_node;
 
 	tree truthvalue_type_node;
 	tree truthvalue_false_node;
 	tree truthvalue_true_node;
 
 	tree ptrdiff_type_node;
@@ -458,13 +456,12 @@ const struct c_common_resword c_common_r
   { "__has_trivial_destructor", RID_HAS_TRIVIAL_DESTRUCTOR, D_CXXONLY },
   { "__has_virtual_destructor", RID_HAS_VIRTUAL_DESTRUCTOR, D_CXXONLY },
   { "__imag",		RID_IMAGPART,	0 },
   { "__imag__",		RID_IMAGPART,	0 },
   { "__inline",		RID_INLINE,	0 },
   { "__inline__",	RID_INLINE,	0 },
-  { "__int128",		RID_INT128,	0 },
   { "__is_abstract",	RID_IS_ABSTRACT, D_CXXONLY },
   { "__is_base_of",	RID_IS_BASE_OF, D_CXXONLY },
   { "__is_class",	RID_IS_CLASS,	D_CXXONLY },
   { "__is_convertible_to", RID_IS_CONVERTIBLE_TO, D_CXXONLY },
   { "__is_empty",	RID_IS_EMPTY,	D_CXXONLY },
   { "__is_enum",	RID_IS_ENUM,	D_CXXONLY },
@@ -3385,12 +3382,14 @@ check_case_bounds (tree type, tree orig_
 /* Return an integer type with BITS bits of precision,
    that is unsigned if UNSIGNEDP is nonzero, otherwise signed.  */
 
 tree
 c_common_type_for_size (unsigned int bits, int unsignedp)
 {
+  int i;
+
   if (bits == TYPE_PRECISION (integer_type_node))
     return unsignedp ? unsigned_type_node : integer_type_node;
 
   if (bits == TYPE_PRECISION (signed_char_type_node))
     return unsignedp ? unsigned_char_type_node : signed_char_type_node;
 
@@ -3401,16 +3400,17 @@ c_common_type_for_size (unsigned int bit
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
 
   if (bits == TYPE_PRECISION (long_long_integer_type_node))
     return (unsignedp ? long_long_unsigned_type_node
 	    : long_long_integer_type_node);
 
-  if (int128_integer_type_node
-      && bits == TYPE_PRECISION (int128_integer_type_node))
-    return (unsignedp ? int128_unsigned_type_node
-	    : int128_integer_type_node);
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+	&& bits == int_n_data[i].bitsize)
+      return (unsignedp ? int_n_trees[i].unsigned_type
+	      : int_n_trees[i].signed_type);
 
   if (bits == TYPE_PRECISION (widest_integer_literal_type_node))
     return (unsignedp ? widest_unsigned_literal_type_node
 	    : widest_integer_literal_type_node);
 
   if (bits <= TYPE_PRECISION (intQI_type_node))
@@ -3468,12 +3468,13 @@ static GTY(()) tree registered_builtin_t
    then UNSIGNEDP selects between saturating and nonsaturating types.  */
 
 tree
 c_common_type_for_mode (enum machine_mode mode, int unsignedp)
 {
   tree t;
+  int i;
 
   if (mode == TYPE_MODE (integer_type_node))
     return unsignedp ? unsigned_type_node : integer_type_node;
 
   if (mode == TYPE_MODE (signed_char_type_node))
     return unsignedp ? unsigned_char_type_node : signed_char_type_node;
@@ -3484,15 +3485,17 @@ c_common_type_for_mode (enum machine_mod
   if (mode == TYPE_MODE (long_integer_type_node))
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
 
   if (mode == TYPE_MODE (long_long_integer_type_node))
     return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
 
-  if (int128_integer_type_node
-      && mode == TYPE_MODE (int128_integer_type_node))
-    return unsignedp ? int128_unsigned_type_node : int128_integer_type_node;
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+	&& mode == int_n_data[i].m)
+      return (unsignedp ? int_n_trees[i].unsigned_type
+	      : int_n_trees[i].signed_type);
 
   if (mode == TYPE_MODE (widest_integer_literal_type_node))
     return unsignedp ? widest_unsigned_literal_type_node
 		     : widest_integer_literal_type_node;
 
   if (mode == QImode)
@@ -3684,12 +3687,13 @@ c_common_signed_type (tree type)
    signed according to UNSIGNEDP.  */
 
 tree
 c_common_signed_or_unsigned_type (int unsignedp, tree type)
 {
   tree type1;
+  int i;
 
   /* This block of code emulates the behavior of the old
      c_common_unsigned_type. In particular, it returns
      long_unsigned_type_node if passed a long, even when a int would
      have the same size. This is necessary for warnings to work
      correctly in archs where sizeof(int) == sizeof(long) */
@@ -3702,16 +3706,20 @@ c_common_signed_or_unsigned_type (int un
   if (type1 == short_integer_type_node || type1 == short_unsigned_type_node)
     return unsignedp ? short_unsigned_type_node : short_integer_type_node;
   if (type1 == long_integer_type_node || type1 == long_unsigned_type_node)
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
   if (type1 == long_long_integer_type_node || type1 == long_long_unsigned_type_node)
     return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
-  if (int128_integer_type_node
-      && (type1 == int128_integer_type_node
-	  || type1 == int128_unsigned_type_node))
-    return unsignedp ? int128_unsigned_type_node : int128_integer_type_node;
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+	&& (type1 == int_n_trees[i].unsigned_type
+	    || type1 == int_n_trees[i].signed_type))
+      return (unsignedp ? int_n_trees[i].unsigned_type
+	      : int_n_trees[i].signed_type);
+
   if (type1 == widest_integer_literal_type_node || type1 == widest_unsigned_literal_type_node)
     return unsignedp ? widest_unsigned_literal_type_node : widest_integer_literal_type_node;
 #if HOST_BITS_PER_WIDE_INT >= 64
   if (type1 == intTI_type_node || type1 == unsigned_intTI_type_node)
     return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
 #endif
@@ -3820,15 +3828,20 @@ c_common_signed_or_unsigned_type (int un
     return unsignedp ? short_unsigned_type_node : short_integer_type_node;
   if (TYPE_OK (long_integer_type_node))
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
   if (TYPE_OK (long_long_integer_type_node))
     return (unsignedp ? long_long_unsigned_type_node
 	    : long_long_integer_type_node);
-  if (int128_integer_type_node && TYPE_OK (int128_integer_type_node))
-    return (unsignedp ? int128_unsigned_type_node
-	    : int128_integer_type_node);
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+	&& TYPE_MODE (type) == int_n_data[i].m
+	&& TYPE_PRECISION (type) == int_n_data[i].bitsize)
+      return (unsignedp ? int_n_trees[i].unsigned_type
+	      : int_n_trees[i].signed_type);
+
   if (TYPE_OK (widest_integer_literal_type_node))
     return (unsignedp ? widest_unsigned_literal_type_node
 	    : widest_integer_literal_type_node);
 
 #if HOST_BITS_PER_WIDE_INT >= 64
   if (TYPE_OK (intTI_type_node))
@@ -3849,12 +3862,14 @@ c_common_signed_or_unsigned_type (int un
 
 /* Build a bit-field integer type for the given WIDTH and UNSIGNEDP.  */
 
 tree
 c_build_bitfield_integer_type (unsigned HOST_WIDE_INT width, int unsignedp)
 {
+  int i;
+
   /* Extended integer types of the same width as a standard type have
      lesser rank, so those of the same width as int promote to int or
      unsigned int and are valid for printf formats expecting int or
      unsigned int.  To avoid such special cases, avoid creating
      extended integer types for bit-fields if a standard integer type
      is available.  */
@@ -3866,16 +3881,17 @@ c_build_bitfield_integer_type (unsigned 
     return unsignedp ? short_unsigned_type_node : short_integer_type_node;
   if (width == TYPE_PRECISION (long_integer_type_node))
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
   if (width == TYPE_PRECISION (long_long_integer_type_node))
     return (unsignedp ? long_long_unsigned_type_node
 	    : long_long_integer_type_node);
-  if (int128_integer_type_node
-      && width == TYPE_PRECISION (int128_integer_type_node))
-    return (unsignedp ? int128_unsigned_type_node
-	    : int128_integer_type_node);
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+	&& width == int_n_data[i].bitsize)
+      return (unsignedp ? int_n_trees[i].unsigned_type
+	      : int_n_trees[i].signed_type);
   return build_nonstandard_integer_type (width, unsignedp);
 }
 
 /* The C version of the register_builtin_type langhook.  */
 
 void
@@ -5283,12 +5299,13 @@ c_common_nodes_and_builtins (void)
   int char16_type_size;
   int char32_type_size;
   int wchar_type_size;
   tree array_domain_type;
   tree va_list_ref_type_node;
   tree va_list_arg_type_node;
+  int i;
 
   build_common_tree_nodes (flag_signed_char, flag_short_double);
 
   /* Define `int' and `char' first so that dbx will output them first.  */
   record_builtin_type (RID_INT, NULL, integer_type_node);
   record_builtin_type (RID_CHAR, "char", char_type_node);
@@ -5299,19 +5316,25 @@ c_common_nodes_and_builtins (void)
   if (c_dialect_cxx ())
     record_builtin_type (RID_SIGNED, NULL, integer_type_node);
   record_builtin_type (RID_LONG, "long int", long_integer_type_node);
   record_builtin_type (RID_UNSIGNED, "unsigned int", unsigned_type_node);
   record_builtin_type (RID_MAX, "long unsigned int",
 		       long_unsigned_type_node);
-  if (int128_integer_type_node != NULL_TREE)
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
     {
-      record_builtin_type (RID_INT128, "__int128",
-			   int128_integer_type_node);
-      record_builtin_type (RID_MAX, "__int128 unsigned",
-			   int128_unsigned_type_node);
+      char name[25];
+
+      sprintf (name, "__int%d", int_n_data[i].bitsize);
+      record_builtin_type ((enum rid)(RID_FIRST_INT_N + i), name,
+			   int_n_trees[i].signed_type);
+      sprintf (name, "__int%d unsigned", int_n_data[i].bitsize);
+      record_builtin_type (RID_MAX, name,
+			   int_n_trees[i].unsigned_type);
     }
+
   if (c_dialect_cxx ())
     record_builtin_type (RID_MAX, "unsigned long", long_unsigned_type_node);
   record_builtin_type (RID_MAX, "long long int",
 		       long_long_integer_type_node);
   record_builtin_type (RID_MAX, "long long unsigned int",
 		       long_long_unsigned_type_node);
@@ -5341,12 +5364,14 @@ c_common_nodes_and_builtins (void)
 					 TYPE_DECL, NULL_TREE,
 					 intSI_type_node));
   lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
 					 TYPE_DECL, NULL_TREE,
 					 intDI_type_node));
 #if HOST_BITS_PER_WIDE_INT >= 64
+  /* Note that this is different than the __int128 type that's part of
+     the generic __intN support.  */
   if (targetm.scalar_mode_supported_p (TImode))
     lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
 					   TYPE_DECL,
 					   get_identifier ("__int128_t"),
 					   intTI_type_node));
 #endif
@@ -11547,13 +11572,12 @@ keyword_begins_type_specifier (enum rid 
     case RID_AUTO_TYPE:
     case RID_INT:
     case RID_CHAR:
     case RID_FLOAT:
     case RID_DOUBLE:
     case RID_VOID:
-    case RID_INT128:
     case RID_UNSIGNED:
     case RID_LONG:
     case RID_SHORT:
     case RID_SIGNED:
     case RID_DFLOAT32:
     case RID_DFLOAT64:
@@ -11570,12 +11594,16 @@ keyword_begins_type_specifier (enum rid 
     case RID_STRUCT:
     case RID_CLASS:
     case RID_UNION:
     case RID_ENUM:
       return true;
     default:
+      if (keyword >= RID_FIRST_INT_N
+	  && keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
+	  && int_n_enabled_p[keyword-RID_FIRST_INT_N])
+	return true;
       return false;
     }
 }
 
 /* Return true if KEYWORD names a type qualifier.  */
 
Index: c-family/c-common.h
===================================================================
--- c-family/c-common.h	(revision 206609)
+++ c-family/c-common.h	(working copy)
@@ -88,13 +88,12 @@ enum rid
   /* C (reserved and imaginary types not implemented, so any use is a
      syntax error) */
   RID_IMAGINARY,
 
   /* C */
   RID_INT,     RID_CHAR,   RID_FLOAT,    RID_DOUBLE, RID_VOID,
-  RID_INT128,
   RID_ENUM,    RID_STRUCT, RID_UNION,    RID_IF,     RID_ELSE,
   RID_WHILE,   RID_DO,     RID_FOR,      RID_SWITCH, RID_CASE,
   RID_DEFAULT, RID_BREAK,  RID_CONTINUE, RID_RETURN, RID_GOTO,
   RID_SIZEOF,
 
   /* C extensions */
@@ -185,12 +184,29 @@ enum rid
   RID_ADDR_SPACE_14,
   RID_ADDR_SPACE_15,
 
   RID_FIRST_ADDR_SPACE = RID_ADDR_SPACE_0,
   RID_LAST_ADDR_SPACE = RID_ADDR_SPACE_15,
 
+  /* __intN_t keywords.  The _N_M here doesn't correspond to the intN
+     in the keyword; use the bitsize in int_n_t_data_t[M] for that.
+     For example, if int_n_t_data_t[0].bitsize is 13, then RID_INT_N_0
+     is for __int13_t.  */
+
+  /* Note that the range to use is RID_FIRST_INT_N through
+     RID_FIRST_INT_N + NUM_INT_N_ENTS - 1 and c-parser.c has a list of
+     all RID_INT_N_* in a case statement.  */
+
+  RID_INT_N_0,
+  RID_INT_N_1,
+  RID_INT_N_2,
+  RID_INT_N_3,
+
+  RID_FIRST_INT_N = RID_INT_N_0,
+  RID_LAST_INT_N = RID_INT_N_3,
+
   RID_MAX,
 
   RID_FIRST_MODIFIER = RID_STATIC,
   RID_LAST_MODIFIER = RID_ONEWAY,
 
   RID_FIRST_CXX0X = RID_CONSTEXPR,
Index: c/c-parser.c
===================================================================
--- c/c-parser.c	(revision 206609)
+++ c/c-parser.c	(working copy)
@@ -109,12 +109,22 @@ c_parse_init (void)
 
       id = get_identifier (c_common_reswords[i].word);
       C_SET_RID_CODE (id, c_common_reswords[i].rid);
       C_IS_RESERVED_WORD (id) = 1;
       ridpointers [(int) c_common_reswords[i].rid] = id;
     }
+
+  for (i = 0; i < NUM_INT_N_ENTS; i++)
+    // We always create the symbols but they aren't always supported
+    {
+      char name[50];
+      sprintf (name, "__int%d", int_n_data[i].bitsize);
+      id = get_identifier (name);
+      C_SET_RID_CODE (id, RID_FIRST_INT_N + i);
+      C_IS_RESERVED_WORD (id) = 1;
+    }
 }
 \f
 /* The C lexer intermediates between the lexer in cpplib and c-lex.c
    and the C parser.  Unlike the C++ lexer, the parser structure
    stores the lexer information instead of using a separate structure.
    Identifiers are separated into ordinary identifiers, type names,
@@ -484,13 +494,12 @@ c_token_starts_typename (c_token *token)
 	}
     case CPP_KEYWORD:
       switch (token->keyword)
 	{
 	case RID_UNSIGNED:
 	case RID_LONG:
-	case RID_INT128:
 	case RID_SHORT:
 	case RID_SIGNED:
 	case RID_COMPLEX:
 	case RID_INT:
 	case RID_CHAR:
 	case RID_FLOAT:
@@ -512,12 +521,16 @@ c_token_starts_typename (c_token *token)
 	case RID_FRACT:
 	case RID_ACCUM:
 	case RID_SAT:
 	case RID_AUTO_TYPE:
 	  return true;
 	default:
+	  if (token->keyword >= RID_FIRST_INT_N
+	      && token->keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
+	      && int_n_enabled_p[token->keyword - RID_FIRST_INT_N])
+	    return true;
 	  return false;
 	}
     case CPP_LESS:
       if (c_dialect_objc ())
 	return true;
       return false;
@@ -642,13 +655,12 @@ c_token_starts_declspecs (c_token *token
 	case RID_INLINE:
 	case RID_NORETURN:
 	case RID_AUTO:
 	case RID_THREAD:
 	case RID_UNSIGNED:
 	case RID_LONG:
-	case RID_INT128:
 	case RID_SHORT:
 	case RID_SIGNED:
 	case RID_COMPLEX:
 	case RID_INT:
 	case RID_CHAR:
 	case RID_FLOAT:
@@ -671,12 +683,16 @@ c_token_starts_declspecs (c_token *token
 	case RID_SAT:
 	case RID_ALIGNAS:
 	case RID_ATOMIC:
 	case RID_AUTO_TYPE:
 	  return true;
 	default:
+	  if (token->keyword >= RID_FIRST_INT_N
+	      && token->keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
+	      && int_n_enabled_p[token->keyword - RID_FIRST_INT_N])
+	    return true;
 	  return false;
 	}
     case CPP_LESS:
       if (c_dialect_objc ())
 	return true;
       return false;
@@ -2136,13 +2152,13 @@ c_parser_static_assert_declaration_no_se
    storage-class-specifier:
      __thread
 
    type-specifier:
      typeof-specifier
      __auto_type
-     __int128
+     __intN
      _Decimal32
      _Decimal64
      _Decimal128
      _Fract
      _Accum
      _Sat
@@ -2290,13 +2306,12 @@ c_parser_declspecs (c_parser *parser, st
 	case RID_AUTO_TYPE:
 	  if (!auto_type_ok)
 	    goto out;
 	  /* Fall through.  */
 	case RID_UNSIGNED:
 	case RID_LONG:
-	case RID_INT128:
 	case RID_SHORT:
 	case RID_SIGNED:
 	case RID_COMPLEX:
 	case RID_INT:
 	case RID_CHAR:
 	case RID_FLOAT:
@@ -2306,12 +2321,16 @@ c_parser_declspecs (c_parser *parser, st
 	case RID_DFLOAT64:
 	case RID_DFLOAT128:
 	case RID_BOOL:
 	case RID_FRACT:
 	case RID_ACCUM:
 	case RID_SAT:
+	case RID_INT_N_0:
+	case RID_INT_N_1:
+	case RID_INT_N_2:
+	case RID_INT_N_3:
 	  if (!typespec_ok)
 	    goto out;
 	  attrs_ok = true;
 	  seen_type = true;
 	  if (c_dialect_objc ())
 	    parser->objc_need_raw_identifier = true;
@@ -3726,13 +3745,12 @@ c_parser_attribute_any_word (c_parser *p
       bool ok;
       switch (c_parser_peek_token (parser)->keyword)
 	{
 	case RID_STATIC:
 	case RID_UNSIGNED:
 	case RID_LONG:
-	case RID_INT128:
 	case RID_CONST:
 	case RID_EXTERN:
 	case RID_REGISTER:
 	case RID_TYPEDEF:
 	case RID_SHORT:
 	case RID_INLINE:
@@ -3756,12 +3774,16 @@ c_parser_attribute_any_word (c_parser *p
 	case RID_ACCUM:
 	case RID_SAT:
 	case RID_TRANSACTION_ATOMIC:
 	case RID_TRANSACTION_CANCEL:
 	case RID_ATOMIC:
 	case RID_AUTO_TYPE:
+	case RID_INT_N_0:
+	case RID_INT_N_1:
+	case RID_INT_N_2:
+	case RID_INT_N_3:
 	  ok = true;
 	  break;
 	default:
 	  ok = false;
 	  break;
 	}
@@ -8888,13 +8910,12 @@ c_parser_objc_selector (c_parser *parser
     case RID_ASM:
     case RID_SIZEOF:
     case RID_TYPEOF:
     case RID_ALIGNOF:
     case RID_UNSIGNED:
     case RID_LONG:
-    case RID_INT128:
     case RID_CONST:
     case RID_SHORT:
     case RID_VOLATILE:
     case RID_SIGNED:
     case RID_RESTRICT:
     case RID_COMPLEX:
@@ -8909,12 +8930,16 @@ c_parser_objc_selector (c_parser *parser
     case RID_FLOAT:
     case RID_DOUBLE:
     case RID_VOID:
     case RID_BOOL:
     case RID_ATOMIC:
     case RID_AUTO_TYPE:
+    case RID_INT_N_0:
+    case RID_INT_N_1:
+    case RID_INT_N_2:
+    case RID_INT_N_3:
       c_parser_consume_token (parser);
       return value;
     default:
       return NULL_TREE;
     }
 }
Index: c/c-tree.h
===================================================================
--- c/c-tree.h	(revision 206609)
+++ c/c-tree.h	(working copy)
@@ -205,13 +205,13 @@ enum c_typespec_keyword {
   cts_none,
   cts_void,
   cts_bool,
   cts_char,
   cts_int,
   cts_float,
-  cts_int128,
+  cts_int_n,
   cts_double,
   cts_dfloat32,
   cts_dfloat64,
   cts_dfloat128,
   cts_fract,
   cts_accum,
@@ -272,12 +272,14 @@ struct c_declspecs {
      separately.  */
   tree attrs;
   /* The base-2 log of the greatest alignment required by an _Alignas
      specifier, in bytes, or -1 if no such specifiers with nonzero
      alignment.  */
   int align_log;
+  /* For the __intN declspec, this stores the index into the int_n_* arrays.  */
+  int int_n_idx;
   /* The storage class specifier, or csc_none if none.  */
   enum c_storage_class storage_class;
   /* Any type specifier keyword used such as "int", not reflecting
      modifiers such as "short", or cts_none if none.  */
   ENUM_BITFIELD (c_typespec_keyword) typespec_word : 8;
   /* The kind of type specifier if one has been seen, ctsk_none
Index: c/c-decl.c
===================================================================
--- c/c-decl.c	(revision 206609)
+++ c/c-decl.c	(working copy)
@@ -9147,16 +9147,17 @@ declspecs_add_type (location_t loc, stru
 			  ("both %<long%> and %<__auto_type%> in "
 			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_void)
 		error_at (loc,
 			  ("both %<long%> and %<void%> in "
 			   "declaration specifiers"));
-	      else if (specs->typespec_word == cts_int128)
+	      else if (specs->typespec_word == cts_int_n)
 		  error_at (loc,
-			    ("both %<long%> and %<__int128%> in "
-			     "declaration specifiers"));
+			    ("both %<long%> and %<__int%d%> in "
+			     "declaration specifiers"),
+			    int_n_data[specs->int_n_idx].bitsize);
 	      else if (specs->typespec_word == cts_bool)
 		error_at (loc,
 			  ("both %<long%> and %<_Bool%> in "
 			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_char)
 		error_at (loc,
@@ -9195,16 +9196,17 @@ declspecs_add_type (location_t loc, stru
 			  ("both %<short%> and %<__auto_type%> in "
 			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_void)
 		error_at (loc,
 			  ("both %<short%> and %<void%> in "
 			   "declaration specifiers"));
-	      else if (specs->typespec_word == cts_int128)
+	      else if (specs->typespec_word == cts_int_n)
 		error_at (loc,
-			  ("both %<short%> and %<__int128%> in "
-			   "declaration specifiers"));
+			  ("both %<short%> and %<__int%d%> in "
+			   "declaration specifiers"),
+			  int_n_data[specs->int_n_idx].bitsize);
 	      else if (specs->typespec_word == cts_bool)
 		error_at (loc,
 			  ("both %<short%> and %<_Bool%> in "
 			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_char)
 		error_at (loc,
@@ -9372,17 +9374,18 @@ declspecs_add_type (location_t loc, stru
 		}
 	      break;
 	    case RID_SAT:
 	      dupe = specs->saturating_p;
 	      pedwarn (loc, OPT_Wpedantic,
 		       "ISO C does not support saturating types");
-	      if (specs->typespec_word == cts_int128)
+	      if (specs->typespec_word == cts_int_n)
 	        {
 		  error_at (loc,
-			    ("both %<_Sat%> and %<__int128%> in "
-			     "declaration specifiers"));
+			    ("both %<_Sat%> and %<__int%d%> in "
+			     "declaration specifiers"),
+			    int_n_data[specs->int_n_idx].bitsize);
 	        }
 	      else if (specs->typespec_word == cts_auto_type)
 		error_at (loc,
 			  ("both %<_Sat%> and %<__auto_type%> in "
 			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_void)
@@ -9440,13 +9443,13 @@ declspecs_add_type (location_t loc, stru
 
 	  return specs;
 	}
       else
 	{
 	  /* "void", "_Bool", "char", "int", "float", "double", "_Decimal32",
-	     "__int128", "_Decimal64", "_Decimal128", "_Fract", "_Accum" or
+	     "__intN", "_Decimal64", "_Decimal128", "_Fract", "_Accum" or
 	     "__auto_type".  */
 	  if (specs->typespec_word != cts_none)
 	    {
 	      error_at (loc,
 			"two or more data types in declaration specifiers");
 	      return specs;
@@ -9481,37 +9484,44 @@ declspecs_add_type (location_t loc, stru
 	      else
 		{
 		  specs->typespec_word = cts_auto_type;
 		  specs->locations[cdw_typespec] = loc;
 		}
 	      return specs;
-	    case RID_INT128:
-	      if (int128_integer_type_node == NULL_TREE)
-		{
-		  error_at (loc, "%<__int128%> is not supported for this target");
-		  return specs;
-		}
+	    case RID_INT_N_0:
+	    case RID_INT_N_1:
+	    case RID_INT_N_2:
+	    case RID_INT_N_3:
+	      specs->int_n_idx = i - RID_INT_N_0;
 	      if (!in_system_header_at (input_location))
 		pedwarn (loc, OPT_Wpedantic,
-			 "ISO C does not support %<__int128%> type");
+			 "ISO C does not support %<__int%d%> types",
+			 int_n_data[specs->int_n_idx].bitsize);
 
 	      if (specs->long_p)
 		error_at (loc,
-			  ("both %<__int128%> and %<long%> in "
-			   "declaration specifiers"));
+			  ("both %<__int%d%> and %<long%> in "
+			   "declaration specifiers"),
+			  int_n_data[specs->int_n_idx].bitsize);
 	      else if (specs->saturating_p)
 		error_at (loc,
-			  ("both %<_Sat%> and %<__int128%> in "
-			   "declaration specifiers"));
+			  ("both %<_Sat%> and %<__int%d%> in "
+			   "declaration specifiers"),
+			  int_n_data[specs->int_n_idx].bitsize);
 	      else if (specs->short_p)
 		error_at (loc,
-			  ("both %<__int128%> and %<short%> in "
-			   "declaration specifiers"));
+			  ("both %<__int%d%> and %<short%> in "
+			   "declaration specifiers"),
+			  int_n_data[specs->int_n_idx].bitsize);
+	      else if (! int_n_enabled_p [specs->int_n_idx])
+		error_at (loc,
+			  "%<__int%d%> is not supported on this target",
+			  int_n_data[specs->int_n_idx].bitsize);
 	      else
 		{
-		  specs->typespec_word = cts_int128;
+		  specs->typespec_word = cts_int_n;
 		  specs->locations[cdw_typespec] = loc;
 		}
 	      return specs;
 	    case RID_VOID:
 	      if (specs->long_p)
 		error_at (loc,
@@ -10070,18 +10080,18 @@ finish_declspecs (struct c_declspecs *sp
 	{
 	  pedwarn (specs->locations[cdw_complex], OPT_Wpedantic,
 		   "ISO C does not support complex integer types");
 	  specs->type = build_complex_type (specs->type);
 	}
       break;
-    case cts_int128:
+    case cts_int_n:
       gcc_assert (!specs->long_p && !specs->short_p && !specs->long_long_p);
       gcc_assert (!(specs->signed_p && specs->unsigned_p));
       specs->type = (specs->unsigned_p
-		     ? int128_unsigned_type_node
-		     : int128_integer_type_node);
+		     ? int_n_trees[specs->int_n_idx].unsigned_type
+		     : int_n_trees[specs->int_n_idx].signed_type);
       if (specs->complex_p)
 	{
 	  pedwarn (specs->locations[cdw_complex], OPT_Wpedantic,
 		   "ISO C does not support complex integer types");
 	  specs->type = build_complex_type (specs->type);
 	}
Index: tree.c
===================================================================
--- tree.c	(revision 206609)
+++ tree.c	(working copy)
@@ -236,12 +236,15 @@ static unsigned int type_hash_list (cons
 static unsigned int attribute_hash_list (const_tree, hashval_t);
 static bool decls_same_for_odr (tree decl1, tree decl2);
 
 tree global_trees[TI_MAX];
 tree integer_types[itk_none];
 
+bool int_n_enabled_p[NUM_INT_N_ENTS];
+int_n_trees_t int_n_trees[NUM_INT_N_ENTS];
+
 unsigned char tree_contains_struct[MAX_TREE_CODES][64];
 
 /* Number of operands for each OpenMP clause.  */
 unsigned const char omp_clause_num_ops[] =
 {
   0, /* OMP_CLAUSE_ERROR  */
@@ -9447,26 +9450,31 @@ make_vector_type (tree innertype, int nu
   return t;
 }
 
 static tree
 make_or_reuse_type (unsigned size, int unsignedp)
 {
+  int i;
+
   if (size == INT_TYPE_SIZE)
     return unsignedp ? unsigned_type_node : integer_type_node;
   if (size == CHAR_TYPE_SIZE)
     return unsignedp ? unsigned_char_type_node : signed_char_type_node;
   if (size == SHORT_TYPE_SIZE)
     return unsignedp ? short_unsigned_type_node : short_integer_type_node;
   if (size == LONG_TYPE_SIZE)
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
   if (size == LONG_LONG_TYPE_SIZE)
     return (unsignedp ? long_long_unsigned_type_node
             : long_long_integer_type_node);
-  if (size == 128 && int128_integer_type_node)
-    return (unsignedp ? int128_unsigned_type_node
-            : int128_integer_type_node);
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (size == int_n_data[i].bitsize
+	&& int_n_enabled_p[i])
+      return (unsignedp ? int_n_trees[i].unsigned_type
+	      : int_n_trees[i].signed_type);
 
   if (unsignedp)
     return make_unsigned_type (size);
   else
     return make_signed_type (size);
 }
@@ -9576,12 +9584,14 @@ build_atomic_base (tree type, unsigned i
    SHORT_DOUBLE specifies whether double should be of the same precision
    as float.  */
 
 void
 build_common_tree_nodes (bool signed_char, bool short_double)
 {
+  int i;
+
   error_mark_node = make_node (ERROR_MARK);
   TREE_TYPE (error_mark_node) = error_mark_node;
 
   initialize_sizetypes ();
 
   /* Define both `signed char' and `unsigned char'.  */
@@ -9603,23 +9613,26 @@ build_common_tree_nodes (bool signed_cha
   integer_type_node = make_signed_type (INT_TYPE_SIZE);
   unsigned_type_node = make_unsigned_type (INT_TYPE_SIZE);
   long_integer_type_node = make_signed_type (LONG_TYPE_SIZE);
   long_unsigned_type_node = make_unsigned_type (LONG_TYPE_SIZE);
   long_long_integer_type_node = make_signed_type (LONG_LONG_TYPE_SIZE);
   long_long_unsigned_type_node = make_unsigned_type (LONG_LONG_TYPE_SIZE);
-#if HOST_BITS_PER_WIDE_INT >= 64
-    /* TODO: This isn't correct, but as logic depends at the moment on
-       host's instead of target's wide-integer.
-       If there is a target not supporting TImode, but has an 128-bit
-       integer-scalar register, this target check needs to be adjusted. */
-    if (targetm.scalar_mode_supported_p (TImode))
-      {
-        int128_integer_type_node = make_signed_type (128);
-        int128_unsigned_type_node = make_unsigned_type (128);
-      }
-#endif
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    {
+      int_n_trees[i].signed_type = make_signed_type (int_n_data[i].bitsize);
+      int_n_trees[i].unsigned_type = make_unsigned_type (int_n_data[i].bitsize);
+      TYPE_SIZE (int_n_trees[i].signed_type) = bitsize_int (int_n_data[i].bitsize);
+      TYPE_SIZE (int_n_trees[i].unsigned_type) = bitsize_int (int_n_data[i].bitsize);
+
+      if (int_n_data[i].bitsize > LONG_LONG_TYPE_SIZE)
+	{
+	  integer_types[itk_intN_0 + i * 2] = int_n_trees[i].signed_type;
+	  integer_types[itk_unsigned_intN_0 + i * 2] = int_n_trees[i].unsigned_type;
+	}
+    }
 
   /* Define a boolean type.  This type only represents boolean values but
      may be larger than char depending on the value of BOOL_TYPE_SIZE.
      Front ends which want to override this size (i.e. Java) can redefine
      boolean_type_node before calling build_common_tree_nodes_2.  */
   boolean_type_node = make_unsigned_type (BOOL_TYPE_SIZE);
Index: tree.h
===================================================================
--- tree.h	(revision 206609)
+++ tree.h	(working copy)
@@ -3373,14 +3373,12 @@ tree_operand_check_code (const_tree __t,
 #define integer_type_node		integer_types[itk_int]
 #define unsigned_type_node		integer_types[itk_unsigned_int]
 #define long_integer_type_node		integer_types[itk_long]
 #define long_unsigned_type_node		integer_types[itk_unsigned_long]
 #define long_long_integer_type_node	integer_types[itk_long_long]
 #define long_long_unsigned_type_node	integer_types[itk_unsigned_long_long]
-#define int128_integer_type_node	integer_types[itk_int128]
-#define int128_unsigned_type_node	integer_types[itk_unsigned_int128]
 
 #define NULL_TREE (tree) NULL
 
 /* True if NODE is an erroneous expression.  */
 
 #define error_operand_p(NODE)					\
@@ -4554,7 +4552,18 @@ extern unsigned int get_pointer_alignmen
 extern tree fold_call_stmt (gimple, bool);
 extern tree gimple_fold_builtin_snprintf_chk (gimple, tree, enum built_in_function);
 extern void set_builtin_user_assembler_name (tree decl, const char *asmspec);
 extern bool is_simple_builtin (tree);
 extern bool is_inexpensive_builtin (tree);
 
+
+typedef struct {
+  /* These parts are initialized at runtime */
+  tree signed_type;
+  tree unsigned_type;
+} int_n_trees_t;
+
+/* This is also in machmode.h */
+extern bool int_n_enabled_p[NUM_INT_N_ENTS];
+extern int_n_trees_t int_n_trees[NUM_INT_N_ENTS];
+
 #endif  /* GCC_TREE_H  */
Index: toplev.c
===================================================================
--- toplev.c	(revision 206609)
+++ toplev.c	(working copy)
@@ -1867,12 +1867,24 @@ finalize (bool no_backend)
     dump_profile_report ();
 
   /* Language-specific end of compilation actions.  */
   lang_hooks.finish ();
 }
 
+static bool
+standard_type_bitsize (int bitsize)
+{
+  if (bitsize == CHAR_TYPE_SIZE
+      || bitsize == SHORT_TYPE_SIZE
+      || bitsize == INT_TYPE_SIZE
+      || bitsize == LONG_TYPE_SIZE
+      || (bitsize == LONG_LONG_TYPE_SIZE && LONG_LONG_TYPE_SIZE < GET_MODE_BITSIZE (TImode)))
+    return true;
+  return false;
+}
+
 /* Initialize the compiler, and compile the input file.  */
 static void
 do_compile (void)
 {
   /* Initialize timing first.  The C front ends read the main file in
      the post_options hook, and C++ does file timings.  */
@@ -1882,19 +1894,32 @@ do_compile (void)
 
   process_options ();
 
   /* Don't do any more if an error has already occurred.  */
   if (!seen_error ())
     {
+      int i;
+
       timevar_start (TV_PHASE_SETUP);
 
       /* This must be run always, because it is needed to compute the FP
 	 predefined macros, such as __LDBL_MAX__, for targets using non
 	 default FP formats.  */
       init_adjust_machine_modes ();
 
+      /* This must happen after the backend has a chance to process
+	 command line options, but before the parsers are
+	 initialized.  */
+      for (i = 0; i < NUM_INT_N_ENTS; i ++)
+	if (targetm.scalar_mode_supported_p (int_n_data[i].m)
+	    && ! standard_type_bitsize (int_n_data[i].bitsize)
+	    && int_n_data[i].bitsize <= HOST_BITS_PER_WIDE_INT * 2)
+	  int_n_enabled_p[i] = true;
+	else
+	  int_n_enabled_p[i] = false;
+
       /* Set up the back-end if requested.  */
       if (!no_backend)
 	backend_init ();
 
       /* Language-dependent initialization.  Returns true on success.  */
       if (lang_dependent_init (main_input_filename))
Index: cp/typeck.c
===================================================================
--- cp/typeck.c	(revision 206609)
+++ cp/typeck.c	(working copy)
@@ -267,12 +267,13 @@ original_type (tree t)
 static tree
 cp_common_type (tree t1, tree t2)
 {
   enum tree_code code1 = TREE_CODE (t1);
   enum tree_code code2 = TREE_CODE (t2);
   tree attributes;
+  int i;
 
 
   /* In what follows, we slightly generalize the rules given in [expr] so
      as to deal with `long long' and `complex'.  First, merge the
      attributes.  */
   attributes = (*targetm.merge_type_attributes) (t1, t2);
@@ -361,22 +362,25 @@ cp_common_type (tree t1, tree t2)
 	{
 	  tree t = ((TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
 		    ? long_long_unsigned_type_node
 		    : long_long_integer_type_node);
 	  return build_type_attribute_variant (t, attributes);
 	}
-      if (int128_integer_type_node != NULL_TREE
-	  && (same_type_p (TYPE_MAIN_VARIANT (t1),
-			   int128_integer_type_node)
-	      || same_type_p (TYPE_MAIN_VARIANT (t2),
-			      int128_integer_type_node)))
+      for (i = 0; i < NUM_INT_N_ENTS; i ++)
 	{
-	  tree t = ((TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
-		    ? int128_unsigned_type_node
-		    : int128_integer_type_node);
-	  return build_type_attribute_variant (t, attributes);
+	  if (int_n_enabled_p [i]
+	      && (same_type_p (TYPE_MAIN_VARIANT (t1),
+			       int_n_trees[i].signed_type)
+		  || same_type_p (TYPE_MAIN_VARIANT (t2),
+				  int_n_trees[i].signed_type)))
+	    {
+	      tree t = ((TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
+			? int_n_trees[i].unsigned_type
+			: int_n_trees[i].signed_type);
+	      return build_type_attribute_variant (t, attributes);
+	    }
 	}
 
       /* Go through the same procedure, but for longs.  */
       if (same_type_p (TYPE_MAIN_VARIANT (t1), long_unsigned_type_node)
 	  || same_type_p (TYPE_MAIN_VARIANT (t2), long_unsigned_type_node))
 	return build_type_attribute_variant (long_unsigned_type_node,
Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 206609)
+++ cp/decl.c	(working copy)
@@ -8728,13 +8728,13 @@ grokdeclarator (const cp_declarator *dec
 		enum decl_context decl_context,
 		int initialized,
 		tree* attrlist)
 {
   tree type = NULL_TREE;
   int longlong = 0;
-  int explicit_int128 = 0;
+  int explicit_intN = 0;
   int virtualp, explicitp, friendp, inlinep, staticp;
   int explicit_int = 0;
   int explicit_char = 0;
   int defaulted_int = 0;
 
   tree typedef_decl = NULL_TREE;
@@ -8799,13 +8799,13 @@ grokdeclarator (const cp_declarator *dec
 
   signed_p = decl_spec_seq_has_spec_p (declspecs, ds_signed);
   unsigned_p = decl_spec_seq_has_spec_p (declspecs, ds_unsigned);
   short_p = decl_spec_seq_has_spec_p (declspecs, ds_short);
   long_p = decl_spec_seq_has_spec_p (declspecs, ds_long);
   longlong = decl_spec_seq_has_spec_p (declspecs, ds_long_long);
-  explicit_int128 = declspecs->explicit_int128_p;
+  explicit_intN = declspecs->explicit_intN_p;
   thread_p = decl_spec_seq_has_spec_p (declspecs, ds_thread);
 
   if (decl_context == FUNCDEF)
     funcdef_flag = true, decl_context = NORMAL;
   else if (decl_context == MEMFUNCDEF)
     funcdef_flag = true, decl_context = FIELD;
@@ -9140,22 +9140,24 @@ grokdeclarator (const cp_declarator *dec
 
       type = integer_type_node;
     }
 
   ctype = NULL_TREE;
 
-  if (explicit_int128)
+  if (explicit_intN)
     {
-      if (int128_integer_type_node == NULL_TREE)
-	{
-	  error ("%<__int128%> is not supported by this target");
-	  explicit_int128 = false;
-	}
+      if (! int_n_enabled_p[declspecs->int_n_idx])
+       {
+         error ("%<__int%d%> is not supported by this target",
+		int_n_data[declspecs->int_n_idx].bitsize);
+         explicit_intN = false;
+       }
       else if (pedantic && ! in_system_header_at (input_location))
-	pedwarn (input_location, OPT_Wpedantic,
-		 "ISO C++ does not support %<__int128%> for %qs", name);
+       pedwarn (input_location, OPT_Wpedantic,
+                "ISO C++ does not support %<__int%d%> for %qs",
+		int_n_data[declspecs->int_n_idx].bitsize,  name);
     }
 
   /* Now process the modifiers that were specified
      and check for invalid combinations.  */
 
   /* Long double is a special combination.  */
@@ -9181,13 +9183,13 @@ grokdeclarator (const cp_declarator *dec
       else if (long_p && TREE_CODE (type) == REAL_TYPE)
 	error ("%<long%> invalid for %qs", name);
       else if (short_p && TREE_CODE (type) == REAL_TYPE)
 	error ("%<short%> invalid for %qs", name);
       else if ((long_p || short_p) && TREE_CODE (type) != INTEGER_TYPE)
 	error ("%<long%> or %<short%> invalid for %qs", name);
-      else if ((long_p || short_p || explicit_char || explicit_int) && explicit_int128)
+      else if ((long_p || short_p || explicit_char || explicit_int) && explicit_intN)
 	error ("%<long%>, %<int%>, %<short%>, or %<char%> invalid for %qs", name);
       else if ((long_p || short_p) && explicit_char)
 	error ("%<long%> or %<short%> specified with char for %qs", name);
       else if (long_p && short_p)
 	error ("%<long%> and %<short%> specified together for %qs", name);
       else if (type == char16_type_node || type == char32_type_node)
@@ -9197,13 +9199,13 @@ grokdeclarator (const cp_declarator *dec
 	  else if (short_p || long_p)
 	    error ("%<short%> or %<long%> invalid for %qs", name);
 	}
       else
 	{
 	  ok = 1;
-	  if (!explicit_int && !defaulted_int && !explicit_char && !explicit_int128 && pedantic)
+	  if (!explicit_int && !defaulted_int && !explicit_char && !explicit_intN && pedantic)
 	    {
 	      pedwarn (input_location, OPT_Wpedantic, 
 		       "long, short, signed or unsigned used invalidly for %qs",
 		       name);
 	      if (flag_pedantic_errors)
 		ok = 0;
@@ -9239,14 +9241,14 @@ grokdeclarator (const cp_declarator *dec
 	     `signed int' cannot be so controlled.  */
 	  && !(typedef_decl
 	       && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl))
 	  && TREE_CODE (type) == INTEGER_TYPE
 	  && !same_type_p (TYPE_MAIN_VARIANT (type), wchar_type_node)))
     {
-      if (explicit_int128)
-	type = int128_unsigned_type_node;
+      if (explicit_intN)
+	type = int_n_trees[declspecs->int_n_idx].unsigned_type;
       else if (longlong)
 	type = long_long_unsigned_type_node;
       else if (long_p)
 	type = long_unsigned_type_node;
       else if (short_p)
 	type = short_unsigned_type_node;
@@ -9256,14 +9258,14 @@ grokdeclarator (const cp_declarator *dec
 	type = unsigned_type_for (type);
       else
 	type = unsigned_type_node;
     }
   else if (signed_p && type == char_type_node)
     type = signed_char_type_node;
-  else if (explicit_int128)
-    type = int128_integer_type_node;
+  else if (explicit_intN)
+    type = int_n_trees[declspecs->int_n_idx].signed_type;
   else if (longlong)
     type = long_long_integer_type_node;
   else if (long_p)
     type = long_integer_type_node;
   else if (short_p)
     type = short_integer_type_node;
@@ -9273,13 +9275,13 @@ grokdeclarator (const cp_declarator *dec
       if (TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE)
 	error ("complex invalid for %qs", name);
       /* If we just have "complex", it is equivalent to
 	 "complex double", but if any modifiers at all are specified it is
 	 the complex form of TYPE.  E.g, "complex short" is
 	 "complex short int".  */
-      else if (defaulted_int && ! longlong && ! explicit_int128
+      else if (defaulted_int && ! longlong && ! explicit_intN
 	       && ! (long_p || short_p || signed_p || unsigned_p))
 	type = complex_double_type_node;
       else if (type == integer_type_node)
 	type = complex_integer_type_node;
       else if (type == float_type_node)
 	type = complex_float_type_node;
Index: cp/rtti.c
===================================================================
--- cp/rtti.c	(revision 206609)
+++ cp/rtti.c	(working copy)
@@ -1483,13 +1483,13 @@ emit_support_tinfos (void)
     &wchar_type_node, &char16_type_node, &char32_type_node,
     &char_type_node, &signed_char_type_node, &unsigned_char_type_node,
     &short_integer_type_node, &short_unsigned_type_node,
     &integer_type_node, &unsigned_type_node,
     &long_integer_type_node, &long_unsigned_type_node,
     &long_long_integer_type_node, &long_long_unsigned_type_node,
-    &int128_integer_type_node, &int128_unsigned_type_node,
+    //    &int128_integer_type_node, &int128_unsigned_type_node,
     &float_type_node, &double_type_node, &long_double_type_node,
     &dfloat32_type_node, &dfloat64_type_node, &dfloat128_type_node,
     &nullptr_type_node,
     0
   };
   int ix;
Index: cp/parser.c
===================================================================
--- cp/parser.c	(revision 206609)
+++ cp/parser.c	(working copy)
@@ -926,13 +926,12 @@ cp_lexer_next_token_is_decl_specifier_ke
     case RID_CHAR32:
     case RID_WCHAR:
     case RID_BOOL:
     case RID_SHORT:
     case RID_INT:
     case RID_LONG:
-    case RID_INT128:
     case RID_SIGNED:
     case RID_UNSIGNED:
     case RID_FLOAT:
     case RID_DOUBLE:
     case RID_VOID:
       /* GNU extensions.  */ 
@@ -941,12 +940,16 @@ cp_lexer_next_token_is_decl_specifier_ke
       /* C++0x extensions.  */
     case RID_DECLTYPE:
     case RID_UNDERLYING_TYPE:
       return true;
 
     default:
+      if (token->keyword >= RID_FIRST_INT_N
+	  && token->keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
+	  && int_n_enabled_p[token->keyword - RID_FIRST_INT_N])
+	return true;
       return false;
     }
 }
 
 /* Returns TRUE iff the token T begins a decltype type.  */
 
@@ -14436,12 +14439,13 @@ static tree
 cp_parser_simple_type_specifier (cp_parser* parser,
 				 cp_decl_specifier_seq *decl_specs,
 				 cp_parser_flags flags)
 {
   tree type = NULL_TREE;
   cp_token *token;
+  int idx;
 
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
 
   /* If we're looking at a keyword, things are easy.  */
   switch (token->keyword)
@@ -14469,18 +14473,25 @@ cp_parser_simple_type_specifier (cp_pars
       break;
     case RID_INT:
       if (decl_specs)
 	decl_specs->explicit_int_p = true;
       type = integer_type_node;
       break;
-    case RID_INT128:
-      if (!int128_integer_type_node)
+    case RID_INT_N_0:
+    case RID_INT_N_1:
+    case RID_INT_N_2:
+    case RID_INT_N_3:
+      idx = token->keyword - RID_INT_N_0;
+      if (! int_n_enabled_p [idx])
 	break;
       if (decl_specs)
-        decl_specs->explicit_int128_p = true;
-      type = int128_integer_type_node;
+	{
+	  decl_specs->explicit_intN_p = true;
+	  decl_specs->int_n_idx = idx;
+	}
+      type = int_n_trees [idx].signed_type;
       break;
     case RID_LONG:
       if (decl_specs)
 	set_and_check_decl_spec_loc (decl_specs, ds_long, token);
       type = long_integer_type_node;
       break;
Index: cp/mangle.c
===================================================================
--- cp/mangle.c	(revision 206609)
+++ cp/mangle.c	(working copy)
@@ -149,14 +149,12 @@ integer_type_codes[itk_none] =
   'i',  /* itk_int */
   'j',  /* itk_unsigned_int */
   'l',  /* itk_long */
   'm',  /* itk_unsigned_long */
   'x',  /* itk_long_long */
   'y',  /* itk_unsigned_long_long */
-  'n',  /* itk_int128 */
-  'o',  /* itk_unsigned_int128  */
 };
 
 static int decl_is_template_id (const tree, tree* const);
 
 /* Functions for handling substitutions.  */
 
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h	(revision 206609)
+++ cp/cp-tree.h	(working copy)
@@ -4810,12 +4810,14 @@ typedef struct cp_decl_specifier_seq {
   /* If non-NULL, a built-in type that the user attempted to redefine
      to some other type.  */
   tree redefined_builtin_type;
   /* The storage class specified -- or sc_none if no storage class was
      explicitly specified.  */
   cp_storage_class storage_class;
+  /* For the __intN declspec, this stores the index into the int_n_* arrays.  */
+  int int_n_idx;
   /* True iff TYPE_SPEC defines a class or enum.  */
   BOOL_BITFIELD type_definition_p : 1;
   /* True iff multiple types were (erroneously) specified for this
      decl-specifier-seq.  */
   BOOL_BITFIELD multiple_types_p : 1;
   /* True iff multiple storage classes were (erroneously) specified
@@ -4825,14 +4827,14 @@ typedef struct cp_decl_specifier_seq {
   /* True iff at least one decl-specifier was found.  */
   BOOL_BITFIELD any_specifiers_p : 1;
   /* True iff at least one type-specifier was found.  */
   BOOL_BITFIELD any_type_specifiers_p : 1;
   /* True iff "int" was explicitly provided.  */
   BOOL_BITFIELD explicit_int_p : 1;
-  /* True iff "__int128" was explicitly provided.  */
-  BOOL_BITFIELD explicit_int128_p : 1;
+  /* True iff "__intN" was explicitly provided.  */
+  BOOL_BITFIELD explicit_intN_p : 1;
   /* True iff "char" was explicitly provided.  */
   BOOL_BITFIELD explicit_char_p : 1;
   /* True iff ds_thread is set for __thread, not thread_local.  */
   BOOL_BITFIELD gnu_thread_keyword_p : 1;
 } cp_decl_specifier_seq;
 
Index: cp/lex.c
===================================================================
--- cp/lex.c	(revision 206609)
+++ cp/lex.c	(working copy)
@@ -190,12 +190,21 @@ init_reswords (void)
       id = get_identifier (c_common_reswords[i].word);
       C_SET_RID_CODE (id, c_common_reswords[i].rid);
       ridpointers [(int) c_common_reswords[i].rid] = id;
       if (! (c_common_reswords[i].disable & mask))
 	C_IS_RESERVED_WORD (id) = 1;
     }
+
+  for (i = 0; i < NUM_INT_N_ENTS; i++)
+    {
+      char name[50];
+      sprintf (name, "__int%d", int_n_data[i].bitsize);
+      id = get_identifier (name);
+      C_SET_RID_CODE (id, RID_FIRST_INT_N + i);
+      C_IS_RESERVED_WORD (id) = 1;
+    }
 }
 
 static void
 init_cp_pragma (void)
 {
   c_register_pragma (0, "vtable", handle_pragma_vtable);
Index: builtin-types.def
===================================================================
--- builtin-types.def	(revision 206609)
+++ builtin-types.def	(working copy)
@@ -70,14 +70,12 @@ DEF_PRIMITIVE_TYPE (BT_BOOL, boolean_typ
 DEF_PRIMITIVE_TYPE (BT_INT, integer_type_node)
 DEF_PRIMITIVE_TYPE (BT_UINT, unsigned_type_node)
 DEF_PRIMITIVE_TYPE (BT_LONG, long_integer_type_node)
 DEF_PRIMITIVE_TYPE (BT_ULONG, long_unsigned_type_node)
 DEF_PRIMITIVE_TYPE (BT_LONGLONG, long_long_integer_type_node)
 DEF_PRIMITIVE_TYPE (BT_ULONGLONG, long_long_unsigned_type_node)
-DEF_PRIMITIVE_TYPE (BT_INT128, int128_integer_type_node)
-DEF_PRIMITIVE_TYPE (BT_UINT128, int128_unsigned_type_node)
 DEF_PRIMITIVE_TYPE (BT_INTMAX, intmax_type_node)
 DEF_PRIMITIVE_TYPE (BT_UINTMAX, uintmax_type_node)
 DEF_PRIMITIVE_TYPE (BT_UINT16, uint16_type_node)
 DEF_PRIMITIVE_TYPE (BT_UINT32, uint32_type_node)
 DEF_PRIMITIVE_TYPE (BT_UINT64, uint64_type_node)
 DEF_PRIMITIVE_TYPE (BT_WORD, (*lang_hooks.types.type_for_mode) (word_mode, 1))
Index: machmode.def
===================================================================
--- machmode.def	(revision 206609)
+++ machmode.def	(working copy)
@@ -189,12 +189,19 @@ INT_MODE (HI, 2);
 INT_MODE (SI, 4);
 INT_MODE (DI, 8);
 INT_MODE (TI, 16);
 
 /* No partial integer modes are defined by default.  */
 
+/* The target normally defines any target-specific __intN types and
+   their modes, but __int128 for TImode is fairly common so define it
+   here.  The type will not be created unless the target supports
+   TImode.  */
+
+INT_N (TI, 128);
+
 /* Basic floating point modes.  SF and DF are the only modes provided
    by default.  The names QF, HF, XF, and TF are reserved for targets
    that need 1-word, 2-word, 80-bit, or 128-bit float types respectively.
 
    These are the IEEE mappings.  They can be overridden with
    RESET_FLOAT_FORMAT or at runtime (in TARGET_OPTION_OVERRIDE).  */
Index: stor-layout.c
===================================================================
--- stor-layout.c	(revision 206609)
+++ stor-layout.c	(working copy)
@@ -310,22 +310,29 @@ finalize_size_functions (void)
    than MAX_FIXED_MODE_SIZE will not be used.  */
 
 enum machine_mode
 mode_for_size (unsigned int size, enum mode_class mclass, int limit)
 {
   enum machine_mode mode;
+  int i;
 
   if (limit && size > MAX_FIXED_MODE_SIZE)
     return BLKmode;
 
   /* Get the first mode which has this size, in the specified class.  */
   for (mode = GET_CLASS_NARROWEST_MODE (mclass); mode != VOIDmode;
        mode = GET_MODE_WIDER_MODE (mode))
     if (GET_MODE_PRECISION (mode) == size)
       return mode;
 
+  if (mclass == MODE_INT && mode == BLKmode)
+    for (i = 0; i < NUM_INT_N_ENTS; i ++)
+      if (int_n_data[i].bitsize == size
+	  && int_n_enabled_p[i])
+	return int_n_data[i].m;
+
   return BLKmode;
 }
 
 /* Similar, except passed a tree node.  */
 
 enum machine_mode
@@ -346,22 +353,33 @@ mode_for_size_tree (const_tree size, enu
 /* Similar, but never return BLKmode; return the narrowest mode that
    contains at least the requested number of value bits.  */
 
 enum machine_mode
 smallest_mode_for_size (unsigned int size, enum mode_class mclass)
 {
-  enum machine_mode mode;
+  enum machine_mode mode = VOIDmode;
+  int i;
 
   /* Get the first mode which has at least this size, in the
      specified class.  */
   for (mode = GET_CLASS_NARROWEST_MODE (mclass); mode != VOIDmode;
        mode = GET_MODE_WIDER_MODE (mode))
     if (GET_MODE_PRECISION (mode) >= size)
-      return mode;
+      break;
 
-  gcc_unreachable ();
+  if (mclass == MODE_INT)
+    for (i = 0; i < NUM_INT_N_ENTS; i ++)
+      if (int_n_data[i].bitsize >= size
+	  && int_n_data[i].bitsize < GET_MODE_PRECISION (mode)
+	  && int_n_enabled_p[i])
+	mode = int_n_data[i].m;
+
+  if (mode == VOIDmode)
+    gcc_unreachable ();
+
+  return mode;
 }
 
 /* Find an integer mode of the exact same size, or BLKmode on failure.  */
 
 enum machine_mode
 int_mode_for_mode (enum machine_mode mode)
Index: genmodes.c
===================================================================
--- genmodes.c	(revision 206609)
+++ genmodes.c	(working copy)
@@ -69,23 +69,25 @@ struct mode_data
 
   const char *file;		/* file and line of definition, */
   unsigned int line;		/* for error reporting */
   unsigned int counter;		/* Rank ordering of modes */
   unsigned int ibit;		/* the number of integral bits */
   unsigned int fbit;		/* the number of fractional bits */
+
+  unsigned int int_n;		/* If nonzero, then __int<INT_N> will be defined */
 };
 
 static struct mode_data *modes[MAX_MODE_CLASS];
 static unsigned int n_modes[MAX_MODE_CLASS];
 static struct mode_data *void_mode;
 
 static const struct mode_data blank_mode = {
   0, "<unknown>", MAX_MODE_CLASS,
   -1U, -1U, -1U, -1U,
   0, 0, 0, 0, 0,
-  "<unknown>", 0, 0, 0, 0
+  "<unknown>", 0, 0, 0, 0, 0
 };
 
 static htab_t modes_by_name;
 
 /* Data structure for recording target-specified runtime adjustments
    to a particular mode.  We support varying the byte size, the
@@ -627,12 +629,40 @@ reset_float_format (const char *name, co
       error ("%s:%d: mode \"%s\" is not a FLOAT class", file, line, name);
       return;
     }
   m->format = format;
 }
 
+/* __intN support.  */
+#define INT_N(M,PREC)				\
+  make_int_n (#M, PREC, __FILE__, __LINE__)
+static void ATTRIBUTE_UNUSED
+make_int_n (const char *m, int bitsize,
+            const char *file, unsigned int line)
+{
+  struct mode_data *component = find_mode (m);
+  if (!component)
+    {
+      error ("%s:%d: no mode \"%s\"", file, line, m);
+      return;
+    }
+  if (component->cl != MODE_INT
+      && component->cl != MODE_PARTIAL_INT)
+    {
+      error ("%s:%d: mode \"%s\" is not class INT or PARTIAL_INT", file, line, m);
+      return;
+    }
+  if (component->int_n != 0)
+    {
+      error ("%s:%d: mode \"%s\" already has an intN", file, line, m);
+      return;
+    }
+
+  component->int_n = bitsize;
+}
+
 /* Partial integer modes are specified by relation to a full integer
    mode.  */
 #define PARTIAL_INT_MODE(M,PREC,NAME)				\
   make_partial_integer_mode (#M, #NAME, PREC, __FILE__, __LINE__)
 static void ATTRIBUTE_UNUSED
 make_partial_integer_mode (const char *base, const char *name,
@@ -906,12 +936,13 @@ emit_max_int (void)
 
 static void
 emit_insn_modes_h (void)
 {
   int c;
   struct mode_data *m, *first, *last;
+  int n_int_n_ents = 0;
 
   printf ("/* Generated automatically from machmode.def%s%s\n",
 	   HAVE_EXTRA_MODES ? " and " : "",
 	   EXTRA_MODES_FILE);
 
   puts ("\
@@ -966,12 +997,19 @@ enum machine_mode\n{");
 #if 0 /* disabled for backward compatibility, temporary */
   printf ("#define CONST_REAL_FORMAT_FOR_MODE%s\n", adj_format ? "" :" const");
 #endif
   printf ("#define CONST_MODE_IBIT%s\n", adj_ibit ? "" : " const");
   printf ("#define CONST_MODE_FBIT%s\n", adj_fbit ? "" : " const");
   emit_max_int ();
+
+  for_all_modes (c, m)
+    if (m->int_n)
+      n_int_n_ents ++;
+
+  printf ("#define NUM_INT_N_ENTS %d\n", n_int_n_ents);
+
   puts ("\
 \n\
 #endif /* insn-modes.h */");
 }
 
 static void
@@ -1409,12 +1447,59 @@ emit_mode_fbit (void)
   for_all_modes (c, m)
     tagged_printf ("%u", m->fbit, m->name);
 
   print_closer ();
 }
 
+/* Emit __intN for all modes.  */
+
+static void
+emit_mode_int_n (void)
+{
+  int c;
+  struct mode_data *m;
+  struct mode_data **mode_sort;
+  int n_modes = 0;
+  int i, j;
+
+  print_decl ("int_n_data_t", "int_n_data", "");
+
+  n_modes = 0;
+  for_all_modes (c, m)
+    if (m->int_n)
+      n_modes ++;
+  mode_sort = XALLOCAVEC (struct mode_data *, n_modes);
+
+  n_modes = 0;
+  for_all_modes (c, m)
+    if (m->int_n)
+      mode_sort[n_modes++] = m;
+
+  /* Yes, this is a bubblesort, but there are at most four (and
+     usually only 1-2) entries to sort.  */
+  for (i = 0; i<n_modes - 1; i++)
+    for (j = i + 1; j < n_modes; j++)
+      if (mode_sort[i]->int_n > mode_sort[j]->int_n)
+	{
+	  m = mode_sort[i];
+	  mode_sort[i] = mode_sort[j];
+	  mode_sort[j] = m;
+	}
+
+  for (i = 0; i < n_modes; i ++)
+    {
+      m = mode_sort[i];
+      printf(" {\n");
+      tagged_printf ("%u", m->int_n, m->name);
+      printf ("%smode,", m->name);
+      printf(" },\n");
+    }
+
+  print_closer ();
+}
+
 
 static void
 emit_insn_modes_c (void)
 {
   emit_insn_modes_c_header ();
   emit_mode_name ();
@@ -1428,12 +1513,13 @@ emit_insn_modes_c (void)
   emit_mode_base_align ();
   emit_class_narrowest_mode ();
   emit_real_format_for_mode ();
   emit_mode_adjustments ();
   emit_mode_ibit ();
   emit_mode_fbit ();
+  emit_mode_int_n ();
 }
 
 static void
 emit_min_insn_modes_c (void)
 {
   emit_min_insn_modes_c_header ();
Index: gimple.c
===================================================================
--- gimple.c	(revision 206609)
+++ gimple.c	(working copy)
@@ -2093,12 +2093,13 @@ gimple_compare_field_offset (tree f1, tr
    signed according to UNSIGNEDP.  */
 
 static tree
 gimple_signed_or_unsigned_type (bool unsignedp, tree type)
 {
   tree type1;
+  int i;
 
   type1 = TYPE_MAIN_VARIANT (type);
   if (type1 == signed_char_type_node
       || type1 == char_type_node
       || type1 == unsigned_char_type_node)
     return unsignedp ? unsigned_char_type_node : signed_char_type_node;
@@ -2110,16 +2111,21 @@ gimple_signed_or_unsigned_type (bool uns
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
   if (type1 == long_long_integer_type_node
       || type1 == long_long_unsigned_type_node)
     return unsignedp
            ? long_long_unsigned_type_node
 	   : long_long_integer_type_node;
-  if (int128_integer_type_node && (type1 == int128_integer_type_node || type1 == int128_unsigned_type_node))
-    return unsignedp
-           ? int128_unsigned_type_node
-	   : int128_integer_type_node;
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+	&& (type1 == int_n_trees[i].unsigned_type
+	    || type1 == int_n_trees[i].signed_type))
+	return unsignedp
+	  ? int_n_trees[i].unsigned_type
+	  : int_n_trees[i].signed_type;
+
 #if HOST_BITS_PER_WIDE_INT >= 64
   if (type1 == intTI_type_node || type1 == unsigned_intTI_type_node)
     return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
 #endif
   if (type1 == intDI_type_node || type1 == unsigned_intDI_type_node)
     return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
@@ -2226,16 +2232,20 @@ gimple_signed_or_unsigned_type (bool uns
   if (TYPE_OK (long_integer_type_node))
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
   if (TYPE_OK (long_long_integer_type_node))
     return (unsignedp
 	    ? long_long_unsigned_type_node
 	    : long_long_integer_type_node);
-  if (int128_integer_type_node && TYPE_OK (int128_integer_type_node))
-    return (unsignedp
-	    ? int128_unsigned_type_node
-	    : int128_integer_type_node);
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+	&& TYPE_MODE (type) == int_n_data[i].m
+	&& TYPE_PRECISION (type) == int_n_data[i].bitsize)
+	return unsignedp
+	  ? int_n_trees[i].unsigned_type
+	  : int_n_trees[i].signed_type;
 
 #if HOST_BITS_PER_WIDE_INT >= 64
   if (TYPE_OK (intTI_type_node))
     return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
 #endif
   if (TYPE_OK (intDI_type_node))
Index: tree-core.h
===================================================================
--- tree-core.h	(revision 206609)
+++ tree-core.h	(working copy)
@@ -560,14 +560,22 @@ enum integer_type_kind {
   itk_int,
   itk_unsigned_int,
   itk_long,
   itk_unsigned_long,
   itk_long_long,
   itk_unsigned_long_long,
-  itk_int128,
-  itk_unsigned_int128,
+
+  itk_intN_0,
+  itk_unsigned_intN_0,
+  itk_intN_1,
+  itk_unsigned_intN_1,
+  itk_intN_2,
+  itk_unsigned_intN_2,
+  itk_intN_3,
+  itk_unsigned_intN_3,
+
   itk_none
 };
 
 /* A pointer-to-function member type looks like:
 
      struct {
Index: config/msp430/msp430.c
===================================================================
--- config/msp430/msp430.c	(revision 206609)
+++ config/msp430/msp430.c	(working copy)
@@ -234,12 +234,23 @@ msp430_option_override (void)
      command line and always sets -O2 in CFLAGS.  Thus it is not
      possible to build newlib with -Os enabled.  Until now...  */
   if (TARGET_OPT_SPACE && optimize < 3)
     optimize_size = 1;
 }
 
+#undef  TARGET_SCALAR_MODE_SUPPORTED_P
+#define TARGET_SCALAR_MODE_SUPPORTED_P msp430_scalar_mode_supported_p
+
+static bool
+msp430_scalar_mode_supported_p (enum machine_mode m)
+{
+  if (m == PSImode && msp430x)
+    return true;
+  return default_scalar_mode_supported_p (m);
+}
+
 \f
 
 /* Storage Layout */
 
 #undef  TARGET_MS_BITFIELD_LAYOUT_P
 #define TARGET_MS_BITFIELD_LAYOUT_P msp430_ms_bitfield_layout_p
Index: config/msp430/msp430-modes.def
===================================================================
--- config/msp430/msp430-modes.def	(revision 206609)
+++ config/msp430/msp430-modes.def	(working copy)
@@ -1,3 +1,4 @@
 /* 20-bit address */
 PARTIAL_INT_MODE (SI, 20, PSI);
 
+INT_N (PSI, 20);

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2014-01-15 12:48                                                             ` DJ Delorie
@ 2014-01-28 21:52                                                               ` DJ Delorie
  2014-01-28 21:58                                                                 ` Joseph S. Myers
  0 siblings, 1 reply; 47+ messages in thread
From: DJ Delorie @ 2014-01-28 21:52 UTC (permalink / raw)
  To: joseph, richard.guenther, gcc


Ping?  Or do I need to repost on the patches list?

http://gcc.gnu.org/ml/gcc/2014-01/msg00130.html

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2014-01-28 21:52                                                               ` DJ Delorie
@ 2014-01-28 21:58                                                                 ` Joseph S. Myers
  2014-01-28 22:24                                                                   ` DJ Delorie
  0 siblings, 1 reply; 47+ messages in thread
From: Joseph S. Myers @ 2014-01-28 21:58 UTC (permalink / raw)
  To: DJ Delorie; +Cc: richard.guenther, gcc

On Tue, 28 Jan 2014, DJ Delorie wrote:

> Ping?  Or do I need to repost on the patches list?

Repost on the patches list (with self-contained write-up, rationale for 
choices made, etc.) at the start of stage 1 for 4.10/5.0, I suggest (this 
clearly isn't stage 3 material).

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: proposal to make SIZE_TYPE more flexible
  2014-01-28 21:58                                                                 ` Joseph S. Myers
@ 2014-01-28 22:24                                                                   ` DJ Delorie
  0 siblings, 0 replies; 47+ messages in thread
From: DJ Delorie @ 2014-01-28 22:24 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: richard.guenther, gcc


> Repost on the patches list (with self-contained write-up, rationale for 
> choices made, etc.) at the start of stage 1 for 4.10/5.0,

Ok.

> I suggest (this clearly isn't stage 3 material).

Yup.  Would be nice to back port it to 4.9 later, but... understood.

^ permalink raw reply	[flat|nested] 47+ messages in thread

end of thread, other threads:[~2014-01-28 21:58 UTC | newest]

Thread overview: 47+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-10-30  4:28 proposal to make SIZE_TYPE more flexible DJ Delorie
2013-10-30 15:53 ` Joseph S. Myers
2013-10-30 19:18   ` DJ Delorie
2013-10-30 20:49     ` Joseph S. Myers
2013-10-30 22:19       ` DJ Delorie
2013-10-30 22:51         ` Joseph S. Myers
2013-11-14  1:58           ` DJ Delorie
2013-11-14 13:26             ` Joseph S. Myers
2013-11-14 18:12               ` DJ Delorie
2013-11-14 18:37                 ` Joseph S. Myers
2013-11-14 18:48                   ` DJ Delorie
2013-11-14 21:40                     ` Joseph S. Myers
2013-11-15  1:47                       ` DJ Delorie
2013-11-15  1:56                         ` Joseph S. Myers
2013-11-15 23:38               ` DJ Delorie
2013-11-16 11:23                 ` Richard Biener
2013-11-16 12:26                   ` Joseph S. Myers
2013-11-21 22:41                     ` DJ Delorie
2013-11-21 22:59                       ` Joseph S. Myers
2013-11-22  8:29                         ` DJ Delorie
2013-11-22 12:43                           ` Joseph S. Myers
2013-11-22 19:33                             ` DJ Delorie
2013-11-22 21:00                               ` Joseph S. Myers
2013-11-22 21:19                                 ` DJ Delorie
2013-11-23  0:41                                   ` Joseph S. Myers
2013-12-10  3:35                                     ` DJ Delorie
2013-12-10 17:17                                       ` Joseph S. Myers
2013-12-10 18:10                                         ` DJ Delorie
2013-12-10 18:38                                           ` Joseph S. Myers
2013-12-10 18:42                                             ` DJ Delorie
2013-12-11  9:27                                               ` Richard Biener
2013-12-20  4:58                                         ` DJ Delorie
2013-12-20 12:42                                           ` Joseph S. Myers
2013-12-20 19:47                                         ` DJ Delorie
2013-12-20 21:53                                           ` Joseph S. Myers
2013-12-20 21:59                                             ` DJ Delorie
2013-12-20 22:15                                               ` Joseph S. Myers
2013-12-20 22:40                                                 ` DJ Delorie
2013-12-21  1:01                                                   ` Joseph S. Myers
2014-01-09  2:31                                                     ` DJ Delorie
2014-01-09  3:23                                                       ` Joseph S. Myers
2014-01-09  7:02                                                         ` DJ Delorie
2014-01-09 16:22                                                           ` Joseph S. Myers
2014-01-15 12:48                                                             ` DJ Delorie
2014-01-28 21:52                                                               ` DJ Delorie
2014-01-28 21:58                                                                 ` Joseph S. Myers
2014-01-28 22:24                                                                   ` DJ Delorie

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).