mirror of
https://github.com/odin-lang/Odin.git
synced 2026-07-12 02:49:31 +00:00
Merge branch 'master' into windows-llvm-13.0.0
This commit is contained in:
@@ -4447,6 +4447,14 @@ gb_internal DECL_ATTRIBUTE_PROC(foreign_import_decl_attribute) {
|
||||
ac->foreign_import_priority_index = exact_value_to_i64(ev);
|
||||
}
|
||||
return true;
|
||||
} else if (name == "extra_linker_flags") {
|
||||
ExactValue ev = check_decl_attribute_value(c, value);
|
||||
if (ev.kind != ExactValue_String) {
|
||||
error(elem, "Expected a string value for '%.*s'", LIT(name));
|
||||
} else {
|
||||
ac->extra_linker_flags = ev.value_string;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -4506,6 +4514,10 @@ gb_internal void check_add_foreign_import_decl(CheckerContext *ctx, Ast *decl) {
|
||||
if (ac.foreign_import_priority_index != 0) {
|
||||
e->LibraryName.priority_index = ac.foreign_import_priority_index;
|
||||
}
|
||||
String extra_linker_flags = string_trim_whitespace(ac.extra_linker_flags);
|
||||
if (extra_linker_flags.len != 0) {
|
||||
e->LibraryName.extra_linker_flags = extra_linker_flags;
|
||||
}
|
||||
|
||||
if (has_asm_extension(fullpath)) {
|
||||
if (build_context.metrics.arch != TargetArch_amd64 ||
|
||||
|
||||
@@ -121,6 +121,7 @@ struct AttributeContext {
|
||||
bool set_cold : 1;
|
||||
u32 optimization_mode; // ProcedureOptimizationMode
|
||||
i64 foreign_import_priority_index;
|
||||
String extra_linker_flags;
|
||||
|
||||
String objc_class;
|
||||
String objc_name;
|
||||
|
||||
@@ -915,18 +915,20 @@ gb_internal void odin_doc_update_entities(OdinDocWriter *w) {
|
||||
auto entities = array_make<Entity *>(heap_allocator(), 0, w->entity_cache.count);
|
||||
defer (array_free(&entities));
|
||||
|
||||
for (auto const &entry : w->entity_cache) {
|
||||
array_add(&entities, entry.key);
|
||||
for (u32 i = 0; i < w->entity_cache.count; i++) {
|
||||
Entity *e = w->entity_cache.entries[i].key;
|
||||
array_add(&entities, e);
|
||||
}
|
||||
for (Entity *e : entities) {
|
||||
GB_ASSERT(e != nullptr);
|
||||
OdinDocTypeIndex type_index = odin_doc_type(w, e->type);
|
||||
gb_unused(type_index);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto const &entry : w->entity_cache) {
|
||||
Entity *e = entry.key;
|
||||
OdinDocEntityIndex entity_index = entry.value;
|
||||
for (u32 i = 0; i < w->entity_cache.count; i++) {
|
||||
Entity *e = w->entity_cache.entries[i].key;
|
||||
OdinDocEntityIndex entity_index = w->entity_cache.entries[i].value;
|
||||
OdinDocTypeIndex type_index = odin_doc_type(w, e->type);
|
||||
|
||||
OdinDocEntityIndex foreign_library = 0;
|
||||
|
||||
@@ -259,6 +259,7 @@ struct Entity {
|
||||
Slice<String> paths;
|
||||
String name;
|
||||
i64 priority_index;
|
||||
String extra_linker_flags;
|
||||
} LibraryName;
|
||||
i32 Nil;
|
||||
struct {
|
||||
|
||||
143
src/llvm_abi.cpp
143
src/llvm_abi.cpp
@@ -563,7 +563,7 @@ namespace lbAbiAmd64SysV {
|
||||
gb_internal void fixup(LLVMTypeRef t, Array<RegClass> *cls);
|
||||
gb_internal lbArgType amd64_type(LLVMContextRef c, LLVMTypeRef type, Amd64TypeAttributeKind attribute_kind, ProcCallingConvention calling_convention);
|
||||
gb_internal Array<RegClass> classify(LLVMTypeRef t);
|
||||
gb_internal LLVMTypeRef llreg(LLVMContextRef c, Array<RegClass> const ®_classes);
|
||||
gb_internal LLVMTypeRef llreg(LLVMContextRef c, Array<RegClass> const ®_classes, LLVMTypeRef type);
|
||||
|
||||
gb_internal LB_ABI_INFO(abi_info) {
|
||||
lbFunctionType *ft = gb_alloc_item(permanent_allocator(), lbFunctionType);
|
||||
@@ -662,7 +662,7 @@ namespace lbAbiAmd64SysV {
|
||||
// the ABI rules for SysV
|
||||
reg_type = type;
|
||||
} else {
|
||||
reg_type = llreg(c, cls);
|
||||
reg_type = llreg(c, cls, type);
|
||||
}
|
||||
return lb_arg_type_direct(type, reg_type, nullptr, nullptr);
|
||||
}
|
||||
@@ -785,67 +785,92 @@ namespace lbAbiAmd64SysV {
|
||||
}
|
||||
|
||||
|
||||
gb_internal LLVMTypeRef llreg(LLVMContextRef c, Array<RegClass> const ®_classes) {
|
||||
gb_internal LLVMTypeRef llreg(LLVMContextRef c, Array<RegClass> const ®_classes, LLVMTypeRef type) {
|
||||
auto types = array_make<LLVMTypeRef>(heap_allocator(), 0, reg_classes.count);
|
||||
for (isize i = 0; i < reg_classes.count; /**/) {
|
||||
RegClass reg_class = reg_classes[i];
|
||||
switch (reg_class) {
|
||||
case RegClass_Int:
|
||||
array_add(&types, LLVMIntTypeInContext(c, 64));
|
||||
break;
|
||||
case RegClass_SSEFv:
|
||||
case RegClass_SSEDv:
|
||||
case RegClass_SSEInt8:
|
||||
case RegClass_SSEInt16:
|
||||
case RegClass_SSEInt32:
|
||||
case RegClass_SSEInt64:
|
||||
{
|
||||
unsigned elems_per_word = 0;
|
||||
LLVMTypeRef elem_type = nullptr;
|
||||
switch (reg_class) {
|
||||
case RegClass_SSEFv:
|
||||
elems_per_word = 2;
|
||||
elem_type = LLVMFloatTypeInContext(c);
|
||||
break;
|
||||
case RegClass_SSEDv:
|
||||
elems_per_word = 1;
|
||||
elem_type = LLVMDoubleTypeInContext(c);
|
||||
break;
|
||||
case RegClass_SSEInt8:
|
||||
elems_per_word = 64/8;
|
||||
elem_type = LLVMIntTypeInContext(c, 8);
|
||||
break;
|
||||
case RegClass_SSEInt16:
|
||||
elems_per_word = 64/16;
|
||||
elem_type = LLVMIntTypeInContext(c, 16);
|
||||
break;
|
||||
case RegClass_SSEInt32:
|
||||
elems_per_word = 64/32;
|
||||
elem_type = LLVMIntTypeInContext(c, 32);
|
||||
break;
|
||||
case RegClass_SSEInt64:
|
||||
elems_per_word = 64/64;
|
||||
elem_type = LLVMIntTypeInContext(c, 64);
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned vec_len = llvec_len(reg_classes, i+1);
|
||||
LLVMTypeRef vec_type = LLVMVectorType(elem_type, vec_len * elems_per_word);
|
||||
array_add(&types, vec_type);
|
||||
i += vec_len;
|
||||
continue;
|
||||
}
|
||||
bool all_ints = true;
|
||||
for (RegClass reg_class : reg_classes) {
|
||||
if (reg_class != RegClass_Int) {
|
||||
all_ints = false;
|
||||
break;
|
||||
case RegClass_SSEFs:
|
||||
array_add(&types, LLVMFloatTypeInContext(c));
|
||||
break;
|
||||
case RegClass_SSEDs:
|
||||
array_add(&types, LLVMDoubleTypeInContext(c));
|
||||
break;
|
||||
default:
|
||||
GB_PANIC("Unhandled RegClass");
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
if (all_ints) {
|
||||
i64 sz = lb_sizeof(type);
|
||||
for_array(i, reg_classes) {
|
||||
GB_ASSERT(sz != 0);
|
||||
// TODO(bill): is this even correct? BECAUSE LLVM DOES NOT DOCUMENT ANY OF THIS!!!
|
||||
if (sz >= 8) {
|
||||
array_add(&types, LLVMIntTypeInContext(c, 64));
|
||||
sz -= 8;
|
||||
} else {
|
||||
array_add(&types, LLVMIntTypeInContext(c, cast(unsigned)(sz*8)));
|
||||
sz = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (isize i = 0; i < reg_classes.count; /**/) {
|
||||
RegClass reg_class = reg_classes[i];
|
||||
switch (reg_class) {
|
||||
case RegClass_Int:
|
||||
// TODO(bill): is this even correct? BECAUSE LLVM DOES NOT DOCUMENT ANY OF THIS!!!
|
||||
array_add(&types, LLVMIntTypeInContext(c, 64));
|
||||
break;
|
||||
case RegClass_SSEFv:
|
||||
case RegClass_SSEDv:
|
||||
case RegClass_SSEInt8:
|
||||
case RegClass_SSEInt16:
|
||||
case RegClass_SSEInt32:
|
||||
case RegClass_SSEInt64:
|
||||
{
|
||||
unsigned elems_per_word = 0;
|
||||
LLVMTypeRef elem_type = nullptr;
|
||||
switch (reg_class) {
|
||||
case RegClass_SSEFv:
|
||||
elems_per_word = 2;
|
||||
elem_type = LLVMFloatTypeInContext(c);
|
||||
break;
|
||||
case RegClass_SSEDv:
|
||||
elems_per_word = 1;
|
||||
elem_type = LLVMDoubleTypeInContext(c);
|
||||
break;
|
||||
case RegClass_SSEInt8:
|
||||
elems_per_word = 64/8;
|
||||
elem_type = LLVMIntTypeInContext(c, 8);
|
||||
break;
|
||||
case RegClass_SSEInt16:
|
||||
elems_per_word = 64/16;
|
||||
elem_type = LLVMIntTypeInContext(c, 16);
|
||||
break;
|
||||
case RegClass_SSEInt32:
|
||||
elems_per_word = 64/32;
|
||||
elem_type = LLVMIntTypeInContext(c, 32);
|
||||
break;
|
||||
case RegClass_SSEInt64:
|
||||
elems_per_word = 64/64;
|
||||
elem_type = LLVMIntTypeInContext(c, 64);
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned vec_len = llvec_len(reg_classes, i+1);
|
||||
LLVMTypeRef vec_type = LLVMVectorType(elem_type, vec_len * elems_per_word);
|
||||
array_add(&types, vec_type);
|
||||
i += vec_len;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case RegClass_SSEFs:
|
||||
array_add(&types, LLVMFloatTypeInContext(c));
|
||||
break;
|
||||
case RegClass_SSEDs:
|
||||
array_add(&types, LLVMDoubleTypeInContext(c));
|
||||
break;
|
||||
default:
|
||||
GB_PANIC("Unhandled RegClass");
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (types.count == 1) {
|
||||
|
||||
19
src/main.cpp
19
src/main.cpp
@@ -278,6 +278,13 @@ gb_internal i32 linker_stage(lbGenerator *gen) {
|
||||
}
|
||||
}
|
||||
|
||||
for (Entity *e : gen->foreign_libraries) {
|
||||
GB_ASSERT(e->kind == Entity_LibraryName);
|
||||
if (e->LibraryName.extra_linker_flags.len != 0) {
|
||||
lib_str = gb_string_append_fmt(lib_str, " %.*s", LIT(e->LibraryName.extra_linker_flags));
|
||||
}
|
||||
}
|
||||
|
||||
if (build_context.build_mode == BuildMode_DynamicLibrary) {
|
||||
link_settings = gb_string_append_fmt(link_settings, " /DLL");
|
||||
} else {
|
||||
@@ -449,6 +456,12 @@ gb_internal i32 linker_stage(lbGenerator *gen) {
|
||||
}
|
||||
}
|
||||
|
||||
for (Entity *e : gen->foreign_libraries) {
|
||||
GB_ASSERT(e->kind == Entity_LibraryName);
|
||||
if (e->LibraryName.extra_linker_flags.len != 0) {
|
||||
lib_str = gb_string_append_fmt(lib_str, " %.*s", LIT(e->LibraryName.extra_linker_flags));
|
||||
}
|
||||
}
|
||||
|
||||
gbString object_files = gb_string_make(heap_allocator(), "");
|
||||
defer (gb_string_free(object_files));
|
||||
@@ -581,13 +594,13 @@ gb_internal Array<String> setup_args(int argc, char const **argv) {
|
||||
|
||||
gb_internal void print_usage_line(i32 indent, char const *fmt, ...) {
|
||||
while (indent --> 0) {
|
||||
gb_printf_err("\t");
|
||||
gb_printf("\t");
|
||||
}
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
gb_printf_err_va(fmt, va);
|
||||
gb_printf_va(fmt, va);
|
||||
va_end(va);
|
||||
gb_printf_err("\n");
|
||||
gb_printf("\n");
|
||||
}
|
||||
|
||||
gb_internal void usage(String argv0) {
|
||||
|
||||
@@ -1411,7 +1411,7 @@ gb_internal Token expect_operator(AstFile *f) {
|
||||
LIT(p));
|
||||
}
|
||||
if (f->curr_token.kind == Token_Ellipsis) {
|
||||
syntax_warning(f->curr_token, "'..' for ranges has now be deprecated, prefer '..='");
|
||||
syntax_warning(f->curr_token, "'..' for ranges has now been deprecated, prefer '..='");
|
||||
f->tokens[f->curr_token_index].flags |= TokenFlag_Replace;
|
||||
}
|
||||
|
||||
@@ -1434,7 +1434,7 @@ gb_internal Token expect_closing_brace_of_field_list(AstFile *f) {
|
||||
return token;
|
||||
}
|
||||
bool ok = true;
|
||||
if (!f->allow_newline) {
|
||||
if (f->allow_newline) {
|
||||
ok = !skip_possible_newline(f);
|
||||
}
|
||||
if (ok && allow_token(f, Token_Semicolon)) {
|
||||
@@ -3191,6 +3191,15 @@ gb_internal Ast *parse_foreign_block(AstFile *f, Token token) {
|
||||
return decl;
|
||||
}
|
||||
|
||||
gb_internal void print_comment_group(CommentGroup *group) {
|
||||
if (group) {
|
||||
for (Token const &token : group->list) {
|
||||
gb_printf_err("%.*s\n", LIT(token.string));
|
||||
}
|
||||
gb_printf_err("\n");
|
||||
}
|
||||
}
|
||||
|
||||
gb_internal Ast *parse_value_decl(AstFile *f, Array<Ast *> names, CommentGroup *docs) {
|
||||
bool is_mutable = true;
|
||||
|
||||
@@ -3232,6 +3241,8 @@ gb_internal Ast *parse_value_decl(AstFile *f, Array<Ast *> names, CommentGroup *
|
||||
values.allocator = heap_allocator();
|
||||
}
|
||||
|
||||
CommentGroup *end_comment = f->lead_comment;
|
||||
|
||||
if (f->expr_level >= 0) {
|
||||
if (f->curr_token.kind == Token_CloseBrace &&
|
||||
f->curr_token.pos.line == f->prev_token.pos.line) {
|
||||
@@ -3252,7 +3263,7 @@ gb_internal Ast *parse_value_decl(AstFile *f, Array<Ast *> names, CommentGroup *
|
||||
}
|
||||
}
|
||||
|
||||
return ast_value_decl(f, names, type, values, is_mutable, docs, f->line_comment);
|
||||
return ast_value_decl(f, names, type, values, is_mutable, docs, end_comment);
|
||||
}
|
||||
|
||||
gb_internal Ast *parse_simple_stmt(AstFile *f, u32 flags) {
|
||||
@@ -3682,9 +3693,11 @@ gb_internal bool allow_field_separator(AstFile *f) {
|
||||
if (allow_token(f, Token_Comma)) {
|
||||
return true;
|
||||
}
|
||||
if (ALLOW_NEWLINE && token.kind == Token_Semicolon && !token_is_newline(token)) {
|
||||
String p = token_to_string(token);
|
||||
syntax_error(token_end_of_line(f, f->prev_token), "Expected a comma, got a %.*s", LIT(p));
|
||||
if (ALLOW_NEWLINE && token.kind == Token_Semicolon) {
|
||||
if (!token_is_newline(token)) {
|
||||
String p = token_to_string(token);
|
||||
syntax_error(token_end_of_line(f, f->prev_token), "Expected a comma, got a %.*s", LIT(p));
|
||||
}
|
||||
advance_token(f);
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user