|
@@ -3127,6 +3127,18 @@ gb_internal DECL_ATTRIBUTE_PROC(foreign_block_decl_attribute) {
|
|
|
error(elem, "Expected a string value for '%.*s'", LIT(name));
|
|
|
}
|
|
|
return true;
|
|
|
+ } else if (name == "link_suffix") {
|
|
|
+ if (ev.kind == ExactValue_String) {
|
|
|
+ String link_suffix = ev.value_string;
|
|
|
+ if (!is_foreign_name_valid(link_suffix)) {
|
|
|
+ error(elem, "Invalid link suffix: '%.*s'", LIT(link_suffix));
|
|
|
+ } else {
|
|
|
+ c->foreign_context.link_suffix = link_suffix;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ error(elem, "Expected a string value for '%.*s'", LIT(name));
|
|
|
+ }
|
|
|
+ return true;
|
|
|
} else if (name == "private") {
|
|
|
EntityVisiblityKind kind = EntityVisiblity_PrivateToPackage;
|
|
|
if (ev.kind == ExactValue_Invalid) {
|
|
@@ -3421,6 +3433,18 @@ gb_internal DECL_ATTRIBUTE_PROC(proc_decl_attribute) {
|
|
|
error(elem, "Expected a string value for '%.*s'", LIT(name));
|
|
|
}
|
|
|
return true;
|
|
|
+ } else if (name == "link_suffix") {
|
|
|
+ ExactValue ev = check_decl_attribute_value(c, value);
|
|
|
+
|
|
|
+ if (ev.kind == ExactValue_String) {
|
|
|
+ ac->link_suffix = ev.value_string;
|
|
|
+ if (!is_foreign_name_valid(ac->link_suffix)) {
|
|
|
+ error(elem, "Invalid link suffix: %.*s", LIT(ac->link_suffix));
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ error(elem, "Expected a string value for '%.*s'", LIT(name));
|
|
|
+ }
|
|
|
+ return true;
|
|
|
} else if (name == "deprecated") {
|
|
|
ExactValue ev = check_decl_attribute_value(c, value);
|
|
|
|
|
@@ -3702,6 +3726,17 @@ gb_internal DECL_ATTRIBUTE_PROC(var_decl_attribute) {
|
|
|
error(elem, "Expected a string value for '%.*s'", LIT(name));
|
|
|
}
|
|
|
return true;
|
|
|
+ } else if (name == "link_suffix") {
|
|
|
+ ExactValue ev = check_decl_attribute_value(c, value);
|
|
|
+ if (ev.kind == ExactValue_String) {
|
|
|
+ ac->link_suffix = ev.value_string;
|
|
|
+ if (!is_foreign_name_valid(ac->link_suffix)) {
|
|
|
+ error(elem, "Invalid link suffix: %.*s", LIT(ac->link_suffix));
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ error(elem, "Expected a string value for '%.*s'", LIT(name));
|
|
|
+ }
|
|
|
+ return true;
|
|
|
} else if (name == "link_section") {
|
|
|
ExactValue ev = check_decl_attribute_value(c, value);
|
|
|
if (ev.kind == ExactValue_String) {
|
|
@@ -3733,6 +3768,7 @@ gb_internal DECL_ATTRIBUTE_PROC(const_decl_attribute) {
|
|
|
name == "linkage" ||
|
|
|
name == "link_name" ||
|
|
|
name == "link_prefix" ||
|
|
|
+ name == "link_suffix" ||
|
|
|
false) {
|
|
|
error(elem, "@(%.*s) is not supported for compile time constant value declarations", LIT(name));
|
|
|
return true;
|
|
@@ -3775,8 +3811,10 @@ gb_internal void check_decl_attributes(CheckerContext *c, Array<Ast *> const &at
|
|
|
if (attributes.count == 0) return;
|
|
|
|
|
|
String original_link_prefix = {};
|
|
|
+ String original_link_suffix = {};
|
|
|
if (ac) {
|
|
|
original_link_prefix = ac->link_prefix;
|
|
|
+ original_link_suffix = ac->link_suffix;
|
|
|
}
|
|
|
|
|
|
StringSet set = {};
|
|
@@ -3851,6 +3889,12 @@ gb_internal void check_decl_attributes(CheckerContext *c, Array<Ast *> const &at
|
|
|
ac->link_prefix.len = 0;
|
|
|
}
|
|
|
}
|
|
|
+ if (ac->link_suffix.text == original_link_suffix.text) {
|
|
|
+ if (ac->link_name.len > 0) {
|
|
|
+ ac->link_suffix.text = nullptr;
|
|
|
+ ac->link_suffix.len = 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -4145,6 +4189,7 @@ gb_internal void check_collect_value_decl(CheckerContext *c, Ast *decl) {
|
|
|
e->Variable.foreign_library_ident = fl;
|
|
|
|
|
|
e->Variable.link_prefix = c->foreign_context.link_prefix;
|
|
|
+ e->Variable.link_suffix = c->foreign_context.link_suffix;
|
|
|
}
|
|
|
|
|
|
Ast *init_expr = value;
|
|
@@ -4219,6 +4264,7 @@ gb_internal void check_collect_value_decl(CheckerContext *c, Ast *decl) {
|
|
|
}
|
|
|
}
|
|
|
e->Procedure.link_prefix = c->foreign_context.link_prefix;
|
|
|
+ e->Procedure.link_suffix = c->foreign_context.link_suffix;
|
|
|
|
|
|
GB_ASSERT(cc != ProcCC_Invalid);
|
|
|
pl->type->ProcType.calling_convention = cc;
|