mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-02 20:58:15 +00:00
using on indexable field; Auto deref for (Index|Slice)Expr
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
set exe_name=odin.exe
|
set exe_name=odin.exe
|
||||||
|
|
||||||
:: Debug = 0, Release = 1
|
:: Debug = 0, Release = 1
|
||||||
set release_mode=1
|
set release_mode=0
|
||||||
|
|
||||||
set compiler_flags= -nologo -Oi -TP -W4 -fp:fast -fp:except- -Gm- -MP -FC -GS- -EHsc- -GR-
|
set compiler_flags= -nologo -Oi -TP -W4 -fp:fast -fp:except- -Gm- -MP -FC -GS- -EHsc- -GR-
|
||||||
|
|
||||||
@@ -44,10 +44,10 @@ rem pushd %build_dir%
|
|||||||
del *.pdb > NUL 2> NUL
|
del *.pdb > NUL 2> NUL
|
||||||
del *.ilk > NUL 2> NUL
|
del *.ilk > NUL 2> NUL
|
||||||
|
|
||||||
rem cl %compiler_settings% "src\main.cpp" ^
|
cl %compiler_settings% "src\main.cpp" ^
|
||||||
rem /link %linker_settings% -OUT:%exe_name% ^
|
/link %linker_settings% -OUT:%exe_name% ^
|
||||||
rem && odin run code/demo.odin
|
&& odin run code/demo.odin
|
||||||
odin run code/demo.odin
|
rem odin run code/demo.odin
|
||||||
|
|
||||||
|
|
||||||
:do_not_compile_exe
|
:do_not_compile_exe
|
||||||
|
|||||||
+12
-54
@@ -3,59 +3,17 @@
|
|||||||
#import "hash.odin"
|
#import "hash.odin"
|
||||||
#import "mem.odin"
|
#import "mem.odin"
|
||||||
|
|
||||||
main :: proc() {
|
|
||||||
{ // New Standard Library stuff
|
|
||||||
s := "Hello"
|
|
||||||
fmt.println(s,
|
|
||||||
utf8.valid_string(s),
|
|
||||||
hash.murmur64(s.data, s.count))
|
|
||||||
|
|
||||||
// utf8.odin
|
A :: struct { using e: [12]int }
|
||||||
// hash.odin
|
Vector2 :: raw_union {
|
||||||
// - crc, fnv, fnva, murmur
|
using _xy: struct #ordered { x, y: f32 }
|
||||||
// mem.odin
|
using v: {2}f32
|
||||||
// - Custom allocators
|
e: [2]f32
|
||||||
// - Helpers
|
}
|
||||||
}
|
|
||||||
|
main :: proc() {
|
||||||
{
|
v: Vector2
|
||||||
arena: mem.Arena
|
v.x = 123
|
||||||
mem.init_arena_from_context(^arena, mem.megabytes(16)) // Uses default allocator
|
v[1] = 321
|
||||||
defer mem.free_arena(^arena)
|
fmt.println(v)
|
||||||
|
|
||||||
push_allocator mem.arena_allocator(^arena) {
|
|
||||||
x := new(int)
|
|
||||||
x^ = 1337
|
|
||||||
|
|
||||||
fmt.println(x^)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
push_allocator x {
|
|
||||||
...
|
|
||||||
}
|
|
||||||
|
|
||||||
is equivalent to this:
|
|
||||||
|
|
||||||
{
|
|
||||||
prev_allocator := current_context().allocator
|
|
||||||
current_context().allocator = x
|
|
||||||
defer current_context().allocator = prev_allocator
|
|
||||||
|
|
||||||
...
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// You can also "push" a context
|
|
||||||
|
|
||||||
c := current_context()
|
|
||||||
c.allocator = mem.arena_allocator(^arena)
|
|
||||||
|
|
||||||
push_context c {
|
|
||||||
x := new(int)
|
|
||||||
x^ = 365
|
|
||||||
|
|
||||||
fmt.println(x^)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -129,6 +129,7 @@ Entity *make_entity_field(gbAllocator a, Scope *scope, Token token, Type *type,
|
|||||||
entity->Variable.field_index = field_index;
|
entity->Variable.field_index = field_index;
|
||||||
entity->Variable.is_field = true;
|
entity->Variable.is_field = true;
|
||||||
entity->Variable.anonymous = cast(b8)is_anonymous;
|
entity->Variable.anonymous = cast(b8)is_anonymous;
|
||||||
|
entity->Variable.is_using = cast(b8)is_anonymous;
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+95
-53
@@ -224,6 +224,8 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
|
|||||||
|
|
||||||
isize other_field_index = 0;
|
isize other_field_index = 0;
|
||||||
|
|
||||||
|
Entity *using_index_expr = NULL;
|
||||||
|
|
||||||
|
|
||||||
// TODO(bill): Random declarations with DeclInfo
|
// TODO(bill): Random declarations with DeclInfo
|
||||||
#if 0
|
#if 0
|
||||||
@@ -365,6 +367,7 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
|
|||||||
Token name_token = name->Ident;
|
Token name_token = name->Ident;
|
||||||
|
|
||||||
Entity *e = make_entity_field(c->allocator, c->context.scope, name_token, type, vd->is_using, cast(i32)field_index);
|
Entity *e = make_entity_field(c->allocator, c->context.scope, name_token, type, vd->is_using, cast(i32)field_index);
|
||||||
|
e->identifier = name;
|
||||||
if (name_token.string == "_") {
|
if (name_token.string == "_") {
|
||||||
fields[field_index++] = e;
|
fields[field_index++] = e;
|
||||||
} else {
|
} else {
|
||||||
@@ -386,8 +389,30 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
|
|||||||
Type *t = base_type(type_deref(type));
|
Type *t = base_type(type_deref(type));
|
||||||
if (!is_type_struct(t) && !is_type_raw_union(t)) {
|
if (!is_type_struct(t) && !is_type_raw_union(t)) {
|
||||||
Token name_token = vd->names[0]->Ident;
|
Token name_token = vd->names[0]->Ident;
|
||||||
error(name_token, "`using` on a field `%.*s` must be a type", LIT(name_token.string));
|
if (is_type_indexable(t)) {
|
||||||
continue;
|
b32 ok = true;
|
||||||
|
gb_for_array(emi, entity_map.entries) {
|
||||||
|
Entity *e = entity_map.entries[emi].value;
|
||||||
|
if (e->kind == Entity_Variable && e->Variable.anonymous) {
|
||||||
|
if (is_type_indexable(e->type)) {
|
||||||
|
if (e->identifier != vd->names[0]) {
|
||||||
|
ok = false;
|
||||||
|
using_index_expr = e;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ok) {
|
||||||
|
using_index_expr = fields[field_index-1];
|
||||||
|
} else {
|
||||||
|
fields[field_index-1]->Variable.anonymous = false;
|
||||||
|
error(name_token, "Previous `using` for an index expression `%.*s`", LIT(name_token.string));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
error(name_token, "`using` on a field `%.*s` must be a `struct` or `raw_union`", LIT(name_token.string));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
populate_using_entity_map(c, node, type, &entity_map);
|
populate_using_entity_map(c, node, type, &entity_map);
|
||||||
@@ -3080,6 +3105,28 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Entity *find_using_index_expr(Type *t) {
|
||||||
|
t = base_type(t);
|
||||||
|
if (t->kind != Type_Record) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (isize i = 0; i < t->Record.field_count; i++) {
|
||||||
|
Entity *f = t->Record.fields[i];
|
||||||
|
if (f->kind == Entity_Variable &&
|
||||||
|
f->Variable.is_field && f->Variable.anonymous) {
|
||||||
|
if (is_type_indexable(f->type)) {
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
Entity *res = find_using_index_expr(f->type);
|
||||||
|
if (res != NULL) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
ExprKind check_call_expr(Checker *c, Operand *operand, AstNode *call) {
|
ExprKind check_call_expr(Checker *c, Operand *operand, AstNode *call) {
|
||||||
GB_ASSERT(call->kind == AstNode_CallExpr);
|
GB_ASSERT(call->kind == AstNode_CallExpr);
|
||||||
ast_node(ce, CallExpr, call);
|
ast_node(ce, CallExpr, call);
|
||||||
@@ -3428,54 +3475,58 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
b32 valid = false;
|
Type *t = base_type(type_deref(o->type));
|
||||||
i64 max_count = -1;
|
|
||||||
Type *t = base_type(o->type);
|
auto set_index_data = [](Operand *o, Type *t, i64 *max_count) -> b32 {
|
||||||
switch (t->kind) {
|
t = base_type(type_deref(t));
|
||||||
case Type_Basic:
|
|
||||||
if (is_type_string(t)) {
|
switch (t->kind) {
|
||||||
valid = true;
|
case Type_Basic:
|
||||||
if (o->mode == Addressing_Constant) {
|
if (is_type_string(t)) {
|
||||||
max_count = o->value.value_string.len;
|
if (o->mode == Addressing_Constant) {
|
||||||
|
*max_count = o->value.value_string.len;
|
||||||
|
}
|
||||||
|
if (o->mode != Addressing_Variable)
|
||||||
|
o->mode = Addressing_Value;
|
||||||
|
o->type = t_u8;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
if (o->mode != Addressing_Variable)
|
break;
|
||||||
|
|
||||||
|
case Type_Array:
|
||||||
|
*max_count = t->Array.count;
|
||||||
|
if (o->mode != Addressing_Variable) {
|
||||||
o->mode = Addressing_Value;
|
o->mode = Addressing_Value;
|
||||||
o->type = t_u8;
|
}
|
||||||
}
|
o->type = t->Array.elem;
|
||||||
break;
|
return true;
|
||||||
|
|
||||||
case Type_Array:
|
case Type_Vector:
|
||||||
valid = true;
|
*max_count = t->Vector.count;
|
||||||
max_count = t->Array.count;
|
if (o->mode != Addressing_Variable) {
|
||||||
if (o->mode != Addressing_Variable)
|
o->mode = Addressing_Value;
|
||||||
o->mode = Addressing_Value;
|
}
|
||||||
o->type = t->Array.elem;
|
o->type = t->Vector.elem;
|
||||||
break;
|
return true;
|
||||||
|
|
||||||
case Type_Vector:
|
|
||||||
valid = true;
|
|
||||||
max_count = t->Vector.count;
|
|
||||||
if (o->mode != Addressing_Variable)
|
|
||||||
o->mode = Addressing_Value;
|
|
||||||
o->type = t->Vector.elem;
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
case Type_Slice:
|
case Type_Slice:
|
||||||
valid = true;
|
o->type = t->Slice.elem;
|
||||||
o->type = t->Slice.elem;
|
|
||||||
o->mode = Addressing_Variable;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Type_Pointer: {
|
|
||||||
Type *bt = base_type(t->Pointer.elem);
|
|
||||||
if (bt->kind == Type_Array) {
|
|
||||||
valid = true;
|
|
||||||
max_count = bt->Array.count;
|
|
||||||
o->mode = Addressing_Variable;
|
o->mode = Addressing_Variable;
|
||||||
o->type = bt->Array.elem;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
i64 max_count = -1;
|
||||||
|
b32 valid = set_index_data(o, t, &max_count);
|
||||||
|
|
||||||
|
if (!valid && (is_type_struct(t) || is_type_raw_union(t))) {
|
||||||
|
Entity *found = find_using_index_expr(t);
|
||||||
|
if (found != NULL) {
|
||||||
|
valid = set_index_data(o, found->type, &max_count);
|
||||||
}
|
}
|
||||||
} break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
@@ -3506,7 +3557,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
|
|||||||
|
|
||||||
b32 valid = false;
|
b32 valid = false;
|
||||||
i64 max_count = -1;
|
i64 max_count = -1;
|
||||||
Type *t = base_type(o->type);
|
Type *t = base_type(type_deref(o->type));
|
||||||
switch (t->kind) {
|
switch (t->kind) {
|
||||||
case Type_Basic:
|
case Type_Basic:
|
||||||
if (is_type_string(t)) {
|
if (is_type_string(t)) {
|
||||||
@@ -3536,15 +3587,6 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
|
|||||||
case Type_Slice:
|
case Type_Slice:
|
||||||
valid = true;
|
valid = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Type_Pointer: {
|
|
||||||
Type *bt = base_type(t->Pointer.elem);
|
|
||||||
if (bt->kind == Type_Array) {
|
|
||||||
valid = true;
|
|
||||||
max_count = bt->Array.count;
|
|
||||||
o->type = make_type_slice(c->allocator, bt->Array.elem);
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
|
|||||||
@@ -487,6 +487,10 @@ b32 is_type_u8(Type *t) {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
b32 is_type_array(Type *t) {
|
||||||
|
t = base_type(t);
|
||||||
|
return t->kind == Type_Array;
|
||||||
|
}
|
||||||
b32 is_type_slice(Type *t) {
|
b32 is_type_slice(Type *t) {
|
||||||
t = base_type(t);
|
t = base_type(t);
|
||||||
return t->kind == Type_Slice;
|
return t->kind == Type_Slice;
|
||||||
@@ -546,6 +550,11 @@ b32 is_type_any(Type *t) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
b32 is_type_indexable(Type *t) {
|
||||||
|
return is_type_array(t) || is_type_slice(t) || is_type_vector(t) || is_type_string(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
b32 is_type_comparable(Type *t) {
|
b32 is_type_comparable(Type *t) {
|
||||||
t = base_type(t);
|
t = base_type(t);
|
||||||
|
|||||||
+73
-16
@@ -2821,9 +2821,35 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
|||||||
Type *t = base_type(type_of_expr(proc->module->info, ie->expr));
|
Type *t = base_type(type_of_expr(proc->module->info, ie->expr));
|
||||||
gbAllocator a = proc->module->allocator;
|
gbAllocator a = proc->module->allocator;
|
||||||
|
|
||||||
|
|
||||||
|
b32 deref = is_type_pointer(t);
|
||||||
|
t = type_deref(t);
|
||||||
|
|
||||||
|
ssaValue *using_addr = NULL;
|
||||||
|
if (!is_type_indexable(t)) {
|
||||||
|
// Using index expression
|
||||||
|
Entity *using_field = find_using_index_expr(t);
|
||||||
|
if (using_field != NULL) {
|
||||||
|
Selection sel = lookup_field(a, t, using_field->token.string, false);
|
||||||
|
ssaValue *e = ssa_build_addr(proc, ie->expr).addr;
|
||||||
|
using_addr = ssa_emit_deep_field_gep(proc, t, e, sel);
|
||||||
|
|
||||||
|
t = using_field->type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
switch (t->kind) {
|
switch (t->kind) {
|
||||||
case Type_Vector: {
|
case Type_Vector: {
|
||||||
ssaValue *vector = ssa_build_addr(proc, ie->expr).addr;
|
ssaValue *vector = NULL;
|
||||||
|
if (using_addr != NULL) {
|
||||||
|
vector = using_addr;
|
||||||
|
} else {
|
||||||
|
vector = ssa_build_addr(proc, ie->expr).addr;
|
||||||
|
if (deref) {
|
||||||
|
vector = ssa_emit_load(proc, vector);
|
||||||
|
}
|
||||||
|
}
|
||||||
ssaValue *index = ssa_emit_conv(proc, ssa_build_expr(proc, ie->index), t_int);
|
ssaValue *index = ssa_emit_conv(proc, ssa_build_expr(proc, ie->index), t_int);
|
||||||
ssaValue *len = ssa_make_const_int(a, t->Vector.count);
|
ssaValue *len = ssa_make_const_int(a, t->Vector.count);
|
||||||
ssa_array_bounds_check(proc, ast_node_token(ie->index), index, len);
|
ssa_array_bounds_check(proc, ast_node_token(ie->index), index, len);
|
||||||
@@ -2831,7 +2857,15 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Type_Array: {
|
case Type_Array: {
|
||||||
ssaValue *array = ssa_build_addr(proc, ie->expr).addr;
|
ssaValue *array = NULL;
|
||||||
|
if (using_addr != NULL) {
|
||||||
|
array = using_addr;
|
||||||
|
} else {
|
||||||
|
array = ssa_build_addr(proc, ie->expr).addr;
|
||||||
|
if (deref) {
|
||||||
|
array = ssa_emit_load(proc, array);
|
||||||
|
}
|
||||||
|
}
|
||||||
Type *et = make_type_pointer(proc->module->allocator, t->Array.elem);
|
Type *et = make_type_pointer(proc->module->allocator, t->Array.elem);
|
||||||
ssaValue *index = ssa_emit_conv(proc, ssa_build_expr(proc, ie->index), t_int);
|
ssaValue *index = ssa_emit_conv(proc, ssa_build_expr(proc, ie->index), t_int);
|
||||||
ssaValue *elem = ssa_emit_struct_gep(proc, array, index, et);
|
ssaValue *elem = ssa_emit_struct_gep(proc, array, index, et);
|
||||||
@@ -2841,7 +2875,15 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Type_Slice: {
|
case Type_Slice: {
|
||||||
ssaValue *slice = ssa_build_expr(proc, ie->expr);
|
ssaValue *slice = NULL;
|
||||||
|
if (using_addr != NULL) {
|
||||||
|
slice = ssa_emit_load(proc, using_addr);
|
||||||
|
} else {
|
||||||
|
slice = ssa_build_expr(proc, ie->expr);
|
||||||
|
if (deref) {
|
||||||
|
slice = ssa_emit_load(proc, slice);
|
||||||
|
}
|
||||||
|
}
|
||||||
ssaValue *elem = ssa_slice_elem(proc, slice);
|
ssaValue *elem = ssa_slice_elem(proc, slice);
|
||||||
ssaValue *len = ssa_slice_len(proc, slice);
|
ssaValue *len = ssa_slice_len(proc, slice);
|
||||||
ssaValue *index = ssa_emit_conv(proc, ssa_build_expr(proc, ie->index), t_int);
|
ssaValue *index = ssa_emit_conv(proc, ssa_build_expr(proc, ie->index), t_int);
|
||||||
@@ -2855,12 +2897,20 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
|||||||
TypeAndValue *tv = map_get(&proc->module->info->types, hash_pointer(ie->expr));
|
TypeAndValue *tv = map_get(&proc->module->info->types, hash_pointer(ie->expr));
|
||||||
ssaValue *elem = NULL;
|
ssaValue *elem = NULL;
|
||||||
ssaValue *len = NULL;
|
ssaValue *len = NULL;
|
||||||
if (tv->mode == Addressing_Constant) {
|
if (tv != NULL && tv->mode == Addressing_Constant) {
|
||||||
ssaValue *array = ssa_add_global_string_array(proc->module, tv->value.value_string);
|
ssaValue *array = ssa_add_global_string_array(proc->module, tv->value.value_string);
|
||||||
elem = ssa_array_elem(proc, array);
|
elem = ssa_array_elem(proc, array);
|
||||||
len = ssa_make_const_int(a, tv->value.value_string.len);
|
len = ssa_make_const_int(a, tv->value.value_string.len);
|
||||||
} else {
|
} else {
|
||||||
ssaValue *str = ssa_build_expr(proc, ie->expr);
|
ssaValue *str = NULL;
|
||||||
|
if (using_addr != NULL) {
|
||||||
|
str = ssa_emit_load(proc, using_addr);
|
||||||
|
} else {
|
||||||
|
str = ssa_build_expr(proc, ie->expr);
|
||||||
|
if (deref) {
|
||||||
|
str = ssa_emit_load(proc, str);
|
||||||
|
}
|
||||||
|
}
|
||||||
elem = ssa_string_elem(proc, str);
|
elem = ssa_string_elem(proc, str);
|
||||||
len = ssa_string_len(proc, str);
|
len = ssa_string_len(proc, str);
|
||||||
}
|
}
|
||||||
@@ -2884,23 +2934,30 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
|||||||
if (se->low != NULL) low = ssa_build_expr(proc, se->low);
|
if (se->low != NULL) low = ssa_build_expr(proc, se->low);
|
||||||
if (se->high != NULL) high = ssa_build_expr(proc, se->high);
|
if (se->high != NULL) high = ssa_build_expr(proc, se->high);
|
||||||
if (se->triple_indexed) max = ssa_build_expr(proc, se->max);
|
if (se->triple_indexed) max = ssa_build_expr(proc, se->max);
|
||||||
ssaAddr base = ssa_build_addr(proc, se->expr);
|
ssaValue *addr = ssa_build_addr(proc, se->expr).addr;
|
||||||
Type *type = base_type(ssa_addr_type(base));
|
ssaValue *base = ssa_emit_load(proc, addr);
|
||||||
|
Type *type = base_type(ssa_type(base));
|
||||||
|
|
||||||
|
if (is_type_pointer(type)) {
|
||||||
|
type = type_deref(type);
|
||||||
|
addr = base;
|
||||||
|
base = ssa_emit_load(proc, base);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(bill): Cleanup like mad!
|
// TODO(bill): Cleanup like mad!
|
||||||
|
|
||||||
switch (type->kind) {
|
switch (type->kind) {
|
||||||
case Type_Slice: {
|
case Type_Slice: {
|
||||||
Type *slice_type = ssa_addr_type(base);
|
Type *slice_type = type;
|
||||||
|
|
||||||
if (high == NULL) high = ssa_slice_len(proc, ssa_emit_load(proc, base.addr));
|
if (high == NULL) high = ssa_slice_len(proc, base);
|
||||||
if (max == NULL) max = ssa_slice_cap(proc, ssa_emit_load(proc, base.addr));
|
if (max == NULL) max = ssa_slice_cap(proc, base);
|
||||||
GB_ASSERT(max != NULL);
|
GB_ASSERT(max != NULL);
|
||||||
|
|
||||||
ssa_slice_bounds_check(proc, se->open, low, high, max, false);
|
ssa_slice_bounds_check(proc, se->open, low, high, max, false);
|
||||||
|
|
||||||
Token op_sub = {Token_Sub};
|
Token op_sub = {Token_Sub};
|
||||||
ssaValue *elem = ssa_slice_elem(proc, ssa_emit_load(proc, base.addr));
|
ssaValue *elem = ssa_slice_elem(proc, base);
|
||||||
ssaValue *len = ssa_emit_arith(proc, op_sub, high, low, t_int);
|
ssaValue *len = ssa_emit_arith(proc, op_sub, high, low, t_int);
|
||||||
ssaValue *cap = ssa_emit_arith(proc, op_sub, max, low, t_int);
|
ssaValue *cap = ssa_emit_arith(proc, op_sub, max, low, t_int);
|
||||||
ssaValue *slice = ssa_add_local_generated(proc, slice_type);
|
ssaValue *slice = ssa_add_local_generated(proc, slice_type);
|
||||||
@@ -2918,14 +2975,14 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
|||||||
case Type_Array: {
|
case Type_Array: {
|
||||||
Type *slice_type = make_type_slice(a, type->Array.elem);
|
Type *slice_type = make_type_slice(a, type->Array.elem);
|
||||||
|
|
||||||
if (high == NULL) high = ssa_array_len(proc, ssa_emit_load(proc, base.addr));
|
if (high == NULL) high = ssa_array_len(proc, base);
|
||||||
if (max == NULL) max = ssa_array_cap(proc, ssa_emit_load(proc, base.addr));
|
if (max == NULL) max = ssa_array_cap(proc, base);
|
||||||
GB_ASSERT(max != NULL);
|
GB_ASSERT(max != NULL);
|
||||||
|
|
||||||
ssa_slice_bounds_check(proc, se->open, low, high, max, false);
|
ssa_slice_bounds_check(proc, se->open, low, high, max, false);
|
||||||
|
|
||||||
Token op_sub = {Token_Sub};
|
Token op_sub = {Token_Sub};
|
||||||
ssaValue *elem = ssa_array_elem(proc, base.addr);
|
ssaValue *elem = ssa_array_elem(proc, addr);
|
||||||
ssaValue *len = ssa_emit_arith(proc, op_sub, high, low, t_int);
|
ssaValue *len = ssa_emit_arith(proc, op_sub, high, low, t_int);
|
||||||
ssaValue *cap = ssa_emit_arith(proc, op_sub, max, low, t_int);
|
ssaValue *cap = ssa_emit_arith(proc, op_sub, max, low, t_int);
|
||||||
ssaValue *slice = ssa_add_local_generated(proc, slice_type);
|
ssaValue *slice = ssa_add_local_generated(proc, slice_type);
|
||||||
@@ -2943,7 +3000,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
|||||||
case Type_Basic: {
|
case Type_Basic: {
|
||||||
GB_ASSERT(type == t_string);
|
GB_ASSERT(type == t_string);
|
||||||
if (high == NULL) {
|
if (high == NULL) {
|
||||||
high = ssa_string_len(proc, ssa_emit_load(proc, base.addr));
|
high = ssa_string_len(proc, base);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssa_slice_bounds_check(proc, se->open, low, high, high, true);
|
ssa_slice_bounds_check(proc, se->open, low, high, high, true);
|
||||||
@@ -2952,7 +3009,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
|||||||
ssaValue *elem, *len;
|
ssaValue *elem, *len;
|
||||||
len = ssa_emit_arith(proc, op_sub, high, low, t_int);
|
len = ssa_emit_arith(proc, op_sub, high, low, t_int);
|
||||||
|
|
||||||
elem = ssa_string_elem(proc, ssa_emit_load(proc, base.addr));
|
elem = ssa_string_elem(proc, base);
|
||||||
elem = ssa_emit_ptr_offset(proc, elem, low);
|
elem = ssa_emit_ptr_offset(proc, elem, low);
|
||||||
|
|
||||||
ssaValue *str = ssa_add_local_generated(proc, t_string);
|
ssaValue *str = ssa_add_local_generated(proc, t_string);
|
||||||
|
|||||||
Reference in New Issue
Block a user