1 /// Copyright: Copyright (c) 2017-2019 Andrey Penechko.
2 /// License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
3 /// Authors: Andrey Penechko.
4 module vox.fe.ast.type.basic;
5 
6 import vox.all;
7 
8 @(AstType.type_basic)
9 struct BasicTypeNode {
10 	mixin AstNodeData!(AstType.type_basic, AstFlags.isType, AstNodeState.type_check_done);
11 	AstIndex type = CommonAstNodes.type_type;
12 	SizeAndAlignment sizealign;
13 	ulong minValue;
14 	ulong maxValue;
15 	BasicType basicType;
16 	ubyte typeFlags;
17 	TypeNode* typeNode() return { return cast(TypeNode*)&this; }
18 	string strId() { return basicTypeNames[basicType]; }
19 
20 	bool isFloat() { return cast(bool)(typeFlags & BasicTypeFlag.isFloat); }
21 	bool isInteger() { return cast(bool)(typeFlags & BasicTypeFlag.isInteger); }
22 	IsSigned isSigned() { return cast(IsSigned)cast(bool)(typeFlags & BasicTypeFlag.isSigned); }
23 	bool isBoolean() { return cast(bool)(typeFlags & BasicTypeFlag.isBoolean); }
24 	bool isAlias() { return basicType == BasicType.t_alias; }
25 	bool isType() { return basicType == BasicType.t_type; }
26 
27 	IrIndex gen_init_value(CompilationContext* c)
28 	{
29 		switch(basicType)
30 		{
31 			case BasicType.t_error: return c.constants.addZeroConstant(makeIrType(IrBasicType.i8));
32 			case BasicType.t_bool:  return c.constants.addZeroConstant(makeIrType(IrBasicType.i8));
33 			case BasicType.t_u8:    return c.constants.addZeroConstant(makeIrType(IrBasicType.i8));
34 			case BasicType.t_i8:    return c.constants.addZeroConstant(makeIrType(IrBasicType.i8));
35 			case BasicType.t_i16:   return c.constants.addZeroConstant(makeIrType(IrBasicType.i16));
36 			case BasicType.t_u16:   return c.constants.addZeroConstant(makeIrType(IrBasicType.i16));
37 			case BasicType.t_i32:   return c.constants.addZeroConstant(makeIrType(IrBasicType.i32));
38 			case BasicType.t_u32:   return c.constants.addZeroConstant(makeIrType(IrBasicType.i32));
39 			case BasicType.t_i64:   return c.constants.addZeroConstant(makeIrType(IrBasicType.i64));
40 			case BasicType.t_u64:   return c.constants.addZeroConstant(makeIrType(IrBasicType.i64));
41 			case BasicType.t_f32:   return c.constants.addZeroConstant(makeIrType(IrBasicType.f32));
42 			case BasicType.t_f64:   return c.constants.addZeroConstant(makeIrType(IrBasicType.f64));
43 			case BasicType.t_alias: return c.constants.addZeroConstant(makeIrType(IrBasicType.i32));
44 			case BasicType.t_type:  return c.constants.addZeroConstant(makeIrType(IrBasicType.i32));
45 			default: c.internal_error(loc, "Cannot convert %s to IrIndex", basicType);
46 		}
47 	}
48 }
49 
50 enum NumBasicTypeNodeSlots = 12;
51 
52 enum BasicTypeFlag : ubyte {
53 	isFloat    = 1 << 0,
54 	isInteger  = 1 << 1,
55 	isSigned   = 1 << 2,
56 	isBoolean  = 1 << 3,
57 }
58 
59 void print_type_basic(BasicTypeNode* node, ref AstPrintState state)
60 {
61 	state.print("TYPE ", node.typeNode.printer(state.context));
62 }
63 
64 IrIndex gen_ir_type_basic(BasicTypeNode* t, CompilationContext* context)
65 	out(res; res.isTypeBasic, "Not a basic type")
66 {
67 	switch(t.basicType)
68 	{
69 		case BasicType.t_noreturn: return makeIrType(IrBasicType.noreturn_t);
70 		case BasicType.t_void: return makeIrType(IrBasicType.void_t);
71 		case BasicType.t_bool: return makeIrType(IrBasicType.i8);
72 		case BasicType.t_null: return makeIrType(IrBasicType.i64);
73 		case BasicType.t_u8: return makeIrType(IrBasicType.i8);
74 		case BasicType.t_i8: return makeIrType(IrBasicType.i8);
75 		case BasicType.t_i16: return makeIrType(IrBasicType.i16);
76 		case BasicType.t_u16: return makeIrType(IrBasicType.i16);
77 		case BasicType.t_i32: return makeIrType(IrBasicType.i32);
78 		case BasicType.t_u32: return makeIrType(IrBasicType.i32);
79 		case BasicType.t_i64: return makeIrType(IrBasicType.i64);
80 		case BasicType.t_u64: return makeIrType(IrBasicType.i64);
81 		case BasicType.t_f32: return makeIrType(IrBasicType.f32);
82 		case BasicType.t_f64: return makeIrType(IrBasicType.f64);
83 		case BasicType.t_alias: return makeIrType(IrBasicType.i32);
84 		case BasicType.t_type: return makeIrType(IrBasicType.i32);
85 		default:
86 			context.internal_error(t.loc, "Cannot convert %s to IrIndex", t.basicType);
87 	}
88 }
89 
90 // leftExpr, rightExpr can be null
91 CommonTypeResult common_type_basic(BasicTypeNode* node, AstIndex typeBIndex, AstIndex leftExpr, AstIndex rightExpr, CompilationContext* c)
92 {
93 	BasicType basicA = node.basicType;
94 	TypeNode* typeB = typeBIndex.get_type(c);
95 	switch(typeB.astType) with(AstType)
96 	{
97 		case type_basic:
98 			BasicType basicB = typeB.as_basic.basicType;
99 			BasicType commonType = commonBasicType[basicA][basicB];
100 			TypeConvResKind kindA = basicConversionKind[basicA][commonType];
101 			TypeConvResKind kindB = basicConversionKind[basicB][commonType];
102 			auto res = CommonTypeResult(c.basicTypeNodes(commonType), kindA, kindB);
103 
104 			if (leftExpr.isDefined && rightExpr.isDefined) {
105 				auto leftExprNode = leftExpr.get_node(c);
106 				auto rightExprNode = rightExpr.get_node(c);
107 				if (leftExprNode.astType == AstType.literal_int)
108 				{
109 					if (rightExprNode.astType == AstType.literal_int) return res;
110 
111 					if (typeB.isInteger)
112 					{
113 						ubyte toSize = integerSize(basicB);
114 						auto lit = leftExprNode.as!IntLiteralExprNode(c);
115 						if (lit.isSigned) {
116 							if (numSignedBytesForInt(lit.value) <= toSize)
117 								return CommonTypeResult(c.basicTypeNodes(basicB), TypeConvResKind.override_expr_type_i, TypeConvResKind.no_i);
118 						} else {
119 							if (numUnsignedBytesForInt(lit.value) <= toSize)
120 								return CommonTypeResult(c.basicTypeNodes(basicB), TypeConvResKind.override_expr_type_i, TypeConvResKind.no_i);
121 						}
122 					}
123 				}
124 				if (rightExprNode.astType == AstType.literal_int) {
125 					if (node.isInteger)
126 					{
127 						ubyte toSize = integerSize(basicA);
128 						auto lit = rightExprNode.as!IntLiteralExprNode(c);
129 						if (lit.isSigned) {
130 							if (numSignedBytesForInt(lit.value) <= toSize)
131 								return CommonTypeResult(c.basicTypeNodes(basicA), TypeConvResKind.no_i, TypeConvResKind.override_expr_type_i);
132 						} else {
133 							if (numUnsignedBytesForInt(lit.value) <= toSize)
134 								return CommonTypeResult(c.basicTypeNodes(basicA), TypeConvResKind.no_i, TypeConvResKind.override_expr_type_i);
135 						}
136 					}
137 				}
138 			}
139 			return res;
140 		case type_ptr:
141 			if (basicA == BasicType.t_null) {
142 				return CommonTypeResult(typeBIndex, TypeConvResKind.override_expr_type_i, TypeConvResKind.no_i);
143 			}
144 			return CommonTypeResult(CommonAstNodes.type_error);
145 		default: assert(false);
146 	}
147 }
148 
149 TypeConvResKind type_conv_basic(BasicTypeNode* node, AstIndex typeBIndex, ref AstIndex expr, CompilationContext* c)
150 {
151 	BasicType fromTypeBasic = node.basicType;
152 	TypeNode* typeTo = typeBIndex.get_type(c);
153 
154 	switch(typeTo.astType) with(AstType)
155 	{
156 		case type_basic:
157 			auto res = basicConversionKind[fromTypeBasic][typeTo.as_basic.basicType];
158 			auto exprNode = expr.get_node(c);
159 			switch(exprNode.astType) {
160 				case AstType.literal_int:
161 					if (typeTo.isInteger)
162 					{
163 						ubyte toSize = integerSize(typeTo.as_basic.basicType);
164 						auto lit = exprNode.as!IntLiteralExprNode(c);
165 						if (lit.isSigned) {
166 							if (numSignedBytesForInt(lit.value) <= toSize) return TypeConvResKind.override_expr_type_i;
167 						} else {
168 							if (numUnsignedBytesForInt(lit.value) <= toSize) return TypeConvResKind.override_expr_type_i;
169 						}
170 					}
171 					return res;
172 				case AstType.literal_float:
173 					if (typeTo.isFloat) return TypeConvResKind.ff_i;
174 					return res;
175 				default: return res;
176 			}
177 		case type_ptr:
178 			if (fromTypeBasic == BasicType.t_null) return TypeConvResKind.override_expr_type_i;
179 			if (fromTypeBasic.isInteger) return TypeConvResKind.ii_e;
180 			return TypeConvResKind.fail;
181 		case type_slice:
182 			if (fromTypeBasic == BasicType.t_null) return TypeConvResKind.override_expr_type_i;
183 			return TypeConvResKind.fail;
184 		case decl_enum:
185 			auto res1 = type_conv_basic(node, typeTo.as_enum.memberType, expr, c);
186 			auto res2 = res1.allowExplicitOnly;
187 			//writefln("type_conv_basic %s %s %s %s", fromTypeBasic, printer(typeTo.as_enum.memberType, c), res1, res2);
188 			return res2;
189 		default: return TypeConvResKind.fail;
190 	}
191 }
192 
193 // The order is the same as in TokenType enum, CommonAstNodes enum, basicTypesArray, basicTypeNames
194 enum BasicType : ubyte {
195 	t_error,
196 	t_auto,
197 	t_noreturn,
198 	t_void,
199 	t_bool,
200 	t_null,
201 
202 	t_i8,
203 	t_i16,
204 	t_i32,
205 	t_i64,
206 
207 	t_u8,
208 	t_u16,
209 	t_u32,
210 	t_u64,
211 
212 	t_f32,
213 	t_f64,
214 
215 	// meta types
216 	t_alias,
217 	t_type,
218 	//t_value,
219 }
220 
221 bool isInteger(BasicType b) {
222 	return b >= BasicType.t_i8 && b <= BasicType.t_u64;
223 }
224 ubyte integerSize(BasicType b) {
225 	switch(b) with(BasicType) {
226 		case t_i8, t_u8: return 1;
227 		case t_i16, t_u16: return 2;
228 		case t_i32, t_u32: return 4;
229 		case t_i64, t_u64: return 8;
230 		default: return 0;
231 	}
232 }
233 bool isSignedInteger(BasicType b) {
234 	return b >= BasicType.t_i8 && b <= BasicType.t_i64;
235 }
236 bool isUnsignedInteger(BasicType b) {
237 	return b >= BasicType.t_u8 && b <= BasicType.t_u64;
238 }
239 bool isFloat(BasicType b) {
240 	return b == BasicType.t_f32 || b == BasicType.t_f64;
241 }
242 bool isBoolean(BasicType b) {
243 	return b == BasicType.t_bool;
244 }
245 
246 // 0b_000_0
247 //        ^
248 //        | 0 e 0 explicit conversion only
249 //        ` 1 i 1 explicit and implicit conversion allowed
250 enum TypeConvResKind : ubyte {
251 	fail = 0b_000_0, // cannot convert
252 	no_e = 0b_001_0, // noop, explicit conversion only
253 	no_i = 0b_001_1, // noop, explicit and implicit conversion allowed
254 
255 	ii_e = 0b_010_0, // i to i explicit conversion only
256 	ii_i = 0b_010_1, // i to i explicit and implicit conversion allowed
257 	if_e = 0b_011_0, // i to f explicit conversion only
258 	if_i = 0b_011_1, // i to f explicit and implicit conversion allowed
259 	ff_e = 0b_100_0, // f to f explicit conversion only
260 	ff_i = 0b_100_1, // f to f explicit and implicit conversion allowed
261 	fi_e = 0b_101_0, // f to i explicit conversion only
262 	fi_i = 0b_101_1, // f to i explicit and implicit conversion allowed
263 
264 	override_expr_type_e = 0b_110_0,
265 	override_expr_type_i = 0b_110_1,
266 
267 	string_literal_to_u8_ptr = 0b_111_0,
268 	array_literal_to_slice = 0b_111_1,
269 }
270 
271 bool isNoop(TypeConvResKind kind) { return (kind & 0b_111_0) == TypeConvResKind.no_e; }
272 bool successful(TypeConvResKind kind) { return kind != TypeConvResKind.fail; }
273 bool canConvertImplicitly(TypeConvResKind kind) {
274 	return (kind & 1) == 1 || kind >= TypeConvResKind.string_literal_to_u8_ptr; }
275 TypeConvResKind allowExplicitOnly(TypeConvResKind kind) {
276 	if (kind >= TypeConvResKind.string_literal_to_u8_ptr) return kind;
277 	return cast(TypeConvResKind)(kind & 0b_111_0);
278 }
279 
280 // usage basicConversionKind[from][to]
281 immutable TypeConvResKind[BasicType.max + 1][BasicType.max + 1] basicConversionKind = (){ with(TypeConvResKind){ return [
282 	//err auto nret void bool null   i8  i16  i32  i64   u8  u16  u32  u64  f32  f64 $alias $type  // to
283 	[no_i,fail,no_i,no_i,no_i,no_i,no_i,no_i,no_i,no_i,no_i,no_i,no_i,no_i,no_i,no_i, no_i, no_i], // from error
284 	[fail,fail,fail,fail,fail,fail,fail,fail,fail,fail,fail,fail,fail,fail,fail,fail, fail, fail], // from auto
285 	[no_i,fail,fail,no_i,no_i,no_i,no_i,no_i,no_i,no_i,no_i,no_i,no_i,no_i,no_i,no_i, fail, fail], // from noreturn
286 	[no_i,fail,fail,no_i,fail,fail,fail,fail,fail,fail,fail,fail,fail,fail,fail,fail, fail, fail], // from void
287 	[no_i,fail,fail,fail,no_i,fail,ii_i,ii_i,ii_i,ii_i,ii_i,ii_i,ii_i,ii_i,if_i,if_i, fail, fail], // from bool
288 	[no_i,fail,fail,fail,ii_i,no_i,ii_e,ii_e,ii_e,ii_e,ii_e,ii_e,ii_e,ii_e,fail,fail, fail, fail], // from null
289 	[no_i,fail,fail,fail,ii_i,fail,no_i,ii_i,ii_i,ii_i,ii_e,ii_e,ii_e,ii_e,if_i,if_i, fail, fail], // from i8
290 	[no_i,fail,fail,fail,ii_i,fail,ii_e,no_i,ii_i,ii_i,ii_e,ii_e,ii_e,ii_e,if_i,if_i, fail, fail], // from i16
291 	[no_i,fail,fail,fail,ii_i,fail,ii_e,ii_e,no_i,ii_i,ii_e,ii_e,ii_e,ii_e,if_i,if_i, fail, fail], // from i32
292 	[no_i,fail,fail,fail,ii_i,fail,ii_e,ii_e,ii_e,no_i,ii_e,ii_e,ii_e,ii_e,if_i,if_i, fail, fail], // from i64
293 	[no_i,fail,fail,fail,ii_i,fail,ii_e,ii_i,ii_i,ii_i,no_i,ii_i,ii_i,ii_i,if_i,if_i, fail, fail], // from u8
294 	[no_i,fail,fail,fail,ii_i,fail,ii_e,ii_e,ii_i,ii_i,ii_e,no_i,ii_i,ii_i,if_i,if_i, fail, fail], // from u16
295 	[no_i,fail,fail,fail,ii_i,fail,ii_e,ii_e,ii_e,ii_i,ii_e,ii_e,no_i,ii_i,if_i,if_i, fail, fail], // from u32
296 	[no_i,fail,fail,fail,ii_i,fail,ii_e,ii_e,ii_e,ii_e,ii_e,ii_e,ii_e,no_i,if_i,if_i, fail, fail], // from u64
297 	[no_i,fail,fail,fail,ii_i,fail,fi_i,fi_i,fi_i,fi_i,fi_i,fi_i,fi_i,fi_i,no_i,ff_i, fail, fail], // from f32
298 	[no_i,fail,fail,fail,ii_i,fail,fi_i,fi_i,fi_i,fi_i,fi_i,fi_i,fi_i,fi_i,ff_e,no_i, fail, fail], // from f64
299 	[no_i,fail,fail,fail,ii_i,fail,fail,fail,fail,fail,fail,fail,fail,fail,fail,fail, no_i, fail], // from $alias
300 	[no_i,fail,fail,fail,ii_i,fail,fail,fail,fail,fail,fail,fail,fail,fail,fail,fail, ii_i, no_i], // from $type
301 ]; }
302 }();
303 
304 immutable BasicType[BasicType.max + 1][BasicType.max + 1] commonBasicType = (){ with(BasicType){ return [
305 	// error     auto  noreturn    void     bool     null       i8      i16      i32      i64       u8      u16      u32      u64      f32      f64   $alias    $type
306 	[t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error], // error
307 	[t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error], // auto
308 	[t_error, t_error,t_noreturn,t_error,t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error], // noreturn
309 	[t_error, t_error, t_error, t_void,  t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_alias, t_type ], // void
310 	[t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_alias, t_type ], // bool
311 	[t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_error, t_alias, t_type ], // null
312 	[t_error, t_error, t_error, t_error, t_error, t_error, t_i8,    t_i16,   t_i32,   t_i64,   t_i8,    t_i16,   t_i32,   t_i64,   t_f32,   t_f64,   t_alias, t_type ], // i8
313 	[t_error, t_error, t_error, t_error, t_error, t_error, t_i16,   t_i16,   t_i32,   t_i64,   t_i16,   t_i16,   t_i32,   t_i64,   t_f32,   t_f64,   t_alias, t_type ], // i16
314 	[t_error, t_error, t_error, t_error, t_error, t_error, t_i32,   t_i32,   t_i32,   t_i64,   t_i32,   t_i32,   t_i32,   t_i64,   t_f32,   t_f64,   t_alias, t_type ], // i32
315 	[t_error, t_error, t_error, t_error, t_error, t_error, t_i64,   t_i64,   t_i64,   t_i64,   t_i64,   t_i64,   t_i64,   t_i64,   t_f32,   t_f64,   t_alias, t_type ], // i64
316 	[t_error, t_error, t_error, t_error, t_error, t_error, t_i8,    t_i16,   t_i32,   t_i64,   t_u8,    t_u16,   t_u32,   t_u64,   t_f32,   t_f64,   t_alias, t_type ], // u8
317 	[t_error, t_error, t_error, t_error, t_error, t_error, t_i16,   t_i16,   t_i32,   t_i64,   t_u16,   t_u16,   t_u32,   t_u64,   t_f32,   t_f64,   t_alias, t_type ], // u16
318 	[t_error, t_error, t_error, t_error, t_error, t_error, t_i32,   t_i32,   t_i32,   t_i64,   t_u32,   t_u32,   t_u32,   t_u64,   t_f32,   t_f64,   t_alias, t_type ], // u32
319 	[t_error, t_error, t_error, t_error, t_error, t_error, t_i64,   t_i64,   t_i64,   t_i64,   t_u64,   t_u64,   t_u64,   t_u64,   t_f32,   t_f64,   t_alias, t_type ], // u64
320 	[t_error, t_error, t_error, t_error, t_error, t_error, t_f32,   t_f32,   t_f32,   t_f32,   t_f32,   t_f32,   t_f32,   t_f32,   t_f32,   t_f64,   t_alias, t_type ], // f32
321 	[t_error, t_error, t_error, t_error, t_error, t_error, t_f64,   t_f64,   t_f64,   t_f64,   t_f64,   t_f64,   t_f64,   t_f64,   t_f64,   t_f64,   t_alias, t_type ], // f64
322 	[t_error, t_error, t_error, t_alias, t_alias, t_alias, t_alias, t_alias, t_alias, t_alias, t_alias, t_alias, t_alias, t_alias, t_alias, t_alias, t_alias, t_alias], // $alias
323 	[t_error, t_error, t_error, t_type,  t_type,  t_type,  t_type,  t_type,  t_type,  t_type,  t_type,  t_type,  t_type,  t_type,  t_type,  t_type,  t_alias, t_type ], // $type
324 ]; }
325 }();
326 
327 string[BasicType.max + 1] basicTypeNames = ["error", "auto", "noreturn", "void", "bool", "typeof(null)", "i8", "i16", "i32",
328 "i64", "u8", "u16", "u32", "u64", "f32", "f64", "$alias", "$type"];
329 
330 bool isBasicTypeToken(TokenType tt) {
331 	return tt >= TYPE_TOKEN_FIRST && tt <= TYPE_TOKEN_LAST;
332 }
333 
334 BasicType tokenTypeToBasicType(TokenType tt) {
335 	return cast(BasicType)(tt - TYPE_TOKEN_FIRST + BasicType.t_noreturn);
336 }
337 
338 ubyte numSignedBytesForInt(long value) {
339 	if (cast(byte)(value & 0xFF) == value)
340 		return 1;
341 	else if (cast(short)(value & 0xFFFF) == value)
342 		return 2;
343 	else if (cast(int)(value & 0xFFFF_FFFF) == value)
344 		return 4;
345 	else
346 		return 8;
347 }
348 
349 ubyte numUnsignedBytesForInt(ulong value) {
350 	if (cast(ubyte)(value & 0xFF) == value)
351 		return 1;
352 	else if (cast(ushort)(value & 0xFFFF) == value)
353 		return 2;
354 	else if (cast(uint)(value & 0xFFFF_FFFF) == value)
355 		return 4;
356 	else
357 		return 8;
358 }
359 
360 IrArgSize argSizeIntSigned(long value) {
361 	if (cast(byte)(value & 0xFF) == value)
362 		return IrArgSize.size8;
363 	else if (cast(short)(value & 0xFFFF) == value)
364 		return IrArgSize.size16;
365 	else if (cast(int)(value & 0xFFFF_FFFF) == value)
366 		return IrArgSize.size32;
367 	else
368 		return IrArgSize.size64;
369 }
370 
371 IrArgSize argSizeIntUnsigned(ulong value) {
372 	if (cast(ubyte)(value & 0xFF) == value)
373 		return IrArgSize.size8;
374 	else if (cast(ushort)(value & 0xFFFF) == value)
375 		return IrArgSize.size16;
376 	else if (cast(uint)(value & 0xFFFF_FFFF) == value)
377 		return IrArgSize.size32;
378 	else
379 		return IrArgSize.size64;
380 }
381 
382 BasicType minUnsignedIntType(ulong value) {
383 	if (cast(ubyte)(value & 0xFF) == value)
384 		return BasicType.t_u8;
385 	else if (cast(ushort)(value & 0xFFFF) == value)
386 		return BasicType.t_u16;
387 	else if (cast(uint)(value & 0xFFFF_FFFF) == value)
388 		return BasicType.t_u32;
389 	else
390 		return BasicType.t_u64;
391 }
392 
393 BasicType minSignedIntType(long value) {
394 	if (cast(long)cast(byte)(value & 0xFF) == value)
395 		return BasicType.t_i8;
396 	else if (cast(long)cast(short)(value & 0xFFFF) == value)
397 		return BasicType.t_i16;
398 	else if (cast(int)(value & 0xFFFF_FFFF) == value)
399 		return BasicType.t_i32;
400 	else
401 		return BasicType.t_i64;
402 }