From 15709b65a6a912257b50ccf29e0eaa094bc0424b Mon Sep 17 00:00:00 2001 From: SpookyDervish Date: Mon, 3 Aug 2026 21:01:34 +1000 Subject: [PATCH] start working on text representation and constants --- Makefile | 6 +-- include/gravity/core.h | 15 +++++-- src/block.c | 24 +++++++++++ src/block.h | 13 +++++- src/builder.c | 40 +++++++++++++++++- src/builder.h | 9 +++- src/function.c | 57 +++++++++++++++++++++++++ src/function.h | 9 +++- src/instruction.c | 30 +++++++++++++ src/instruction.h | 8 +++- src/module.c | 13 ++++++ src/module.h | 4 ++ src/strb.c | 37 ++++++++++++++++ src/strb.h | 18 ++++++++ src/type.c | 44 +++++++++++++++++++ src/type.h | 9 ++++ src/value.c | 96 ++++++++++++++++++++++++++++++++++++++++++ src/value.h | 35 +++++++++++++-- test.c | 8 +++- 19 files changed, 457 insertions(+), 18 deletions(-) create mode 100644 src/block.c create mode 100644 src/function.c create mode 100644 src/instruction.c create mode 100644 src/strb.c create mode 100644 src/strb.h create mode 100644 src/value.c diff --git a/Makefile b/Makefile index ee939bf..0dc9e71 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ SRC=src OBJ=obj CC=gcc -CFLAGS=-Wall -Wextra -O3 +CFLAGS=-Wall -Wextra -fPIC -O3 TARGET=libgravity.so TEST_TARGET=testapp @@ -17,7 +17,7 @@ $(OBJ)/%.o: $(SRC)/%.c $(CC) $(CFLAGS) -c $< -o $@ $(TEST_TARGET): test.c $(TARGET) - $(CC) $(CFLAGS) test.c -lgravity -L. -o $(TEST_TARGET) + $(CC) $(CFLAGS) test.c -lgravity -L. -o $(TEST_TARGET) test: $(TEST_TARGET) @@ -25,9 +25,9 @@ setup: mkdir -p $(OBJ) clean: + rm -r $(OBJ)/*.o rm $(TARGET) rm $(TEST_TARGET) - rm -r $(OBJ)/*.o install: $(TARGET) sudo cp $(TARGET) /usr/local/lib/ diff --git a/include/gravity/core.h b/include/gravity/core.h index 7f47cd3..31e7466 100644 --- a/include/gravity/core.h +++ b/include/gravity/core.h @@ -6,12 +6,10 @@ // === TYPE DEFINITIONS === // typedef struct GravityOpaqueModule* GravityModule; - typedef struct GravityOpaqueValue* GravityValue; - typedef struct GravityOpaqueBuilder* GravityBuilder; - typedef struct GravityOpaqueFunction* GravityFunction; +typedef struct GravityOpaqueBlock* GravityBlock; typedef struct GravityOpaqueType* GravityType; typedef enum { @@ -27,9 +25,20 @@ GravityModule gravityCreateModule(void); GravityBuilder gravityCreateBuilder(void); GravityFunction gravityNewFunction(GravityModule module, const char* name, GravityType functionType); +GravityBlock gravityStartBlock(const char* name, GravityFunction function, uint16_t numBlockParams, ...); + +GravityValue newIntConstant(GravityType intType, int64_t value); GravityType gravityCreateFunctionType(int numArgs, GravityType* argTypes, GravityType returnType); GravityType gravityCreateIntegerType(uint8_t width, bool isSigned); + +char* gravityModuleToCStr(GravityModule module); +char* gravityTypeToCStr(GravityType type); +char* gravityFunctionToCStr(GravityFunction function); +char* gravityValueToCStr(GravityValue value); + +void gravityPositionBuilderAtEnd(GravityBuilder builder, GravityBlock block); +GravityValue gravityBuildAlloc(GravityBuilder builder, GravityType type, const char* name); // ============================ // #endif \ No newline at end of file diff --git a/src/block.c b/src/block.c new file mode 100644 index 0000000..b205e00 --- /dev/null +++ b/src/block.c @@ -0,0 +1,24 @@ +#include "block.h" + +char* gravityBlockToCStr(GravityBlock block) { + StringBuffer buff; + initStringBuff(&buff); + + // print block header + sbAppend(&buff, "%s (", block->name); + for (unsigned int i = 0; i < block->numParams; i++) { + if (i < block->numParams - 1) { + sbAppend(&buff, "%s, ", gravityTypeToCStr(block->paramTypes[i])); + } else { + sbAppend(&buff, "%s", gravityTypeToCStr(block->paramTypes[i])); + } + } + sbAppend(&buff, "):\n"); + + for (unsigned int i = 0; i < block->instructions.count; i++) { + GravityInstruction inst = *get(block->instructions, i); + sbAppend(&buff, " %s\n", gravityInstructionToCStr(inst)); + } + + return buff.data; +} \ No newline at end of file diff --git a/src/block.h b/src/block.h index 05d3c71..0f4f73a 100644 --- a/src/block.h +++ b/src/block.h @@ -3,11 +3,20 @@ #include "list.h" #include "instruction.h" +#include "type.h" + +typedef struct GravityOpaqueBlock* GravityBlock; UseList(GravityInstruction); -typedef struct { +struct GravityOpaqueBlock { + const char* name; + GravityType* paramTypes; + uint16_t numParams; + List(GravityInstruction) instructions; -} GravityBlock; +}; + +char* gravityBlockToCStr(GravityBlock block); #endif \ No newline at end of file diff --git a/src/builder.c b/src/builder.c index d5ac4a3..dec785b 100644 --- a/src/builder.c +++ b/src/builder.c @@ -1,8 +1,44 @@ #include "builder.h" -GravityBuilder* gravityCreateBuilder(void) { - GravityBuilder* newBuilder = malloc(sizeof(GravityBuilder)); +void gravityBuildInstruction(GravityBuilder builder, GravityOpcode opcode, GravityValue* operands, size_t numOperands, GravityValue result) { + assert(builder->currentBlock != NULL); + + // copy operands list to avoid stack lifetime + GravityValue* operandsCopy = calloc(numOperands, sizeof(GravityValue)); + if (!operandsCopy) + return; + memcpy(operandsCopy, operands, sizeof(GravityValue) * numOperands); + + GravityInstruction newInst = { + .opcode = opcode, + .operands = operandsCopy, + .numOperands = numOperands, + .result = result + }; + + append(builder->currentBlock->instructions, newInst); +} + +GravityBuilder gravityCreateBuilder(void) { + GravityBuilder newBuilder = malloc(sizeof(struct GravityOpaqueBuilder)); if (newBuilder == NULL) return newBuilder; return newBuilder; +} + +void gravityPositionBuilderAtEnd(GravityBuilder builder, GravityBlock block) { + builder->currentBlock = block; +} + +GravityValue gravityBuildAlloc(GravityBuilder builder, GravityType type, const char* name) { + GravityValue result = gravityNewValue(name, gravityCreatePointerType()); + + GravityType wrapperType = gravityCreateType(); + wrapperType->typeKind = GravityTypeTypeKind; + wrapperType->typeData = type;\ + + GravityValue constant = gravityNewConstant(wrapperType); + gravityBuildInstruction(builder, GravityOpcodeAlloc, (GravityValue[]){constant}, 1, result); + + return result; } \ No newline at end of file diff --git a/src/builder.h b/src/builder.h index de414c5..088b55a 100644 --- a/src/builder.h +++ b/src/builder.h @@ -3,13 +3,18 @@ #include "block.h" #include +#include typedef struct GravityOpaqueBuilder* GravityBuilder; -struct { +struct GravityOpaqueBuilder { GravityBlock currentBlock; -} GravityOpaqueBuilder; +}; GravityBuilder gravityCreateBuilder(void); +void gravityPositionBuilderAtEnd(GravityBuilder builder, GravityBlock block); + +GravityValue gravityBuildAlloc(GravityBuilder builder, GravityType type, const char* name); + #endif \ No newline at end of file diff --git a/src/function.c b/src/function.c new file mode 100644 index 0000000..5b7d0f2 --- /dev/null +++ b/src/function.c @@ -0,0 +1,57 @@ +#include "function.h" + +GravityBlock gravityStartBlock(const char* name, GravityFunction function, uint16_t numBlockParams, ...) { + GravityBlock newBlock = malloc(sizeof(struct GravityOpaqueBlock)); + if (newBlock == NULL) return newBlock; + + newBlock->name = strdup(name); + + GravityType* paramTypes = calloc(numBlockParams, sizeof(GravityType)); + if (paramTypes == NULL) { + free(newBlock); + return NULL; + } + + va_list vargs; + va_start(vargs, numBlockParams); + + for (unsigned int i = 0; i < numBlockParams; i++) { + paramTypes[i] = va_arg(vargs, GravityType); + } + + newBlock->numParams = numBlockParams; + newBlock->paramTypes = paramTypes; + newBlock->instructions = newList(GravityInstruction); + + append(function->blocks, newBlock); + + return newBlock; +} + +char* gravityFunctionToCStr(GravityFunction function) { + StringBuffer buff; + initStringBuff(&buff); + + // print func header + sbAppend(&buff, "fn %s (", function->name); + for (unsigned int i = 0; i < function->functionType.numArgs; i++) { + if (i < function->functionType.numArgs) { + sbAppend(&buff, "%s, ", gravityTypeToCStr(function->functionType.argTypes[i])); + + } else { + sbAppend(&buff, "%s", gravityTypeToCStr(function->functionType.argTypes[i])); + } + + break; + } + + // print function blocks + sbAppend(&buff, ") %s {\n", gravityTypeToCStr(function->functionType.returnType)); + for (unsigned int i = 0; i < function->blocks.count; i++) { + GravityBlock block = *get(function->blocks, i); + sbAppend(&buff, "%s\n", gravityBlockToCStr(block)); + } + sbAppend(&buff, "}"); + + return buff.data; +} \ No newline at end of file diff --git a/src/function.h b/src/function.h index 7efa1ac..837736f 100644 --- a/src/function.h +++ b/src/function.h @@ -4,7 +4,10 @@ #include "type.h" #include "block.h" #include "list.h" -#include +#include "strb.h" +#include +#include +#include UseList(GravityBlock); @@ -13,6 +16,10 @@ typedef struct GravityOpaqueFunction* GravityFunction; struct GravityOpaqueFunction { GravityFunctionType functionType; List(GravityBlock) blocks; + const char* name; }; +GravityBlock gravityStartBlock(const char* name, GravityFunction function, uint16_t numBlockParams, ...); +char* gravityFunctionToCStr(GravityFunction function); + #endif \ No newline at end of file diff --git a/src/instruction.c b/src/instruction.c new file mode 100644 index 0000000..0c0a442 --- /dev/null +++ b/src/instruction.c @@ -0,0 +1,30 @@ +#include "instruction.h" + +char* gravityOpcodeToCStr(GravityOpcode opcode) { + switch (opcode) { + case GravityOpcodeAlloc: return "alloc"; + case GravityOpcodeStore: return "store"; + case GravityOpcodeLoad: return "load"; + default: return "fixme"; + } +} + +char* gravityInstructionToCStr(GravityInstruction inst) { + StringBuffer buff; + initStringBuff(&buff); + + if (inst.result != NULL) { + sbAppend(&buff, "%s = ", gravityValueToCStr(inst.result)); + } + + sbAppend(&buff, "%s ", gravityOpcodeToCStr(inst.opcode)); + for (unsigned int i = 0; i < inst.numOperands; i++) { + if (i < inst.numOperands - 1) { + sbAppend(&buff, "%s, ", gravityValueToCStr(inst.operands[i])); + } else { + sbAppend(&buff, "%s", gravityValueToCStr(inst.operands[i])); + } + } + + return buff.data; +} \ No newline at end of file diff --git a/src/instruction.h b/src/instruction.h index 9425f17..a1e9ee9 100644 --- a/src/instruction.h +++ b/src/instruction.h @@ -5,13 +5,19 @@ #include typedef enum { - GravityOpcodeAdd = 0 + GravityOpcodeAlloc = 0, + GravityOpcodeStore, + GravityOpcodeLoad } GravityOpcode; typedef struct { GravityOpcode opcode; GravityValue* operands; size_t numOperands; + GravityValue result; } GravityInstruction; +char* gravityInstructionToCStr(GravityInstruction inst); +char* gravityOpcodeToCStr(GravityOpcode opcode); + #endif \ No newline at end of file diff --git a/src/module.c b/src/module.c index 5bb0629..2296d69 100644 --- a/src/module.c +++ b/src/module.c @@ -15,10 +15,23 @@ GravityFunction gravityNewFunction(GravityModule module, const char* name, Gravi GravityFunction newFunc = malloc(sizeof(struct GravityOpaqueFunction)); if (newFunc == NULL) return newFunc; + newFunc->name = strdup(name); newFunc->blocks = newList(GravityBlock); newFunc->functionType = functionType->function; append(module->functions, newFunc); return newFunc; +} + +char* gravityModuleToCStr(GravityModule module) { + StringBuffer buff; + initStringBuff(&buff); + + for (unsigned int i = 0; i < module->functions.count; i++) { + GravityFunction func = *get(module->functions, i); + sbAppend(&buff, "%s\n\n", gravityFunctionToCStr(func)); + } + + return buff.data; } \ No newline at end of file diff --git a/src/module.h b/src/module.h index 25a6b68..0697e7c 100644 --- a/src/module.h +++ b/src/module.h @@ -3,7 +3,9 @@ #include "function.h" #include "list.h" +#include "strb.h" #include +#include typedef struct GravityOpaqueModule* GravityModule; @@ -17,4 +19,6 @@ GravityModule gravityCreateModule(void); GravityFunction gravityNewFunction(GravityModule module, const char* name, GravityType functionType); +char* gravityModuleToCStr(GravityModule module); + #endif \ No newline at end of file diff --git a/src/strb.c b/src/strb.c new file mode 100644 index 0000000..3e35ee7 --- /dev/null +++ b/src/strb.c @@ -0,0 +1,37 @@ +#include "strb.h" + +void initStringBuff(StringBuffer* sb) { + sb->capacity = 128; + sb->length = 0; + sb->data = (char*)malloc(sb->capacity); + sb->data[0] = '\0'; +} + +void sbAppend(StringBuffer* sb, const char* fmt, ...) { + va_list args; + va_start(args, fmt); + + // Check how much space we need + va_list args_copy; + va_copy(args_copy, args); + int needed = vsnprintf(NULL, 0, fmt, args_copy); + va_end(args_copy); + + if (needed < 0) { + va_end(args); + return; + } + + // Grow buffer if needed + if (sb->length + needed >= sb->capacity) { + while (sb->length + needed >= sb->capacity) { + sb->capacity *= 2; + } + sb->data = (char*)realloc(sb->data, sb->capacity); + } + + // Append the string safely + vsnprintf(sb->data + sb->length, needed + 1, fmt, args); + sb->length += needed; + va_end(args); +} \ No newline at end of file diff --git a/src/strb.h b/src/strb.h new file mode 100644 index 0000000..eccb00e --- /dev/null +++ b/src/strb.h @@ -0,0 +1,18 @@ +#ifndef __GRAVITY__STRB_H +#define __GRAVITY__STRB_H + +#include +#include +#include +#include + +typedef struct { + char* data; + size_t length; + size_t capacity; +} StringBuffer; + +void initStringBuff(StringBuffer* sb); +void sbAppend(StringBuffer* sb, const char* fmt, ...); + +#endif \ No newline at end of file diff --git a/src/type.c b/src/type.c index 6649eec..071197f 100644 --- a/src/type.c +++ b/src/type.c @@ -2,6 +2,7 @@ GravityType gravityCreateType(void) { GravityType type = malloc(sizeof(struct GravityOpaqueType)); + type->typeKind = GravityIntTypeKind; return type; } @@ -24,4 +25,47 @@ GravityType gravityCreateIntegerType(uint8_t width, bool isSigned) { type->integer.isSigned = isSigned; return type; +} + +GravityType gravityCreatePointerType(void) { + GravityType type = gravityCreateType(); + if (type == NULL) return type; + + type->typeKind = GravityPointerTypeKind; + + return type; +} + +char* gravityTypeToCStr(GravityType type) { + StringBuffer buff; + initStringBuff(&buff); + + switch (type->typeKind) { + case GravityIntTypeKind: { + if (type->integer.isSigned) { + sbAppend(&buff, "i%d", type->integer.width); + } else { + sbAppend(&buff, "u%d", type->integer.width); + } + + break; + } + + case GravityPointerTypeKind: { + sbAppend(&buff, "pointer"); + break; + } + + case GravityTypeTypeKind: { + sbAppend(&buff, "%s", gravityTypeToCStr(type->typeData)); + break; + } + + default: { + sbAppend(&buff, "type_fixme"); + break; + } + } + + return buff.data; } \ No newline at end of file diff --git a/src/type.h b/src/type.h index c8325e5..7933926 100644 --- a/src/type.h +++ b/src/type.h @@ -2,9 +2,11 @@ #define __GRAVITY__TYPE_H #include "list.h" +#include "strb.h" #include #include #include +#include typedef struct GravityOpaqueType* GravityType; @@ -13,6 +15,7 @@ typedef enum { GravityFloatTypeKind, GravityPointerTypeKind, GravityFunctionTypeKind, + GravityTypeTypeKind, // type name } GravityTypeKind; typedef struct { @@ -31,11 +34,17 @@ struct GravityOpaqueType { union { GravityFunctionType function; GravityIntType integer; + GravityType typeData; }; }; +UseList(GravityType); + GravityType gravityCreateFunctionType(int numArgs, GravityType* argTypes, GravityType returnType); GravityType gravityCreateIntegerType(uint8_t width, bool isSigned); GravityType gravityCreateType(void); +GravityType gravityCreatePointerType(void); + +char* gravityTypeToCStr(GravityType type); #endif \ No newline at end of file diff --git a/src/value.c b/src/value.c new file mode 100644 index 0000000..dcb35b6 --- /dev/null +++ b/src/value.c @@ -0,0 +1,96 @@ +#include "value.h" + +uint32_t globalValueIncrementer = 0; + +char* getIncrementedName(void) { + char* buffer = malloc(32); + if (buffer == NULL) return buffer; + + snprintf(buffer, 32, "%%%d", globalValueIncrementer); + + globalValueIncrementer++; + + return buffer; +} + +GravityValue gravityNewValue(const char* name, GravityType type) { + GravityValue newValue = malloc(sizeof(struct GravityOpaqueValue)); + if (newValue == NULL) return newValue; + + newValue->kind = GravityLocalValueKind; + newValue->type = type; + + if (name == NULL) { + name = getIncrementedName(); + } else { + name = strdup(name); + } + + newValue->name = name; + + return newValue; +} + +GravityValue gravityTypeToTypeValue(GravityType type) { + GravityType valueType = gravityCreateType(); + valueType->typeKind = GravityTypeTypeKind; + valueType->typeData = type; + + GravityValue newValue = gravityNewValue(NULL, valueType); + if (newValue == NULL) return newValue; + + return newValue; +} + +char* gravityValueToCStr(GravityValue value) { + switch (value->kind) { + case GravityLocalValueKind: + + return strdup(value->name); + + case GravityConstantValueKind: { + StringBuffer buff; + initStringBuff(&buff); + + switch (value->type->typeKind) { + case GravityIntTypeKind: { + sbAppend(&buff, "%ld", value->constant.intValue); + break; + } + + case GravityTypeTypeKind: { + sbAppend(&buff, "%s", gravityTypeToCStr(value->type->typeData)); + break; + } + + default: assert(false); + } + + return buff.data; + } + + default: assert(false); + } +} + +GravityValue gravityNewConstant(GravityType type) { + GravityValue newValue = malloc(sizeof(struct GravityOpaqueValue)); + if (newValue == NULL) return newValue; + + newValue->kind = GravityConstantValueKind; + newValue->type = type; + newValue->name = NULL; + + return newValue; +} + +GravityValue newIntConstant(GravityType intType, int64_t value) { + assert(intType->typeKind == GravityIntTypeKind); + + GravityValue newValue = gravityNewConstant(intType); + if (newValue == NULL) return newValue; + + newValue->constant.intValue = value; + + return newValue; +} \ No newline at end of file diff --git a/src/value.h b/src/value.h index 0c66768..50771b7 100644 --- a/src/value.h +++ b/src/value.h @@ -3,9 +3,38 @@ #include "type.h" -typedef struct { +extern uint32_t globalValueIncrementer; + +typedef struct GravityOpaqueValue* GravityValue; +typedef struct GravityOpaqueConstant* GravityConstant; + +typedef enum { + GravityLocalValueKind, + GravityConstantValueKind +} GravityValueKind; + +struct GravityOpaqueValue { + GravityValueKind kind; GravityType type; - const char* name; -} GravityValue; + const char* name; // local name + + union { + int64_t intValue; + } constant; +}; + +struct GravityOpaqueConstant { + GravityType type; + union { + int64_t intValue; + }; +}; + +GravityValue gravityNewValue(const char* name, GravityType type); +GravityValue gravityTypeToTypeValue(GravityType type); +char* gravityValueToCStr(GravityValue value); + +GravityValue gravityNewConstant(GravityType type); +GravityValue newIntConstant(GravityType intType, int64_t value); #endif \ No newline at end of file diff --git a/test.c b/test.c index 5891221..3e49cc0 100644 --- a/test.c +++ b/test.c @@ -5,10 +5,16 @@ int main(void) { GravityModule module = gravityCreateModule(); GravityBuilder builder = gravityCreateBuilder(); - GravityType charType = gravityCreateIntegerType(1, false); + GravityType charType = gravityCreateIntegerType(8, false); GravityType mainFuncType = gravityCreateFunctionType(0, NULL, charType); GravityFunction mainFunc = gravityNewFunction(module, "main", mainFuncType); + GravityBlock entryBlock = gravityStartBlock("entry", mainFunc, 0); + + gravityPositionBuilderAtEnd(builder, entryBlock); + GravityValue something = gravityBuildAlloc(builder, charType, NULL); + + printf("%s\n", gravityFunctionToCStr(mainFunc)); return 0; } \ No newline at end of file