home bbs files messages ]

Forums before death by AOL, social media and spammers... "We can't have nice things"

   comp.lang.c      Meh, in C you gotta define EVERYTHING      243,242 messages   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]

   Message 241,274 of 243,242   
   Kaz Kylheku to bart   
   Re: Nice way of allocating flexible stru   
   10 Oct 25 01:54:29   
   
   From: 643-408-1753@kylheku.com   
      
   On 2025-10-10, bart  wrote:   
   > On 09/10/2025 04:49, BGB wrote:   
   >> On 10/8/2025 2:04 PM, Janis Papanagnou wrote:   
   >>> On 08.10.2025 19:29, BGB wrote:   
   >   
   >> Though, similar was often a problem in my other language design   
   >> attempts: The most efficient way to do things was often also the C way.   
   >>   
   >>   
   >>   
   >> The only real exception I have found to this rule basically being in   
   >> relation to some features I have borrowed from languages like GLSL and   
   >> Verilog. But, some of this stuff isn't so much making the language   
   >> "higher level" as much as "being easier to map to ISA features and   
   >> optimize".   
   >>   
   >> Say:   
   >>    vd[62:52]=vs[20:10];   
   >> Being easier to optimize than, say:   
   >>    vd=(vd&(~(2047ULL<<52)))|(((vs>>10)&2047ULL)<<52);   
   >   
   > Using special bit-features makes it easier to generate decent code for a   
   > simple compiler.   
   >   
   > But gcc for example has no trouble optimising that masking/shifting version.   
   >   
   > (It can do it in four x64 instructions, whereas I need nine working from   
   > vd.[62..52] := vs.[20..10]. It could be improved though; I don't need to   
   > extract the data to bits 10..0 first for example.)   
   >   
   > The main advantage is that it is a LOT easier to write, read and   
   > understand. The C would need macros to make it practical.   
      
   I'm skeptical that the C macro system is powerful enough to actually   
   create an operand like   
      
     bits(vd, 52, 62)   
      
   such that this constitutes an lvalue that can be assigned,   
   such that those range of bits will receive the value.   
      
   The closest C mechanism to that is the bitfield, which has   
   compartments decided at compile-time.   
      
   What if 52 and 62 could be variables?   
      
   Common Lisp has this feature, via the LDB macro (load byte).   
      
   For instance:   
      
   [3]> (ldb (byte 4 2) 100)   
   9   
      
   I.e. 100 is 1100100 binary, and we are taking 4 bits starting   
   from bit 2 (zero based), taking the 1001.   
      
   If we have a variable that holds 100 we can overwrite those 4   
   bits with say 15:   
      
   [4]> (let ((x 100))   
          (setf (ldb (byte 4 2) x) 15)   
          x)   
   124   
      
   I.e. 1111100 which is 31 x 4 = 124.   
      
   What is (byte 4 2)? It is a function which constructs an implementation-defined   
   object that represents a "byte specification".   
      
   When ldb is behaving as an assignable place, it can access the syntax to get to   
   the constants; the function isn't necessarily called at run-time to construct a   
   value, though such code can be generated also, in a less optimized   
   implementation. I.e. it can generate code which calls the function dpb (deposit   
   byte) which takes a byte spec and value.   
      
   Such code has to be used in the worst cases, like when instead of   
   (byte ...) expressions you have something which evaluates to a byte   
   expression otherwise, like a varible:   
      
     (let ((x (byte-spec-out-of-thin-air)))   
           (y 73))   
       (setf (ldb x y) 0))   
      
   Let's see how CLISP deals with that one:   
      
     [1]> (ext:expand-form '(setf (ldb x y) 0)) ;; output indented and annotated:   
     (LET* ((#:BYTESPEC-3319 X)  ;; evaluate x bytespec to temporary var   
            (#:NEW-3320 0))      ;; evaluate 0 to temporary var   
        ;; call DPB on these to put the bitfield into value taken from Y.   
         (LET ((#:NEW-3318 (DPB #:NEW-3320 #:BYTESPEC-3319 Y)))   
           ;; store edited value back into Y   
           (SETQ Y #:NEW-3318)   
           ;; return edited value   
           #:NEW-3320)) ;   
      
   If you didn't have byte and ldb in Common Lisp, you could write them   
   yourself, and have them work with setf.   
      
   You'd have to write a "setf expansion" for ldb, and you could have it   
   spit out inline code to do shifting and masking, when the argument   
   is a (byte ...) expression from which your expansion code can pull out the   
   offset and width.   
      
      
   --   
   TXR Programming Language: http://nongnu.org/txr   
   Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal   
   Mastodon: @Kazinator@mstdn.ca   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]


(c) 1994,  bbs@darkrealms.ca