From 018951ef40ef6fa1fed258468e429b013fbe67d6 Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Wed, 27 Feb 2008 15:13:11 +0000 Subject: [PATCH] Fixed the shift behaviour by moving it out into functions like the add and subtract operations already were --- backends/GenerateC.hs | 24 ++---------------------- tock_support.h | 25 ++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/backends/GenerateC.hs b/backends/GenerateC.hs index 7087b54..12a4554 100644 --- a/backends/GenerateC.hs +++ b/backends/GenerateC.hs @@ -263,15 +263,6 @@ cgetScalarType A.Timer = Just "Time" cgetScalarType A.Time = Just "Time" cgetScalarType _ = Nothing -cgetUnsignedType :: A.Type -> Maybe String -cgetUnsignedType t | elem t [A.Byte, A.UInt16, A.UInt32, A.UInt64] = cgetScalarType t -cgetUnsignedType A.Int8 = cgetScalarType A.Byte -cgetUnsignedType A.Int = cgetScalarType A.UInt32 -cgetUnsignedType A.Int16 = cgetScalarType A.UInt16 -cgetUnsignedType A.Int32 = cgetScalarType A.UInt32 -cgetUnsignedType A.Int64 = cgetScalarType A.UInt64 -cgetUnsignedType _ = Nothing - -- | Generate the C type corresponding to a variable being declared. -- It must be possible to use this in arrays. cgenType :: A.Type -> CGen () @@ -853,19 +844,8 @@ cgenDyadic m A.Rem e f = call genFuncDyadic m "rem" e f cgenDyadic _ A.Plus e f = call genSimpleDyadic "+" e f cgenDyadic _ A.Minus e f = call genSimpleDyadic "-" e f cgenDyadic _ A.Times e f = call genSimpleDyadic "*" e f -cgenDyadic _ A.LeftShift e f = call genSimpleDyadic "<<" e f -cgenDyadic m A.RightShift e f - = do t <- typeOfExpression e - (normalT, unsignedT) <- case (cgetScalarType t, cgetUnsignedType t) of - (Just x, Just y) -> return (x,y) - _ -> diePC m $ formatCode "Attempting to shift non-integer type: %" t - if (normalT == unsignedT) - then call genSimpleDyadic ">>" e f - else do tell ["((", normalT, ")(((", unsignedT, ")"] - call genExpression e - tell [") >> "] - call genExpression f - tell ["))"] +cgenDyadic m A.LeftShift e f = call genFuncDyadic m "lshift" e f +cgenDyadic m A.RightShift e f = call genFuncDyadic m "rshift" e f cgenDyadic _ A.BitAnd e f = call genSimpleDyadic "&" e f cgenDyadic _ A.BitOr e f = call genSimpleDyadic "|" e f cgenDyadic _ A.BitXor e f = call genSimpleDyadic "^" e f diff --git a/tock_support.h b/tock_support.h index c370a39..2a52fdd 100644 --- a/tock_support.h +++ b/tock_support.h @@ -180,6 +180,28 @@ static inline int occam_check_retype (int src, int dest, const char *pos) { return a - (i * b); \ } +#define MAKE_SHIFT(type) \ + static inline type occam_lshift_##type (type, int, const char*) occam_unused; \ + static inline type occam_lshift_##type (type a, int b, const char* pos) { \ + if (b < 0 || b > sizeof(type) * CHAR_BIT) { \ + occam_stop (pos, "left shift by negative value or value (strictly) greater than number of bits in type"); \ + } else if (b == sizeof(type) * CHAR_BIT) { \ + return 0; \ + } else { \ + return (a << b); \ + } \ + } \ + static inline type occam_rshift_##type (type, int, const char*) occam_unused; \ + static inline type occam_rshift_##type (type a, int b, const char* pos) { \ + if (b < 0 || b > sizeof(type) * CHAR_BIT) { \ + occam_stop (pos, "right shift by negative value or value (strictly) greater than number of bits in type"); \ + } else if (b == sizeof(type) * CHAR_BIT) { \ + return 0; \ + } else { \ + return (type)(((u##type)a) >> b); \ + } \ + } + #define MAKE_ALL_SIGNED(type,flag) \ MAKE_RANGE_CHECK(type,flag) \ MAKE_ADD(type) \ @@ -187,7 +209,8 @@ static inline int occam_check_retype (int src, int dest, const char *pos) { MAKE_MUL(type) \ MAKE_DIV(type) \ MAKE_REM(type) \ - MAKE_NEGATE(type) + MAKE_NEGATE(type) \ + MAKE_SHIFT(type) //{{{ uint8_t MAKE_RANGE_CHECK(uint8_t, "%d")