On 08/25/18 19:38, H. Peter Anvin wrote: > > If it was worthwhile it would make more sense to at least force this > into the rodata section with the string, something like the attached > file for an example; however, I have a hunch it doesn't matter. > An even nuttier version which avoids the extra pointer indirection. Read it and fear. -hpa
#include <stddef.h> #include <string.h> #define _RET_IP_ ((unsigned long)__builtin_return_address(0)) #define no_inline __attribute__((noinline)) #define must_inline __attribute__((always_inline)) inline struct myputs_string { unsigned short len; char str[0]; }; int _myputs_struct(const struct myputs_string * const strs); int _myputs_string(const char *str); int __myputs(unsigned long ip, const char *str, size_t len); int no_inline _myputs_struct(const struct myputs_string * const strs) { return __myputs(_RET_IP_, strs->str, strs->len); } int no_inline _myputs_string(const char *str) { return __myputs(_RET_IP_, str, strlen(str)+1); } #define ifconst(x,y) __builtin_choose_expr(__builtin_constant_p(x),(x),(y)) #define myputs(s) \ ({ \ int _rv; \ if (__builtin_constant_p(s) && \ __builtin_constant_p(strlen(s)) && \ strlen(s)+1 == sizeof(s) && \ sizeof(s) <= (size_t)65535) { \ static const struct { \ struct myputs_string _mps_hdr; \ char _mps_str[sizeof(s)]; \ } _mps = { \ ._mps_hdr.len = sizeof(s), \ ._mps_str = ifconst(s,""), \ }; \ _rv = _myputs_struct(&_mps._mps_hdr); \ } else { \ _rv = _myputs_string(s); \ } \ _rv; \ }) int test1(void); int test2(const char *strx); int test1(void) { return myputs("Foobar"); } int test2(const char *strx) { return myputs(strx); }