aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2021-05-15 16:40:40 +0100
committergingerBill <bill@gingerbill.org>2021-05-15 16:40:40 +0100
commitb01c2e101712cf58e60bfc41d85fc33b60fcf349 (patch)
tree4eac823f639370f2a1dd229a3eb9e7ea5b72ba65
parent63b54ce7c695fb1e204fe77db029cdebf7206b28 (diff)
Disallow slicing of constant values
-rw-r--r--src/check_expr.cpp13
-rw-r--r--src/llvm_backend.cpp19
2 files changed, 28 insertions, 4 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index 51dad8f79..18f210b63 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -7811,10 +7811,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
return kind;
}
- o->mode = Addressing_Value;
-
if (se->low == nullptr && se->high != nullptr) {
- // error(se->interval0, "1st index is required if a 2nd index is specified");
// It is okay to continue as it will assume the 1st index is zero
}
@@ -7849,6 +7846,16 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
}
}
+ if (max_count < 0) {
+ if (o->mode == Addressing_Constant) {
+ gbString s = expr_to_string(se->expr);
+ error(se->expr, "Cannot slice constant value '%s'", s);
+ gb_string_free(s);
+ }
+ }
+
+ o->mode = Addressing_Value;
+
if (is_type_string(t) && max_count >= 0) {
bool all_constant = true;
for (isize i = 0; i < gb_count_of(nodes); i++) {
diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp
index dc36100a4..66c45793b 100644
--- a/src/llvm_backend.cpp
+++ b/src/llvm_backend.cpp
@@ -11360,6 +11360,15 @@ lbValue lb_find_ident(lbProcedure *p, lbModule *m, Entity *e, Ast *expr) {
return {};
}
+bool lb_is_expr_constant_zero(Ast *expr) {
+ GB_ASSERT(expr != nullptr);
+ auto v = exact_value_to_integer(expr->tav.value);
+ if (v.kind == ExactValue_Integer) {
+ return big_int_cmp_zero(&v.value_integer) == 0;
+ }
+ return false;
+}
+
lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
lbModule *m = p->module;
@@ -11683,6 +11692,13 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
case_end;
case_ast_node(se, SliceExpr, expr);
+ if (is_type_slice(type_of_expr(se->expr))) {
+ // NOTE(bill): Quick optimization
+ if (se->high == nullptr &&
+ (se->low == nullptr || lb_is_expr_constant_zero(se->low))) {
+ return lb_build_expr(p, se->expr);
+ }
+ }
return lb_addr_load(p, lb_build_addr(p, expr));
case_end;
@@ -12303,6 +12319,7 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
case_end;
case_ast_node(se, SliceExpr, expr);
+
lbValue low = lb_const_int(p->module, t_int, 0);
lbValue high = {};
@@ -13268,7 +13285,7 @@ lbAddr lb_add_global_generated(lbModule *m, Type *type, lbValue value) {
g.type = alloc_type_pointer(type);
g.value = LLVMAddGlobal(m->mod, lb_type(m, type), cast(char const *)str);
if (value.value != nullptr) {
- GB_ASSERT(LLVMIsConstant(value.value));
+ GB_ASSERT_MSG(LLVMIsConstant(value.value), LLVMPrintValueToString(value.value));
LLVMSetInitializer(g.value, value.value);
} else {
LLVMSetInitializer(g.value, LLVMConstNull(lb_type(m, type)));