[Mesa-dev] [PATCH 06/11] compiler/blob: make blob_reserve_bytes() more useful

Jordan Justen jordan.l.justen at intel.com
Thu Oct 12 22:59:43 UTC 2017


On 2017-10-11 13:38:46, Jason Ekstrand wrote:
> From: Connor Abbott <cwabbott0 at gmail.com>
> 
> Despite the name, it could only be used if you immediately wrote to the
> pointer. Noboby was using it outside of one test, so clearly this
> behavior wasn't that useful. Instead, make it return an offset into the
> data buffer so that the result isn't invalidated if you later write to
> the blob. In conjunction with blob_overwrite_bytes(), this will be
> useful for leaving a placeholder and then filling it in later, which
> we'll need to do for handling phi nodes when serializing NIR.
> 
> v2 (Jason Ekstrand):
>  - Improve the blob_overwrite_uint32 documentation
>  - Detect overflow in the offset + to_write computation
>  - Add a blob_reserve_uint32 helper
>  - Add a blob_overwrite_intptr helper

Why not add blob_reserve_uint32 and blob_overwrite_intptr in a
separate patch? I think fixing the alignment issue is worth
highlighting in its own patch.

-Jordan

> ---
>  src/compiler/blob.c                 | 37 +++++++++++++++++++++----
>  src/compiler/blob.h                 | 54 ++++++++++++++++++++++++++-----------
>  src/compiler/glsl/tests/blob_test.c |  4 +--
>  3 files changed, 73 insertions(+), 22 deletions(-)
> 
> diff --git a/src/compiler/blob.c b/src/compiler/blob.c
> index 59ad8a3..c5ed9f5 100644
> --- a/src/compiler/blob.c
> +++ b/src/compiler/blob.c
> @@ -130,7 +130,7 @@ blob_overwrite_bytes(struct blob *blob,
>                       size_t to_write)
>  {
>     /* Detect an attempt to overwrite data out of bounds. */
> -   if (blob->size < offset + to_write)
> +   if (offset + to_write < offset || blob->size < offset + to_write)
>        return false;
>  
>     VG(VALGRIND_CHECK_MEM_IS_DEFINED(bytes, to_write));
> @@ -156,20 +156,34 @@ blob_write_bytes(struct blob *blob, const void *bytes, size_t to_write)
>     return true;
>  }
>  
> -uint8_t *
> +ssize_t
>  blob_reserve_bytes(struct blob *blob, size_t to_write)
>  {
> -   uint8_t *ret;
> +   ssize_t ret;
>  
>     if (! grow_to_fit (blob, to_write))
> -      return NULL;
> +      return -1;
>  
> -   ret = blob->data + blob->size;
> +   ret = blob->size;
>     blob->size += to_write;
>  
>     return ret;
>  }
>  
> +ssize_t
> +blob_reserve_uint32(struct blob *blob)
> +{
> +   align_blob(blob, sizeof(uint32_t));
> +   return blob_reserve_bytes(blob, sizeof(uint32_t));
> +}
> +
> +ssize_t
> +blob_reserve_intptr(struct blob *blob)
> +{
> +   align_blob(blob, sizeof(intptr_t));
> +   return blob_reserve_bytes(blob, sizeof(intptr_t));
> +}
> +
>  bool
>  blob_write_uint32(struct blob *blob, uint32_t value)
>  {
> @@ -178,11 +192,15 @@ blob_write_uint32(struct blob *blob, uint32_t value)
>     return blob_write_bytes(blob, &value, sizeof(value));
>  }
>  
> +#define ASSERT_ALIGNED(_offset, _align) \
> +   assert(ALIGN((_offset), (_align)) == (_offset))
> +
>  bool
>  blob_overwrite_uint32 (struct blob *blob,
>                         size_t offset,
>                         uint32_t value)
>  {
> +   ASSERT_ALIGNED(offset, sizeof(value));
>     return blob_overwrite_bytes(blob, offset, &value, sizeof(value));
>  }
>  
> @@ -203,6 +221,15 @@ blob_write_intptr(struct blob *blob, intptr_t value)
>  }
>  
>  bool
> +blob_overwrite_intptr (struct blob *blob,
> +                       size_t offset,
> +                       intptr_t value)
> +{
> +   ASSERT_ALIGNED(offset, sizeof(value));
> +   return blob_overwrite_bytes(blob, offset, &value, sizeof(value));
> +}
> +
> +bool
>  blob_write_string(struct blob *blob, const char *str)
>  {
>     return blob_write_bytes(blob, str, strlen(str) + 1);
> diff --git a/src/compiler/blob.h b/src/compiler/blob.h
> index 1ef6d99..ad4b6fa 100644
> --- a/src/compiler/blob.h
> +++ b/src/compiler/blob.h
> @@ -126,24 +126,32 @@ blob_write_bytes(struct blob *blob, const void *bytes, size_t to_write);
>   * Reserve space in \blob for a number of bytes.
>   *
>   * Space will be allocated within the blob for these byes, but the bytes will
> - * be left uninitialized. The caller is expected to use the return value to
> - * write directly (and immediately) to these bytes.
> + * be left uninitialized. The caller is expected to use \sa
> + * blob_overwrite_bytes to write to these bytes.
>   *
> - * \note The return value is valid immediately upon return, but can be
> - * invalidated by any other call to a blob function. So the caller should call
> - * blob_reserve_byes immediately before writing through the returned pointer.
> - *
> - * This function is intended to be used when interfacing with an existing API
> - * that is not aware of the blob API, (so that blob_write_bytes cannot be
> - * called).
> - *
> - * \return A pointer to space allocated within \blob to which \to_write bytes
> - * can be written, (or NULL in case of any allocation error).
> + * \return An offset to space allocated within \blob to which \to_write bytes
> + * can be written, (or -1 in case of any allocation error).
>   */
> -uint8_t *
> +ssize_t
>  blob_reserve_bytes(struct blob *blob, size_t to_write);
>  
>  /**
> + * Similar to \sa blob_reserve_bytes, but only reserves an uint32_t worth of
> + * space. Note that this must be used if later reading with \sa
> + * blob_read_uint32, since it aligns the offset correctly.
> + */
> +ssize_t
> +blob_reserve_uint32(struct blob *blob);
> +
> +/**
> + * Similar to \sa blob_reserve_bytes, but only reserves an intptr_t worth of
> + * space. Note that this must be used if later reading with \sa
> + * blob_read_intptr, since it aligns the offset correctly.
> + */
> +ssize_t
> +blob_reserve_intptr(struct blob *blob);
> +
> +/**
>   * Overwrite some data previously written to the blob.
>   *
>   * Writes data to an existing portion of the blob at an offset of \offset.
> @@ -186,8 +194,7 @@ blob_write_uint32(struct blob *blob, uint32_t value);
>   *
>   *     size_t offset;
>   *
> - *     offset = blob->size;
> - *     blob_write_uint32 (blob, 0); // placeholder
> + *     offset = blob_reserve_uint32(blob);
>   *     ... various blob write calls, writing N items ...
>   *     blob_overwrite_uint32 (blob, offset, N);
>   *
> @@ -226,6 +233,23 @@ bool
>  blob_write_intptr(struct blob *blob, intptr_t value);
>  
>  /**
> + * Overwrite a uint32_t previously written to the blob.
> + *
> + * Writes a uint32_t value to an existing portion of the blob at an offset of
> + * \offset.  This data range must have previously been written to the blob by
> + * one of the blob_write_* calls.
> + *
> + * For example usage, see blob_overwrite_uint32
> + *
> + * \return True unless the requested position or position+to_write lie outside
> + * the current blob's size.
> + */
> +bool
> +blob_overwrite_intptr(struct blob *blob,
> +                      size_t offset,
> +                      intptr_t value);
> +
> +/**
>   * Add a NULL-terminated string to a blob, (including the NULL terminator).
>   *
>   * \return True unless allocation failed.
> diff --git a/src/compiler/glsl/tests/blob_test.c b/src/compiler/glsl/tests/blob_test.c
> index df0e91a..1b3ab6e 100644
> --- a/src/compiler/glsl/tests/blob_test.c
> +++ b/src/compiler/glsl/tests/blob_test.c
> @@ -120,7 +120,7 @@ test_write_and_read_functions (void)
>  {
>     struct blob *blob;
>     struct blob_reader reader;
> -   uint8_t *reserved;
> +   ssize_t reserved;
>     size_t str_offset, uint_offset;
>     uint8_t reserve_buf[sizeof(reserve_test_str)];
>  
> @@ -131,7 +131,7 @@ test_write_and_read_functions (void)
>     blob_write_bytes(blob, bytes_test_str, sizeof(bytes_test_str));
>  
>     reserved = blob_reserve_bytes(blob, sizeof(reserve_test_str));
> -   memcpy(reserved, reserve_test_str, sizeof(reserve_test_str));
> +   blob_overwrite_bytes(blob, reserved, reserve_test_str, sizeof(reserve_test_str));
>  
>     /* Write a placeholder, (to be replaced later via overwrite_bytes) */
>     str_offset = blob->size;
> -- 
> 2.5.0.400.gff86faf
> 
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list