mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-24 11:00:11 +01:00
driconf: add uint64 type
This is needed for panvk, where we want to expose uint64 core masks. The previous int parsing logic was technically UB rather than guaranteed truncate-on-overflow, but was likely compiled to truncate in practice. It is very unlikely that anyone was relying on this. Signed-off-by: Benjamin Lee <benjamin.lee@collabora.com> Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/34374>
This commit is contained in:
parent
141f0ef4e4
commit
d46e76be02
3 changed files with 108 additions and 18 deletions
|
|
@ -58,6 +58,12 @@
|
|||
.end = { ._int = max }, \
|
||||
} \
|
||||
|
||||
#define DRI_CONF_RANGE_U64(min, max) \
|
||||
.range = { \
|
||||
.start = { ._uint64 = min }, \
|
||||
.end = { ._uint64 = max }, \
|
||||
}
|
||||
|
||||
#define DRI_CONF_RANGE_F(min, max) \
|
||||
.range = { \
|
||||
.start = { ._float = min }, \
|
||||
|
|
@ -88,6 +94,16 @@
|
|||
.value = { ._int = def }, \
|
||||
},
|
||||
|
||||
#define DRI_CONF_OPT_U64(_name, def, min, max, _desc) { \
|
||||
.desc = _desc, \
|
||||
.info = { \
|
||||
.name = #_name, \
|
||||
.type = DRI_UINT64, \
|
||||
DRI_CONF_RANGE_U64(min, max), \
|
||||
}, \
|
||||
.value = { ._uint64 = def }, \
|
||||
},
|
||||
|
||||
#define DRI_CONF_OPT_F(_name, def, min, max, _desc) { \
|
||||
.desc = _desc, \
|
||||
.info = { \
|
||||
|
|
|
|||
|
|
@ -76,31 +76,35 @@ be_verbose(void)
|
|||
return strstr(s, "silent") == NULL;
|
||||
}
|
||||
|
||||
/** \brief Locale-independent integer parser.
|
||||
/** \brief Locale-independent 64-bit integer parser.
|
||||
*
|
||||
* Works similar to strtol. Leading space is NOT skipped. The input
|
||||
* number may have an optional sign. Radix is specified by base. If
|
||||
* base is 0 then decimal is assumed unless the input number is
|
||||
* prefixed by 0x or 0X for hexadecimal or 0 for octal. After
|
||||
* returning tail points to the first character that is not part of
|
||||
* the integer number. If no number was found then tail points to the
|
||||
* start of the input string. */
|
||||
static int
|
||||
strToI(const char *string, const char **tail, int base)
|
||||
* Works similar to strtol. Leading space is NOT skipped. If the sign
|
||||
* argument is non-null, the input number may have an optional sign.
|
||||
* Radix is specified by base. If base is 0 then decimal is assumed
|
||||
* unless the input number is prefixed by 0x or 0X for hexadecimal or
|
||||
* 0 for octal. After returning tail points to the first character
|
||||
* that is not part of the integer number. If no number was found then
|
||||
* tail points to the start of the input string. Out-of-range values
|
||||
* are truncated. */
|
||||
static uint64_t
|
||||
strToInteger(const char *string, const char **tail, int *sign, int base)
|
||||
{
|
||||
int radix = base == 0 ? 10 : base;
|
||||
int result = 0;
|
||||
int sign = 1;
|
||||
uint64_t result = 0;
|
||||
bool numberFound = false;
|
||||
const char *start = string;
|
||||
|
||||
assert(radix >= 2 && radix <= 36);
|
||||
|
||||
if (*string == '-') {
|
||||
sign = -1;
|
||||
string++;
|
||||
} else if (*string == '+')
|
||||
string++;
|
||||
if (sign) {
|
||||
*sign = 1;
|
||||
if (*string == '-') {
|
||||
*sign = -1;
|
||||
string++;
|
||||
} else if (*string == '+')
|
||||
string++;
|
||||
}
|
||||
|
||||
if (base == 0 && *string == '0') {
|
||||
numberFound = true;
|
||||
if (*(string+1) == 'x' || *(string+1) == 'X') {
|
||||
|
|
@ -132,9 +136,30 @@ strToI(const char *string, const char **tail, int base)
|
|||
break;
|
||||
} while (true);
|
||||
*tail = numberFound ? string : start;
|
||||
return result;
|
||||
}
|
||||
|
||||
/** \brief Locale-independent integer parser.
|
||||
*
|
||||
* Follows the semantics of strToInteger, allowing a sign character. */
|
||||
static int
|
||||
strToI(const char *string, const char **tail, int base)
|
||||
{
|
||||
int sign;
|
||||
int result = strToInteger(string, tail, &sign, base);
|
||||
return sign * result;
|
||||
}
|
||||
|
||||
/** \brief Locale-independent 64-bit unsigned integer parser.
|
||||
*
|
||||
* Follows the semantics of strToInteger, without allowing a sign
|
||||
* character. */
|
||||
static uint64_t
|
||||
strToU64(const char *string, const char **tail, int base)
|
||||
{
|
||||
return strToInteger(string, tail, NULL, base);
|
||||
}
|
||||
|
||||
/** \brief Locale-independent floating-point parser.
|
||||
*
|
||||
* Works similar to strtod. Leading space is NOT skipped. The input
|
||||
|
|
@ -233,6 +258,9 @@ parseValue(driOptionValue *v, driOptionType type, const char *string)
|
|||
case DRI_INT:
|
||||
v->_int = strToI(string, &tail, 0);
|
||||
break;
|
||||
case DRI_UINT64:
|
||||
v->_uint64 = strToU64(string, &tail, 0);
|
||||
break;
|
||||
case DRI_FLOAT:
|
||||
v->_float = strToF(string, &tail);
|
||||
break;
|
||||
|
|
@ -303,6 +331,11 @@ checkValue(const driOptionValue *v, const driOptionInfo *info)
|
|||
(v->_int >= info->range.start._int &&
|
||||
v->_int <= info->range.end._int));
|
||||
|
||||
case DRI_UINT64:
|
||||
return (info->range.start._uint64 == info->range.end._uint64 ||
|
||||
(v->_uint64 >= info->range.start._uint64 &&
|
||||
v->_uint64 <= info->range.end._uint64));
|
||||
|
||||
case DRI_FLOAT:
|
||||
return (info->range.start._float == info->range.end._float ||
|
||||
(v->_float >= info->range.start._float &&
|
||||
|
|
@ -368,6 +401,10 @@ driParseOptionInfo(driOptionCache *info,
|
|||
optval->_int = opt->value._int;
|
||||
break;
|
||||
|
||||
case DRI_UINT64:
|
||||
optval->_uint64 = opt->value._uint64;
|
||||
break;
|
||||
|
||||
case DRI_FLOAT:
|
||||
optval->_float = opt->value._float;
|
||||
break;
|
||||
|
|
@ -437,6 +474,7 @@ driGetOptionsXml(const driOptionDescription *configOptions, unsigned numOptions)
|
|||
const char *types[] = {
|
||||
[DRI_BOOL] = "bool",
|
||||
[DRI_INT] = "int",
|
||||
[DRI_UINT64] = "uint64",
|
||||
[DRI_FLOAT] = "float",
|
||||
[DRI_ENUM] = "enum",
|
||||
[DRI_STRING] = "string",
|
||||
|
|
@ -470,6 +508,10 @@ driGetOptionsXml(const driOptionDescription *configOptions, unsigned numOptions)
|
|||
ralloc_asprintf_append(&str, "%d", opt->value._int);
|
||||
break;
|
||||
|
||||
case DRI_UINT64:
|
||||
ralloc_asprintf_append(&str, "%" PRIu64, opt->value._uint64);
|
||||
break;
|
||||
|
||||
case DRI_FLOAT:
|
||||
ralloc_asprintf_append(&str, "%f", opt->value._float);
|
||||
break;
|
||||
|
|
@ -495,6 +537,14 @@ driGetOptionsXml(const driOptionDescription *configOptions, unsigned numOptions)
|
|||
}
|
||||
break;
|
||||
|
||||
case DRI_UINT64:
|
||||
if (opt->info.range.start._uint64 < opt->info.range.end._uint64) {
|
||||
ralloc_asprintf_append(&str, " valid=\"%" PRIu64 ":%" PRIu64 "\"",
|
||||
opt->info.range.start._uint64,
|
||||
opt->info.range.end._uint64);
|
||||
}
|
||||
break;
|
||||
|
||||
case DRI_FLOAT:
|
||||
if (opt->info.range.start._float < opt->info.range.end._float) {
|
||||
ralloc_asprintf_append(&str, " valid=\"%f:%f\"",
|
||||
|
|
@ -639,6 +689,11 @@ parseRange(driOptionInfo *info, const char *string)
|
|||
free(cp);
|
||||
return false;
|
||||
}
|
||||
if (info->type == DRI_UINT64 &&
|
||||
info->range.start._uint64 >= info->range.end._uint64) {
|
||||
free(cp);
|
||||
return false;
|
||||
}
|
||||
if (info->type == DRI_FLOAT &&
|
||||
info->range.start._float >= info->range.end._float) {
|
||||
free(cp);
|
||||
|
|
@ -1278,6 +1333,16 @@ driQueryOptioni(const driOptionCache *cache, const char *name)
|
|||
return cache->values[i]._int;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
driQueryOptionu64(const driOptionCache *cache, const char *name)
|
||||
{
|
||||
uint32_t i = findOption(cache, name);
|
||||
/* make sure the option is defined and has the correct type */
|
||||
assert(cache->info[i].name != NULL);
|
||||
assert(cache->info[i].type == DRI_UINT64);
|
||||
return cache->values[i]._uint64;
|
||||
}
|
||||
|
||||
float
|
||||
driQueryOptionf(const driOptionCache *cache, const char *name)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "util/ralloc.h"
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
@ -43,13 +44,14 @@ extern "C" {
|
|||
|
||||
/** \brief Option data types */
|
||||
typedef enum driOptionType {
|
||||
DRI_BOOL, DRI_ENUM, DRI_INT, DRI_FLOAT, DRI_STRING, DRI_SECTION
|
||||
DRI_BOOL, DRI_ENUM, DRI_INT, DRI_UINT64, DRI_FLOAT, DRI_STRING, DRI_SECTION
|
||||
} driOptionType;
|
||||
|
||||
/** \brief Option value */
|
||||
typedef union driOptionValue {
|
||||
unsigned char _bool; /**< \brief Boolean */
|
||||
int _int; /**< \brief Integer or Enum */
|
||||
uint64_t _uint64; /**< \brief Unsigned 64-bit Integer */
|
||||
float _float; /**< \brief Floating-point */
|
||||
char *_string; /**< \brief String */
|
||||
} driOptionValue;
|
||||
|
|
@ -153,6 +155,8 @@ unsigned char driCheckOption(const driOptionCache *cache, const char *name,
|
|||
unsigned char driQueryOptionb(const driOptionCache *cache, const char *name);
|
||||
/** \brief Query an integer option value */
|
||||
int driQueryOptioni(const driOptionCache *cache, const char *name);
|
||||
/** \brief Query a 64-bit unsigned integer option value */
|
||||
uint64_t driQueryOptionu64(const driOptionCache *cache, const char *name);
|
||||
/** \brief Query a floating-point option value */
|
||||
float driQueryOptionf(const driOptionCache *cache, const char *name);
|
||||
/** \brief Query a string option value */
|
||||
|
|
@ -187,6 +191,11 @@ driComputeOptionsSha1(const driOptionCache *cache, unsigned char *sha1)
|
|||
cache->info[i].name,
|
||||
cache->values[i]._int);
|
||||
break;
|
||||
case DRI_UINT64:
|
||||
ret = ralloc_asprintf_append(&dri_options, "%s:%" PRIu64 ",",
|
||||
cache->info[i].name,
|
||||
cache->values[i]._uint64);
|
||||
break;
|
||||
case DRI_FLOAT:
|
||||
ret = ralloc_asprintf_append(&dri_options, "%s:%f,",
|
||||
cache->info[i].name,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue