1
0
mirror of https://github.com/google/cpu_features.git synced 2025-04-28 15:33:37 +02:00

Merge pull request #95 from gchatelet/master

Address comments in https://github.com/google/cpu_features/pull/94
This commit is contained in:
Guillaume Chatelet 2019-11-12 17:17:59 +01:00 committed by GitHub
commit 3d07d083f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -18,6 +18,7 @@
#include <assert.h> #include <assert.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -49,119 +50,122 @@ typedef struct {
size_t size; size_t size;
} BumpAllocator; } BumpAllocator;
// Allocate a buffer of size `size`. char gGlobalBuffer[64 * 1024];
static BumpAllocator BA_Create(size_t size) { BumpAllocator gBumpAllocator = {.ptr = gGlobalBuffer,
char* const ptr = (char*)malloc(size); .size = sizeof(gGlobalBuffer)};
BumpAllocator BA;
if (ptr) BA = (BumpAllocator){.ptr = ptr, .size = size}; static void internal_error() {
return BA; fputs("internal error\n", stderr);
exit(EXIT_FAILURE);
}
#define ALIGN 8
static void assertAligned() {
if ((uintptr_t)(gBumpAllocator.ptr) % ALIGN) internal_error();
}
static void BA_Align() {
while (gBumpAllocator.size && (uintptr_t)(gBumpAllocator.ptr) % ALIGN) {
--gBumpAllocator.size;
++gBumpAllocator.ptr;
}
assertAligned();
} }
// Update the available memory left in the BumpAllocator. // Update the available memory left in the BumpAllocator.
static void* BA_Bump(BumpAllocator* BA, size_t size) { static void* BA_Bump(size_t size) {
assert(BA->size >= size); assertAligned();
void* ptr = BA->ptr; // Align size to next 8B boundary.
BA->size -= size; size = (size + ALIGN - 1) / ALIGN * ALIGN;
BA->ptr += size; if (gBumpAllocator.size < size) internal_error();
void* ptr = gBumpAllocator.ptr;
gBumpAllocator.size -= size;
gBumpAllocator.ptr += size;
return ptr; return ptr;
} }
// The type of the nodes in the tree. // The type of the nodes in the tree.
typedef enum { typedef enum {
TNT_INVALID, NT_INVALID,
TNT_INT, NT_INT,
TNT_MAP, NT_MAP,
TNT_MAP_ENTRY, NT_MAP_ENTRY,
TNT_ARRAY, NT_ARRAY,
TNT_ARRAY_ELEMENT, NT_ARRAY_ELEMENT,
TNT_STRING, NT_STRING,
} TreeValueType; } NodeType;
// The node in the tree. // The node in the tree.
typedef struct TreeValue { typedef struct Node {
TreeValueType type; NodeType type;
unsigned integer; unsigned integer;
const char* string; const char* string;
struct TreeValue* value; struct Node* value;
struct TreeValue* next; struct Node* next;
} TreeValue; } Node;
// Allocates a node inside a BumpAllocator. // Creates an initialized Node.
static TreeValue* BA_TreeValue(BumpAllocator* BA, TreeValueType type) { static Node* BA_CreateNode(NodeType type) {
TreeValue* TV = (TreeValue*)BA_Bump(BA, sizeof(TreeValue)); Node* tv = (Node*)BA_Bump(sizeof(Node));
assert(TV); assert(tv);
TV->type = type; *tv = (Node){.type = type};
return TV; return tv;
} }
// Allocates an integer node inside a BumpAllocator. // Adds an integer node.
static TreeValue* CreateInt(BumpAllocator* BA, int value) { static Node* CreateInt(int value) {
TreeValue* TV = BA_TreeValue(BA, TNT_INT); Node* tv = BA_CreateNode(NT_INT);
TV->integer = value; tv->integer = value;
return TV; return tv;
} }
// Allocates a string node inside a BumpAllocator. // Adds a string node.
// `value` must outlive the tree. // `value` must outlive the tree.
static TreeValue* CreateConstantString(BumpAllocator* BA, const char* value) { static Node* CreateConstantString(const char* value) {
TreeValue* TV = BA_TreeValue(BA, TNT_STRING); Node* tv = BA_CreateNode(NT_STRING);
TV->string = value; tv->string = value;
return TV; return tv;
} }
// Allocates a map node inside a BumpAllocator. // Adds a map node.
static TreeValue* CreateMap(BumpAllocator* BA) { static Node* CreateMap() { return BA_CreateNode(NT_MAP); }
TreeValue* TV = BA_TreeValue(BA, TNT_MAP);
TV->next = NULL;
return TV;
}
// Allocates an array node inside a BumpAllocator. // Adds an array node.
static TreeValue* CreateArray(BumpAllocator* BA) { static Node* CreateArray() { return BA_CreateNode(NT_ARRAY); }
TreeValue* TV = BA_TreeValue(BA, TNT_ARRAY);
TV->next = NULL;
return TV;
}
// Allocates a formatted string inside a BumpAllocator. // Adds a formatted string node.
static TreeValue* CreatePrintfString(BumpAllocator* BA, const char* format, static Node* CreatePrintfString(const char* format, ...) {
...) {
va_list arglist; va_list arglist;
va_start(arglist, format); va_start(arglist, format);
char* const ptr = BA->ptr; char* const ptr = gBumpAllocator.ptr;
const int written = vsnprintf(ptr, BA->size, format, arglist); const int written = vsnprintf(ptr, gBumpAllocator.size, format, arglist);
va_end(arglist); va_end(arglist);
if (written < 0 || written >= BA->size) return NULL; if (written < 0 || written >= gBumpAllocator.size) internal_error();
return CreateConstantString(BA, (char*)BA_Bump(BA, written)); return CreateConstantString((char*)BA_Bump(written));
} }
static TreeValue* CreateString(BumpAllocator* BA, const char* value) { // Adds a string node.
return CreatePrintfString(BA, "%s", value); static Node* CreateString(const char* value) {
return CreatePrintfString("%s", value);
} }
// Allocates a map entry node inside a BumpAllocator. // Adds a map entry node.
static void AddMapEntry(BumpAllocator* BA, TreeValue* map, const char* key, static void AddMapEntry(Node* map, const char* key, Node* value) {
TreeValue* value) { assert(map && map->type == NT_MAP);
assert(map && map->type == TNT_MAP); Node* current = map;
TreeValue* current = map;
while (current->next) current = current->next; while (current->next) current = current->next;
current->next = (TreeValue*)BA_Bump(BA, sizeof(TreeValue)); current->next = (Node*)BA_Bump(sizeof(Node));
current->next->type = TNT_MAP_ENTRY; *current->next = (Node){.type = NT_MAP_ENTRY, .string = key, .value = value};
current->next->string = key;
current->next->value = value;
current->next->next = NULL;
} }
// Allocates aan array element node inside a BumpAllocator. // Adds an array element node.
static void AddArrayElement(BumpAllocator* BA, TreeValue* array, static void AddArrayElement(Node* array, Node* value) {
TreeValue* value) { assert(array && array->type == NT_ARRAY);
assert(array && array->type == TNT_ARRAY); Node* current = array;
TreeValue* current = array;
while (current->next) current = current->next; while (current->next) current = current->next;
current->next = (TreeValue*)BA_Bump(BA, sizeof(TreeValue)); current->next = (Node*)BA_Bump(sizeof(Node));
current->next->type = TNT_ARRAY_ELEMENT; *current->next = (Node){.type = NT_ARRAY_ELEMENT, .value = value};
current->next->value = value;
current->next->next = NULL;
} }
static int cmp(const void* p1, const void* p2) { static int cmp(const void* p1, const void* p2) {
@ -169,8 +173,7 @@ static int cmp(const void* p1, const void* p2) {
} }
#define DEFINE_ADD_FLAGS(HasFeature, FeatureName, FeatureType, LastEnum) \ #define DEFINE_ADD_FLAGS(HasFeature, FeatureName, FeatureType, LastEnum) \
static void AddFlags(BumpAllocator* BA, TreeValue* map, \ static void AddFlags(Node* map, const FeatureType* features) { \
const FeatureType* features) { \
size_t i; \ size_t i; \
const char* ptrs[LastEnum] = {0}; \ const char* ptrs[LastEnum] = {0}; \
size_t count = 0; \ size_t count = 0; \
@ -181,10 +184,10 @@ static int cmp(const void* p1, const void* p2) {
} \ } \
} \ } \
qsort((void*)ptrs, count, sizeof(char*), cmp); \ qsort((void*)ptrs, count, sizeof(char*), cmp); \
TreeValue* const array = CreateArray(BA); \ Node* const array = CreateArray(); \
for (i = 0; i < count; ++i) \ for (i = 0; i < count; ++i) \
AddArrayElement(BA, array, CreateConstantString(BA, ptrs[i])); \ AddArrayElement(array, CreateConstantString(ptrs[i])); \
AddMapEntry(BA, map, "flags", array); \ AddMapEntry(map, "flags", array); \
} }
#if defined(CPU_FEATURES_ARCH_X86) #if defined(CPU_FEATURES_ARCH_X86)
@ -224,27 +227,27 @@ static void printJsonString(const char* str) {
putchar('"'); putchar('"');
} }
// Walks a TreeValue and print it as json. // Walks a Node and print it as json.
static void printJson(const TreeValue* current) { static void printJson(const Node* current) {
assert(current); assert(current);
switch (current->type) { switch (current->type) {
case TNT_INT: case NT_INT:
printf("%d", current->integer); printf("%d", current->integer);
break; break;
case TNT_STRING: case NT_STRING:
printJsonString(current->string); printJsonString(current->string);
break; break;
case TNT_ARRAY: case NT_ARRAY:
putchar('['); putchar('[');
if (current->next) printJson(current->next); if (current->next) printJson(current->next);
putchar(']'); putchar(']');
break; break;
case TNT_MAP: case NT_MAP:
putchar('{'); putchar('{');
if (current->next) printJson(current->next); if (current->next) printJson(current->next);
putchar('}'); putchar('}');
break; break;
case TNT_MAP_ENTRY: case NT_MAP_ENTRY:
printf("\"%s\":", current->string); printf("\"%s\":", current->string);
printJson(current->value); printJson(current->value);
if (current->next) { if (current->next) {
@ -252,7 +255,7 @@ static void printJson(const TreeValue* current) {
printJson(current->next); printJson(current->next);
} }
break; break;
case TNT_ARRAY_ELEMENT: case NT_ARRAY_ELEMENT:
printJson(current->value); printJson(current->value);
if (current->next) { if (current->next) {
putchar(','); putchar(',');
@ -262,22 +265,22 @@ static void printJson(const TreeValue* current) {
} }
} }
// Walks a TreeValue and print it as text. // Walks a Node and print it as text.
static void printTextField(const TreeValue* current) { static void printTextField(const Node* current) {
switch (current->type) { switch (current->type) {
case TNT_INT: case NT_INT:
printf("%3d (0x%02X)", current->integer, current->integer); printf("%3d (0x%02X)", current->integer, current->integer);
break; break;
case TNT_STRING: case NT_STRING:
fputs(current->string, stdout); fputs(current->string, stdout);
break; break;
case TNT_ARRAY: case NT_ARRAY:
if (current->next) printTextField(current->next); if (current->next) printTextField(current->next);
break; break;
case TNT_MAP: case NT_MAP:
if (current->next) printJson(current->next); if (current->next) printJson(current->next);
break; break;
case TNT_MAP_ENTRY: case NT_MAP_ENTRY:
printf("%-15s : ", current->string); printf("%-15s : ", current->string);
printTextField(current->value); printTextField(current->value);
if (current->next) { if (current->next) {
@ -285,7 +288,7 @@ static void printTextField(const TreeValue* current) {
printTextField(current->next); printTextField(current->next);
} }
break; break;
case TNT_ARRAY_ELEMENT: case NT_ARRAY_ELEMENT:
printTextField(current->value); printTextField(current->value);
if (current->next) { if (current->next) {
putchar(','); putchar(',');
@ -295,9 +298,10 @@ static void printTextField(const TreeValue* current) {
} }
} }
static void printTextRoot(const TreeValue* current) { static void printTextRoot(const Node* current) {
if (current->type == TNT_MAP && current->next) printTextField(current->next); if (current->type == NT_MAP && current->next) printTextField(current->next);
} }
static void showUsage(const char* name) { static void showUsage(const char* name) {
printf( printf(
"\n" "\n"
@ -309,61 +313,61 @@ static void showUsage(const char* name) {
name); name);
} }
static TreeValue* CreateTree(BumpAllocator* BA) { static Node* CreateTree() {
TreeValue* root = CreateMap(BA); Node* root = CreateMap(gBumpAllocator);
#if defined(CPU_FEATURES_ARCH_X86) #if defined(CPU_FEATURES_ARCH_X86)
char brand_string[49]; char brand_string[49];
const X86Info info = GetX86Info(); const X86Info info = GetX86Info();
FillX86BrandString(brand_string); FillX86BrandString(brand_string);
AddMapEntry(BA, root, "arch", CreateString(BA, "x86")); AddMapEntry(root, "arch", CreateString("x86"));
AddMapEntry(BA, root, "brand", CreateString(BA, brand_string)); AddMapEntry(root, "brand", CreateString(brand_string));
AddMapEntry(BA, root, "family", CreateInt(BA, info.family)); AddMapEntry(root, "family", CreateInt(info.family));
AddMapEntry(BA, root, "model", CreateInt(BA, info.model)); AddMapEntry(root, "model", CreateInt(info.model));
AddMapEntry(BA, root, "stepping", CreateInt(BA, info.stepping)); AddMapEntry(root, "stepping", CreateInt(info.stepping));
AddMapEntry(BA, root, "uarch", AddMapEntry(root, "uarch",
CreateString(BA, GetX86MicroarchitectureName( CreateString(
GetX86Microarchitecture(&info)))); GetX86MicroarchitectureName(GetX86Microarchitecture(&info))));
AddFlags(BA, root, &info.features); AddFlags(root, &info.features);
#elif defined(CPU_FEATURES_ARCH_ARM) #elif defined(CPU_FEATURES_ARCH_ARM)
const ArmInfo info = GetArmInfo(); const ArmInfo info = GetArmInfo();
AddMapEntry(BA, root, "arch", CreateString(BA, "ARM")); AddMapEntry(root, "arch", CreateString("ARM"));
AddMapEntry(BA, root, "implementer", CreateInt(BA, info.implementer)); AddMapEntry(root, "implementer", CreateInt(info.implementer));
AddMapEntry(BA, root, "architecture", CreateInt(BA, info.architecture)); AddMapEntry(root, "architecture", CreateInt(info.architecture));
AddMapEntry(BA, root, "variant", CreateInt(BA, info.variant)); AddMapEntry(root, "variant", CreateInt(info.variant));
AddMapEntry(BA, root, "part", CreateInt(BA, info.part)); AddMapEntry(root, "part", CreateInt(info.part));
AddMapEntry(BA, root, "revision", CreateInt(BA, info.revision)); AddMapEntry(root, "revision", CreateInt(info.revision));
AddFlags(BA, root, &info.features); AddFlags(root, &info.features);
#elif defined(CPU_FEATURES_ARCH_AARCH64) #elif defined(CPU_FEATURES_ARCH_AARCH64)
const Aarch64Info info = GetAarch64Info(); const Aarch64Info info = GetAarch64Info();
AddMapEntry(BA, root, "arch", CreateString(BA, "aarch64")); AddMapEntry(root, "arch", CreateString("aarch64"));
AddMapEntry(BA, root, "implementer", CreateInt(BA, info.implementer)); AddMapEntry(root, "implementer", CreateInt(info.implementer));
AddMapEntry(BA, root, "variant", CreateInt(BA, info.variant)); AddMapEntry(root, "variant", CreateInt(info.variant));
AddMapEntry(BA, root, "part", CreateInt(BA, info.part)); AddMapEntry(root, "part", CreateInt(info.part));
AddMapEntry(BA, root, "revision", CreateInt(BA, info.revision)); AddMapEntry(root, "revision", CreateInt(info.revision));
AddFlags(BA, root, &info.features); AddFlags(root, &info.features);
#elif defined(CPU_FEATURES_ARCH_MIPS) #elif defined(CPU_FEATURES_ARCH_MIPS)
const MipsInfo info = GetMipsInfo(); const MipsInfo info = GetMipsInfo();
AddMapEntry(BA, root, "arch", CreateString(BA, "mips")); AddMapEntry(root, "arch", CreateString("mips"));
AddFlags(BA, root, &info.features); AddFlags(root, &info.features);
#elif defined(CPU_FEATURES_ARCH_PPC) #elif defined(CPU_FEATURES_ARCH_PPC)
const PPCInfo info = GetPPCInfo(); const PPCInfo info = GetPPCInfo();
const PPCPlatformStrings strings = GetPPCPlatformStrings(); const PPCPlatformStrings strings = GetPPCPlatformStrings();
AddMapEntry(BA, root, "arch", CreateString(BA, "ppc")); AddMapEntry(root, "arch", CreateString("ppc"));
AddMapEntry(BA, root, "platform", CreateString(BA, strings.platform)); AddMapEntry(root, "platform", CreateString(strings.platform));
AddMapEntry(BA, root, "model", CreateString(BA, strings.model)); AddMapEntry(root, "model", CreateString(strings.model));
AddMapEntry(BA, root, "machine", CreateString(BA, strings.machine)); AddMapEntry(root, "machine", CreateString(strings.machine));
AddMapEntry(BA, root, "cpu", CreateString(BA, strings.cpu)); AddMapEntry(root, "cpu", CreateString(strings.cpu));
AddMapEntry(BA, root, "instruction", CreateString(BA, strings.type.platform)); AddMapEntry(root, "instruction", CreateString(strings.type.platform));
AddMapEntry(BA, root, "microarchitecture", AddMapEntry(root, "microarchitecture",
CreateString(BA, strings.type.base_platform)); CreateString(strings.type.base_platform));
AddFlags(BA, root, &info.features); AddFlags(root, &info.features);
#endif #endif
return root; return root;
} }
int main(int argc, char** argv) { int main(int argc, char** argv) {
BumpAllocator BA = BA_Create(64 * 1024); BA_Align();
const TreeValue* const root = CreateTree(&BA); const Node* const root = CreateTree(&gBumpAllocator);
bool outputJson = false; bool outputJson = false;
int i = 1; int i = 1;
for (; i < argc; ++i) { for (; i < argc; ++i) {