mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Fix for nolibc (eg wasm). Add multi global declarations. Simplicity wasm export / import. Prevent "extern" functions to have a function body.
This commit is contained in:
@@ -41,12 +41,13 @@ macro double! decfloat(char[] chars, int $bits, int $emin, int sign)
|
||||
int emax = - $emin - $bits + 3;
|
||||
|
||||
const int[*] P10S = { 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 };
|
||||
usz index = 0;
|
||||
usz index;
|
||||
bool got_digit = chars[0] == '0';
|
||||
bool got_rad;
|
||||
long lrp, dc;
|
||||
int k, j, lnz;
|
||||
usz len = chars.len;
|
||||
usz last_char = len - 1;
|
||||
long lrp = 0;
|
||||
|
||||
assert(len);
|
||||
|
||||
@@ -77,10 +78,6 @@ macro double! decfloat(char[] chars, int $bits, int $emin, int sign)
|
||||
}
|
||||
}
|
||||
|
||||
long dc = 0;
|
||||
int k;
|
||||
int j;
|
||||
int lnz;
|
||||
while (c - '0' < 10u || c == '.')
|
||||
{
|
||||
switch
|
||||
|
||||
@@ -250,11 +250,16 @@ fn int fseek(CFile stream, SeekIndex offset, int whence) @weak @extern("fseek")
|
||||
{
|
||||
unreachable("'fseek' not available.");
|
||||
}
|
||||
fn CFile fopen(char* filename, char* mode) @weak @extern("fopen")
|
||||
fn CFile fopen(ZString filename, ZString mode) @weak @extern("fopen")
|
||||
{
|
||||
unreachable("'fopen' not available.");
|
||||
}
|
||||
|
||||
fn CFile freopen(ZString filename, ZString mode, CFile stream) @weak @extern("fopen")
|
||||
{
|
||||
unreachable("'freopen' not available.");
|
||||
}
|
||||
|
||||
fn usz fwrite(void* ptr, usz size, usz nmemb, CFile stream) @weak @extern("fwrite")
|
||||
{
|
||||
unreachable("'fwrite' not available.");
|
||||
@@ -280,7 +285,7 @@ fn int fputc(int c, CFile stream) @weak @extern("fputc")
|
||||
unreachable("'fputc' not available.");
|
||||
}
|
||||
|
||||
fn char* fgets(char* str, int n, CFile stream) @weak @extern("fgets")
|
||||
fn char* fgets(ZString str, int n, CFile stream) @weak @extern("fgets")
|
||||
{
|
||||
unreachable("'fgets' not available.");
|
||||
}
|
||||
@@ -303,7 +308,7 @@ fn int putchar(int c) @weak @extern("putchar")
|
||||
{
|
||||
unreachable("'putchar' not available.");
|
||||
}
|
||||
fn int puts(char* str) @weak @extern("puts")
|
||||
fn int puts(ZString str) @weak @extern("puts")
|
||||
{
|
||||
unreachable("'puts' not available.");
|
||||
}
|
||||
|
||||
@@ -98,6 +98,7 @@ Decl *decl_new_with_type(const char *name, SourceSpan loc, DeclKind decl_type, V
|
||||
case DECL_FINALIZE:
|
||||
case DECL_CT_ECHO:
|
||||
case DECL_CT_INCLUDE:
|
||||
case DECL_GLOBALS:
|
||||
UNREACHABLE
|
||||
}
|
||||
Type *type = type_new(kind, name ? name : "$anon");
|
||||
@@ -175,6 +176,8 @@ const char *decl_to_a_name(Decl *decl)
|
||||
return "a static finalizer";
|
||||
case DECL_CT_INCLUDE:
|
||||
return "an include";
|
||||
case DECL_GLOBALS:
|
||||
return "globals";
|
||||
case DECL_VAR:
|
||||
switch (decl->var.kind)
|
||||
{
|
||||
|
||||
@@ -674,7 +674,6 @@ typedef struct Decl_
|
||||
bool obfuscate : 1;
|
||||
bool is_dynamic : 1;
|
||||
bool is_synthetic : 1;
|
||||
bool is_wasm_interface : 1;
|
||||
bool is_export : 1;
|
||||
OperatorOverload operator : 4;
|
||||
union
|
||||
@@ -727,6 +726,7 @@ typedef struct Decl_
|
||||
EnumConstantDecl enum_constant;
|
||||
FuncDecl func_decl;
|
||||
AttrDecl attr_decl;
|
||||
Decl** decls;
|
||||
TypedefDecl typedef_decl;
|
||||
DefineDecl define_decl;
|
||||
CtIfDecl ct_if_decl;
|
||||
|
||||
@@ -149,6 +149,7 @@ void decl_register(Decl *decl)
|
||||
case DECL_DECLARRAY:
|
||||
case DECL_BODYPARAM:
|
||||
case DECL_CT_INCLUDE:
|
||||
case DECL_GLOBALS:
|
||||
UNREACHABLE
|
||||
case DECL_ATTRIBUTE:
|
||||
case DECL_BITSTRUCT:
|
||||
@@ -260,6 +261,7 @@ void unit_register_global_decl(CompilationUnit *unit, Decl *decl)
|
||||
case DECL_CT_CASE:
|
||||
case DECL_DECLARRAY:
|
||||
case DECL_BODYPARAM:
|
||||
case DECL_GLOBALS:
|
||||
UNREACHABLE
|
||||
case DECL_CT_IF:
|
||||
case DECL_CT_SWITCH:
|
||||
|
||||
@@ -850,6 +850,7 @@ Decl *copy_decl(CopyStruct *c, Decl *decl)
|
||||
MACRO_COPY_DECL_LIST(copy->methods);
|
||||
break;
|
||||
case DECL_DECLARRAY:
|
||||
case DECL_GLOBALS:
|
||||
UNREACHABLE
|
||||
case DECL_BITSTRUCT:
|
||||
copy_decl_type(copy);
|
||||
|
||||
@@ -143,6 +143,7 @@ typedef enum
|
||||
DECL_FAULT,
|
||||
DECL_FAULTVALUE,
|
||||
DECL_FUNC,
|
||||
DECL_GLOBALS,
|
||||
DECL_INITIALIZE,
|
||||
DECL_FINALIZE,
|
||||
DECL_GENERIC,
|
||||
@@ -162,7 +163,7 @@ typedef enum
|
||||
case DECL_DECLARRAY: case DECL_CT_IF: case DECL_CT_ELSE: case DECL_CT_ELIF: \
|
||||
case DECL_CT_SWITCH: case DECL_CT_CASE: case DECL_ATTRIBUTE: case DECL_LABEL: \
|
||||
case DECL_DEFINE: case DECL_CT_ASSERT: case DECL_GENERIC: case DECL_INITIALIZE: \
|
||||
case DECL_FINALIZE: case DECL_CT_ECHO: case DECL_CT_INCLUDE
|
||||
case DECL_FINALIZE: case DECL_CT_ECHO: case DECL_CT_INCLUDE: case DECL_GLOBALS
|
||||
|
||||
#define NON_RUNTIME_EXPR EXPR_DESIGNATOR: case EXPR_POISONED: \
|
||||
case EXPR_TYPEINFO: case EXPR_CT_IDENT: case EXPR_HASH_IDENT: \
|
||||
|
||||
@@ -1021,17 +1021,17 @@ void llvm_append_function_attributes(GenContext *c, Decl *decl)
|
||||
{
|
||||
llvm_attribute_add(c, function, attribute_id.noreturn, -1);
|
||||
}
|
||||
if (decl->is_wasm_interface && arch_is_wasm(platform_target.arch))
|
||||
if (decl->is_export && arch_is_wasm(platform_target.arch))
|
||||
{
|
||||
if (decl->visibility == VISIBLE_EXTERN)
|
||||
{
|
||||
llvm_attribute_add_string(c, function, "wasm-import-name", decl_get_extname(decl), -1);
|
||||
}
|
||||
else if (c->code_module == decl->unit->module)
|
||||
if (c->code_module == decl->unit->module)
|
||||
{
|
||||
llvm_attribute_add_string(c, function, "wasm-export-name", decl_get_extname(decl), -1);
|
||||
}
|
||||
}
|
||||
if (decl->visibility == VISIBLE_EXTERN && arch_is_wasm(platform_target.arch))
|
||||
{
|
||||
llvm_attribute_add_string(c, function, "wasm-import-name", decl_get_extname(decl), -1);
|
||||
}
|
||||
if (decl->alignment != type_abi_alignment(decl->type))
|
||||
{
|
||||
llvm_set_alignment(function, decl->alignment);
|
||||
@@ -1104,6 +1104,7 @@ LLVMValueRef llvm_get_ref(GenContext *c, Decl *decl)
|
||||
case DECL_BODYPARAM:
|
||||
case DECL_CT_ECHO:
|
||||
case DECL_CT_INCLUDE:
|
||||
case DECL_GLOBALS:
|
||||
UNREACHABLE;
|
||||
}
|
||||
UNREACHABLE
|
||||
|
||||
@@ -96,7 +96,7 @@ static inline bool parse_top_level_block(ParseContext *c, Decl ***decls, TokenTy
|
||||
assert(decl);
|
||||
if (decl_ok(decl))
|
||||
{
|
||||
vec_add(*decls, decl);
|
||||
add_decl_to_list(decls, decl);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -175,7 +175,7 @@ static inline Decl *parse_ct_case(ParseContext *c)
|
||||
TokenType type = c->tok;
|
||||
if (type == TOKEN_CT_DEFAULT || type == TOKEN_CT_CASE || type == TOKEN_CT_ENDSWITCH) break;
|
||||
ASSIGN_DECL_OR_RET(Decl *stmt, parse_top_level_statement(c, NULL), poisoned_decl);
|
||||
vec_add(decl->ct_case_decl.body, stmt);
|
||||
add_decl_to_list(&decl->ct_case_decl.body, stmt);
|
||||
}
|
||||
return decl;
|
||||
}
|
||||
@@ -1062,9 +1062,6 @@ static inline Decl *parse_global_declaration(ParseContext *c, Visibility visibil
|
||||
|
||||
ASSIGN_TYPE_OR_RET(TypeInfo *type, parse_optional_type(c), poisoned_decl);
|
||||
|
||||
Decl *decl = DECL_VAR_NEW(type, VARDECL_GLOBAL, visibility);
|
||||
|
||||
decl->var.is_threadlocal = threadlocal;
|
||||
|
||||
if (tok_is(c, TOKEN_CONST_IDENT))
|
||||
{
|
||||
@@ -1072,23 +1069,54 @@ static inline Decl *parse_global_declaration(ParseContext *c, Visibility visibil
|
||||
return poisoned_decl;
|
||||
}
|
||||
|
||||
if (!try_consume(c, TOKEN_IDENT))
|
||||
Decl *decl;
|
||||
Decl **decls = NULL;
|
||||
while (true)
|
||||
{
|
||||
if (token_is_some_ident(c->tok))
|
||||
decl = DECL_VAR_NEW(type, VARDECL_GLOBAL, visibility);
|
||||
decl->var.is_threadlocal = threadlocal;
|
||||
if (!try_consume(c, TOKEN_IDENT))
|
||||
{
|
||||
SEMA_ERROR_HERE("I expected a variable name here, but global variables need to start with lower case.");
|
||||
if (token_is_some_ident(c->tok))
|
||||
{
|
||||
SEMA_ERROR_HERE("I expected a variable name here, but global variables need to start with lower case.");
|
||||
return poisoned_decl;
|
||||
}
|
||||
SEMA_ERROR_HERE("The name of a global variable was expected here");
|
||||
return poisoned_decl;
|
||||
}
|
||||
SEMA_ERROR_HERE("The name of a global variable was expected here");
|
||||
return poisoned_decl;
|
||||
if (!try_consume(c, TOKEN_COMMA)) break;
|
||||
vec_add(decls, decl);
|
||||
}
|
||||
// Add the last, or we miss it.
|
||||
if (decls) vec_add(decls, decl);
|
||||
|
||||
if (!parse_attributes(c, &decl->attributes)) return poisoned_decl;
|
||||
if (try_consume(c, TOKEN_EQ))
|
||||
{
|
||||
if (decls)
|
||||
{
|
||||
SEMA_ERROR_HERE("Initialization is not allowed with multiple declarations.");
|
||||
return poisoned_decl;
|
||||
}
|
||||
if (!parse_decl_initializer(c, decl, true)) return poisoned_decl;
|
||||
}
|
||||
CONSUME_EOS_OR_RET(poisoned_decl);
|
||||
Attr **attributes = decl->attributes;
|
||||
if (attributes)
|
||||
{
|
||||
FOREACH_BEGIN(Decl *d, decls)
|
||||
if (d == decl) continue;
|
||||
d->attributes = copy_attributes_single(attributes);
|
||||
FOREACH_END();
|
||||
}
|
||||
if (decls)
|
||||
{
|
||||
decl = decl_calloc();
|
||||
decl->decl_kind = DECL_GLOBALS;
|
||||
decl->decls = decls;
|
||||
return decl;
|
||||
}
|
||||
return decl;
|
||||
}
|
||||
|
||||
@@ -2606,7 +2634,7 @@ static Decl *parse_include(ParseContext *c)
|
||||
decl_poison(decl);
|
||||
goto END;
|
||||
}
|
||||
vec_add(list, inner);
|
||||
add_decl_to_list(&list, inner);
|
||||
}
|
||||
decl->include.decls = list;
|
||||
END:
|
||||
|
||||
@@ -73,7 +73,7 @@ static inline void parse_translation_unit(ParseContext *c)
|
||||
if (!decl) continue;
|
||||
if (decl_ok(decl))
|
||||
{
|
||||
vec_add(c->unit->global_decls, decl);
|
||||
add_decl_to_list(&c->unit->global_decls, decl);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -62,6 +62,18 @@ bool parse_parameters(ParseContext *c, Visibility visibility, Decl ***params_ref
|
||||
bool parse_arg_list(ParseContext *c, Expr ***result, TokenType param_end, bool *splat, bool vasplat);
|
||||
Expr *parse_type_compound_literal_expr_after_type(ParseContext *c, TypeInfo *type_info);
|
||||
|
||||
INLINE void add_decl_to_list(Decl ***list, Decl *decl)
|
||||
{
|
||||
if (decl->decl_kind == DECL_GLOBALS)
|
||||
{
|
||||
FOREACH_BEGIN(Decl *d, decl->decls)
|
||||
vec_add(*list, d);
|
||||
FOREACH_END();
|
||||
return;
|
||||
}
|
||||
vec_add(*list, decl);
|
||||
}
|
||||
|
||||
bool parse_module(ParseContext *c, AstId docs);
|
||||
Expr *parse_generic_parameter(ParseContext *c);
|
||||
bool try_consume(ParseContext *c, TokenType type);
|
||||
|
||||
@@ -1656,7 +1656,7 @@ static bool sema_analyse_attribute(SemaContext *context, Decl *decl, Attr *attr,
|
||||
decl->is_weak = true;
|
||||
break;
|
||||
case ATTRIBUTE_WASM:
|
||||
decl->is_wasm_interface = true;
|
||||
decl->is_export = true;
|
||||
break;
|
||||
case ATTRIBUTE_NAKED:
|
||||
assert(domain == ATTR_FUNC);
|
||||
@@ -1969,7 +1969,10 @@ static inline MainType sema_find_main_type(SemaContext *context, Signature *sig,
|
||||
|
||||
static inline Decl *sema_create_synthetic_main(SemaContext *context, Decl *decl, MainType main, bool int_return, bool err_return, bool is_winmain, bool is_wmain)
|
||||
{
|
||||
Decl *function = decl_new(DECL_FUNC, NULL, decl->span, VISIBLE_EXTERN);
|
||||
Decl *function = decl_new(DECL_FUNC, NULL, decl->span, VISIBLE_PUBLIC);
|
||||
function->is_export = true;
|
||||
function->has_extname = true;
|
||||
function->extname = kw_mainstub;
|
||||
function->name = kw_mainstub;
|
||||
function->unit = decl->unit;
|
||||
|
||||
@@ -2158,7 +2161,9 @@ static inline bool sema_analyse_main_function(SemaContext *context, Decl *decl)
|
||||
if ((type == MAIN_TYPE_RAW || type == MAIN_TYPE_NO_ARGS) && is_int_return && !is_winmain)
|
||||
{
|
||||
// Int return is pass-through at the moment.
|
||||
decl->visibility = VISIBLE_EXTERN;
|
||||
decl->is_export = true;
|
||||
decl->has_extname = true;
|
||||
decl->extname = kw_main;
|
||||
function = decl;
|
||||
goto REGISTER_MAIN;
|
||||
}
|
||||
@@ -3052,6 +3057,7 @@ bool sema_analyse_decl(SemaContext *context, Decl *decl)
|
||||
case DECL_DECLARRAY:
|
||||
case DECL_BODYPARAM:
|
||||
case DECL_CT_INCLUDE:
|
||||
case DECL_GLOBALS:
|
||||
UNREACHABLE
|
||||
}
|
||||
decl->resolve_status = RESOLVE_DONE;
|
||||
|
||||
@@ -549,6 +549,7 @@ static inline bool sema_cast_ident_rvalue(SemaContext *context, Expr *expr)
|
||||
case DECL_INITIALIZE:
|
||||
case DECL_FINALIZE:
|
||||
case DECL_CT_INCLUDE:
|
||||
case DECL_GLOBALS:
|
||||
UNREACHABLE
|
||||
case DECL_POISONED:
|
||||
return expr_poison(expr);
|
||||
|
||||
@@ -368,6 +368,11 @@ void sema_analysis_pass_ct_echo(Module *module)
|
||||
static inline bool analyse_func_body(SemaContext *context, Decl *decl)
|
||||
{
|
||||
if (!decl->func_decl.body) return true;
|
||||
if (decl->visibility == VISIBLE_EXTERN)
|
||||
{
|
||||
SEMA_ERROR(decl, "'extern' functions should never have a body.");
|
||||
return decl_poison(decl);
|
||||
}
|
||||
// Don't analyse functions that are tests.
|
||||
if (decl->func_decl.attr_test && !active_target.testing) return true;
|
||||
if (!sema_analyse_function_body(context, decl)) return decl_poison(decl);
|
||||
|
||||
@@ -245,6 +245,7 @@ static bool sema_resolve_type_identifier(SemaContext *context, TypeInfo *type_in
|
||||
case DECL_DECLARRAY:
|
||||
case DECL_BODYPARAM:
|
||||
case DECL_CT_INCLUDE:
|
||||
case DECL_GLOBALS:
|
||||
UNREACHABLE
|
||||
}
|
||||
UNREACHABLE
|
||||
|
||||
@@ -181,6 +181,7 @@ static void register_generic_decls(CompilationUnit *unit, Decl **decls)
|
||||
case DECL_CT_ELSE:
|
||||
case DECL_BODYPARAM:
|
||||
case DECL_CT_INCLUDE:
|
||||
case DECL_GLOBALS:
|
||||
UNREACHABLE
|
||||
case DECL_MACRO:
|
||||
case DECL_DEFINE:
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define COMPILER_VERSION "0.4.58"
|
||||
#define COMPILER_VERSION "0.4.59"
|
||||
@@ -5,12 +5,13 @@ struct Vector2 {
|
||||
float x;
|
||||
float y;
|
||||
}
|
||||
extern fn Vector2 vector2_zero() { return Vector2 {}; }
|
||||
extern fn Vector2 vector2_one() { return Vector2 {}; }
|
||||
extern fn Vector2 vector2_add(Vector2 v1, Vector2 v2) { return Vector2 {}; }
|
||||
extern fn Vector2 vector2_add_value(Vector2 v, float add) { return Vector2 {}; }
|
||||
extern fn Vector2 vector2_subtract(Vector2 v1, Vector2 v2) { return Vector2 {}; }
|
||||
extern fn Vector2 vector2_subtract_value(Vector2 v, float sub) { return Vector2 {}; }
|
||||
fn Vector2 vector2_zero() @extern("vector2_zero") { return Vector2 {}; }
|
||||
fn Vector2 vector2_one() @extern("vector2_one") { return Vector2 {}; }
|
||||
fn Vector2 vector2_add(Vector2 v1, Vector2 v2) @extern("vector2_add") { return Vector2 {}; }
|
||||
fn Vector2 vector2_add_value(Vector2 v, float add) @extern("vector2_add_value") { return Vector2 {}; }
|
||||
fn Vector2 vector2_subtract(Vector2 v1, Vector2 v2) @extern("vector2_subtract") { return Vector2 {}; }
|
||||
fn Vector2 vector2_subtract_value(Vector2 v, float sub) @extern("vector2_subtract_value") { return Vector2 {}; }
|
||||
|
||||
|
||||
/* #expect: abi.ll
|
||||
|
||||
|
||||
@@ -5,12 +5,12 @@ struct Vector2 {
|
||||
float x;
|
||||
float y;
|
||||
}
|
||||
extern fn Vector2 vector2_zero() { return Vector2 {}; }
|
||||
extern fn Vector2 vector2_one() { return Vector2 {}; }
|
||||
extern fn Vector2 vector2_add(Vector2 v1, Vector2 v2) { return Vector2 {}; }
|
||||
extern fn Vector2 vector2_add_value(Vector2 v, float add) { return Vector2 {}; }
|
||||
extern fn Vector2 vector2_subtract(Vector2 v1, Vector2 v2) { return Vector2 {}; }
|
||||
extern fn Vector2 vector2_subtract_value(Vector2 v, float sub) { return Vector2 {}; }
|
||||
fn Vector2 vector2_zero() @extern("vector2_zero") { return Vector2 {}; }
|
||||
fn Vector2 vector2_one() @extern("vector2_one") { return Vector2 {}; }
|
||||
fn Vector2 vector2_add(Vector2 v1, Vector2 v2) @extern("vector2_add") { return Vector2 {}; }
|
||||
fn Vector2 vector2_add_value(Vector2 v, float add) @extern("vector2_add_value") { return Vector2 {}; }
|
||||
fn Vector2 vector2_subtract(Vector2 v1, Vector2 v2) @extern("vector2_subtract") { return Vector2 {}; }
|
||||
fn Vector2 vector2_subtract_value(Vector2 v, float sub) @extern("vector2_subtract_value") { return Vector2 {}; }
|
||||
|
||||
/* #expect: abi.ll
|
||||
|
||||
@@ -73,7 +73,6 @@ entry:
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define void @vector2_subtract_value(ptr noalias sret(%Vector2) align 4 %0, ptr byval(%Vector2) align 4 %1, float %2) #0 {
|
||||
entry:
|
||||
%literal = alloca %Vector2, align 4
|
||||
|
||||
@@ -5,12 +5,12 @@ struct Vector2 {
|
||||
float x;
|
||||
float y;
|
||||
}
|
||||
extern fn Vector2 vector2_zero() { return Vector2 {}; }
|
||||
extern fn Vector2 vector2_one() { return Vector2 {}; }
|
||||
extern fn Vector2 vector2_add(Vector2 v1, Vector2 v2) { return Vector2 {}; }
|
||||
extern fn Vector2 vector2_add_value(Vector2 v, float add) { return Vector2 {}; }
|
||||
extern fn Vector2 vector2_subtract(Vector2 v1, Vector2 v2) { return Vector2 {}; }
|
||||
extern fn Vector2 vector2_subtract_value(Vector2 v, float sub) { return Vector2 {}; }
|
||||
fn Vector2 vector2_zero() @extern("vector2_zero") { return Vector2 {}; }
|
||||
fn Vector2 vector2_one() @extern("vector2_one") { return Vector2 {}; }
|
||||
fn Vector2 vector2_add(Vector2 v1, Vector2 v2) @extern("vector2_add") { return Vector2 {}; }
|
||||
fn Vector2 vector2_add_value(Vector2 v, float add) @extern("vector2_add_value") { return Vector2 {}; }
|
||||
fn Vector2 vector2_subtract(Vector2 v1, Vector2 v2) @extern("vector2_subtract") { return Vector2 {}; }
|
||||
fn Vector2 vector2_subtract_value(Vector2 v, float sub) @extern("vector2_subtract_value") { return Vector2 {}; }
|
||||
|
||||
/* #expect: abi.ll
|
||||
|
||||
|
||||
17
test/test_suite/abi/wasm_extern.c3t
Normal file
17
test/test_suite/abi/wasm_extern.c3t
Normal file
@@ -0,0 +1,17 @@
|
||||
// #target: wasm32
|
||||
module test;
|
||||
extern fn int get_abc();
|
||||
fn int hello() @export("fgh")
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
target triple = "wasm32-unknown-unknown"
|
||||
|
||||
declare i32 @get_abc() #0
|
||||
define i32 @fgh() #1
|
||||
|
||||
attributes #0 = { nounwind "wasm-import-name"="get_abc" }
|
||||
attributes #1 = { nounwind "wasm-export-name"="fgh" }
|
||||
@@ -7,6 +7,10 @@ struct Abc
|
||||
int z @noinit;
|
||||
Abc y @noinit;
|
||||
|
||||
int a, b, c;
|
||||
int x1, y1 @noinit;
|
||||
tlocal int w, v;
|
||||
|
||||
fn void main()
|
||||
{
|
||||
z = y.x[0];
|
||||
@@ -16,10 +20,13 @@ fn void main()
|
||||
|
||||
@test_z = local_unnamed_addr global i32 undef, align 4
|
||||
@test_y = local_unnamed_addr global %Abc undef, align 4
|
||||
@test_a = local_unnamed_addr global i32 0, align 4
|
||||
@test_b = local_unnamed_addr global i32 0, align 4
|
||||
@test_c = local_unnamed_addr global i32 0, align 4
|
||||
@test_x1 = local_unnamed_addr global i32 undef, align 4
|
||||
@test_y1 = local_unnamed_addr global i32 undef, align 4
|
||||
@test_w = thread_local local_unnamed_addr global i32 0, align 4
|
||||
@test_v = thread_local local_unnamed_addr global i32 0, align 4
|
||||
|
||||
define void @test_main() #0 {
|
||||
entry:
|
||||
%0 = load i32, ptr @test_y, align 4
|
||||
store i32 %0, ptr @test_z, align 4
|
||||
ret void
|
||||
}
|
||||
%0 = load i32, ptr @test_y, align 4
|
||||
store i32 %0, ptr @test_z, align 4
|
||||
|
||||
Reference in New Issue
Block a user