appendString (InitStringChar ("'"))
END
ELSE
- appendString (InitStringCharStar ('CHR (')) ;
+ appendString (InitString ('CHR (')) ;
appendString (InitStringCharStar (CSTIntToString (value))) ;
appendString (InitStringChar (')'))
END
FROM m2convert IMPORT BuildConvert ;
FROM m2expr IMPORT BuildSub, BuildLSL, BuildTBitSize, BuildAdd, BuildDivTrunc, BuildModTrunc,
- BuildSize, TreeOverflow,
+ BuildSize, TreeOverflow, AreConstantsEqual,
GetPointerZero, GetIntegerZero, GetIntegerOne ;
FROM m2block IMPORT RememberType, pushGlobalScope, popGlobalScope, pushFunctionScope, popFunctionScope,
VAR
type,
gccsym : Tree ;
+ align,
high, low: CARDINAL ;
location: location_t ;
BEGIN
location := TokenToLocation (GetDeclaredMod (sym)) ;
GetSubrange (sym, high, low) ;
- (* type := BuildSmallestTypeRange (location, Mod2Gcc(low), Mod2Gcc(high)) ; *)
- type := Mod2Gcc (GetSType (sym)) ;
+ align := GetAlignment (sym) ;
+ IF align # NulSym
+ THEN
+ IF AreConstantsEqual (GetIntegerZero (location), Mod2Gcc (align))
+ THEN
+ type := BuildSmallestTypeRange (location, Mod2Gcc (low), Mod2Gcc (high))
+ ELSE
+ MetaError1 ('a non-zero alignment in a subrange type {%1Wa} is currently not implemented and will be ignored',
+ sym) ;
+ type := Mod2Gcc (GetSType (sym))
+ END
+ ELSE
+ type := Mod2Gcc (GetSType (sym))
+ END ;
gccsym := BuildSubrangeType (location,
- KeyToCharStar (GetFullSymName(sym)),
+ KeyToCharStar (GetFullSymName (sym)),
type, Mod2Gcc (low), Mod2Gcc (high)) ;
RETURN gccsym
END DeclareSubrange ;
PROCEDURE WalkSubrangeDependants (sym: CARDINAL; p: WalkAction) ;
VAR
- type,
- high, low: CARDINAL ;
+ type, align,
+ high, low : CARDINAL ;
BEGIN
GetSubrange(sym, high, low) ;
CheckResolveSubrange (sym) ;
END ;
(* low and high are not types but constants and they are resolved by M2GenGCC *)
p(low) ;
- p(high)
+ p(high) ;
+ align := GetAlignment (sym) ;
+ IF align # NulSym
+ THEN
+ p(align)
+ END
END WalkSubrangeDependants ;
PROCEDURE IsSubrangeDependants (sym: CARDINAL; q: IsAction) : BOOLEAN ;
VAR
result : BOOLEAN ;
+ align,
type,
high, low: CARDINAL ;
BEGIN
THEN
result := FALSE
END ;
+ align := GetAlignment(sym) ;
+ IF (align#NulSym) AND (NOT q(align))
+ THEN
+ result := FALSE
+ END ;
RETURN( result )
END IsSubrangeDependants ;
PushTtok (m2strnul, tok) ;
PushT (1) ;
BuildAdrFunction
-END BuildAdrFunction ;
+END BuildStringAdrParam ;
(*
type,
align : CARDINAL ;
BEGIN
- PopT(alignment) ;
- IF alignment=MakeKey('bytealignment')
+ PopT (alignment) ;
+ IF alignment = MakeKey ('bytealignment')
THEN
- PopT(align) ;
- PopT(type) ;
- IF align#NulSym
+ PopT (align) ;
+ PopT (type) ;
+ IF align # NulSym
THEN
- IF IsRecord(type) OR IsRecordField(type) OR IsType(type) OR IsArray(type) OR IsPointer(type)
+ IF IsRecord (type) OR IsRecordField (type) OR IsType (type) OR
+ IsArray (type) OR IsPointer( type) OR IsSubrange (type)
THEN
- PutAlignment(type, align)
+ PutAlignment (type, align)
ELSE
- MetaError1('not allowed to add an alignment attribute to type {%1ad}', type)
+ MetaError1 ('not allowed to add an alignment attribute to type {%1ad}', type)
END
END
- ELSIF alignment#NulName
+ ELSIF alignment # NulName
THEN
- WriteFormat1('unknown type alignment attribute, %a', alignment)
+ WriteFormat1 ('unknown type alignment attribute, %a', alignment)
ELSE
- PopT(type)
+ PopT (type)
END
END BuildTypeAlignment ;
Size : PtrToValue ; (* Size of subrange type. *)
Type : CARDINAL ; (* Index to type symbol for *)
(* the type of subrange. *)
+ Align : CARDINAL ; (* Alignment for this type. *)
ConstLitTree: SymbolTree ; (* constants of this type. *)
packedInfo : PackedInfo ; (* the equivalent packed type *)
oafamily : CARDINAL ; (* The oafamily for this sym *)
(* ConstExpression. *)
Type := NulSym ; (* Index to a type. Determines *)
(* the type of subrange. *)
+ Align := NulSym ; (* The alignment of this type. *)
InitPacked(packedInfo) ; (* not packed and no equivalent *)
InitTree(ConstLitTree) ; (* constants of this type. *)
Size := InitValue() ; (* Size determines the type size *)
RecordFieldSym: RecordField.Align := align |
TypeSym : Type.Align := align |
ArraySym : Array.Align := align |
- PointerSym : Pointer.Align := align
+ PointerSym : Pointer.Align := align |
+ SubrangeSym : Subrange.Align := align
ELSE
- InternalError ('expecting record, field, pointer, type or an array symbol')
+ InternalError ('expecting record, field, pointer, type, subrange or an array symbol')
END
END
END PutAlignment ;
ArraySym : RETURN( Array.Align ) |
PointerSym : RETURN( Pointer.Align ) |
VarientFieldSym: RETURN( GetAlignment(VarientField.Parent) ) |
- VarientSym : RETURN( GetAlignment(Varient.Parent) )
+ VarientSym : RETURN( GetAlignment(Varient.Parent) ) |
+ SubrangeSym : RETURN( Subrange.Align )
ELSE
- InternalError ('expecting record, field, pointer, type or an array symbol')
+ InternalError ('expecting record, field, pointer, type, subrange or an array symbol')
END
END
END GetAlignment ;
{
int bits = tree_floor_log2 (values);
- if (integer_pow2p (values))
- return m2decl_BuildIntegerConstant (bits + 1);
- else
- return m2decl_BuildIntegerConstant (bits + 1);
+ return m2decl_BuildIntegerConstant (bits + 1);
}
-/* getMax return the result of max(a, b). */
+/* getMax return the result of max (a, b). */
static tree
getMax (tree a, tree b)
/* calcNbits return the smallest number of bits required to
represent: min..max. */
-static tree
-calcNbits (location_t location, tree min, tree max)
+tree
+m2expr_calcNbits (location_t location, tree min, tree max)
{
int negative = false;
tree t = testLimits (location, m2type_GetIntegerType (), min, max);
TYPE_MAX_VALUE (type), false);
min = m2convert_BuildConvert (location, m2type_GetIntegerType (),
TYPE_MIN_VALUE (type), false);
- return calcNbits (location, min, max);
+ return m2expr_calcNbits (location, min, max);
case BOOLEAN_TYPE:
return m2expr_GetIntegerOne (location);
default:
PROCEDURE BuildAddAddress (location: location_t; op1, op2: Tree) : Tree ;
+(*
+ calcNbits - return the smallest number of bits required to
+ represent: min..max.
+*)
+
+PROCEDURE calcNbits (location: location_t; min, max: Tree) : Tree ;
+
+
END m2expr.
EXTERN tree m2expr_BuildRDiv (location_t location, tree op1, tree op2,
bool needconvert);
EXTERN int m2expr_GetCstInteger (tree cst);
-
+EXTERN tree m2expr_calcNbits (location_t location, tree min, tree max);
EXTERN void m2expr_init (location_t location);
#undef EXTERN
return m2_cardinal_address_type_node;
}
-/* noBitsRequired returns the number of bits required to contain,
- values. How many bits are required to represent all numbers
- between: 0..values-1 */
-
-static tree
-noBitsRequired (tree values)
-{
- int bits = tree_floor_log2 (values);
-
- if (integer_pow2p (values))
- /* remember we start counting from zero. */
- return m2decl_BuildIntegerConstant (bits);
- else
- return m2decl_BuildIntegerConstant (bits + 1);
-}
-
#if 0
/* build_set_type creates a set type from the, domain, [low..high].
The values low..high all have type, range_type. */
m2assert_AssertLocation (location);
low = fold (low);
high = fold (high);
- bits = fold (noBitsRequired (
- m2expr_BuildAdd (location, m2expr_BuildSub (location, high, low, false),
- m2expr_GetIntegerOne (location), false)));
+ bits = fold (m2expr_calcNbits (location, low, high));
return build_m2_specific_size_type (location, INTEGER_TYPE,
TREE_INT_CST_LOW (bits),
tree_int_cst_sgn (low) < 0);
error ("high bound for the subrange has overflowed");
/* First build a type with the base range. */
- range_type = build_range_type (type, TYPE_MIN_VALUE (type),
- TYPE_MAX_VALUE (type));
+ range_type = build_range_type (type, lowval, highval);
TYPE_UNSIGNED (range_type) = TYPE_UNSIGNED (type);
#if 0
--- /dev/null
+MODULE packedrecord3 ; (*!m2iso+gm2*)
+
+FROM libc IMPORT printf, exit ;
+
+TYPE
+ subrange = [0..63] <* bytealignment (0) *> ;
+
+ packedrec = RECORD
+ <* bytealignment (0) *>
+ bool: BOOLEAN ;
+ col : (white, black) ;
+ sub : subrange ;
+ END ;
+
+
+VAR
+ global: subrange ;
+ pr : packedrec ;
+
+
+PROCEDURE test (s: subrange; level: CARDINAL) ;
+BEGIN
+ IF s # global
+ THEN
+ printf ("failed to pass %d into test\n", ORD (s)) ;
+ exit (1)
+ END ;
+ IF level > 0
+ THEN
+ test (s, level-1)
+ END
+END test ;
+
+
+BEGIN
+ IF SIZE (pr) # 1
+ THEN
+ printf ("test failed as SIZE (pr) should be 1 not %d\n", SIZE (pr)) ;
+ exit (1)
+ END ;
+ FOR global := MIN (subrange) TO MAX (subrange) DO
+ test (global, 2)
+ END ;
+ FOR global := MIN (subrange) TO MAX (subrange) DO
+ pr.bool := FALSE ;
+ pr.sub := global ;
+ test (pr.sub, 2)
+ END
+END packedrecord3.