Files
klang/src/test/struct/struct.c
nitrix bacc40d844 GenASM: Make sure the stack is 16 byte aligned before calling malloc or free.
The GenASM visitor only uses quad mnemonics so each manipulation to the stack is done in 8 byte chunks. This means our stack is always 8 byte aligned which is fine when only calling KLang code. libc functions like 'malloc' or 'free' require the stack to be 16 byte aligned which isn't automatically guaranteed when being 8 byte aligned. This is why we need to be careful when manipulating the stack (e.g. pushq, popq, subq x, %rsp). By assuming that we are stack aligned at the beginning of execution and by tracking the number of pushq operations we can deduce whether we misaligned the stack and align it again by adding another 8 byte to the stack.

This re-alignment of the stack is done directly before entering a function body or calling malloc. Since there are no stack manipulations involved when generating the code to calling 'free' there is reason to check for alignment there.
2023-03-21 22:21:14 +01:00

132 lines
3.5 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include "struct.h"
#include "../print/print.h"
// C equivalent implementations of the funcitons written in k
struct testStruct* cGetTestStruct(long a, bool b, long c) {
struct testStruct* result = (struct testStruct*) malloc(sizeof(struct testStruct));
result->a = a;
result->b = b;
result->c = c;
return result;
}
struct testStructRec* cGetTestStructRec(long a, struct testStructRec* b) {
struct testStructRec* result = (struct testStructRec*) malloc(sizeof(struct testStructRec));
result->a = a;
result->b = b;
return result;
}
int struct_testExpected_l(char *name, long expected, long result)
{
if (expected == result)
{
succ(name, expected, result);
return 0;
}
else
{
err(name, expected, result);
return 1;
}
}
int struct_testExpected_s(char *name, void* expected, void* result)
{
if (expected == result)
{
succ_s(name, expected, result);
return 0;
}
else
{
err_s(name, expected, result);
return 1;
}
}
int struct_testExpected_f(char *name, double expected, double result)
{
if (expected == result)
{
succ_f(name, expected, result);
return 0;
}
else
{
err_f(name, expected, result);
return 1;
}
}
int struct_testExpected_b(char *name, bool expected, bool result)
{
if (expected == result)
{
succ_b(name, expected, result);
return 0;
}
else
{
err_b(name, expected, result);
return 1;
}
}
int testStructCreation() {
printf("\nStruct creation tests\n");
struct testStruct* result = getTestStruct(1, false, 23.3);
struct_testExpected_l("init field a", 1, result->a);
struct_testExpected_b("init field b", false, result->b);
struct_testExpected_f("init field c", 23.3, result->c);
free(result);
printf("\nRecursive struct creation tests\n");
struct testStructRec* innerStruct = getTestStructRec(20, NULL);
struct testStructRec* resultRec = getTestStructRec(10, innerStruct);
struct_testExpected_l("init rec field a", 10, resultRec->a);
struct_testExpected_s("init rec field b", innerStruct, resultRec->b);
struct_testExpected_l("init inner field a", 20, resultRec->b->a);
struct_testExpected_s("init inner field b", NULL, resultRec->b->b);
// The result of this test is always 1 because if the tests fail
// a segmentation fault occurs.
long alignmentResult = isStackAlignedBeforeFunctionCall();
struct_testExpected_l("stack alignment before malloc", 1, alignmentResult);
free(resultRec);
free(innerStruct);
}
int testStructGet() {
printf("\nStruct getter tests\n");
struct testStruct* result = getTestStruct(1, false, 23.3);
struct_testExpected_l("get field a", 1, getStructFieldA(result));
struct_testExpected_b("get field b", false, getStructFieldB(result));
struct_testExpected_f("get field c", 23.3, getStructFieldC(result));
free(result);
printf("\nStruct getter tests\n");
struct testStructRec* innerStruct = getTestStructRec(1, NULL);
struct testStructRec* resultRec = getTestStructRec(20, innerStruct);
struct_testExpected_l("get rec field a", 20, getStructFieldRecA(resultRec));
struct_testExpected_s("get rec field b", innerStruct, getStructFieldRecB(resultRec));
struct_testExpected_l("get inner field a", 1, getStructFieldRecA(getStructFieldRecB(resultRec)));
struct_testExpected_s("get inner field b", NULL, getStructFieldRecB(getStructFieldRecB(resultRec)));
free(resultRec);
free(innerStruct);
}
void runStructTests() {
testStructCreation();
testStructGet();
}