-
-
Notifications
You must be signed in to change notification settings - Fork 230
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
0.5.4: Hash variables accept designated initializers. @safemacro over…
…rides the need for `@` in macro names. Fixes to macro context evaluation. Updated allocator api. Removed install_win_reqs.bat. Deterministic @init for MacOS.
- Loading branch information
Showing
14 changed files
with
978 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,254 @@ | ||
module std::core::machoruntime @if(env::DARWIN) @private; | ||
|
||
struct SegmentCommand64 | ||
{ | ||
uint cmd; | ||
uint cmdsize; | ||
char[16] segname; | ||
ulong vmaddr; | ||
ulong vmsize; | ||
ulong fileoff; | ||
ulong filesize; | ||
uint maxprot; | ||
uint initprot; | ||
uint nsects; | ||
uint flags; | ||
} | ||
|
||
struct LoadCommand | ||
{ | ||
uint cmd; | ||
uint cmdsize; | ||
} | ||
|
||
struct Section64 | ||
{ | ||
char[16] sectname; | ||
char[16] segname; | ||
ulong addr; | ||
ulong size; | ||
uint offset; | ||
uint align; | ||
uint reloff; | ||
uint nreloc; | ||
uint flags; | ||
uint reserved1; | ||
uint reserved2; | ||
uint reserved3; | ||
} | ||
|
||
struct MachHeader | ||
{ | ||
uint magic; | ||
uint cputype; | ||
uint cpusubtype; | ||
uint filetype; | ||
uint ncmds; | ||
uint sizeofcmds; | ||
uint flags; | ||
} | ||
|
||
struct MachHeader64 | ||
{ | ||
inline MachHeader header; | ||
uint reserved; | ||
} | ||
|
||
const LC_SEGMENT_64 = 0x19; | ||
|
||
fault MachoSearch | ||
{ | ||
NOT_FOUND | ||
} | ||
fn bool name_cmp(char* a, char[16]* b) | ||
{ | ||
for (usz i = 0; i < 16; i++) | ||
{ | ||
if (a[i] != (*b)[i]) return false; | ||
if (a[i] == '\0') return true; | ||
} | ||
return false; | ||
} | ||
|
||
fn SegmentCommand64*! find_segment(MachHeader* header, char* segname) | ||
{ | ||
LoadCommand* command = (void*)header + MachHeader64.sizeof; | ||
for (uint i = 0; i < header.ncmds; i++) | ||
{ | ||
if (command.cmd == LC_SEGMENT_64) | ||
{ | ||
SegmentCommand64* segment = (SegmentCommand64*)command; | ||
if (name_cmp(segname, &segment.segname)) return segment; | ||
} | ||
command = (void*)command + command.cmdsize; | ||
} | ||
return MachoSearch.NOT_FOUND?; | ||
} | ||
fn Section64*! find_section(SegmentCommand64* command, char* sectname) | ||
{ | ||
Section64* section = (void*)command + SegmentCommand64.sizeof; | ||
for (uint i = 0; i < command.nsects; i++) | ||
{ | ||
if (name_cmp(sectname, §ion.sectname)) return section; | ||
section++; | ||
} | ||
return MachoSearch.NOT_FOUND?; | ||
} | ||
|
||
macro find_segment_section_body(MachHeader* header, char* segname, char* sectname, $Type) | ||
{ | ||
|
||
Section64*! section = find_section(find_segment(header, segname), sectname); | ||
if (catch section) | ||
{ | ||
return $Type[] {}; | ||
} | ||
$Type* ptr = (void*)header + section.offset; | ||
return ptr[:section.size / $Type.sizeof]; | ||
} | ||
|
||
def DyldCallback = fn void (MachHeader* mh, isz vmaddr_slide); | ||
|
||
extern fn void _dyld_register_func_for_add_image(DyldCallback); | ||
|
||
|
||
struct DlInfo | ||
{ | ||
char* dli_fname; | ||
void* dli_fbase; | ||
char* dli_sname; | ||
void* dli_saddr; | ||
} | ||
|
||
extern fn void printf(char*, ...); | ||
extern fn int dladdr(MachHeader* mh, DlInfo* dlinfo); | ||
extern fn void* realloc(void* ptr, usz size); | ||
extern fn void* malloc(usz size); | ||
extern fn void free(void* ptr); | ||
|
||
def CallbackFn = fn void(); | ||
struct Callback | ||
{ | ||
uint priority; | ||
CallbackFn xtor; | ||
Callback* next; | ||
} | ||
struct DynamicMethod | ||
{ | ||
void* fn_ptr; | ||
char* sel; | ||
union | ||
{ | ||
DynamicMethod* next; | ||
TypeId* type; | ||
} | ||
} | ||
|
||
enum StartupState | ||
{ | ||
NOT_STARTED, | ||
INIT, | ||
RUN_CTORS, | ||
READ_DYLIB, | ||
RUN_DYLIB_CTORS, | ||
RUN_DTORS, | ||
SHUTDOWN | ||
} | ||
|
||
StartupState runtime_state = NOT_STARTED; | ||
|
||
Callback* ctor_first; | ||
Callback* dtor_first; | ||
|
||
fn void runtime_startup() @public @export("__c3_runtime_startup") | ||
{ | ||
if (runtime_state != NOT_STARTED) return; | ||
runtime_state = INIT; | ||
_dyld_register_func_for_add_image(&dl_reg_callback); | ||
assert(runtime_state == INIT); | ||
runtime_state = RUN_CTORS; | ||
Callback* ctor = ctor_first; | ||
while (ctor) | ||
{ | ||
ctor.xtor(); | ||
ctor = ctor.next; | ||
} | ||
assert(runtime_state == RUN_CTORS); | ||
runtime_state = READ_DYLIB; | ||
ctor = null; | ||
} | ||
|
||
fn void runtime_finalize() @public @export("__c3_runtime_finalize") | ||
{ | ||
if (runtime_state != READ_DYLIB) return; | ||
runtime_state = RUN_DTORS; | ||
Callback* dtor = dtor_first; | ||
while (dtor) | ||
{ | ||
dtor.xtor(); | ||
dtor = dtor.next; | ||
} | ||
assert(runtime_state == RUN_DTORS); | ||
runtime_state = SHUTDOWN; | ||
} | ||
|
||
fn void append_xxlizer(Callback** ref, Callback* cb) | ||
{ | ||
while (Callback* current = *ref, current) | ||
{ | ||
if (current.priority > cb.priority) | ||
{ | ||
cb.next = current; | ||
break; | ||
} | ||
ref = ¤t.next; | ||
} | ||
*ref = cb; | ||
} | ||
|
||
struct TypeId | ||
{ | ||
char type; | ||
TypeId* parentof; | ||
DynamicMethod* dtable; | ||
usz sizeof; | ||
TypeId* inner; | ||
usz len; | ||
typeid[*] additional; | ||
} | ||
|
||
fn void dl_reg_callback(MachHeader* mh, isz vmaddr_slide) | ||
{ | ||
usz size = 0; | ||
assert(runtime_state == INIT || runtime_state == READ_DYLIB, "State was %s", runtime_state); | ||
foreach (&dm : find_segment_section_body(mh, "__DATA", "__c3_dynamic", DynamicMethod)) | ||
{ | ||
TypeId* type = dm.type; | ||
dm.next = type.dtable; | ||
type.dtable = dm; | ||
DynamicMethod* m = dm; | ||
while (m) | ||
{ | ||
m = m.next; | ||
} | ||
} | ||
foreach (&cb : find_segment_section_body(mh, "__DATA", "__c3dtor", Callback)) | ||
{ | ||
append_xxlizer(&dtor_first, cb); | ||
} | ||
foreach (&cb : find_segment_section_body(mh, "__DATA", "__c3ctor", Callback)) | ||
{ | ||
append_xxlizer(&ctor_first, cb); | ||
} | ||
if (runtime_state != READ_DYLIB) return; | ||
runtime_state = RUN_DYLIB_CTORS; | ||
Callback* ctor = ctor_first; | ||
ctor_first = null; | ||
while (ctor) | ||
{ | ||
ctor.xtor(); | ||
ctor = ctor.next; | ||
} | ||
assert(runtime_state == RUN_DYLIB_CTORS); | ||
runtime_state = READ_DYLIB; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -850,7 +850,6 @@ typedef enum | |
|
||
typedef enum | ||
{ | ||
|
||
BUILTIN_ABS, | ||
BUILTIN_ANY_MAKE, | ||
BUILTIN_ATOMIC_LOAD, | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.