Add bgamari's C++11 checksumming approach.
authorAdam Green <adamgr@foo.bar>
Thu, 31 Jan 2013 07:28:31 +0000 (23:28 -0800)
committerAdam Green <adamgr@foo.bar>
Thu, 31 Jan 2013 07:28:31 +0000 (23:28 -0800)
I haved added bgamari's cool C++11 user defined literals approach.  In simple
cases it generates the exact same code as the C preprocessor approach but if
multiple checkums are calculated in the same function, I see the constant
folding not happening for some which makes the code even larger than just
having the string in the code.  For this reason I have disabled it for now but
left it in so that it is easy to test out in the future and hopefully switch
to as its implementation is much shorter and clearer.

Maybe just an issue in GCC as these features are new or maybe there is an
optimizer setting that needs to be set.  I tried GCC 4.7 from
https://launchpad.net/gcc-arm-embedded/+milestone/4.7-2012-q4-major

src/libs/checksumm.h

index 40e0ccb..46c605c 100644 (file)
@@ -1,6 +1,4 @@
 /*
-    Copyright 2013 Adam Green (https://github.com/adamgreen)
-
     This file is part of Smoothie (http://smoothieware.org/)
     The motion control part is heavily based on Grbl (https://github.com/simen/grbl)
 
 #ifndef _CHECKSUM_MACRO_H_
 #define _CHECKSUM_MACRO_H_
 
+/* There are two compile time checksumming approaches in this file.  One uses
+   the C preprocessor and the other uses new C++11 features.  They should both
+   do the same thing but my current compiler, GCC 4.7, doesn't always do the
+   constant folding for the C++ approach and this causes code bloat.  The C 
+   preprocessor approach can currently generate the exact same code in 
+   Checked/Release builds as the old method of pre-calculating checksums by 
+   hand and pasting them into the code.
+   
+   Keeping both versions here: the active C version and the C++ version
+   that we should switch to later if newer compilers do the required constant
+   folding (maybe there are optimization flags to help here.)
+*/
+#ifdef CHECKSUM_USE_CPP
+
+/* Cool C++11 approach contributed by bgamari on smoothieware IRC channel. */
+constexpr uint16_t checksum(const char* s, size_t n, size_t i, uint16_t sum1, uint16_t sum2) {
+  return (i <= n) ? checksum(s, n, i+1, (sum1 + s[i]) % 255, (sum2 + sum1) % 255) : ((sum2 << 8) | sum1);
+}
+
+constexpr uint16_t operator "" _checksum(const char* s, size_t n) {
+  return checksum(s, n, 0, 0, 0);
+}
+
+#define CHECKSUM(X) X##_checksum
+
+#else
+
+/* Adam Green's old and crusty C approach. */
 /* Recursively define SUM1, the basic checksum % 255 */
 #define SUM1_1(X) ((X)[0] % 255)
 #define SUM1_2(X) ((SUM1_1(X) + (X)[1]) % 255)
                      sizeof(X) == 32 ? CHECKSUM_31(X) : \
                      sizeof(X) == 33 ? CHECKSUM_32(X) : \
                      0xFFFF)
+#endif
 
 #endif /* _CHECKSUM_MACRO_H_ */