Moved stdlib to a seperate folder and added some more headers that are required for compiling libgcc (no implementation yet).

This commit is contained in:
2024-02-02 00:01:48 +01:00
parent 00f4e0de3a
commit 712b95c9d7
22 changed files with 154 additions and 42 deletions

View File

@@ -0,0 +1,20 @@
#include <assert.h>
#include <cstdio>
#include <cstdlib>
extern "C"
{
#if !defined(NDEBUG)
void __ba__assert_fail(const char* filename, int line, const char* condition) noexcept
{
std::printf(R"(
Assertion failed:
File: %s
Line: %d
Condition: %s)" "\n", filename, line, condition);
std::abort();
}
#endif
} // extern "C"

View File

@@ -0,0 +1,239 @@
#include <stdio.h>
#include <algorithm>
#include <stdarg.h>
#include "os/tty.hpp"
#include "os/tools/printf_helper.hpp"
#include "os/tools/ringbuffer.hpp"
#if defined(__baos_kernel_source__)
#include "os/serial.hpp"
#else
#include "os/syscall.hpp"
#endif
struct __file
{
protected:
static constexpr unsigned BUFFER_SIZE = 4096;
baos::RingBuffer<char, BUFFER_SIZE> mBuffer;
bool mEof = false;
bool mError = false;
protected:
virtual bool underflow() noexcept = 0;
public:
[[nodiscard]] bool isEof() const noexcept { return mEof; }
[[nodiscard]] bool isError() const noexcept { return mError; }
bool readChar(char& outChar) noexcept
{
while (!mBuffer.next(outChar)) {
if (!underflow()) {
return false;
}
}
return true;
}
bool readLine(std::string& outLine) noexcept
{
outLine.clear();
while(true)
{
while (mBuffer.empty()) {
if (!underflow()) {
return false;
}
}
// first check if there is a \n in the stream
std::size_t count = mBuffer.size();
for (std::size_t idx = 0; idx < mBuffer.size(); ++idx)
{
if (mBuffer[idx] == '\n')
{
count = idx + 1;
break;
}
}
outLine.reserve(outLine.size() + count);
for (std::size_t idx = 0; idx < count; ++idx)
{
char chr = '\0';
mBuffer.next(chr);
outLine.append(chr);
}
if (outLine.back() == '\n')
{
return true;
}
}
}
};
namespace
{
struct RegularPrinter
{
void putchar(int chr) noexcept // NOLINT
{
::putchar(chr);
}
};
struct BufferPrinter
{
char* pos = nullptr;
char* end = nullptr;
void putchar(int chr) noexcept // NOLINT
{
if (pos != end)
{
*pos = static_cast<char>(chr);
++pos;
}
}
};
class StdinFile : public __file
{
public:
bool underflow() noexcept override
{
for (char chr : tty::readLine()) {
mBuffer.append(chr);
}
return true;
}
};
StdinFile gStdin;
}
extern "C"
{
FILE* __stdin = &gStdin;
// TODO: line-buffering
int putchar(int chr) noexcept
{
#if defined(__baos_kernel_source__)
tty::putChar(static_cast<char>(chr));
if (chr == '\n')
{
serialWrite(PORT_COM1, '\r');
serialWrite(PORT_COM1, '\n');
}
else
{
serialWrite(PORT_COM1, static_cast<std::uint8_t>(chr));
}
return 0;
#else
char asChar = static_cast<char>(chr);
baos::doSyscall(baos::Syscall::FILE_WRITE, 0, &asChar, 1);
return 0;
#endif
}
int puts(const char* str) noexcept
{
#if defined(__baos_kernel_source__)
while (*str)
{
putchar(*str);
++str;
}
putchar('\n');
return 0;
#else
baos::doSyscall(baos::Syscall::FILE_WRITE, 0, str, std::strlen(str));
return 0;
#endif
}
int printf(const char* format, ...) noexcept
{
va_list parameters;
va_start(parameters, format);
const int result = vprintf(format, parameters);
va_end(parameters);
return result;
}
int vprintf(const char* format, va_list vlist) BA_CXX_NOEXCEPT
{
return baos::PrintFHelper<RegularPrinter>().vprintf(format, vlist);
}
int snprintf(char* buffer, size_t bufferSize, const char* format, ...) noexcept
{
va_list parameters;
va_start(parameters, format);
const int result = vsnprintf(buffer, bufferSize, format, parameters);
va_end(parameters);
return result;
}
int vsnprintf(char* buffer, size_t bufferSize, const char* format, va_list vlist) noexcept
{
BufferPrinter printer{
.pos = buffer,
.end = bufferSize > 0 ? buffer + bufferSize - 1 : buffer
};
const int length = baos::PrintFHelper(printer).vprintf(format, vlist);
if (bufferSize > 0)
{
buffer[std::min(static_cast<int>(bufferSize - 1), length)] = '\0';
}
return length;
}
int fgetc(FILE* stream) noexcept
{
char chr;
if (!stream->readChar(chr))
{
return EOF;
}
return chr;
}
char* fgets(char* buffer, int count, FILE* stream) noexcept
{
if (count < 1) {
return nullptr;
}
if (count == 1)
{
*buffer = '\0';
return buffer;
}
int pos = 0;
for (; pos < count - 1; ++pos)
{
if (!stream->readChar(buffer[pos]))
{
if (stream->isError() || pos == 0)
{
return nullptr;
}
break;
}
}
buffer[pos] = '\0';
return buffer;
}
} // extern "C"
namespace std
{
bool fgetline(FILE* stream, std::string& outLine) noexcept
{
return stream->readLine(outLine);
}
}

View File

@@ -0,0 +1,124 @@
#include <stdlib.h>
#include <stddef.h>
#include "os/memory.hpp"
#include "os/tty.hpp"
namespace
{
inline const size_t INIT_MALLOC_SPACE_ELEMENTS = 1024 * 1024;
inline const size_t INIT_MALLOC_SPACE_BYTES = INIT_MALLOC_SPACE_ELEMENTS * alignof(max_align_t);
max_align_t gInitMallocSpace[INIT_MALLOC_SPACE_ELEMENTS];
struct MallocBlock
{
size_t elements;
MallocBlock* nextBlock;
};
struct AllocInfo
{
size_t elements;
};
static_assert(sizeof(MallocBlock) <= alignof(max_align_t));
static_assert(sizeof(AllocInfo) <= alignof(max_align_t));
MallocBlock* gNextBlock = nullptr;
}
void __ba_initInitialHeap() noexcept
{
gNextBlock = reinterpret_cast<MallocBlock*>(gInitMallocSpace);
gNextBlock->elements = INIT_MALLOC_SPACE_ELEMENTS;
gNextBlock->nextBlock = nullptr;
}
extern "C"
{
void abort()
{
tty::write("Abort called!");
__asm__ volatile("hlt");
while(true) {};
__builtin_unreachable();
}
void* malloc(size_t size) noexcept
{
if (size == 0)
{
return nullptr;
}
const size_t requiredElements = (size + sizeof(max_align_t) - 1) / sizeof(max_align_t) + 1;
MallocBlock* prevBlock = nullptr;
for (MallocBlock* block = gNextBlock; block != nullptr; block = block->nextBlock)
{
if (block->elements >= requiredElements)
{
MallocBlock* newBlock = nullptr;
if (block->elements > requiredElements)
{
newBlock = reinterpret_cast<MallocBlock*>(reinterpret_cast<max_align_t*>(block) + requiredElements);
newBlock->nextBlock = block->nextBlock;
newBlock->elements = block->elements - requiredElements;
}
else
{
newBlock = block->nextBlock;
}
if (prevBlock != nullptr)
{
prevBlock->nextBlock = newBlock;
}
else
{
gNextBlock = newBlock;
}
AllocInfo* allocInfo = reinterpret_cast<AllocInfo*>(block);
allocInfo->elements = requiredElements;
return reinterpret_cast<max_align_t*>(block) + 1;
}
prevBlock = block;
}
baos::PageRange pages = baos::allocatePages({
.numPages = std::max(1ul, baos::bytesToPages(size, /* bigPages = */ true)),
.bigPages = true
});
if (!pages) {
return nullptr;
}
std::span<std::uint8_t> memory = pages.getMemory();
MallocBlock* newBlock = std::bit_cast<MallocBlock*>(memory.begin());
newBlock->nextBlock = gNextBlock;
newBlock->elements = memory.size();
gNextBlock = newBlock;
return malloc(size);
}
void free(void* memory) noexcept
{
if (memory == nullptr)
{
return;
}
MallocBlock* block = reinterpret_cast<MallocBlock*>(static_cast<max_align_t*>(memory) - 1);
block->nextBlock = gNextBlock;
gNextBlock = block;
}
int __cxa_atexit(void (*func)(void*), void* arg, void* dsoHandle)
{
(void) func;
(void) arg;
(void) dsoHandle;
// NOOP for now
// TODO
return 0;
}
} // extern "C"

View File

@@ -0,0 +1,69 @@
#include <string.h>
#include <stdint.h>
extern "C"
{
int memcmp(const void* lhs, const void* rhs, size_t count) noexcept
{
for (size_t pos = 0; pos < count; ++pos)
{
const unsigned char left = *(static_cast<const unsigned char*>(lhs) + pos);
const unsigned char right = *(static_cast<const unsigned char*>(rhs) + pos);
if (left != right) {
return left - right;
}
}
return 0;
}
#if !defined(__x86_64__)
void* memcpy(void* dest, const void* src, size_t count) noexcept
{
for (size_t pos = 0; pos < count; ++pos)
{
*(static_cast<uint8_t*>(dest) + pos) = *(static_cast<const uint8_t*>(src) + pos);
}
return dest;
}
void* memmove(void* dest, const void* src, size_t count) noexcept
{
if (dest < src)
{
for (size_t pos = 0; pos < count; ++pos)
{
*(static_cast<uint8_t*>(dest) + pos) = *(static_cast<const uint8_t*>(src) + pos);
}
}
else
{
for (size_t pos = 0; pos < count; ++pos)
{
*(static_cast<uint8_t*>(dest) + count - pos - 1) = *(static_cast<const uint8_t*>(src) + count - pos - 1);
}
}
return dest;
}
#endif
void* memset(void* dest, int value, size_t count) noexcept
{
for (size_t pos = 0; pos < count; ++pos)
{
*(static_cast<unsigned char*>(dest) + pos) = static_cast<unsigned char>(value);
}
return dest;
}
size_t strlen(const char* str) noexcept
{
size_t len = 0;
while (str[len] != '\0') {
++len;
}
return len;
}
}