Giter VIP home page Giter VIP logo

lwdr's Introduction

LWDR - Light Weight D Runtime

Notice:

This is not a port of druntime! This is a completely new implementation for low-resource environments. Normal D code may not work here!

LWDR is now part of the Symmetry Autumn of Code 2021. The work plan is here.

What is this?

This is the light weight D runtime - it is a barebones runtime targeting ARM Cortex CPUs. It works by abstracting hooks that the user can connect to their selected backend (be it an RTOS such as FreeRTOS, ChibiOS, etc or a minimalist system).

What works?

  1. Class allocations and deallocations (via new and delete)
  2. Struct heap allocations and deallocations (via new and delete)
  3. Invariants
  4. Asserts
  5. Contract programming
  6. Basic RTTI (via TypeInfo stubs)
  7. Interfaces
  8. Static Arrays
  9. Virtual functions and overrides
  10. Abstract classes
  11. Static classes
  12. Allocation and deallocation of dynamic arrays (opt in by version LWDR_DynamicArray)
  13. Concatenate an item to a dynamic array (opt in by version LWDR_DynamicArray)
  14. Concatenate two dynamic arrays together (opt in by version LWDR_DynamicArray)
  15. Dynamic array resizing (opt in by version LWDR_DynamicArray)
  16. Thread local storage (opt in by version LWDR_TLS)
  17. Delegates/closures (opt-in by version LWDR_ManualDelegate)
  18. Module constructors and destructors (opt-in by version LWDR_ModuleCtors)
  19. Static constructors and destructors (opt-in by version LWDR_ModuleCtors)
  20. Shared static constructors and destructor (opt-in by version LWDR_ModuleCtors)
  21. Module info (opt-in by version LWDR_ModuleCtors)
  22. Object monitors (opt in by version LWDR_Sync)
  23. Shared and sychronized (opt in by version LWDR_Sync)

What doesn't work?

  1. Exceptions and Throwables (experimental implementation was removed)
  2. There is no GC implementation (primitive memory tracking is now available with LWDR_TrackMem, RefCount!T and Unique!T are now available)
  3. Associative arrays

Which compilers can be used?

LDC works the best. DMD is not compatible. GDC will work but points 18-21 inclusive aren't supported.

Has this been run on real hardware?

Yes, as of currently it has been run on an STM32F407.

How to use this?

You have to hook the functions declared in rtoslink.d by implementing them in your MCU development environment. For example, with FreeRTOS, rtosbackend_heapalloc points to a wrapper in the C/C++ land that wraps pvPortMalloc(...).

Example usage

First off, you will need an existing C/C++ project for your target microcontroller that has a C compiler and link, and has some form of memory management (RTOS preferred). The C/C++ code can then call into your D functions (they must be marked extern(C)).

LWDR can be used with DUB and LDC. Simply add it to your dependencies. Build instructions are here for DUB and LDC.

This will output a lib archive that you can link into your C/C++ project and execute on an MCU.

Here is an example code using FreeRTOS:

//myapp.d
module myapp;

import lwdr;

class Foo 
{
  this() 
  {
    // do something
  }
  
  void bar()
  {
    // do something
  }
}

extern(C) void myDFunction() 
{
  Foo foo = new Foo; // this will invoke rtosbackend_heapalloc(..)
  foo.bar;
  LWDR.free(foo); // don't forget to free - there is no GC
  // LWDR.free will invoke rtosbackend_heapfreealloc(..)
}
// main.h
#ifndef __MAIN_H
#define __MAIN_H

#ifdef __cplusplus
extern "C" {
#endif

// defined in rtoslink.d
void* rtosbackend_heapalloc(unsigned int sz);
void rtosbackend_heapfreealloc(void* ptr);

void rtosbackend_arrayBoundFailure(char* file, unsigned int line);
void rtosbackend_assert(char* file, unsigned int line);
void rtosbackend_assertmsg(char* msg, char* file, unsigned int line);

void myDFunction(); // defined in myapp.d
#ifdef __cplusplus
}
#endif

#endif __MAIN_H
// main.cpp
#include "cmsis_os.h"

void* rtosbackend_heapalloc(unsigned int sz) // defined in rtoslink.d
{
  return pvPortMalloc(sz); // allocate some heap memory for D 
}

void rtosbackend_heapfreealloc(void* ptr)// defined in rtoslink.d
{
  vPortFree(ptr); // deallocate some heap memory for D
}
void rtosbackend_arrayBoundFailure(char* file, unsigned int line)
{}
void rtosbackend_assert(char* file, unsigned int line)
{}
void rtosbackend_assertmsg(char* msg, char* file, unsigned int line)
{}

osThreadId_t defaultTaskHandle; // thread handle
osThreadAttr_t defaultTask_attributes; // thread attributes

void myTask(void *argument)
{
  myDFunction();
}

int main()
{
  osKernelInitialize();
  defaultTask_attributes.name = "defaultTask";
	defaultTask_attributes.priority = (osPriority_t) osPriorityNormal;
	defaultTask_attributes .stack_size = 128 * 4;
  // create a thread that executes myTask
  defaultTaskHandle = osThreadNew(myTask, NULL, &defaultTask_attributes);
  osKernelStart(); // start the scheduler
  
  while(1) {}
  
  return 1;
}

GDB will be able to set breakpoints in D code and perform steps normally.

Credit

Credit to Adam D. Ruppe for his webassembly project that forms the basis of this project.

Credit to D Language Foundation for its D runtime.

Credit to LDC Developers for its D runtime.

Credit to GDC for its D runtime.

Credit to denizzka for his d_c_arm_test which helped with the implementation of TLS (thread local storage).

lwdr's People

Contributors

hmmdyl avatar moonlightsentinel avatar mrcsnm avatar webfreak001 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

lwdr's Issues

Allocation purity

With the addition of memory tracking, _d_newarrayU, _d_arraysetlengthT, _d_arraysetlengthiT, _d_newitemU, _d_newitemT, _d_newitemiT and calling functions cannot be pure.

Support Thread Local Storage (TLS)

Thread Local Storage (TLS) is not supported. TLS is reliant on RTOS support - TLS variables are allocated in a heap and the pointer is stored in the RTOS' Thread Control Block (TCB). __aeabi_read_tp must then read this pointer.

Unknown error after all errors were worked around (I believe this should be delegate error)

0x00007FF6341B505B (0x000000141F9FDEC0 0x000001BD40D82608 0x0000000000000004 0x000000141F9FDEC0)
0x00007FF6341ABA6E (0x000000141F9FDEC0 0x00007FF63422496D 0x000000004229D201 0x00007FF634225271)
0x00007FF636BBDB51 (0x0000000000000000 0x00007FF63876F5A8 0x0000000000000004 0x000000141F9FDFE0)
0x00007FF636BBD988 (0x0000000000000000 0x0000000000000000 0x0000000000000000 0x00007FF6341DA141)
0x00007FF636B61EE1 (0xFFFFFFFFFFFFFFFF 0xFFFFFFFFFFFFFFFF 0xFFFFFFFFFFFFFFFF 0xFFFFFFFFFFFFFFFF)
0x00007FF636B60370 (0x000001BD4027EB10 0x00007FF63694E91D 0x0000000000000000 0x00007FF636B54CC6)
0x00007FF636B5FBE6 (0x000000141F9FE1F0 0x000001BD41E8DF28 0x000001BD40E82270 0x000001BD40D06910)
0x00007FF636ADEFF5 (0x0000000000000000 0x00007FF6341DA141 0x000001BD4267D070 0x00007FF636C5DFC8)
0x00007FF636B6302E (0xFFFFFFFFFFFFFFFF 0xFFFFFFFFFFFFFFFF 0xFFFFFFFFFFFFFFFF 0xFFFFFFFFFFFFFFFF)
0x00007FF636B60370 (0x000001BD4027EB10 0x00007FF63694DE74 0x000001BD40D647C0 0x00007FF63419518D)
0x00007FF636B5FBE6 (0x000001BD40E82270 0x00007FF638505EA0 0x000001BD422E5B38 0x00007FF6341AEA09)
0x00007FF636ADEFF5 (0x000001BD40181E38 0x0000000000000027 0x000000141F9FE578 0x000001BD40BEA4D0)
0x00007FF636B27C72 (0x000001BD00000000 0x000001BD4221AA40 0x000001BD424D6D58 0x00007FF636BB62BB)
0x00007FF636B14C18 (0x0000000000000000 0x0000000000000000 0x0000F1F68EEDB449 0x000001BD401819B0)
0x00007FF636B1493B (0x0000000001DF0070 0x0000000000000000 0x000001BD422472E0 0x0000000000000040)
0x00007FF636B5E0C2 (0x000000141F9FEC10 0x000001BD41519FA0 0x000001BD3F909E70 0x00007FF636B650B6)
0x00007FF636B63E5D (0x00007FF63869A000 0x00007FFB4A1095F1 0x0000000000370500 0x000000141F9FEAE0)
0x00007FF636AEEDD8 (0x00007FF6368B02B0 0x0000000000005E08 0x000001BD3E060FC0 0x0000000000000001)
0x00007FF636B0B3DA (0x0000000000000000 0x000000141F9FF300 0x0000000000000000 0x00007FF6386745A5)
0x00007FF636AA3E11 (0x000000000000001F 0x0000000000000000 0x000000000000001F 0x000001BD3FAFEED0)
0x00007FF636B08A22 (0x000001BD3DEADA00 0x0000000000000000 0x0000000000000000 0x0000000000000000)
0x00007FF636C0F029 (0x0000000000000000 0x00007FF636C48F16 0x000001BD3E060000 0x000000141F9FFB28)
0x00007FF636C0EC6A (0x000001BD3DE9A578 0x000000141F9FFD68 0x000000141F9FFB90 0x0000000000000001)
0x00007FF636C0EFB1 (0x0000000000000042 0x0000000000000000 0x000001BD3DF10715 0x0000000000000042)
0x00007FF636B03B8F (0x0000000000000000 0x00007FF636C38E6D 0x0000000000000000 0x0000000000000000)
0x00007FF636C38DF4 (0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000)
0x00007FFB48736FD4 (0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000), BaseThreadInitThunk() + 0x14 bytes(s)
0x00007FFB4A13CF31 (0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000), RtlUserThreadStart() + 0x21 bytes(s)

Undefined reference to _d_arraybounds_index

Trying to to use LWDR for the psvita using vitasdk:

c:/msys64/usr/local/vitasdk/bin/../lib/gcc/arm-vita-eabi/10.3.0/../../../../arm-vita-eabi/bin/ld.exe: C:/msys64/usr/local/dlibs/\libtest.a(util.o): in function _D4util17stringCmpInternalFNeMxAaMxQeZi': C:\/Users\Marcelo\AppData\Local\dub\packages\lwdr-0.3.0\lwdr\source/util.d:6: undefined reference to _d_arraybounds_index'
c:/msys64/usr/local/vitasdk/bin/../lib/gcc/arm-vita-eabi/10.3.0/../../../../arm-vita-eabi/bin/ld.exe: C:/Users\Marcelo\AppData\Local\dub\packages\lwdr-0.3.0\lwdr\source/util.d:6: undefined reference to _d_arraybounds_index' c:/msys64/usr/local/vitasdk/bin/../lib/gcc/arm-vita-eabi/10.3.0/../../../../arm-vita-eabi/bin/ld.exe: C:\/Users\Marcelo\AppData\Local\dub\packages\lwdr-0.3.0\lwdr\source/util.d:6: undefined reference to _d_arraybounds_index'
c:/msys64/usr/local/vitasdk/bin/../lib/gcc/arm-vita-eabi/10.3.0/../../../../arm-vita-eabi/bin/ld.exe: C:/Users\Marcelo\AppData\Local\dub\packages\lwdr-0.3.0\lwdr\source/util.d:6: undefined reference to `_d_arraybounds_index'
collect2.exe: error: ld returned 1 exit status

This is my dub:

"dflags": [
		"-mtriple=armv7a-unknown-unknown",
		"-mcpu=cortex-a9",
		"-g",
		"-float-abi=hard",
		"-O0",
		"-fthread-model=local-exec"
	],
	"targetType": "staticLibrary",

My D source:

class Test
{
	immutable(char*) getStringFromD()
	{
		return "Hello World from D! Simple Test".ptr;
	}
}


class UltraTest : Test
{
	override immutable(char*) getStringFromD()
	{
		return "Hello World from D!!! Ultra Test!".ptr;
	}
}

extern(C) immutable(char*) getStringFromD()
{
	return new UltraTest().getStringFromD;
}

How to use

One thing that gets some of us to try and contribute is when we have a section on how to use a package in the README.

Import, basic examples, how to compile...tipsπŸ™

That'll be handy

Undefined functions

  • _d_throw_exception
  • _d_eh_personality
  • _d_eh_enter_catch
  • _d_eh_resume_unwind
  • _aaInX
  • _aaApply
  • _aaEqual

The try/catch thing seems to be generated by the struct destructors

It was a nice proof of concept. With the current state of LWDR I was almost able to port my entire engine :D

Now those functions are quite complex for me to implement so I can't help more than that :(

undefined reference to __aeabi_read_tp on ModuleCtors

In dub.json I have:

"dflags": [
		"-mtriple=armv7a-unknown-unknown",
		"-mcpu=cortex-a9",
		"-g",
		"-float-abi=hard",
		"-O0",
		"--boundscheck=off",
		"-fthread-model=local-exec"
	],

"versions": [
		"LWDR_DynamicArray",
		"LWDR_ModuleCtors"
	],

My D code:

class Test
{
	static int[] testStaticConstructor;
	immutable(char*) getStringFromD()
	{
		return "Hello World from D! Simple Test".ptr;
	}
}

static this()
{
	for(int i = 0; i < 5; i++)
		Test.testStaticConstructor~= i;
}

No property `reserve` for type `string`

Reserve makes part for dynamic array API for append operation, it will avoid reallocations. I'm documenting API differentiations while trying to convert my engine to be LWDR compatible

TLS variable bug

Very first TLS allocated variable appears to be corrupt. The value in it seems to be a bitshift of the size of the TLS sector.

LDC compatibility

LDC for the moment is incompatible with a GCC C/C++ backend. The cause of the issue is error/exception handling.

I will need to write glue code to accept LDC's compiler generated exception-code and make it interact with GCC's (not GDC!!) exception code.

Buffer overrun when making .length smaller

For a dynamic array, setting .length to be smaller than the current length will create a buffer overrun and subsequent assert error. This is due to a lack of checking before invoking memcpy

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.