Skip to content

Commit

Permalink
$embed.
Browse files Browse the repository at this point in the history
  • Loading branch information
lerno committed Jul 8, 2023
1 parent 77b3214 commit 8b605d9
Show file tree
Hide file tree
Showing 33 changed files with 474 additions and 195 deletions.
2 changes: 2 additions & 0 deletions releasenotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
## 0.5.0 Change List

### Changes / improvements
- Globals may now be initialized with optional values.
- New generic syntax.
- Added `$embed` to embed binary data.
- Ad hoc generics are now allowed.
- Allow inferred type on method first argument.
- Fix to void expression blocks
Expand Down
37 changes: 27 additions & 10 deletions src/compiler/compiler_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,16 +194,11 @@ typedef struct
uint64_t ptr;
bool b;
struct
{
const char *chars;
ArraySize len;
} string;
Decl *enum_err_val;
struct
{
const char *ptr;
TypeSize len;
ArraySize len;
} bytes;
Decl *enum_err_val;
Type *typeid;
ConstInitializer *initializer;
Expr **untyped_list;
Expand All @@ -218,10 +213,12 @@ typedef struct


typedef uint16_t FileId;

typedef struct
{
FileId file_id;
const char *contents;
size_t content_len;
char *name;
char *dir_path;
const char *full_path;
Expand Down Expand Up @@ -593,7 +590,7 @@ typedef struct

typedef enum
{
DEFINE_TYPE_GENERIC,
DEFINE_TYPE_GENERIC_OLD,
DEFINE_IDENT_ALIAS,
DEFINE_IDENT_GENERIC,
} DefineType;
Expand Down Expand Up @@ -846,6 +843,11 @@ typedef struct
ExprId inner;
} ExprBuiltinAccess;

typedef struct
{
Expr *filename;
Expr *len;
} ExprEmbedExpr;
typedef struct
{
ExprId parent;
Expand Down Expand Up @@ -1146,6 +1148,7 @@ struct Expr_
ExprTryUnwrap try_unwrap_expr; // 24
ExprCall call_expr; // 32
Expr *inner_expr; // 8
ExprEmbedExpr embed_expr;
ExprBuiltinAccess builtin_access_expr;
ExprGenericIdent generic_ident_expr;
ExprCatchUnwrap catch_unwrap_expr; // 24
Expand Down Expand Up @@ -1707,6 +1710,7 @@ typedef struct
Type *string_type;
Decl *panic_var;
Decl *panicf;
Decl *io_error_file_not_found;
Decl *main;
Decl *test_func;
Decl *decl_stack[MAX_GLOBAL_DECL_STACK];
Expand Down Expand Up @@ -1861,8 +1865,11 @@ extern const char *builtin_defines[NUMBER_OF_BUILTIN_DEFINES];
extern const char *type_property_list[NUMBER_OF_TYPE_PROPERTIES];
extern const char *kw_std__core;
extern const char *kw_std__core__types;
extern const char *kw_std__io;
extern const char *kw___run_default_test_runner;
extern const char *kw_typekind;
extern const char *kw_FILE_NOT_FOUND;
extern const char *kw_IoError;

extern const char *kw_argc;
extern const char *kw_argv;
Expand Down Expand Up @@ -2213,7 +2220,7 @@ Path *path_create_from_string(const char *string, uint32_t len, SourceSpan span)
#define SEMA_ERROR(_node, ...) sema_error_at((_node)->span, __VA_ARGS__)
#define RETURN_SEMA_ERROR(_node, ...) do { sema_error_at((_node)->span, __VA_ARGS__); return false; } while (0)
#define SEMA_NOTE(_node, ...) sema_error_prev_at((_node)->span, __VA_ARGS__)
#define EXPAND_EXPR_STRING(str_) (str_)->const_expr.string.len, (str_)->const_expr.string.chars
#define EXPAND_EXPR_STRING(str_) (str_)->const_expr.bytes.len, (str_)->const_expr.bytes.ptr
#define TABLE_MAX_LOAD 0.5

void sema_analysis_run(void);
Expand Down Expand Up @@ -2941,7 +2948,7 @@ INLINE bool decl_is_user_defined_type(Decl *decl)

INLINE Decl *decl_flatten(Decl *decl)
{
if (decl->decl_kind == DECL_DEFINE && decl->define_decl.define_kind != DEFINE_TYPE_GENERIC)
if (decl->decl_kind == DECL_DEFINE && decl->define_decl.define_kind != DEFINE_TYPE_GENERIC_OLD)
{
return decl->define_decl.alias;
}
Expand Down Expand Up @@ -3320,11 +3327,21 @@ INLINE bool expr_is_const_pointer(Expr *expr)
return expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_POINTER;
}

INLINE bool expr_is_const_bool(Expr *expr)
{
return expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_BOOL;
}

INLINE bool expr_is_const_initializer(Expr *expr)
{
return expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_INITIALIZER;
}

INLINE bool expr_is_const_bytes(Expr *expr)
{
return expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_BYTES;
}

INLINE bool expr_is_const_untyped_list(Expr *expr)
{
return expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_UNTYPED_LIST;
Expand Down
6 changes: 5 additions & 1 deletion src/compiler/copying.c
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,10 @@ Expr *copy_expr(CopyStruct *c, Expr *source_expr)
{
case EXPR_ANYSWITCH:
UNREACHABLE
case EXPR_EMBED:
MACRO_COPY_EXPR(expr->embed_expr.len);
MACRO_COPY_EXPR(expr->embed_expr.filename);
return expr;
case EXPR_GENERIC_IDENT:
MACRO_COPY_EXPRID(expr->generic_ident_expr.parent);
MACRO_COPY_EXPR_LIST(expr->generic_ident_expr.parmeters);
Expand Down Expand Up @@ -971,7 +975,7 @@ Decl *copy_decl(CopyStruct *c, Decl *decl)
case DECL_DEFINE:
switch (decl->define_decl.define_kind)
{
case DEFINE_TYPE_GENERIC:
case DEFINE_TYPE_GENERIC_OLD:
case DEFINE_IDENT_GENERIC:
MACRO_COPY_EXPR_LIST(decl->define_decl.generic_params);
break;
Expand Down
2 changes: 2 additions & 0 deletions src/compiler/enums.h
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ typedef enum
EXPR_DECL,
EXPR_DESIGNATED_INITIALIZER_LIST,
EXPR_DESIGNATOR,
EXPR_EMBED,
EXPR_EXPRESSION_LIST,
EXPR_EXPR_BLOCK,
EXPR_OPTIONAL,
Expand Down Expand Up @@ -556,6 +557,7 @@ typedef enum
TOKEN_CT_DEFINED, // $defined
TOKEN_CT_ECHO, // $echo
TOKEN_CT_ELSE, // $else
TOKEN_CT_EMBED, // $embed
TOKEN_CT_ENDFOR, // $endfor
TOKEN_CT_ENDFOREACH, // $endforeach
TOKEN_CT_ENDIF, // $endif
Expand Down
8 changes: 6 additions & 2 deletions src/compiler/expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ bool expr_may_addr(Expr *expr)
case EXPR_SWIZZLE:
case EXPR_LAMBDA:
case EXPR_GENERIC_IDENT:
case EXPR_EMBED:
return false;
}
UNREACHABLE
Expand Down Expand Up @@ -203,6 +204,7 @@ bool expr_is_constant_eval(Expr *expr, ConstantEvalKind eval_kind)
case EXPR_STRINGIFY:
case EXPR_CT_CHECKS:
case EXPR_LAMBDA:
case EXPR_EMBED:
return true;
case EXPR_COND:
return expr_list_is_constant_eval(expr->cond_expr, eval_kind);
Expand Down Expand Up @@ -406,6 +408,7 @@ static inline bool expr_unary_addr_is_constant_eval(Expr *expr, ConstantEvalKind
// An address is never a constant value.
if (eval_kind == CONSTANT_EVAL_CONSTANT_VALUE) return false;
Expr *inner = expr->unary_expr.expr;
if (eval_kind == CONSTANT_EVAL_GLOBAL_INIT && IS_OPTIONAL(inner)) return false;
switch (inner->expr_kind)
{
case EXPR_ACCESS:
Expand Down Expand Up @@ -662,6 +665,7 @@ bool expr_is_pure(Expr *expr)
case EXPR_OPERATOR_CHARS:
case EXPR_CT_CHECKS:
case EXPR_LAMBDA:
case EXPR_EMBED:
return true;
case EXPR_VASPLAT:
return true;
Expand Down Expand Up @@ -932,9 +936,9 @@ void expr_rewrite_to_string(Expr *expr_to_rewrite, const char *string)
{
expr_to_rewrite->expr_kind = EXPR_CONST;
expr_to_rewrite->const_expr.const_kind = CONST_STRING;
expr_to_rewrite->const_expr.string.chars = (char *)string;
expr_to_rewrite->const_expr.bytes.ptr = (char *)string;
ArraySize len = (ArraySize)strlen(string);
expr_to_rewrite->const_expr.string.len = len;
expr_to_rewrite->const_expr.bytes.len = len;
expr_to_rewrite->resolve_status = RESOLVE_DONE;
expr_to_rewrite->type = type_string;
}
Expand Down
6 changes: 3 additions & 3 deletions src/compiler/headers.c
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,7 @@ static void header_gen_global_var(FILE *file, FILE *file_type, HTable *table, De
Expr *init = decl->var.init_expr;
if (type_is_arraylike(type) || type_is_user_defined(type) || !init) return;
OUTPUT("#define %s ", decl_get_extname(decl));
assert(init->expr_kind == EXPR_CONST);
assert(expr_is_const(init));
switch (init->const_expr.const_kind)
{
case CONST_INTEGER:
Expand All @@ -503,9 +503,9 @@ static void header_gen_global_var(FILE *file, FILE *file_type, HTable *table, De
return;
case CONST_STRING:
putc('\"', file);
for (unsigned i = 0; i < init->const_expr.string.len; i++)
for (unsigned i = 0; i < init->const_expr.bytes.len; i++)
{
char ch = init->const_expr.string.chars[i];
char ch = init->const_expr.bytes.ptr[i];
if (ch >= ' ' && ch <= 127 && ch != '"')
{
fputc(ch, file);
Expand Down
26 changes: 12 additions & 14 deletions src/compiler/llvm_codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -393,25 +393,18 @@ void llvm_emit_global_variable_init(GenContext *c, Decl *decl)
{
init_expr = init_expr->identifier_expr.decl->var.init_expr;
}
if (init_expr)
if (init_expr && init_expr->expr_kind != EXPR_OPTIONAL)
{
if (init_expr->expr_kind == EXPR_CONST && init_expr->const_expr.const_kind == CONST_INITIALIZER)
if (expr_is_const_initializer(init_expr))
{
ConstInitializer *list = init_expr->const_expr.initializer;
init_value = llvm_emit_const_initializer(c, list);
}
else
{
BEValue value;
if (init_expr->expr_kind == EXPR_CONST && init_expr->const_expr.const_kind == CONST_BYTES)
{
init_value = llvm_get_bytes(c, init_expr->const_expr.bytes.ptr, init_expr->const_expr.bytes.len);
}
else
{
llvm_emit_expr(c, &value, decl->var.init_expr);
init_value = llvm_load_value_store(c, &value);
}
llvm_emit_expr(c, &value, decl->var.init_expr);
init_value = llvm_load_value_store(c, &value);
}
}
else
Expand Down Expand Up @@ -446,16 +439,21 @@ void llvm_emit_global_variable_init(GenContext *c, Decl *decl)
llvm_set_alignment(optional_ref, type_alloca_alignment(type_anyfault));
LLVMSetUnnamedAddress(optional_ref, LLVMGlobalUnnamedAddr);
}
LLVMValueRef optional_value = NULL;
if (init_expr && IS_OPTIONAL(init_expr) && init_expr->expr_kind == EXPR_OPTIONAL)
{
UNREACHABLE
Expr *inner = init_expr->inner_expr;
assert(expr_is_const(inner) && inner->const_expr.const_kind == CONST_ERR);
BEValue value;
llvm_emit_expr(c, &value, inner);
optional_value = llvm_load_value_store(c, &value);
}
if (!decl->is_extern)
{
LLVMSetInitializer(decl->backend_ref, init_value);
if (optional_ref)
{
LLVMSetInitializer(optional_ref, llvm_get_zero(c, type_anyfault));
LLVMSetInitializer(optional_ref, optional_value ? optional_value : llvm_get_zero(c, type_anyfault));
}
}

Expand Down Expand Up @@ -1071,7 +1069,7 @@ LLVMValueRef llvm_get_ref(GenContext *c, Decl *decl)
}
return backend_ref;
case DECL_DEFINE:
if (decl->define_decl.define_kind != DEFINE_TYPE_GENERIC) return llvm_get_ref(c, decl->define_decl.alias);
if (decl->define_decl.define_kind != DEFINE_TYPE_GENERIC_OLD) return llvm_get_ref(c, decl->define_decl.alias);
UNREACHABLE
case DECL_FAULTVALUE:
if (!decl->backend_ref)
Expand Down
Loading

0 comments on commit 8b605d9

Please sign in to comment.