Add string debugging
This commit is contained in:
@@ -102,6 +102,7 @@ public class Generator
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
""");
|
||||
|
||||
@@ -148,6 +149,13 @@ public class Generator
|
||||
(
|
||||
"""
|
||||
#define FLAG_STRING_LITERAL 1
|
||||
#define STRING_DEBUG 1
|
||||
|
||||
#if STRING_DEBUG
|
||||
#define STR_DBG(fmt, ...) fprintf(stderr, "[STR] " fmt "\n", ##__VA_ARGS__)
|
||||
#else
|
||||
#define STR_DBG(fmt, ...)
|
||||
#endif
|
||||
|
||||
struct nub_core_string
|
||||
{
|
||||
@@ -157,54 +165,114 @@ public class Generator
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
#if STRING_DEBUG
|
||||
static size_t nub_core_string_allocs = 0;
|
||||
static size_t nub_core_string_frees = 0;
|
||||
|
||||
__attribute__((destructor))
|
||||
static void string_debug_report(void)
|
||||
{
|
||||
fprintf(stderr, "[STR] REPORT allocs=%zu frees=%zu leaks=%zu\n", nub_core_string_allocs, nub_core_string_frees, nub_core_string_allocs - nub_core_string_frees);
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void string_rc_inc(struct nub_core_string *string)
|
||||
{
|
||||
if (string == NULL)
|
||||
{
|
||||
STR_DBG("INC null string");
|
||||
return;
|
||||
}
|
||||
|
||||
if (string->flags & FLAG_STRING_LITERAL)
|
||||
return;
|
||||
|
||||
string->ref += 1;
|
||||
|
||||
STR_DBG("INC: str=%p ref=%u \"%s\"", (void*)string, string->ref, string->data);
|
||||
}
|
||||
|
||||
static inline void string_rc_dec(struct nub_core_string *string)
|
||||
{
|
||||
if (string == NULL)
|
||||
{
|
||||
STR_DBG("DEC null string");
|
||||
return;
|
||||
}
|
||||
|
||||
if (string->flags & FLAG_STRING_LITERAL)
|
||||
return;
|
||||
|
||||
if (string->ref == 0)
|
||||
{
|
||||
STR_DBG("ERROR: DEC on zero refcount str=%p", (void*)string);
|
||||
return;
|
||||
}
|
||||
|
||||
string->ref -= 1;
|
||||
|
||||
STR_DBG("DEC: str=%p ref=%u \"%s\"", (void*)string, string->ref, string->data);
|
||||
|
||||
if (string->ref == 0)
|
||||
{
|
||||
free(string->data);
|
||||
free(string);
|
||||
STR_DBG("FREE: str=%p data=%p \"%s\"", (void*)string, (void*)string->data, string->data);
|
||||
|
||||
char *data_ptr = string->data;
|
||||
struct nub_core_string *str_ptr = string;
|
||||
|
||||
#if STRING_DEBUG
|
||||
nub_core_string_frees++;
|
||||
|
||||
memset(data_ptr, 0xDD, str_ptr->length);
|
||||
memset(str_ptr, 0xDD, sizeof(*str_ptr));
|
||||
#endif
|
||||
|
||||
free(data_ptr);
|
||||
free(str_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
static inline struct nub_core_string *string_concat(struct nub_core_string *left, struct nub_core_string *right)
|
||||
{
|
||||
size_t new_length = left->length + right->length;
|
||||
|
||||
struct nub_core_string *result = malloc(sizeof(struct nub_core_string));
|
||||
result->data = malloc(new_length + 1);
|
||||
|
||||
memcpy(result->data, left->data, left->length);
|
||||
memcpy(result->data + left->length, right->data, right->length);
|
||||
|
||||
result->data[new_length] = '\0';
|
||||
result->length = new_length;
|
||||
result->ref = 1;
|
||||
result->flags = 0;
|
||||
|
||||
#if STRING_DEBUG
|
||||
nub_core_string_allocs++;
|
||||
STR_DBG("NEW concat: str=%p ref=%u \"%s\"", (void*)result, result->ref, result->data);
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline struct nub_core_string *string_from_cstr(const char* cstr)
|
||||
static inline struct nub_core_string *string_from_cstr(char* cstr)
|
||||
{
|
||||
size_t len = strlen(cstr);
|
||||
|
||||
struct nub_core_string *result = malloc(sizeof(struct nub_core_string));
|
||||
result->data = malloc(len + 1);
|
||||
|
||||
memcpy(result->data, cstr, len + 1);
|
||||
|
||||
result->length = len;
|
||||
result->ref = 1;
|
||||
result->flags = 0;
|
||||
|
||||
#if STRING_DEBUG
|
||||
nub_core_string_allocs++;
|
||||
STR_DBG("NEW from_cstr: str=%p ref=%u \"%s\"", (void*)result, result->ref, result->data);
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -491,6 +559,7 @@ public class Generator
|
||||
TypedNodeExpressionStringLiteral expression => EmitExpressionStringLiteral(expression),
|
||||
TypedNodeExpressionStructLiteral expression => EmitExpressionStructLiteral(expression),
|
||||
TypedNodeExpressionEnumLiteral expression => EmitExpressionEnumLiteral(expression),
|
||||
TypedNodeExpressionStringConstructor expression => EmitExpressionStringConstructor(expression),
|
||||
TypedNodeExpressionStructMemberAccess expression => EmitExpressionMemberAccess(expression),
|
||||
TypedNodeExpressionStringLength expression => EmitExpressionStringLength(expression),
|
||||
TypedNodeExpressionStringPointer expression => EmitExpressionStringPointer(expression),
|
||||
@@ -562,7 +631,7 @@ public class Generator
|
||||
{
|
||||
var name = Tmp();
|
||||
referencedStringLiterals.Add(name, expression.Value.Value);
|
||||
return $"&{name}";
|
||||
return $"(&{name})";
|
||||
}
|
||||
|
||||
private string EmitExpressionStructLiteral(TypedNodeExpressionStructLiteral expression)
|
||||
@@ -616,6 +685,15 @@ public class Generator
|
||||
return name;
|
||||
}
|
||||
|
||||
private string EmitExpressionStringConstructor(TypedNodeExpressionStringConstructor expression)
|
||||
{
|
||||
var name = Tmp();
|
||||
scopes.Peek().DeconstructableNames.Add((name, expression.Type));
|
||||
var value = EmitExpression(expression.Value);
|
||||
writer.WriteLine($"{CType(expression.Type, name)} = string_from_cstr({value});");
|
||||
return name;
|
||||
}
|
||||
|
||||
private string EmitExpressionMemberAccess(TypedNodeExpressionStructMemberAccess expression)
|
||||
{
|
||||
var target = EmitExpression(expression.Target);
|
||||
|
||||
Reference in New Issue
Block a user