mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 03:51:18 +00:00
Support for subscripts. Added helloworld.
This commit is contained in:
@@ -154,6 +154,6 @@ add_executable(c3c
|
|||||||
src/compiler/llvm_codegen_type.c
|
src/compiler/llvm_codegen_type.c
|
||||||
src/compiler/llvm_codegen_function.c)
|
src/compiler/llvm_codegen_function.c)
|
||||||
|
|
||||||
target_compile_options(c3c PRIVATE -Werror -Wall -Wextra -Wno-unused-function -Wno-unused-variable -Wno-unused-parameter)
|
target_compile_options(c3c PRIVATE -Wimplicit-int -Werror -Wall -Wextra -Wno-unused-function -Wno-unused-variable -Wno-unused-parameter)
|
||||||
|
|
||||||
target_link_libraries(c3c ${llvm_libs})
|
target_link_libraries(c3c m ${llvm_libs})
|
||||||
8
resources/testfragments/helloworld.c3
Normal file
8
resources/testfragments/helloworld.c3
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
module helloworld;
|
||||||
|
|
||||||
|
func void printf(char *str);
|
||||||
|
|
||||||
|
func void main()
|
||||||
|
{
|
||||||
|
printf("Hello World!\n");
|
||||||
|
}
|
||||||
@@ -92,6 +92,17 @@ func int main(int x)
|
|||||||
Test2 efe;
|
Test2 efe;
|
||||||
efe.t.a = 3;
|
efe.t.a = 3;
|
||||||
if (efe.t.a > 2) printf("Works!\n");
|
if (efe.t.a > 2) printf("Works!\n");
|
||||||
|
int ef = 3;
|
||||||
|
int *eff = &ef;
|
||||||
|
eff[0] = 4;
|
||||||
|
byte *ex = cast(byte *, eff);
|
||||||
|
ex[0] = 5;
|
||||||
|
if (eff[0] == 5) printf("Works-5!\n");
|
||||||
|
ex[1] = 5;
|
||||||
|
if (eff[0] == 5 + 5 * 256) printf("Works-5*256!\n");
|
||||||
|
if (ef == 4) printf("Works5!\n");
|
||||||
|
if (ef == 4) printf("Works1!\n");
|
||||||
|
ef = 0;
|
||||||
/*
|
/*
|
||||||
byte a = 2;
|
byte a = 2;
|
||||||
short b = 3;
|
short b = 3;
|
||||||
@@ -103,8 +114,21 @@ JUMP:
|
|||||||
i = i + 1;
|
i = i + 1;
|
||||||
//@hello();
|
//@hello();
|
||||||
printf("Hello worldABC" "D" "E\u2701\n");
|
printf("Hello worldABC" "D" "E\u2701\n");
|
||||||
float f = 10.0;
|
float f = 3.0;
|
||||||
float* pf = &f;
|
float* pf = &f;
|
||||||
|
switch (i)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
printf("c0\n");
|
||||||
|
case 1:
|
||||||
|
printf("c1\n");
|
||||||
|
case 2:
|
||||||
|
printf("c2\n");
|
||||||
|
case 3:
|
||||||
|
printf("c3\n");
|
||||||
|
default:
|
||||||
|
printf("default\n");
|
||||||
|
}
|
||||||
if (*pf > i) goto JUMP;
|
if (*pf > i) goto JUMP;
|
||||||
goto EX;
|
goto EX;
|
||||||
YEF:
|
YEF:
|
||||||
@@ -161,5 +185,6 @@ func void test2(int* x, int y, int z)
|
|||||||
i = i - 1;
|
i = i - 1;
|
||||||
ui = ui - 1;
|
ui = ui - 1;
|
||||||
x + 1;
|
x + 1;
|
||||||
// TODO x + 1;
|
int j1 = x[0];
|
||||||
|
j1 = *x;
|
||||||
}
|
}
|
||||||
@@ -27,7 +27,7 @@ static inline const uint64_t *bigint_ptr(const BigInt *big_int)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define alloc_digits(_digits) (_digits ? malloc_arena(sizeof(uint64_t) * _digits) : NULL)
|
#define alloc_digits(_digits) ((_digits) ? malloc_arena(sizeof(uint64_t) * (_digits)) : NULL)
|
||||||
|
|
||||||
static void normalize(BigInt *big_int)
|
static void normalize(BigInt *big_int)
|
||||||
{
|
{
|
||||||
@@ -76,7 +76,7 @@ static bool bit_at_index(const BigInt *big_int, size_t index)
|
|||||||
size_t digit_bit_index = index % 64;
|
size_t digit_bit_index = index % 64;
|
||||||
const uint64_t *digits = bigint_ptr(big_int);
|
const uint64_t *digits = bigint_ptr(big_int);
|
||||||
uint64_t digit = digits[digit_index];
|
uint64_t digit = digits[digit_index];
|
||||||
return ((digit >> digit_bit_index) & 0x1) == 0x1;
|
return ((digit >> digit_bit_index) & 0x1U) == 0x1U;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t bigint_hash(BigInt x)
|
uint32_t bigint_hash(BigInt x)
|
||||||
@@ -392,7 +392,7 @@ void bigint_write_twos_complement(const BigInt *big_int, uint8_t *buf, size_t bi
|
|||||||
|
|
||||||
for (size_t byte_index = 7;;)
|
for (size_t byte_index = 7;;)
|
||||||
{
|
{
|
||||||
uint8_t byte = (uint8_t) (x & 0xff);
|
uint8_t byte = (uint8_t) (x & 0xffU);
|
||||||
if (digit_index == last_digit_index)
|
if (digit_index == last_digit_index)
|
||||||
{
|
{
|
||||||
buf[buf_index + byte_index - unwritten_byte_count] = byte;
|
buf[buf_index + byte_index - unwritten_byte_count] = byte;
|
||||||
@@ -405,7 +405,7 @@ void bigint_write_twos_complement(const BigInt *big_int, uint8_t *buf, size_t bi
|
|||||||
|
|
||||||
if (byte_index == 0) break;
|
if (byte_index == 0) break;
|
||||||
byte_index -= 1;
|
byte_index -= 1;
|
||||||
x >>= 8;
|
x >>= 8U;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (digit_index == 0) break;
|
if (digit_index == 0) break;
|
||||||
@@ -432,10 +432,10 @@ void bigint_write_twos_complement(const BigInt *big_int, uint8_t *buf, size_t bi
|
|||||||
byte_index < 8 && (digit_index + 1 < digit_count || byte_index < bytes_in_last_digit);
|
byte_index < 8 && (digit_index + 1 < digit_count || byte_index < bytes_in_last_digit);
|
||||||
byte_index += 1)
|
byte_index += 1)
|
||||||
{
|
{
|
||||||
uint8_t byte = (uint8_t) (x & 0xff);
|
uint8_t byte = (uint8_t) (x & 0xffU);
|
||||||
buf[buf_index] = byte;
|
buf[buf_index] = byte;
|
||||||
buf_index += 1;
|
buf_index += 1;
|
||||||
x >>= 8;
|
x >>= 8U;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -492,7 +492,7 @@ void bigint_read_twos_complement(BigInt *dest, const uint8_t *buf, size_t bit_co
|
|||||||
{
|
{
|
||||||
uint8_t byte = buf[buf_index];
|
uint8_t byte = buf[buf_index];
|
||||||
buf_index += 1;
|
buf_index += 1;
|
||||||
digit <<= 8;
|
digit <<= 8U;
|
||||||
digit |= byte;
|
digit |= byte;
|
||||||
}
|
}
|
||||||
digits[dest->digit_count - 1] = digit;
|
digits[dest->digit_count - 1] = digit;
|
||||||
@@ -937,7 +937,7 @@ static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t *r, unsigne
|
|||||||
u[m + n] = u_carry;
|
u[m + n] = u_carry;
|
||||||
|
|
||||||
// D2. [Initialize j.] Set j to m. This is the loop counter over the places.
|
// D2. [Initialize j.] Set j to m. This is the loop counter over the places.
|
||||||
int j = m;
|
int j = (int)m;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
// D3. [Calculate q'.].
|
// D3. [Calculate q'.].
|
||||||
@@ -1016,7 +1016,7 @@ static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t *r, unsigne
|
|||||||
if (shift)
|
if (shift)
|
||||||
{
|
{
|
||||||
uint32_t carry = 0;
|
uint32_t carry = 0;
|
||||||
for (int i = n - 1; i >= 0; i--)
|
for (int i = (int)n - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
r[i] = (u[i] >> shift) | carry;
|
r[i] = (u[i] >> shift) | carry;
|
||||||
carry = u[i] << (32 - shift);
|
carry = u[i] << (32 - shift);
|
||||||
@@ -1024,7 +1024,7 @@ static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t *r, unsigne
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (int i = n - 1; i >= 0; i--)
|
for (int i = (int)n - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
r[i] = u[i];
|
r[i] = u[i];
|
||||||
}
|
}
|
||||||
@@ -1151,7 +1151,7 @@ static void bigint_unsigned_division(const BigInt *op1, const BigInt *op2, BigIn
|
|||||||
{
|
{
|
||||||
uint32_t divisor = V[0];
|
uint32_t divisor = V[0];
|
||||||
uint32_t rem = 0;
|
uint32_t rem = 0;
|
||||||
for (int i = m; i >= 0; i--)
|
for (int i = (int)m; i >= 0; i--)
|
||||||
{
|
{
|
||||||
uint64_t partial_dividend = make_64(rem, U[i]);
|
uint64_t partial_dividend = make_64(rem, U[i]);
|
||||||
if (partial_dividend == 0)
|
if (partial_dividend == 0)
|
||||||
@@ -2076,7 +2076,7 @@ long double bigint_as_float(const BigInt *bigint)
|
|||||||
return bigint->is_negative ? bigint_as_signed(bigint) : bigint_as_unsigned(bigint);
|
return bigint->is_negative ? bigint_as_signed(bigint) : bigint_as_unsigned(bigint);
|
||||||
}
|
}
|
||||||
BigInt div;
|
BigInt div;
|
||||||
uint64_t mult = 0x100000000000ull;
|
uint64_t mult = 0x100000000000ULL;
|
||||||
long double mul = 1;
|
long double mul = 1;
|
||||||
bigint_init_unsigned(&div, mult);
|
bigint_init_unsigned(&div, mult);
|
||||||
BigInt current;
|
BigInt current;
|
||||||
|
|||||||
@@ -538,125 +538,6 @@ bool vapt(Expr* left, Type *from, Type *canonical, Type *type, CastType cast_typ
|
|||||||
TODO
|
TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
CastFunc conversion(TypeKind from, Type *to)
|
|
||||||
{
|
|
||||||
switch (from)
|
|
||||||
{
|
|
||||||
case TYPE_POISONED:
|
|
||||||
return &erro;
|
|
||||||
case TYPE_VOID:
|
|
||||||
return &erro;
|
|
||||||
case TYPE_BOOL:
|
|
||||||
if (type_is_integer(to)) return &boxi;
|
|
||||||
if (type_is_float(to)) return &bofp;
|
|
||||||
return &erro;
|
|
||||||
case TYPE_ERROR_UNION:
|
|
||||||
TODO
|
|
||||||
case TYPE_I8:
|
|
||||||
case TYPE_I16:
|
|
||||||
case TYPE_I32:
|
|
||||||
case TYPE_I64:
|
|
||||||
case TYPE_IXX:
|
|
||||||
if (type_is_unsigned_integer(to)) return &siui;
|
|
||||||
if (type_is_signed_integer(to)) return &sisi;
|
|
||||||
if (type_is_float(to)) return &sifp;
|
|
||||||
if (to == type_bool) return &xibo;
|
|
||||||
if (to->type_kind == TYPE_POINTER) return &ptxi;
|
|
||||||
return &erro;
|
|
||||||
case TYPE_U8:
|
|
||||||
case TYPE_U16:
|
|
||||||
case TYPE_U32:
|
|
||||||
case TYPE_U64:
|
|
||||||
case TYPE_UXX:
|
|
||||||
if (type_is_unsigned_integer(to)) return &uiui;
|
|
||||||
if (type_is_signed_integer(to)) return &uisi;
|
|
||||||
if (type_is_float(to)) return &uifp;
|
|
||||||
if (to == type_bool) return &xibo;
|
|
||||||
if (to->type_kind == TYPE_POINTER) return &ptxi;
|
|
||||||
return &erro;
|
|
||||||
case TYPE_F32:
|
|
||||||
case TYPE_F64:
|
|
||||||
case TYPE_FXX:
|
|
||||||
if (type_is_unsigned_integer(to)) return &fpui;
|
|
||||||
if (type_is_signed_integer(to)) return &fpsi;
|
|
||||||
if (to == type_bool) return &fpbo;
|
|
||||||
if (type_is_float(to)) return &fpfp;
|
|
||||||
return &erro;
|
|
||||||
case TYPE_POINTER:
|
|
||||||
if (type_is_integer(to)) return &ptxi;
|
|
||||||
if (to->type_kind == TYPE_BOOL) return &ptbo;
|
|
||||||
if (to->type_kind == TYPE_POINTER) return &ptpt;
|
|
||||||
if (to->type_kind == TYPE_FUNC) return &ptfu;
|
|
||||||
if (to->type_kind == TYPE_VARARRAY) return &ptva;
|
|
||||||
return &erro;
|
|
||||||
case TYPE_ENUM:
|
|
||||||
if (type_is_integer(to)) return &enxi;
|
|
||||||
return &erro;
|
|
||||||
case TYPE_ERROR:
|
|
||||||
if (type_is_integer(to)) return &erxi;
|
|
||||||
return &erro;
|
|
||||||
case TYPE_FUNC:
|
|
||||||
if (type_is_integer(to)) return &ptxi;
|
|
||||||
if (to->type_kind == TYPE_POINTER) return &fupt;
|
|
||||||
return &erro;
|
|
||||||
case TYPE_STRUCT:
|
|
||||||
if (to->type_kind == TYPE_STRUCT) return &stst;
|
|
||||||
if (to->type_kind == TYPE_UNION) return &stun;
|
|
||||||
return &erro;
|
|
||||||
case TYPE_UNION:
|
|
||||||
if (to->type_kind == TYPE_STRUCT) return &unst;
|
|
||||||
if (to->type_kind == TYPE_UNION) return &unun;
|
|
||||||
return &erro;
|
|
||||||
case TYPE_TYPEDEF:
|
|
||||||
UNREACHABLE
|
|
||||||
case TYPE_STRING:
|
|
||||||
if (to->type_kind == TYPE_POINTER) return &strpt;
|
|
||||||
return &erro;
|
|
||||||
case TYPE_ARRAY:
|
|
||||||
return &erro;
|
|
||||||
case TYPE_VARARRAY:
|
|
||||||
if (to->type_kind == TYPE_SUBARRAY) return &vasa;
|
|
||||||
if (to->type_kind == TYPE_VARARRAY) return &vava;
|
|
||||||
if (to->type_kind == TYPE_POINTER) return &vapt;
|
|
||||||
return &erro;
|
|
||||||
case TYPE_SUBARRAY:
|
|
||||||
if (to->type_kind == TYPE_POINTER) return &sapt;
|
|
||||||
// if (to->type_kind == )
|
|
||||||
return &erro;
|
|
||||||
}
|
|
||||||
UNREACHABLE
|
|
||||||
}
|
|
||||||
|
|
||||||
Type t_cpy = { .name = "cpy" };
|
|
||||||
Type t_err = { .name = "err" };
|
|
||||||
|
|
||||||
Type *ARITHMETIC_PROMOTION[19][19] = {
|
|
||||||
//other bool, char, short, int, long, ctint, byte, ushort, int, ulong, ctuint, float, double, ctreal, user, ptr, str, arr, varr // from:
|
|
||||||
{ &t_u1, &t_i8, &t_i16, &t_i32, &t_i64, &t_u1, &t_u8, &t_u16, &t_u32, &t_u64, &t_u1, &t_f32, &t_f64, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err }, // bool
|
|
||||||
{ &t_i8, &t_i8, &t_i16, &t_i32, &t_i64, &t_i8, &t_i8, &t_i16, &t_i32, &t_i64, &t_i8, &t_f32, &t_f64, &t_err, &t_err, &t_isz, &t_err, &t_err, &t_err }, // char
|
|
||||||
{ &t_i16, &t_i16, &t_i16, &t_i32, &t_i64, &t_i16, &t_i16, &t_i16, &t_i32, &t_i64, &t_i16, &t_f32, &t_f64, &t_err, &t_err, &t_isz, &t_err, &t_err, &t_err }, // short
|
|
||||||
{ &t_i32, &t_i32, &t_i32, &t_i32, &t_i64, &t_i32, &t_i32, &t_i32, &t_i32, &t_i64, &t_i32, &t_f32, &t_f64, &t_err, &t_err, &t_isz, &t_err, &t_err, &t_err }, // int
|
|
||||||
{ &t_i64, &t_i64, &t_i64, &t_i64, &t_i64, &t_i64, &t_i64, &t_i64, &t_i64, &t_i64, &t_i64, &t_f32, &t_f64, &t_err, &t_err, &t_isz, &t_err, &t_err, &t_err }, // long
|
|
||||||
{ &t_u1, &t_i8, &t_i16, &t_i32, &t_i64, &t_ixx, &t_i8, &t_i16, &t_i32, &t_i64, &t_ixx, &t_f32, &t_f64, &t_fxx, &t_err, &t_isz, &t_err, &t_err, &t_err }, // ixx
|
|
||||||
{ &t_u8, &t_i8, &t_i16, &t_i32, &t_i64, &t_u8, &t_u8, &t_u16, &t_u32, &t_i64, &t_uxx, &t_f32, &t_f64, &t_err, &t_err, &t_usz, &t_err, &t_err, &t_err }, // byte
|
|
||||||
{ &t_u16, &t_i16, &t_i16, &t_i32, &t_i64, &t_u16, &t_u16, &t_u16, &t_u32, &t_i64, &t_uxx, &t_f32, &t_f64, &t_err, &t_err, &t_usz, &t_err, &t_err, &t_err }, // ushort
|
|
||||||
{ &t_u32, &t_i32, &t_i32, &t_i32, &t_i64, &t_u32, &t_u32, &t_u32, &t_u32, &t_i64, &t_uxx, &t_f32, &t_f64, &t_err, &t_err, &t_usz, &t_err, &t_err, &t_err }, // uint
|
|
||||||
{ &t_u64, &t_i64, &t_i64, &t_i64, &t_i64, &t_u64, &t_u64, &t_u64, &t_u64, &t_i64, &t_uxx, &t_f32, &t_f64, &t_err, &t_err, &t_usz, &t_err, &t_err, &t_err }, // ulong
|
|
||||||
{ &t_u1, &t_i8, &t_i16, &t_i32, &t_i64, &t_uxx, &t_u8, &t_u16, &t_u32, &t_u64, &t_uxx, &t_f32, &t_f64, &t_fxx, &t_err, &t_usz, &t_err, &t_err, &t_err }, // uxx
|
|
||||||
{ &t_f32, &t_f32, &t_f32, &t_f32, &t_f32, &t_f32, &t_f32, &t_f32, &t_f32, &t_f32, &t_f32, &t_f32, &t_f64, &t_f32, &t_err, &t_err, &t_err, &t_err, &t_err }, // float
|
|
||||||
{ &t_f64, &t_f64, &t_f64, &t_f64, &t_f64, &t_f64, &t_f64, &t_f64, &t_f64, &t_f64, &t_f64, &t_f64, &t_f64, &t_f64, &t_err, &t_err, &t_err, &t_err, &t_err }, // double
|
|
||||||
{ &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_f32, &t_f64, &t_fxx, &t_err, &t_err, &t_err, &t_err, &t_err }, // fxx
|
|
||||||
{ &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err }, // user
|
|
||||||
{ &t_err, &t_cpy, &t_cpy, &t_cpy, &t_cpy, &t_cpy, &t_cpy, &t_cpy, &t_cpy, &t_cpy, &t_cpy, &t_cpy, &t_err, &t_err, &t_err, &t_cpy, &t_err, &t_err, &t_err }, // ptr
|
|
||||||
{ &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err }, // str
|
|
||||||
{ &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err }, // arr
|
|
||||||
{ &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err }, // varr
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline bool cannot_convert(TypeKind type_kind)
|
|
||||||
{
|
|
||||||
return type_kind <= TYPE_VOID || type_kind > TYPE_ARRAY;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool cast_to_runtime(Expr *expr)
|
bool cast_to_runtime(Expr *expr)
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ static bool expr_is_ltype(Expr *expr)
|
|||||||
return expr->unary_expr.operator == TOKEN_STAR;
|
return expr->unary_expr.operator == TOKEN_STAR;
|
||||||
case EXPR_ACCESS:
|
case EXPR_ACCESS:
|
||||||
return expr_is_ltype(expr->access_expr.parent);
|
return expr_is_ltype(expr->access_expr.parent);
|
||||||
|
case EXPR_SUBSCRIPT:
|
||||||
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -163,7 +165,6 @@ static inline bool sema_expr_analyse_call(Context *context, Type *to, Expr *expr
|
|||||||
default:
|
default:
|
||||||
SEMA_ERROR(expr->loc, "The expression cannot be called.");
|
SEMA_ERROR(expr->loc, "The expression cannot be called.");
|
||||||
return false;
|
return false;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,7 +180,33 @@ static inline bool sema_expr_analyse_struct_init_values(Context *context, Type *
|
|||||||
|
|
||||||
static inline bool sema_expr_analyse_subscript(Context *context, Type *to, Expr *expr)
|
static inline bool sema_expr_analyse_subscript(Context *context, Type *to, Expr *expr)
|
||||||
{
|
{
|
||||||
TODO
|
if (!sema_analyse_expr(context, NULL, expr->subscript_expr.expr)) return false;
|
||||||
|
|
||||||
|
Type *type = expr->subscript_expr.expr->type->canonical;
|
||||||
|
Type *inner_type;
|
||||||
|
switch (type->type_kind)
|
||||||
|
{
|
||||||
|
case TYPE_POINTER:
|
||||||
|
inner_type = type->pointer;
|
||||||
|
break;
|
||||||
|
case TYPE_VARARRAY:
|
||||||
|
case TYPE_ARRAY:
|
||||||
|
inner_type = type->array.base;
|
||||||
|
break;
|
||||||
|
case TYPE_SUBARRAY:
|
||||||
|
TODO
|
||||||
|
case TYPE_STRING:
|
||||||
|
inner_type = type_char;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
SEMA_ERROR(expr->subscript_expr.expr->loc, "Cannot index '%s'.", type_to_error_string(type));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sema_analyse_expr(context, type_isize, expr->subscript_expr.index)) return false;
|
||||||
|
|
||||||
|
expr->type = inner_type;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool sema_expr_analyse_method_function(Context *context, Expr *expr, Decl *decl, bool is_pointer)
|
static inline bool sema_expr_analyse_method_function(Context *context, Expr *expr, Decl *decl, bool is_pointer)
|
||||||
@@ -1445,6 +1472,8 @@ static inline bool sema_analyse_expr_dispatch(Context *context, Type *to, Expr *
|
|||||||
}
|
}
|
||||||
UNREACHABLE
|
UNREACHABLE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool sema_analyse_expr(Context *context, Type *to, Expr *expr)
|
bool sema_analyse_expr(Context *context, Type *to, Expr *expr)
|
||||||
{
|
{
|
||||||
switch (expr->resolve_status)
|
switch (expr->resolve_status)
|
||||||
|
|||||||
@@ -5,54 +5,63 @@
|
|||||||
#include "llvm_codegen_internal.h"
|
#include "llvm_codegen_internal.h"
|
||||||
#include "compiler_internal.h"
|
#include "compiler_internal.h"
|
||||||
|
|
||||||
|
static inline LLVMValueRef gencontext_emit_subscript_addr(GenContext *context, Expr *expr)
|
||||||
|
{
|
||||||
|
LLVMValueRef index = gencontext_emit_expr(context, expr->subscript_expr.index);
|
||||||
|
switch (expr->subscript_expr.expr->type->canonical->type_kind)
|
||||||
|
{
|
||||||
|
case TYPE_ARRAY:
|
||||||
|
TODO
|
||||||
|
case TYPE_POINTER:
|
||||||
|
return LLVMBuildGEP(context->builder,
|
||||||
|
gencontext_emit_expr(context, expr->subscript_expr.expr),
|
||||||
|
&index, 1, "[]");
|
||||||
|
case TYPE_VARARRAY:
|
||||||
|
case TYPE_SUBARRAY:
|
||||||
|
case TYPE_STRING:
|
||||||
|
TODO
|
||||||
|
default:
|
||||||
|
UNREACHABLE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline LLVMValueRef gencontext_emit_access_addr(GenContext *context, Expr *expr)
|
||||||
|
{
|
||||||
|
LLVMValueRef value = gencontext_emit_address(context, expr->access_expr.parent);
|
||||||
|
return LLVMBuildStructGEP(context->builder, value, (unsigned)expr->access_expr.index, "");
|
||||||
|
}
|
||||||
|
|
||||||
LLVMValueRef gencontext_emit_address(GenContext *context, Expr *expr)
|
LLVMValueRef gencontext_emit_address(GenContext *context, Expr *expr)
|
||||||
{
|
{
|
||||||
switch (expr->expr_kind)
|
switch (expr->expr_kind)
|
||||||
{
|
{
|
||||||
case EXPR_IDENTIFIER:
|
case EXPR_IDENTIFIER:
|
||||||
return expr->identifier_expr.decl->var.backend_ref;
|
return expr->identifier_expr.decl->var.backend_ref;
|
||||||
|
case EXPR_UNARY:
|
||||||
|
assert(unaryop_from_token(expr->unary_expr.operator) == UNARYOP_DEREF);
|
||||||
|
return gencontext_emit_expr(context, expr->unary_expr.expr);
|
||||||
|
case EXPR_ACCESS:
|
||||||
|
return gencontext_emit_access_addr(context, expr);
|
||||||
|
case EXPR_SUBSCRIPT:
|
||||||
|
return gencontext_emit_subscript_addr(context, expr);
|
||||||
case EXPR_CONST:
|
case EXPR_CONST:
|
||||||
case EXPR_TYPE:
|
case EXPR_TYPE:
|
||||||
UNREACHABLE
|
|
||||||
case EXPR_UNARY:
|
|
||||||
{
|
|
||||||
UnaryOp op = unaryop_from_token(expr->unary_expr.operator);
|
|
||||||
assert(op == UNARYOP_DEREF);
|
|
||||||
return gencontext_emit_expr(context, expr->unary_expr.expr);
|
|
||||||
}
|
|
||||||
case EXPR_ACCESS:
|
|
||||||
{
|
|
||||||
LLVMValueRef value = gencontext_emit_address(context, expr->access_expr.parent);
|
|
||||||
return LLVMBuildStructGEP(context->builder, value, (unsigned)expr->access_expr.index, "");
|
|
||||||
}
|
|
||||||
case EXPR_POISONED:
|
case EXPR_POISONED:
|
||||||
case EXPR_TRY:
|
case EXPR_TRY:
|
||||||
case EXPR_SIZEOF:
|
case EXPR_SIZEOF:
|
||||||
UNREACHABLE
|
|
||||||
case EXPR_BINARY:
|
case EXPR_BINARY:
|
||||||
TODO;
|
|
||||||
case EXPR_CONDITIONAL:
|
case EXPR_CONDITIONAL:
|
||||||
TODO;
|
|
||||||
case EXPR_POST_UNARY:
|
case EXPR_POST_UNARY:
|
||||||
TODO;
|
|
||||||
case EXPR_TYPE_ACCESS:
|
case EXPR_TYPE_ACCESS:
|
||||||
TODO
|
|
||||||
case EXPR_CALL:
|
case EXPR_CALL:
|
||||||
TODO
|
|
||||||
case EXPR_SUBSCRIPT:
|
|
||||||
TODO
|
|
||||||
case EXPR_STRUCT_VALUE:
|
case EXPR_STRUCT_VALUE:
|
||||||
TODO
|
|
||||||
case EXPR_STRUCT_INIT_VALUES:
|
case EXPR_STRUCT_INIT_VALUES:
|
||||||
TODO
|
|
||||||
case EXPR_INITIALIZER_LIST:
|
case EXPR_INITIALIZER_LIST:
|
||||||
TODO
|
|
||||||
case EXPR_EXPRESSION_LIST:
|
case EXPR_EXPRESSION_LIST:
|
||||||
TODO
|
|
||||||
case EXPR_CAST:
|
case EXPR_CAST:
|
||||||
TODO
|
UNREACHABLE
|
||||||
}
|
}
|
||||||
return NULL;
|
UNREACHABLE
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline LLVMValueRef gencontext_emit_cast_expr(GenContext *context, Expr *expr)
|
static inline LLVMValueRef gencontext_emit_cast_expr(GenContext *context, Expr *expr)
|
||||||
@@ -98,7 +107,6 @@ static inline LLVMValueRef gencontext_emit_cast_expr(GenContext *context, Expr *
|
|||||||
return type_convert_will_trunc(expr->type, expr->cast_expr.expr->type)
|
return type_convert_will_trunc(expr->type, expr->cast_expr.expr->type)
|
||||||
? LLVMBuildTrunc(context->builder, rhs, BACKEND_TYPE(expr->type), "siuitrunc")
|
? LLVMBuildTrunc(context->builder, rhs, BACKEND_TYPE(expr->type), "siuitrunc")
|
||||||
: LLVMBuildZExt(context->builder, rhs, BACKEND_TYPE(expr->type), "siuiext");
|
: LLVMBuildZExt(context->builder, rhs, BACKEND_TYPE(expr->type), "siuiext");
|
||||||
break;
|
|
||||||
case CAST_SIFP:
|
case CAST_SIFP:
|
||||||
return LLVMBuildSIToFP(context->builder, rhs, BACKEND_TYPE(expr->type), "sifp");
|
return LLVMBuildSIToFP(context->builder, rhs, BACKEND_TYPE(expr->type), "sifp");
|
||||||
case CAST_XIPTR:
|
case CAST_XIPTR:
|
||||||
@@ -421,7 +429,7 @@ LLVMValueRef gencontext_emit_const_expr(GenContext *context, Expr *expr)
|
|||||||
LLVMSetInitializer(global_name, LLVMConstStringInContext(context->context,
|
LLVMSetInitializer(global_name, LLVMConstStringInContext(context->context,
|
||||||
expr->const_expr.string.chars,
|
expr->const_expr.string.chars,
|
||||||
expr->const_expr.string.len,
|
expr->const_expr.string.len,
|
||||||
1));
|
0));
|
||||||
return global_name;
|
return global_name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -444,6 +452,48 @@ LLVMValueRef gencontext_emit_call_expr(GenContext *context, Expr *expr)
|
|||||||
LLVMSetInstructionCallConv(fncallret, LLVMX86StdcallCallConv);
|
LLVMSetInstructionCallConv(fncallret, LLVMX86StdcallCallConv);
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static inline LLVMValueRef gencontext_emit_access_expr(GenContext *context, Expr *expr)
|
||||||
|
{
|
||||||
|
// Improve, add string description to the access?
|
||||||
|
LLVMValueRef value = gencontext_emit_address(context, expr->access_expr.parent);
|
||||||
|
LLVMValueRef val = LLVMBuildStructGEP(context->builder, value, (unsigned)expr->access_expr.index, "");
|
||||||
|
return LLVMBuildLoad2(context->builder, gencontext_get_llvm_type(context, expr->type), val, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline LLVMValueRef gencontext_emit_expression_list_expr(GenContext *context, Expr *expr)
|
||||||
|
{
|
||||||
|
LLVMValueRef value = NULL;
|
||||||
|
VECEACH(expr->expression_list, i)
|
||||||
|
{
|
||||||
|
value = gencontext_emit_expr(context, expr->expression_list[i]);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline LLVMValueRef gencontext_emit_struct_value_expr(GenContext *context, Expr *expr)
|
||||||
|
{
|
||||||
|
TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline LLVMValueRef gencontext_emit_initializer_list_expr(GenContext *context, Expr *expr)
|
||||||
|
{
|
||||||
|
TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline LLVMValueRef gencontext_emit_struct_init_values_expr(GenContext *context, Expr *expr)
|
||||||
|
{
|
||||||
|
TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline LLVMValueRef gencontext_load_expr(GenContext *context, LLVMValueRef value)
|
||||||
|
{
|
||||||
|
return LLVMBuildLoad(context->builder, value, "");
|
||||||
|
}
|
||||||
|
|
||||||
LLVMValueRef gencontext_emit_expr(GenContext *context, Expr *expr)
|
LLVMValueRef gencontext_emit_expr(GenContext *context, Expr *expr)
|
||||||
{
|
{
|
||||||
switch (expr->expr_kind)
|
switch (expr->expr_kind)
|
||||||
@@ -452,8 +502,6 @@ LLVMValueRef gencontext_emit_expr(GenContext *context, Expr *expr)
|
|||||||
UNREACHABLE
|
UNREACHABLE
|
||||||
case EXPR_UNARY:
|
case EXPR_UNARY:
|
||||||
return gencontext_emit_unary_expr(context, expr);
|
return gencontext_emit_unary_expr(context, expr);
|
||||||
case EXPR_TRY:
|
|
||||||
break;
|
|
||||||
case EXPR_CONST:
|
case EXPR_CONST:
|
||||||
return gencontext_emit_const_expr(context, expr);
|
return gencontext_emit_const_expr(context, expr);
|
||||||
case EXPR_BINARY:
|
case EXPR_BINARY:
|
||||||
@@ -463,33 +511,28 @@ LLVMValueRef gencontext_emit_expr(GenContext *context, Expr *expr)
|
|||||||
case EXPR_POST_UNARY:
|
case EXPR_POST_UNARY:
|
||||||
return gencontext_emit_post_unary_expr(context, expr);
|
return gencontext_emit_post_unary_expr(context, expr);
|
||||||
case EXPR_TYPE:
|
case EXPR_TYPE:
|
||||||
break;
|
case EXPR_SIZEOF:
|
||||||
case EXPR_IDENTIFIER:
|
|
||||||
return gencontext_emit_identifier_expr(context, expr);
|
|
||||||
case EXPR_TYPE_ACCESS:
|
case EXPR_TYPE_ACCESS:
|
||||||
break;
|
case EXPR_TRY:
|
||||||
|
// These are folded in the semantic analysis step.
|
||||||
|
UNREACHABLE
|
||||||
|
case EXPR_IDENTIFIER:
|
||||||
|
case EXPR_SUBSCRIPT:
|
||||||
|
return gencontext_load_expr(context, gencontext_emit_address(context, expr));
|
||||||
case EXPR_CALL:
|
case EXPR_CALL:
|
||||||
return gencontext_emit_call_expr(context, expr);
|
return gencontext_emit_call_expr(context, expr);
|
||||||
case EXPR_SIZEOF:
|
|
||||||
break;
|
|
||||||
case EXPR_SUBSCRIPT:
|
|
||||||
break;
|
|
||||||
case EXPR_ACCESS:
|
case EXPR_ACCESS:
|
||||||
{
|
return gencontext_emit_access_expr(context, expr);
|
||||||
LLVMValueRef value = gencontext_emit_address(context, expr->access_expr.parent);
|
|
||||||
LLVMValueRef val = LLVMBuildStructGEP(context->builder, value, (unsigned)expr->access_expr.index, "");
|
|
||||||
return LLVMBuildLoad2(context->builder, gencontext_get_llvm_type(context, expr->type), val, "");
|
|
||||||
}
|
|
||||||
case EXPR_STRUCT_VALUE:
|
case EXPR_STRUCT_VALUE:
|
||||||
break;
|
return gencontext_emit_struct_value_expr(context, expr);
|
||||||
case EXPR_STRUCT_INIT_VALUES:
|
case EXPR_STRUCT_INIT_VALUES:
|
||||||
break;
|
return gencontext_emit_struct_init_values_expr(context, expr);
|
||||||
case EXPR_INITIALIZER_LIST:
|
case EXPR_INITIALIZER_LIST:
|
||||||
break;
|
return gencontext_emit_initializer_list_expr(context, expr);
|
||||||
case EXPR_EXPRESSION_LIST:
|
case EXPR_EXPRESSION_LIST:
|
||||||
break;
|
return gencontext_emit_expression_list_expr(context, expr);
|
||||||
case EXPR_CAST:
|
case EXPR_CAST:
|
||||||
return gencontext_emit_cast_expr(context, expr);
|
return gencontext_emit_cast_expr(context, expr);
|
||||||
}
|
}
|
||||||
TODO
|
UNREACHABLE
|
||||||
}
|
}
|
||||||
@@ -13,5 +13,5 @@ void bench_begin(void)
|
|||||||
}
|
}
|
||||||
double bench_mark(void)
|
double bench_mark(void)
|
||||||
{
|
{
|
||||||
return (clock() - begin) / (double)CLOCKS_PER_SEC;
|
return (double)(clock() - begin) / (double)CLOCKS_PER_SEC;
|
||||||
}
|
}
|
||||||
@@ -59,7 +59,6 @@ char *read_file(const char *path, size_t *return_size)
|
|||||||
if (file == NULL)
|
if (file == NULL)
|
||||||
{
|
{
|
||||||
error_exit("Could not open file \"%s\".\n", path);
|
error_exit("Could not open file \"%s\".\n", path);
|
||||||
exit(74);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fseek(file, 0L, SEEK_END);
|
fseek(file, 0L, SEEK_END);
|
||||||
|
|||||||
@@ -28,11 +28,11 @@ static inline bool is_power_of_two(uint64_t x)
|
|||||||
static inline uint32_t nextHighestPowerOf2(uint32_t v)
|
static inline uint32_t nextHighestPowerOf2(uint32_t v)
|
||||||
{
|
{
|
||||||
v--;
|
v--;
|
||||||
v |= v >> 1u;
|
v |= v >> 1U;
|
||||||
v |= v >> 2u;
|
v |= v >> 2U;
|
||||||
v |= v >> 4u;
|
v |= v >> 4U;
|
||||||
v |= v >> 8u;
|
v |= v >> 8U;
|
||||||
v |= v >> 16u;
|
v |= v >> 16U;
|
||||||
v++;
|
v++;
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
@@ -66,12 +66,12 @@ static inline bool is_oct_or_(char c)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool is_binary(c)
|
static inline bool is_binary(char c)
|
||||||
{
|
{
|
||||||
return c == '0' || c == '1';
|
return c == '0' || c == '1';
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool is_binary_or_(c)
|
static inline bool is_binary_or_(char c)
|
||||||
{
|
{
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
@@ -251,10 +251,10 @@ static inline void* _expand(void *vec, size_t element_size)
|
|||||||
header->size++;
|
header->size++;
|
||||||
if (header->size == header->capacity)
|
if (header->size == header->capacity)
|
||||||
{
|
{
|
||||||
_VHeader *new_array = _vec_new(element_size, header->capacity << 1u);
|
_VHeader *new_array = _vec_new(element_size, header->capacity << 1U);
|
||||||
memcpy(new_array, header, element_size * header->capacity + sizeof(_VHeader));
|
memcpy(new_array, header, element_size * header->capacity + sizeof(_VHeader));
|
||||||
header = new_array;
|
header = new_array;
|
||||||
new_array->capacity = header->capacity << 1u;
|
new_array->capacity = header->capacity << 1U;
|
||||||
vec = header + 1;
|
vec = header + 1;
|
||||||
}
|
}
|
||||||
return vec;
|
return vec;
|
||||||
|
|||||||
Reference in New Issue
Block a user