On Fri, 11 Jan 2019, Ted Unangst wrote:

> Stefan Fritsch wrote:
> > +#define CREAD(sc, memb)                                                    
> >         \
> > +   ({                                                                      
> > \
> > +           struct virtio_pci_common_cfg c;                                 
> > \
> > +           size_t off = offsetof(struct virtio_pci_common_cfg, memb);      
> > \
> > +           size_t size = sizeof(c.memb);                                   
> > \
> > +           typeof(c.memb) val;                                             
> > \
> > +                                                                           
> > \
> > +           switch (size) {                                                 
> > \
> > +           case 1:                                                         
> > \
> > +                   val = bus_space_read_1(sc->sc_iot, sc->sc_ioh, off);    
> > \
> > +                   break;                                                  
> > \
> > +           case 2:                                                         
> > \
> > +                   val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, off);    
> > \
> > +                   break;                                                  
> > \
> > +           case 4:                                                         
> > \
> > +                   val = bus_space_read_4(sc->sc_iot, sc->sc_ioh, off);    
> > \
> > +                   break;                                                  
> > \
> > +           case 8:                                                         
> > \
> > +                   val = bus_space_read_8(sc->sc_iot, sc->sc_ioh, off);    
> > \
> > +                   break;                                                  
> > \
> > +           }                                                               
> > \
> > +           DNPRINTF(2, "%s: %d: off %#zx size %#zx read %#llx\n",          
> > \
> > +              __func__, __LINE__, off, size, (unsigned long long)val);     
> > \
> > +           val;                                                            
> > \
> > +   })
> 
> I'm not a big fan of statement expressions. I thought we purged most of them
> from the tree in fact. I would say just use an inline. And no typeof.
> 
> (There's only one typeof in sys/ outside of drm, and I added it, but no more
> please.)
> 

A simple inline function does not work because memb is the name of a 
member of a struct. But combined with a macro it would work. Like this:


/* only used for sizeof, not actually allocated */
extern struct virtio_pci_common_cfg ccfg;

static inline
uint64_t _cread(struct virtio_pci_softc *sc, unsigned off, unsigned size)
{
        uint64_t val;
        switch (size) {
        case 1:
                val = bus_space_read_1(sc->sc_iot, sc->sc_ioh, off);
                break;
        case 2:
                val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, off);
                break;
        case 4:
                val = bus_space_read_4(sc->sc_iot, sc->sc_ioh, off);
                break;
        case 8:
                val = bus_space_read_8(sc->sc_iot, sc->sc_ioh, off);
                break;
        }
        return val;
}

#define CREAD(sc, memb)  _cread(sc, \
    offsetof(struct virtio_pci_common_cfg, memb), sizeof(ccfg.memb))


The compiler should optimize this to the same code as the complicated 
macro above. You think this variant is acceptable?

Cheers,
Stefan

Reply via email to