mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-07 16:18:52 +00:00
Modify ABI for the Odin calling conventions on SysV slightly
This commit is contained in:
+14
-30
@@ -11,6 +11,8 @@ struct lbArgType {
|
|||||||
LLVMTypeRef pad_type; // Optional
|
LLVMTypeRef pad_type; // Optional
|
||||||
LLVMAttributeRef attribute; // Optional
|
LLVMAttributeRef attribute; // Optional
|
||||||
LLVMAttributeRef align_attribute; // Optional
|
LLVMAttributeRef align_attribute; // Optional
|
||||||
|
i64 byval_alignment;
|
||||||
|
bool is_byval;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -18,14 +20,14 @@ i64 lb_sizeof(LLVMTypeRef type);
|
|||||||
i64 lb_alignof(LLVMTypeRef type);
|
i64 lb_alignof(LLVMTypeRef type);
|
||||||
|
|
||||||
lbArgType lb_arg_type_direct(LLVMTypeRef type, LLVMTypeRef cast_type, LLVMTypeRef pad_type, LLVMAttributeRef attr) {
|
lbArgType lb_arg_type_direct(LLVMTypeRef type, LLVMTypeRef cast_type, LLVMTypeRef pad_type, LLVMAttributeRef attr) {
|
||||||
return lbArgType{lbArg_Direct, type, cast_type, pad_type, attr, nullptr};
|
return lbArgType{lbArg_Direct, type, cast_type, pad_type, attr, nullptr, 0, false};
|
||||||
}
|
}
|
||||||
lbArgType lb_arg_type_direct(LLVMTypeRef type) {
|
lbArgType lb_arg_type_direct(LLVMTypeRef type) {
|
||||||
return lb_arg_type_direct(type, nullptr, nullptr, nullptr);
|
return lb_arg_type_direct(type, nullptr, nullptr, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
lbArgType lb_arg_type_indirect(LLVMTypeRef type, LLVMAttributeRef attr) {
|
lbArgType lb_arg_type_indirect(LLVMTypeRef type, LLVMAttributeRef attr) {
|
||||||
return lbArgType{lbArg_Indirect, type, nullptr, nullptr, attr, nullptr};
|
return lbArgType{lbArg_Indirect, type, nullptr, nullptr, attr, nullptr, 0, false};
|
||||||
}
|
}
|
||||||
|
|
||||||
lbArgType lb_arg_type_indirect_byval(LLVMContextRef c, LLVMTypeRef type) {
|
lbArgType lb_arg_type_indirect_byval(LLVMContextRef c, LLVMTypeRef type) {
|
||||||
@@ -34,11 +36,11 @@ lbArgType lb_arg_type_indirect_byval(LLVMContextRef c, LLVMTypeRef type) {
|
|||||||
|
|
||||||
LLVMAttributeRef byval_attr = lb_create_enum_attribute_with_type(c, "byval", type);
|
LLVMAttributeRef byval_attr = lb_create_enum_attribute_with_type(c, "byval", type);
|
||||||
LLVMAttributeRef align_attr = lb_create_enum_attribute(c, "align", alignment);
|
LLVMAttributeRef align_attr = lb_create_enum_attribute(c, "align", alignment);
|
||||||
return lbArgType{lbArg_Indirect, type, nullptr, nullptr, byval_attr, align_attr};
|
return lbArgType{lbArg_Indirect, type, nullptr, nullptr, byval_attr, align_attr, alignment, true};
|
||||||
}
|
}
|
||||||
|
|
||||||
lbArgType lb_arg_type_ignore(LLVMTypeRef type) {
|
lbArgType lb_arg_type_ignore(LLVMTypeRef type) {
|
||||||
return lbArgType{lbArg_Ignore, type, nullptr, nullptr, nullptr, nullptr};
|
return lbArgType{lbArg_Ignore, type, nullptr, nullptr, nullptr, nullptr, 0, false};
|
||||||
}
|
}
|
||||||
|
|
||||||
struct lbFunctionType {
|
struct lbFunctionType {
|
||||||
@@ -458,11 +460,10 @@ namespace lbAbiAmd64SysV {
|
|||||||
Amd64TypeAttribute_StructRect,
|
Amd64TypeAttribute_StructRect,
|
||||||
};
|
};
|
||||||
|
|
||||||
Array<lbArgType> compute_arg_types(LLVMContextRef c, LLVMTypeRef *arg_types, unsigned arg_count);
|
|
||||||
lbArgType compute_return_type(LLVMContextRef c, LLVMTypeRef return_type, bool return_is_defined);
|
lbArgType compute_return_type(LLVMContextRef c, LLVMTypeRef return_type, bool return_is_defined);
|
||||||
void classify_with(LLVMTypeRef t, Array<RegClass> *cls, i64 ix, i64 off);
|
void classify_with(LLVMTypeRef t, Array<RegClass> *cls, i64 ix, i64 off);
|
||||||
void fixup(LLVMTypeRef t, Array<RegClass> *cls);
|
void fixup(LLVMTypeRef t, Array<RegClass> *cls);
|
||||||
lbArgType amd64_type(LLVMContextRef c, LLVMTypeRef type, Amd64TypeAttributeKind attribute_kind);
|
lbArgType amd64_type(LLVMContextRef c, LLVMTypeRef type, Amd64TypeAttributeKind attribute_kind, ProcCallingConvention calling_convention);
|
||||||
Array<RegClass> classify(LLVMTypeRef t);
|
Array<RegClass> classify(LLVMTypeRef t);
|
||||||
LLVMTypeRef llreg(LLVMContextRef c, Array<RegClass> const ®_classes);
|
LLVMTypeRef llreg(LLVMContextRef c, Array<RegClass> const ®_classes);
|
||||||
|
|
||||||
@@ -473,11 +474,11 @@ namespace lbAbiAmd64SysV {
|
|||||||
|
|
||||||
ft->args = array_make<lbArgType>(heap_allocator(), arg_count);
|
ft->args = array_make<lbArgType>(heap_allocator(), arg_count);
|
||||||
for (unsigned i = 0; i < arg_count; i++) {
|
for (unsigned i = 0; i < arg_count; i++) {
|
||||||
ft->args[i] = amd64_type(c, arg_types[i], Amd64TypeAttribute_ByVal);
|
ft->args[i] = amd64_type(c, arg_types[i], Amd64TypeAttribute_ByVal, calling_convention);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (return_is_defined) {
|
if (return_is_defined) {
|
||||||
ft->ret = amd64_type(c, return_type, Amd64TypeAttribute_StructRect);
|
ft->ret = amd64_type(c, return_type, Amd64TypeAttribute_StructRect, calling_convention);
|
||||||
} else {
|
} else {
|
||||||
ft->ret = lb_arg_type_direct(LLVMVoidTypeInContext(c));
|
ft->ret = lb_arg_type_direct(LLVMVoidTypeInContext(c));
|
||||||
}
|
}
|
||||||
@@ -514,7 +515,7 @@ namespace lbAbiAmd64SysV {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
lbArgType amd64_type(LLVMContextRef c, LLVMTypeRef type, Amd64TypeAttributeKind attribute_kind) {
|
lbArgType amd64_type(LLVMContextRef c, LLVMTypeRef type, Amd64TypeAttributeKind attribute_kind, ProcCallingConvention calling_convention) {
|
||||||
if (is_register(type)) {
|
if (is_register(type)) {
|
||||||
LLVMAttributeRef attribute = nullptr;
|
LLVMAttributeRef attribute = nullptr;
|
||||||
if (type == LLVMInt1TypeInContext(c)) {
|
if (type == LLVMInt1TypeInContext(c)) {
|
||||||
@@ -527,7 +528,10 @@ namespace lbAbiAmd64SysV {
|
|||||||
if (is_mem_cls(cls, attribute_kind)) {
|
if (is_mem_cls(cls, attribute_kind)) {
|
||||||
LLVMAttributeRef attribute = nullptr;
|
LLVMAttributeRef attribute = nullptr;
|
||||||
if (attribute_kind == Amd64TypeAttribute_ByVal) {
|
if (attribute_kind == Amd64TypeAttribute_ByVal) {
|
||||||
return lb_arg_type_indirect_byval(c, type);
|
if (!is_calling_convention_odin(calling_convention)) {
|
||||||
|
return lb_arg_type_indirect_byval(c, type);
|
||||||
|
}
|
||||||
|
attribute = nullptr;
|
||||||
} else if (attribute_kind == Amd64TypeAttribute_StructRect) {
|
} else if (attribute_kind == Amd64TypeAttribute_StructRect) {
|
||||||
attribute = lb_create_enum_attribute_with_type(c, "sret", type);
|
attribute = lb_create_enum_attribute_with_type(c, "sret", type);
|
||||||
}
|
}
|
||||||
@@ -817,26 +821,6 @@ namespace lbAbiAmd64SysV {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Array<lbArgType> compute_arg_types(LLVMContextRef c, LLVMTypeRef *arg_types, unsigned arg_count) {
|
|
||||||
auto args = array_make<lbArgType>(heap_allocator(), arg_count);
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < arg_count; i++) {
|
|
||||||
LLVMTypeRef t = arg_types[i];
|
|
||||||
LLVMTypeKind kind = LLVMGetTypeKind(t);
|
|
||||||
if (kind == LLVMStructTypeKind) {
|
|
||||||
i64 sz = lb_sizeof(t);
|
|
||||||
if (sz == 0) {
|
|
||||||
args[i] = lb_arg_type_ignore(t);
|
|
||||||
} else {
|
|
||||||
args[i] = lb_arg_type_indirect_byval(c, t);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
args[i] = non_struct(c, t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return args;
|
|
||||||
}
|
|
||||||
|
|
||||||
lbArgType compute_return_type(LLVMContextRef c, LLVMTypeRef return_type, bool return_is_defined) {
|
lbArgType compute_return_type(LLVMContextRef c, LLVMTypeRef return_type, bool return_is_defined) {
|
||||||
if (!return_is_defined) {
|
if (!return_is_defined) {
|
||||||
return lb_arg_type_direct(LLVMVoidTypeInContext(c));
|
return lb_arg_type_direct(LLVMVoidTypeInContext(c));
|
||||||
|
|||||||
@@ -3712,11 +3712,8 @@ void lb_build_constant_value_decl(lbProcedure *p, AstValueDecl *vd) {
|
|||||||
value.type = nested_proc->type;
|
value.type = nested_proc->type;
|
||||||
|
|
||||||
array_add(&p->module->procedures_to_generate, nested_proc);
|
array_add(&p->module->procedures_to_generate, nested_proc);
|
||||||
if (p != nullptr) {
|
array_add(&p->children, nested_proc);
|
||||||
array_add(&p->children, nested_proc);
|
string_map_set(&p->module->members, name, value);
|
||||||
} else {
|
|
||||||
string_map_set(&p->module->members, name, value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8507,7 +8504,9 @@ lbValue lb_emit_call(lbProcedure *p, lbValue value, Array<lbValue> const &args,
|
|||||||
|
|
||||||
} else if (arg->kind == lbArg_Indirect) {
|
} else if (arg->kind == lbArg_Indirect) {
|
||||||
lbValue ptr = {};
|
lbValue ptr = {};
|
||||||
if (is_calling_convention_odin(pt->Proc.calling_convention)) {
|
if (arg->is_byval) {
|
||||||
|
ptr = lb_copy_value_to_ptr(p, x, original_type, arg->byval_alignment);
|
||||||
|
} else if (is_calling_convention_odin(pt->Proc.calling_convention)) {
|
||||||
// NOTE(bill): Odin parameters are immutable so the original value can be passed if possible
|
// NOTE(bill): Odin parameters are immutable so the original value can be passed if possible
|
||||||
// i.e. `T const &` in C++
|
// i.e. `T const &` in C++
|
||||||
ptr = lb_address_from_load_or_generate_local(p, x);
|
ptr = lb_address_from_load_or_generate_local(p, x);
|
||||||
|
|||||||
Reference in New Issue
Block a user