mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 23:58:50 +00:00
Basic work on obj generation
This commit is contained in:
BIN
Binary file not shown.
@@ -50,8 +50,13 @@ del *.ilk > NUL 2> NUL
|
|||||||
cl %compiler_settings% "src\main.cpp" ^
|
cl %compiler_settings% "src\main.cpp" ^
|
||||||
/link %linker_settings% -OUT:%exe_name% ^
|
/link %linker_settings% -OUT:%exe_name% ^
|
||||||
&& odin build examples/llvm-demo/demo.odin -llvm-api
|
&& odin build examples/llvm-demo/demo.odin -llvm-api
|
||||||
|
if %errorlevel% neq 0 (
|
||||||
|
goto end_of_build
|
||||||
|
)
|
||||||
|
|
||||||
rem && link -nologo llvm_demo.obj kernel32.lib -OUT:llvm_demo.exe
|
link llvm_demo.obj kernel32.lib user32.lib /OUT:llvm_demo.exe ^
|
||||||
|
/nologo /incremental:no /opt:ref /subsystem:CONSOLE /defaultlib:libcmt -debug ^
|
||||||
|
&& llvm_demo
|
||||||
|
|
||||||
del *.obj > NUL 2> NUL
|
del *.obj > NUL 2> NUL
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -15,14 +15,14 @@ set :: proc "contextless" (data: rawptr, value: byte, len: int) -> rawptr {
|
|||||||
foreign _ {
|
foreign _ {
|
||||||
when size_of(rawptr) == 8 {
|
when size_of(rawptr) == 8 {
|
||||||
@(link_name="llvm.memset.p0i8.i64")
|
@(link_name="llvm.memset.p0i8.i64")
|
||||||
llvm_memset :: proc(dst: rawptr, val: byte, len: int, align: i32, is_volatile: bool) ---;
|
llvm_memset :: proc(dst: rawptr, val: byte, len: int, is_volatile: bool) ---;
|
||||||
} else {
|
} else {
|
||||||
@(link_name="llvm.memset.p0i8.i32")
|
@(link_name="llvm.memset.p0i8.i32")
|
||||||
llvm_memset :: proc(dst: rawptr, val: byte, len: int, align: i32, is_volatile: bool) ---;
|
llvm_memset :: proc(dst: rawptr, val: byte, len: int, is_volatile: bool) ---;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm_memset(data, value, len, 1, false);
|
llvm_memset(data, value, len, false);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
zero :: inline proc "contextless" (data: rawptr, len: int) -> rawptr {
|
zero :: inline proc "contextless" (data: rawptr, len: int) -> rawptr {
|
||||||
|
|||||||
@@ -42,10 +42,10 @@ mem_zero :: proc "contextless" (data: rawptr, len: int) -> rawptr {
|
|||||||
foreign _ {
|
foreign _ {
|
||||||
when size_of(rawptr) == 8 {
|
when size_of(rawptr) == 8 {
|
||||||
@(link_name="llvm.memset.p0i8.i64")
|
@(link_name="llvm.memset.p0i8.i64")
|
||||||
memset :: proc(dst: rawptr, val: byte, len: int, align: i32 = 1, is_volatile: bool = false) ---;
|
memset :: proc(dst: rawptr, val: byte, len: int, is_volatile: bool = false) ---;
|
||||||
} else {
|
} else {
|
||||||
@(link_name="llvm.memset.p0i8.i32")
|
@(link_name="llvm.memset.p0i8.i32")
|
||||||
memset :: proc(dst: rawptr, val: byte, len: int, align: i32 = 1, is_volatile: bool = false) ---;
|
memset :: proc(dst: rawptr, val: byte, len: int, is_volatile: bool = false) ---;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -59,13 +59,13 @@ mem_copy :: proc "contextless" (dst, src: rawptr, len: int) -> rawptr {
|
|||||||
foreign _ {
|
foreign _ {
|
||||||
when size_of(rawptr) == 8 {
|
when size_of(rawptr) == 8 {
|
||||||
@(link_name="llvm.memmove.p0i8.p0i8.i64")
|
@(link_name="llvm.memmove.p0i8.p0i8.i64")
|
||||||
llvm_memmove :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) ---;
|
llvm_memmove :: proc(dst, src: rawptr, len: int, is_volatile: bool = false) ---;
|
||||||
} else {
|
} else {
|
||||||
@(link_name="llvm.memmove.p0i8.p0i8.i32")
|
@(link_name="llvm.memmove.p0i8.p0i8.i32")
|
||||||
llvm_memmove :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) ---;
|
llvm_memmove :: proc(dst, src: rawptr, len: int, is_volatile: bool = false) ---;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
llvm_memmove(dst, src, len, 1, false);
|
llvm_memmove(dst, src, len);
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,13 +75,13 @@ mem_copy_non_overlapping :: proc "contextless" (dst, src: rawptr, len: int) -> r
|
|||||||
foreign _ {
|
foreign _ {
|
||||||
when size_of(rawptr) == 8 {
|
when size_of(rawptr) == 8 {
|
||||||
@(link_name="llvm.memcpy.p0i8.p0i8.i64")
|
@(link_name="llvm.memcpy.p0i8.p0i8.i64")
|
||||||
llvm_memcpy :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) ---;
|
llvm_memcpy :: proc(dst, src: rawptr, len: int, is_volatile: bool = false) ---;
|
||||||
} else {
|
} else {
|
||||||
@(link_name="llvm.memcpy.p0i8.p0i8.i32")
|
@(link_name="llvm.memcpy.p0i8.p0i8.i32")
|
||||||
llvm_memcpy :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) ---;
|
llvm_memcpy :: proc(dst, src: rawptr, len: int, is_volatile: bool = false) ---;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
llvm_memcpy(dst, src, len, 1, false);
|
llvm_memcpy(dst, src, len);
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,15 +2,15 @@ package runtime
|
|||||||
|
|
||||||
foreign import kernel32 "system:Kernel32.lib"
|
foreign import kernel32 "system:Kernel32.lib"
|
||||||
|
|
||||||
@private
|
// @private
|
||||||
@(link_name="_tls_index")
|
// @(link_name="_tls_index")
|
||||||
_tls_index: u32;
|
// _tls_index: u32;
|
||||||
|
|
||||||
@private
|
// @private
|
||||||
@(link_name="_fltused")
|
// @(link_name="_fltused")
|
||||||
_fltused: i32 = 0x9875;
|
// _fltused: i32 = 0x9875;
|
||||||
|
|
||||||
@(link_name="memcpy")
|
// @(link_name="memcpy")
|
||||||
memcpy :: proc "c" (dst, src: rawptr, len: int) -> rawptr {
|
memcpy :: proc "c" (dst, src: rawptr, len: int) -> rawptr {
|
||||||
foreign kernel32 {
|
foreign kernel32 {
|
||||||
RtlCopyMemory :: proc "c" (dst, src: rawptr, len: int) ---
|
RtlCopyMemory :: proc "c" (dst, src: rawptr, len: int) ---
|
||||||
@@ -19,7 +19,7 @@ memcpy :: proc "c" (dst, src: rawptr, len: int) -> rawptr {
|
|||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
@(link_name="memmove")
|
// @(link_name="memmove")
|
||||||
memmove :: proc "c" (dst, src: rawptr, len: int) -> rawptr {
|
memmove :: proc "c" (dst, src: rawptr, len: int) -> rawptr {
|
||||||
foreign kernel32 {
|
foreign kernel32 {
|
||||||
RtlMoveMemory :: proc "c" (dst, src: rawptr, len: int) ---
|
RtlMoveMemory :: proc "c" (dst, src: rawptr, len: int) ---
|
||||||
@@ -28,7 +28,7 @@ memmove :: proc "c" (dst, src: rawptr, len: int) -> rawptr {
|
|||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
@(link_name="memset")
|
// @(link_name="memset")
|
||||||
memset :: proc "c" (ptr: rawptr, val: i32, len: int) -> rawptr {
|
memset :: proc "c" (ptr: rawptr, val: i32, len: int) -> rawptr {
|
||||||
foreign kernel32 {
|
foreign kernel32 {
|
||||||
RtlFillMemory :: proc "c" (dst: rawptr, len: int, fill: byte) ---
|
RtlFillMemory :: proc "c" (dst: rawptr, len: int, fill: byte) ---
|
||||||
|
|||||||
@@ -1,56 +1,62 @@
|
|||||||
package demo
|
package demo
|
||||||
|
|
||||||
import "core:os"
|
import "core:os"
|
||||||
|
import "core:sys/win32"
|
||||||
|
|
||||||
BarBar :: struct {
|
foreign import kernel32 "system:Kernel32.lib"
|
||||||
x, y: int,
|
foreign import user32 "system:User32.lib"
|
||||||
};
|
|
||||||
foo :: proc(x: int) -> (b: BarBar) {
|
foreign user32 {
|
||||||
b = {1, 2};
|
MessageBoxA :: proc "c" (hWnd: rawptr, text, caption: cstring, uType: u32) -> i32 ---
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreign kernel32 {
|
||||||
|
FlushFileBuffers :: proc "c" (hFile: win32.Handle) -> b32 ---
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
Foo :: enum {A=1, B, C, D};
|
f := os.get_std_handle(win32.STD_OUTPUT_HANDLE);
|
||||||
Foo_Set :: bit_set[Foo];
|
os.write_string(f, "Hellope!\n");
|
||||||
foo_set := Foo_Set{.A, .C};
|
|
||||||
|
|
||||||
array := [4]int{3 = 1, 0 .. 1 = 3, 2 = 9};
|
// Foo :: enum {A=1, B, C, D};
|
||||||
slice := []int{1, 2, 3, 4};
|
// Foo_Set :: bit_set[Foo];
|
||||||
|
// foo_set := Foo_Set{.A, .C};
|
||||||
|
|
||||||
x: ^int = nil;
|
// array := [4]int{3 = 1, 0 .. 1 = 3, 2 = 9};
|
||||||
y := slice != nil;
|
// slice := []int{1, 2, 3, 4};
|
||||||
|
|
||||||
@thread_local a: int;
|
// x: ^int = nil;
|
||||||
|
// y := slice != nil;
|
||||||
|
|
||||||
if true {
|
// @thread_local a: int;
|
||||||
foo(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
x1 := i32(1);
|
// if true {
|
||||||
y1 := i32(2);
|
// foo(1);
|
||||||
z1 := x1 + y1;
|
// }
|
||||||
w1 := z1 - 2;
|
|
||||||
|
|
||||||
f := foo;
|
// x := i32(1);
|
||||||
|
// y := i32(2);
|
||||||
|
// z := x + y;
|
||||||
|
// w := z - 2;
|
||||||
|
|
||||||
c := 1 + 2i;
|
// f := foo;
|
||||||
q := 1 + 2i + 3j + 4k;
|
|
||||||
|
|
||||||
s := "Hellope";
|
// c := 1 + 2i;
|
||||||
|
// q := 1 + 2i + 3j + 4k;
|
||||||
|
|
||||||
b := true;
|
// s := "Hellope";
|
||||||
aaa := b ? int(123) : int(34);
|
|
||||||
defer aaa = 333;
|
|
||||||
|
|
||||||
p := proc(x: int) {};
|
// b := true;
|
||||||
|
// aaa := b ? int(123) : int(34);
|
||||||
|
// defer aaa = 333;
|
||||||
|
|
||||||
|
// bb := BarBar{1, 2};
|
||||||
bb := BarBar{1, 2};
|
// pc: proc "contextless" (x: i32) -> BarBar;
|
||||||
pc: proc "contextless" (x: i32) -> BarBar;
|
// po: proc "odin" (x: i32) -> BarBar;
|
||||||
po: proc "odin" (x: i32) -> BarBar;
|
// e: enum{A, B, C};
|
||||||
e: enum{A, B, C};
|
// u: union{i32, bool};
|
||||||
u: union{i32, bool};
|
// u1: union{i32};
|
||||||
u1: union{i32};
|
// um: union #maybe {^int};
|
||||||
um: union #maybe {^int};
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1685,6 +1685,8 @@ void generate_minimum_dependency_set(Checker *c, Entity *start) {
|
|||||||
str_lit("udivti3"),
|
str_lit("udivti3"),
|
||||||
|
|
||||||
str_lit("memset"),
|
str_lit("memset"),
|
||||||
|
str_lit("memcpy"),
|
||||||
|
str_lit("memmove"),
|
||||||
|
|
||||||
str_lit("memory_compare"),
|
str_lit("memory_compare"),
|
||||||
str_lit("memory_compare_zero"),
|
str_lit("memory_compare_zero"),
|
||||||
|
|||||||
+200
-31
@@ -199,6 +199,10 @@ lbValue lb_addr_load(lbProcedure *p, lbAddr const &addr) {
|
|||||||
} else if (addr.kind == lbAddr_SoaVariable) {
|
} else if (addr.kind == lbAddr_SoaVariable) {
|
||||||
GB_PANIC("lbAddr_SoaVariable");
|
GB_PANIC("lbAddr_SoaVariable");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_type_proc(addr.addr.type)) {
|
||||||
|
return addr.addr;
|
||||||
|
}
|
||||||
return lb_emit_load(p, addr.addr);
|
return lb_emit_load(p, addr.addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -831,7 +835,6 @@ lbProcedure *lb_create_procedure(lbModule *m, Entity *entity) {
|
|||||||
lb_add_entity(m, entity, proc_value);
|
lb_add_entity(m, entity, proc_value);
|
||||||
lb_add_member(m, p->name, proc_value);
|
lb_add_member(m, p->name, proc_value);
|
||||||
|
|
||||||
LLVMContextRef ctx = LLVMGetModuleContext(m->mod);
|
|
||||||
|
|
||||||
// NOTE(bill): offset==0 is the return value
|
// NOTE(bill): offset==0 is the return value
|
||||||
isize offset = 1;
|
isize offset = 1;
|
||||||
@@ -874,8 +877,29 @@ lbProcedure *lb_create_procedure(lbModule *m, Entity *entity) {
|
|||||||
lb_add_proc_attribute_at_index(p, offset+parameter_index, "noalias");
|
lb_add_proc_attribute_at_index(p, offset+parameter_index, "noalias");
|
||||||
lb_add_proc_attribute_at_index(p, offset+parameter_index, "nonnull");
|
lb_add_proc_attribute_at_index(p, offset+parameter_index, "nonnull");
|
||||||
lb_add_proc_attribute_at_index(p, offset+parameter_index, "nocapture");
|
lb_add_proc_attribute_at_index(p, offset+parameter_index, "nocapture");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{ // Debug Information
|
||||||
|
unsigned line = cast(unsigned)entity->token.pos.line;
|
||||||
|
|
||||||
|
LLVMMetadataRef file = nullptr;
|
||||||
|
if (entity->file != nullptr) {
|
||||||
|
cast(LLVMMetadataRef)entity->file->llvm_metadata;
|
||||||
|
}
|
||||||
|
LLVMMetadataRef scope = nullptr;
|
||||||
|
|
||||||
|
|
||||||
|
LLVMMetadataRef res = LLVMDIBuilderCreateFunction(m->debug_builder, scope,
|
||||||
|
cast(char const *)entity->token.string.text, entity->token.string.len,
|
||||||
|
cast(char const *)p->name.text, p->name.len,
|
||||||
|
file, line, nullptr,
|
||||||
|
true, p->body == nullptr,
|
||||||
|
line, LLVMDIFlagZero, false
|
||||||
|
);
|
||||||
|
GB_ASSERT(res != nullptr);
|
||||||
|
map_set(&m->debug_values, hash_pointer(p), res);
|
||||||
|
}
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3163,6 +3187,14 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
|
|||||||
lb_addr_store(p, default_value, value);
|
lb_addr_store(p, default_value, value);
|
||||||
return lb_emit_conv(p, lb_addr_load(p, default_value), t_any);
|
return lb_emit_conv(p, lb_addr_load(p, default_value), t_any);
|
||||||
} else if (dst->kind == Type_Basic) {
|
} else if (dst->kind == Type_Basic) {
|
||||||
|
if (src->Basic.kind == Basic_string && dst->Basic.kind == Basic_cstring) {
|
||||||
|
unsigned indices[1] = {0};
|
||||||
|
LLVMValueRef data = LLVMConstExtractValue(value.value, indices, 1);
|
||||||
|
char const *text = nullptr;
|
||||||
|
size_t length = 0;
|
||||||
|
text = LLVMGetAsString(data, &length);
|
||||||
|
GB_PANIC("HERE %.*s", cast(int)length, text);
|
||||||
|
}
|
||||||
// if (is_type_float(dst)) {
|
// if (is_type_float(dst)) {
|
||||||
// return value;
|
// return value;
|
||||||
// } else if (is_type_integer(dst)) {
|
// } else if (is_type_integer(dst)) {
|
||||||
@@ -4110,7 +4142,7 @@ lbValue lb_emit_call_internal(lbProcedure *p, lbValue value, lbValue return_ptr,
|
|||||||
LLVMBasicBlockRef curr_block = LLVMGetInsertBlock(p->builder);
|
LLVMBasicBlockRef curr_block = LLVMGetInsertBlock(p->builder);
|
||||||
GB_ASSERT(curr_block != p->decl_block->block);
|
GB_ASSERT(curr_block != p->decl_block->block);
|
||||||
|
|
||||||
LLVMValueRef ret = LLVMBuildCall(p->builder, value.value, args, arg_count, "");;
|
LLVMValueRef ret = LLVMBuildCall2(p->builder, LLVMGetElementType(lb_type(p->module, value.type)), value.value, args, arg_count, "");;
|
||||||
lbValue res = {};
|
lbValue res = {};
|
||||||
res.value = ret;
|
res.value = ret;
|
||||||
res.type = abi_rt;
|
res.type = abi_rt;
|
||||||
@@ -7310,6 +7342,9 @@ bool lb_init_generator(lbGenerator *gen, Checker *c) {
|
|||||||
// gen->ctx = LLVMContextCreate();
|
// gen->ctx = LLVMContextCreate();
|
||||||
gen->module.ctx = LLVMGetGlobalContext();
|
gen->module.ctx = LLVMGetGlobalContext();
|
||||||
gen->module.mod = LLVMModuleCreateWithNameInContext("odin_module", gen->module.ctx);
|
gen->module.mod = LLVMModuleCreateWithNameInContext("odin_module", gen->module.ctx);
|
||||||
|
gen->module.debug_builder = LLVMCreateDIBuilder(gen->module.mod);
|
||||||
|
|
||||||
|
|
||||||
gb_mutex_init(&gen->module.mutex);
|
gb_mutex_init(&gen->module.mutex);
|
||||||
gbAllocator a = heap_allocator();
|
gbAllocator a = heap_allocator();
|
||||||
map_init(&gen->module.types, a);
|
map_init(&gen->module.types, a);
|
||||||
@@ -7321,6 +7356,8 @@ bool lb_init_generator(lbGenerator *gen, Checker *c) {
|
|||||||
map_init(&gen->module.anonymous_proc_lits, a);
|
map_init(&gen->module.anonymous_proc_lits, a);
|
||||||
array_init(&gen->module.procedures_to_generate, a);
|
array_init(&gen->module.procedures_to_generate, a);
|
||||||
|
|
||||||
|
map_init(&gen->module.debug_values, a);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7366,6 +7403,30 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
|
|
||||||
auto *min_dep_set = &info->minimum_dependency_set;
|
auto *min_dep_set = &info->minimum_dependency_set;
|
||||||
|
|
||||||
|
{ // Debug Info
|
||||||
|
for_array(i, info->files.entries) {
|
||||||
|
AstFile *f = info->files.entries[i].value;
|
||||||
|
String fullpath = f->fullpath;
|
||||||
|
String filename = filename_from_path(fullpath);
|
||||||
|
String directory = directory_from_path(fullpath);
|
||||||
|
LLVMMetadataRef res = LLVMDIBuilderCreateFile(m->debug_builder,
|
||||||
|
cast(char const *)filename.text, filename.len,
|
||||||
|
cast(char const *)directory.text, directory.len);
|
||||||
|
map_set(&m->debug_values, hash_pointer(f), res);
|
||||||
|
f->llvm_metadata = res;
|
||||||
|
}
|
||||||
|
|
||||||
|
m->debug_compile_unit = LLVMDIBuilderCreateCompileUnit(m->debug_builder, LLVMDWARFSourceLanguageC,
|
||||||
|
cast(LLVMMetadataRef)m->info->files.entries[0].value->llvm_metadata,
|
||||||
|
"odin", 4,
|
||||||
|
false, "", 0,
|
||||||
|
1, "", 0,
|
||||||
|
LLVMDWARFEmissionFull, 0, true,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
isize global_variable_max_count = 0;
|
isize global_variable_max_count = 0;
|
||||||
Entity *entry_point = info->entry_point;
|
Entity *entry_point = info->entry_point;
|
||||||
@@ -7507,9 +7568,6 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
case Entity_Procedure:
|
case Entity_Procedure:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (e->token.string == "RtlFillMemory") {
|
|
||||||
gb_printf_err("%.*s\n", LIT(e->token.string));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool polymorphic_struct = false;
|
bool polymorphic_struct = false;
|
||||||
if (e->type != nullptr && e->kind == Entity_TypeName) {
|
if (e->type != nullptr && e->kind == Entity_TypeName) {
|
||||||
@@ -7533,14 +7591,6 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
break;
|
break;
|
||||||
case Entity_Procedure:
|
case Entity_Procedure:
|
||||||
{
|
{
|
||||||
|
|
||||||
if (e->pkg->name == "demo") {
|
|
||||||
// } else if (e->pkg->name == "runtime") {
|
|
||||||
// } else if (e->pkg->name == "os") {
|
|
||||||
} else {
|
|
||||||
// continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
lbProcedure *p = lb_create_procedure(m, e);
|
lbProcedure *p = lb_create_procedure(m, e);
|
||||||
array_add(&m->procedures_to_generate, p);
|
array_add(&m->procedures_to_generate, p);
|
||||||
}
|
}
|
||||||
@@ -7558,38 +7608,157 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
lb_end_procedure(p);
|
lb_end_procedure(p);
|
||||||
|
|
||||||
if (LLVMVerifyFunction(p->value, LLVMReturnStatusAction)) {
|
if (LLVMVerifyFunction(p->value, LLVMReturnStatusAction)) {
|
||||||
gb_printf_err("FAILED FOR: %.*s\n", LIT(p->name));
|
gb_printf_err("LLVM CODE GEN FAILED FOR PROCEDURE: %.*s\n", LIT(p->name));
|
||||||
LLVMDumpValue(p->value);
|
LLVMDumpValue(p->value);
|
||||||
gb_printf_err("\n\n\n\n");
|
gb_printf_err("\n\n\n\n");
|
||||||
LLVMVerifyFunction(p->value, LLVMAbortProcessAction);
|
LLVMVerifyFunction(p->value, LLVMAbortProcessAction);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
LLVMPassRegistryRef pass_registry = LLVMGetGlobalPassRegistry();
|
||||||
|
LLVMPassManagerRef function_pass_manager = LLVMCreateFunctionPassManagerForModule(mod);
|
||||||
|
defer (LLVMDisposePassManager(function_pass_manager));
|
||||||
|
|
||||||
|
LLVMAddPromoteMemoryToRegisterPass(function_pass_manager);
|
||||||
|
LLVMAddMergedLoadStoreMotionPass(function_pass_manager);
|
||||||
|
LLVMAddAggressiveInstCombinerPass(function_pass_manager);
|
||||||
|
LLVMAddConstantPropagationPass(function_pass_manager);
|
||||||
|
LLVMAddAggressiveDCEPass(function_pass_manager);
|
||||||
|
LLVMAddDeadStoreEliminationPass(function_pass_manager);
|
||||||
|
LLVMAddLoopIdiomPass(function_pass_manager);
|
||||||
|
LLVMAddPromoteMemoryToRegisterPass(function_pass_manager);
|
||||||
|
// LLVMAddUnifyFunctionExitNodesPass(function_pass_manager);
|
||||||
|
|
||||||
|
for_array(i, m->procedures_to_generate) {
|
||||||
|
lbProcedure *p = m->procedures_to_generate[i];
|
||||||
|
if (p->body != nullptr) { // Build Procedure
|
||||||
|
LLVMRunFunctionPassManager(function_pass_manager, p->value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LLVMPassManagerRef module_pass_manager = LLVMCreatePassManager();
|
||||||
|
defer (LLVMDisposePassManager(module_pass_manager));
|
||||||
|
LLVMAddAlwaysInlinerPass(module_pass_manager);
|
||||||
|
LLVMAddStripDeadPrototypesPass(module_pass_manager);
|
||||||
|
|
||||||
|
LLVMPassManagerBuilderRef pass_manager_builder = LLVMPassManagerBuilderCreate();
|
||||||
|
defer (LLVMPassManagerBuilderDispose(pass_manager_builder));
|
||||||
|
LLVMPassManagerBuilderSetOptLevel(pass_manager_builder, 0);
|
||||||
|
LLVMPassManagerBuilderSetSizeLevel(pass_manager_builder, 0);
|
||||||
|
|
||||||
|
LLVMPassManagerBuilderPopulateLTOPassManager(pass_manager_builder, module_pass_manager, false, false);
|
||||||
|
LLVMRunPassManager(module_pass_manager, mod);
|
||||||
|
gb_printf_err("Done\n");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (!(build_context.is_dll && !has_dll_main)) {
|
||||||
|
LLVMContextRef ctx = LLVMGetModuleContext(mod);
|
||||||
|
|
||||||
|
LLVMTypeRef llvm_i32 = LLVMInt32TypeInContext(ctx);
|
||||||
|
|
||||||
|
LLVMTypeRef ptr_cstr = LLVMPointerType(LLVMPointerType(LLVMInt8TypeInContext(ctx), 0), 0);
|
||||||
|
LLVMTypeRef params[2] = {llvm_i32, ptr_cstr};
|
||||||
|
LLVMTypeRef func_type = LLVMFunctionType(llvm_i32, params, gb_count_of(params), false);
|
||||||
|
|
||||||
|
LLVMValueRef fn = LLVMAddFunction(mod, "main", func_type);
|
||||||
|
|
||||||
|
LLVMBuilderRef builder = LLVMCreateBuilder();
|
||||||
|
LLVMBasicBlockRef block = LLVMAppendBasicBlockInContext(ctx, fn, "entry");
|
||||||
|
LLVMPositionBuilderAtEnd(builder, block);
|
||||||
|
|
||||||
|
// for_array(i, global_variables) {
|
||||||
|
// auto *var = &global_variables[i];
|
||||||
|
// if (var->decl->init_expr != nullptr) {
|
||||||
|
// var->init = ir_build_expr(proc, var->decl->init_expr);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Entity *e = var->var->Global.entity;
|
||||||
|
// GB_ASSERT(e->kind == Entity_Variable);
|
||||||
|
|
||||||
|
// if (e->Variable.is_foreign) {
|
||||||
|
// Entity *fl = e->Procedure.foreign_library;
|
||||||
|
// ir_add_foreign_library_path(m, fl);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (e->flags & EntityFlag_Static) {
|
||||||
|
// var->var->Global.is_internal = true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (var->init != nullptr) {
|
||||||
|
// Type *t = type_deref(ir_type(var->var));
|
||||||
|
|
||||||
|
// if (is_type_any(t)) {
|
||||||
|
// // NOTE(bill): Edge case for 'any' type
|
||||||
|
// Type *var_type = default_type(ir_type(var->init));
|
||||||
|
// irValue *g = ir_add_global_generated(proc->module, var_type, var->init);
|
||||||
|
// ir_emit_store(proc, g, var->init);
|
||||||
|
|
||||||
|
// irValue *data = ir_emit_struct_ep(proc, var->var, 0);
|
||||||
|
// irValue *ti = ir_emit_struct_ep(proc, var->var, 1);
|
||||||
|
// ir_emit_store(proc, data, ir_emit_conv(proc, g, t_rawptr));
|
||||||
|
// ir_emit_store(proc, ti, ir_type_info(proc, var_type));
|
||||||
|
// } else {
|
||||||
|
// ir_emit_store(proc, var->var, ir_emit_conv(proc, var->init, t));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
lbValue *found = map_get(&m->values, hash_entity(entry_point));
|
||||||
|
GB_ASSERT(found != nullptr);
|
||||||
|
|
||||||
|
LLVMBuildCall2(builder, LLVMGetElementType(lb_type(m, found->type)), found->value, nullptr, 0, "");
|
||||||
|
LLVMBuildRet(builder, LLVMConstInt(llvm_i32, 0, false));
|
||||||
|
|
||||||
|
LLVMDisposeBuilder(builder);
|
||||||
|
|
||||||
|
if (LLVMVerifyFunction(fn, LLVMReturnStatusAction)) {
|
||||||
|
gb_printf_err("LLVM CODE GEN FAILED FOR PROCEDURE: %s\n", "main");
|
||||||
|
LLVMDumpValue(fn);
|
||||||
|
gb_printf_err("\n\n\n\n");
|
||||||
|
LLVMVerifyFunction(fn, LLVMAbortProcessAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
LLVMRunFunctionPassManager(function_pass_manager, fn);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
char *llvm_error = nullptr;
|
char *llvm_error = nullptr;
|
||||||
defer (LLVMDisposeMessage(llvm_error));
|
defer (LLVMDisposeMessage(llvm_error));
|
||||||
|
|
||||||
|
|
||||||
LLVMDumpModule(mod);
|
LLVMDIBuilderFinalize(m->debug_builder);
|
||||||
// LLVMVerifyModule(mod, LLVMAbortProcessAction, &llvm_error);
|
LLVMVerifyModule(mod, LLVMAbortProcessAction, &llvm_error);
|
||||||
|
llvm_error = nullptr;
|
||||||
|
LLVMBool failure = LLVMPrintModuleToFile(mod, "llvm_demo.ll", &llvm_error);
|
||||||
|
|
||||||
|
|
||||||
|
LLVMInitializeAllTargetInfos();
|
||||||
|
LLVMInitializeAllTargets();
|
||||||
|
LLVMInitializeAllTargetMCs();
|
||||||
|
LLVMInitializeAllAsmPrinters();
|
||||||
|
LLVMInitializeAllAsmParsers();
|
||||||
|
LLVMInitializeAllDisassemblers();
|
||||||
|
LLVMInitializeNativeTarget();
|
||||||
|
|
||||||
|
char const *target_triple = "x86_64-pc-windows-msvc";
|
||||||
|
char const *target_data_layout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128";
|
||||||
|
LLVMSetTarget(mod, target_triple);
|
||||||
|
|
||||||
// char const *target_triple = "x86_64-pc-windows-msvc";
|
LLVMTargetRef target = {};
|
||||||
// char const *target_data_layout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128";
|
LLVMGetTargetFromTriple(target_triple, &target, &llvm_error);
|
||||||
// LLVMSetTarget(mod, target_triple);
|
GB_ASSERT(target != nullptr);
|
||||||
|
|
||||||
// LLVMTargetRef target = {};
|
LLVMTargetMachineRef target_machine = LLVMCreateTargetMachine(target, target_triple, "generic", "", LLVMCodeGenLevelNone, LLVMRelocDefault, LLVMCodeModelDefault);
|
||||||
// LLVMGetTargetFromTriple(target_triple, &target, &llvm_error);
|
defer (LLVMDisposeTargetMachine(target_machine));
|
||||||
// GB_ASSERT(target != nullptr);
|
|
||||||
|
|
||||||
// LLVMTargetMachineRef target_machine = LLVMCreateTargetMachine(target, target_triple, "generic", "", LLVMCodeGenLevelNone, LLVMRelocDefault, LLVMCodeModelDefault);
|
LLVMBool ok = LLVMTargetMachineEmitToFile(target_machine, mod, "llvm_demo.obj", LLVMObjectFile, &llvm_error);
|
||||||
// defer (LLVMDisposeTargetMachine(target_machine));
|
if (ok) {
|
||||||
|
gb_printf_err("LLVM Error: %s\n", llvm_error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
gb_printf_err(".obj generated\n");
|
||||||
|
|
||||||
// LLVMBool ok = LLVMTargetMachineEmitToFile(target_machine, mod, "llvm_demo.obj", LLVMObjectFile, &llvm_error);
|
|
||||||
// if (ok) {
|
|
||||||
// gb_printf_err("LLVM Error: %s\n", llvm_error);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,14 @@
|
|||||||
#include "llvm-c/Analysis.h"
|
#include "llvm-c/Analysis.h"
|
||||||
#include "llvm-c/Object.h"
|
#include "llvm-c/Object.h"
|
||||||
#include "llvm-c/BitWriter.h"
|
#include "llvm-c/BitWriter.h"
|
||||||
|
#include "llvm-c/DebugInfo.h"
|
||||||
#include "llvm-c/Transforms/AggressiveInstCombine.h"
|
#include "llvm-c/Transforms/AggressiveInstCombine.h"
|
||||||
#include "llvm-c/Transforms/InstCombine.h"
|
#include "llvm-c/Transforms/InstCombine.h"
|
||||||
#include "llvm-c/Transforms/IPO.h"
|
#include "llvm-c/Transforms/IPO.h"
|
||||||
|
#include "llvm-c/Transforms/PassManagerBuilder.h"
|
||||||
|
#include "llvm-c/Transforms/Scalar.h"
|
||||||
|
#include "llvm-c/Transforms/Utils.h"
|
||||||
|
#include "llvm-c/Transforms/Vectorize.h"
|
||||||
|
|
||||||
struct lbProcedure;
|
struct lbProcedure;
|
||||||
|
|
||||||
@@ -49,6 +54,7 @@ struct lbAddr {
|
|||||||
struct lbModule {
|
struct lbModule {
|
||||||
LLVMModuleRef mod;
|
LLVMModuleRef mod;
|
||||||
LLVMContextRef ctx;
|
LLVMContextRef ctx;
|
||||||
|
|
||||||
CheckerInfo *info;
|
CheckerInfo *info;
|
||||||
|
|
||||||
gbMutex mutex;
|
gbMutex mutex;
|
||||||
@@ -70,6 +76,11 @@ struct lbModule {
|
|||||||
u32 global_generated_index;
|
u32 global_generated_index;
|
||||||
|
|
||||||
Array<lbProcedure *> procedures_to_generate;
|
Array<lbProcedure *> procedures_to_generate;
|
||||||
|
|
||||||
|
|
||||||
|
LLVMDIBuilderRef debug_builder;
|
||||||
|
LLVMMetadataRef debug_compile_unit;
|
||||||
|
Map<LLVMMetadataRef> debug_values; // Key: Pointer
|
||||||
};
|
};
|
||||||
|
|
||||||
struct lbGenerator {
|
struct lbGenerator {
|
||||||
|
|||||||
+3
-1
@@ -98,7 +98,6 @@ struct AstFile {
|
|||||||
Array<Ast *> imports; // 'import' 'using import'
|
Array<Ast *> imports; // 'import' 'using import'
|
||||||
isize directive_count;
|
isize directive_count;
|
||||||
|
|
||||||
|
|
||||||
Ast * curr_proc;
|
Ast * curr_proc;
|
||||||
isize error_count;
|
isize error_count;
|
||||||
|
|
||||||
@@ -111,6 +110,9 @@ struct AstFile {
|
|||||||
#define PARSER_MAX_FIX_COUNT 6
|
#define PARSER_MAX_FIX_COUNT 6
|
||||||
isize fix_count;
|
isize fix_count;
|
||||||
TokenPos fix_prev_pos;
|
TokenPos fix_prev_pos;
|
||||||
|
|
||||||
|
struct LLVMOpaqueMetadata *llvm_metadata;
|
||||||
|
struct LLVMOpaqueMetadata *llvm_metadata_scope;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user