chiark / gitweb /
src/builtin.lisp, src/codegen-proto.lisp: Improve slot initialization.
authorMark Wooding <mdw@distorted.org.uk>
Wed, 21 Oct 2015 23:46:28 +0000 (00:46 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Sat, 7 Nov 2015 14:23:54 +0000 (14:23 +0000)
The fundamental difficulty is that actually we're not initializing an
instance's slots: we're assigning values to them.

Previously, we tried to distinguish scalar from aggregate initializers.
The former got converted into

sod__obj->nick.slot = EXPR;

while the latter ended up as

sod__obj->nick.slot = (TYPE) { COMPOUND-INIT };

There are two problems with this.  The first is easy: aggregate
literals, such are used in the latter case, are shiny and new in C99.
The second is more subtle: we distinguish aggregate from scalar
initializers from whether they're wrapped up in braces -- but in fact
they needn't be if they've been concealed in a macro, e.g.,
`PTHREAD_MUTEX_INITIALIZER', or `DSTR_INIT'.  Under the previous rules,
you'd have to write something like

pthread_mutex_t slot = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;

as your slot definition in order to get the right effect, and that's
just annoying.  (It would be a disservice to users to insert the cast
unconditionally, of course, since that would eliminate useful type
checking.)

Change all of this.  Instead, actually initialize an object of the right
type (we know that type that is, of course), and then assign it to the
slot.  A decent compiler will turn this into exactly the same object
code (yes, I tested this), and it means that our heuristic is no longer
needed for anything important.  I've preserved the distinction anyway,
because we can format compound initializers slightly more prettily, but
it no longer makes any semantic difference, and the dependency on C99
has been eliminated.

src/builtin.lisp
src/codegen-proto.lisp

index 5aad5f54f985fe1c2f97edfea7548cea25715484..7bb38e5b62957b8e7d741697f2fad6cd2f125c64 100644 (file)
@@ -140,19 +140,22 @@ (define-class-slot "init" (class stream)
                               "  struct ~A *sod__obj = ~A__imprint(p);~2%"
                               (ilayout-struct-tag class) class)
                       (setf used t))
-                    (format stream "  ~A.~A =" isl
-                            (sod-slot-name dslot))
+                    (format stream "  {~%    ~A ~A ="
+                            (sod-slot-type dslot)
+                            *sod-tmp-val*)
                     (ecase (sod-initializer-value-kind init)
                       (:simple (write (sod-initializer-value-form init)
                                       :stream stream
                                       :pretty nil :escape nil)
                                (format stream ";~%"))
-                      (:compound (format stream " (~A) {"
-                                         (sod-slot-type dslot))
+                      (:compound (format stream " {")
                                  (write (sod-initializer-value-form init)
                                         :stream stream
                                         :pretty nil :escape nil)
-                                 (format stream "};~%"))))))))))))
+                                 (format stream "    };~%")))
+                    (format stream "    ~A.~A = ~A;~%  }~%"
+                            isl (sod-slot-name dslot)
+                            *sod-tmp-val*))))))))))
     (unless used
       (format stream "  ~A__imprint(p);~%" class))
     (format stream "~&~:
index 42175a5e208b06b568221b0d67aecdbe35a6df52..6dc6dc10fd60c5692d8fd6cb34557d3f20d6fda9 100644 (file)
@@ -64,6 +64,8 @@ (defparameter *sod-master-ap*
   (make-instance 'temporary-name :tag "sod__master_ap"))
 (defparameter *sod-tmp-ap*
   (make-instance 'temporary-name :tag "sod__tmp_ap"))
+(defparameter *sod-tmp-val*
+  (make-instance 'temporary-name :tag "sod__t"))
 
 ;;;--------------------------------------------------------------------------
 ;;; Instructions.