mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 20:11:17 +00:00
Compound literal works properly.
This commit is contained in:
committed by
Christoffer Lerno
parent
2c573c8a15
commit
6da6b0f571
@@ -71,51 +71,20 @@ static inline LLVMValueRef gencontext_emit_sub_int(GenContext *context, Type *ty
|
||||
? LLVMBuildNUWSub(context->builder, left, right, "usub")
|
||||
: LLVMBuildNSWSub(context->builder, left, right, "sub");
|
||||
}
|
||||
static inline LLVMValueRef gencontext_emit_subscript_addr_from_value(GenContext *context, LLVMValueRef parent, Type *parent_type, Expr *index_expr)
|
||||
{
|
||||
assert(parent_type->canonical == parent_type);
|
||||
LLVMValueRef index = gencontext_emit_expr(context, index_expr);
|
||||
switch (parent_type->type_kind)
|
||||
{
|
||||
case TYPE_POINTER:
|
||||
return LLVMBuildGEP2(context->builder,
|
||||
llvm_type(parent_type->pointer),
|
||||
parent, &index, 1, "[]");
|
||||
case TYPE_ARRAY:
|
||||
// TODO insert trap on overflow.
|
||||
{
|
||||
LLVMValueRef zero = LLVMConstInt(llvm_type(type_int), 0, false);
|
||||
LLVMValueRef indices[2] = {
|
||||
zero,
|
||||
index,
|
||||
};
|
||||
return LLVMBuildInBoundsGEP2(context->builder,
|
||||
llvm_type(parent_type),
|
||||
parent, indices, 2, "[x]");
|
||||
|
||||
}
|
||||
case TYPE_VARARRAY:
|
||||
case TYPE_SUBARRAY:
|
||||
case TYPE_STRING:
|
||||
TODO
|
||||
default:
|
||||
UNREACHABLE
|
||||
}
|
||||
|
||||
}
|
||||
static inline LLVMValueRef gencontext_emit_subscript_addr(GenContext *context, Expr *expr)
|
||||
{
|
||||
Expr *parent = expr->subscript_expr.expr;
|
||||
Expr *index = expr->subscript_expr.index;
|
||||
LLVMValueRef index_value = gencontext_emit_expr(context, index);
|
||||
LLVMValueRef parent_value;
|
||||
switch (parent->type->canonical->type_kind)
|
||||
Type *type = parent->type->canonical;
|
||||
switch (type->type_kind)
|
||||
{
|
||||
case TYPE_POINTER:
|
||||
parent_value = gencontext_emit_expr(context, expr->subscript_expr.expr);
|
||||
return LLVMBuildGEP2(context->builder,
|
||||
llvm_type(parent->type->canonical),
|
||||
parent_value, &index_value, 1, "[]");
|
||||
return LLVMBuildInBoundsGEP2(context->builder,
|
||||
llvm_type(type->pointer),
|
||||
parent_value, &index_value, 1, "ptridx");
|
||||
case TYPE_ARRAY:
|
||||
{
|
||||
// TODO insert trap on overflow.
|
||||
@@ -126,8 +95,8 @@ static inline LLVMValueRef gencontext_emit_subscript_addr(GenContext *context, E
|
||||
};
|
||||
parent_value = gencontext_emit_address(context, expr->subscript_expr.expr);
|
||||
return LLVMBuildInBoundsGEP2(context->builder,
|
||||
llvm_type(parent->type),
|
||||
parent_value, indices, 2, "[x]");
|
||||
llvm_type(type),
|
||||
parent_value, indices, 2, "arridx");
|
||||
}
|
||||
case TYPE_VARARRAY:
|
||||
case TYPE_SUBARRAY:
|
||||
@@ -190,6 +159,8 @@ LLVMValueRef gencontext_emit_scoped_expr_address(GenContext *context, Expr *expr
|
||||
return value;
|
||||
}
|
||||
|
||||
static inline LLVMValueRef gencontext_emit_initializer_list_expr_addr(GenContext *context, Expr *expr, LLVMValueRef optional_ref);
|
||||
|
||||
LLVMValueRef gencontext_emit_address(GenContext *context, Expr *expr)
|
||||
{
|
||||
switch (expr->expr_kind)
|
||||
@@ -206,6 +177,8 @@ LLVMValueRef gencontext_emit_address(GenContext *context, Expr *expr)
|
||||
case EXPR_UNARY:
|
||||
assert(expr->unary_expr.operator == UNARYOP_DEREF);
|
||||
return gencontext_emit_expr(context, expr->unary_expr.expr);
|
||||
case EXPR_COMPOUND_LITERAL:
|
||||
return gencontext_emit_initializer_list_expr_addr(context, expr->expr_compound_literal.initializer, NULL);
|
||||
case EXPR_ACCESS:
|
||||
return gencontext_emit_access_addr(context, expr);
|
||||
case EXPR_SUBSCRIPT:
|
||||
@@ -308,7 +281,7 @@ static inline LLVMValueRef gencontext_emit_cast_expr(GenContext *context, Expr *
|
||||
* Improve: Direct assign in the case where this is assigning to a variable.
|
||||
* Improve: Create constant initializer for the constant case and do a memcopy
|
||||
*/
|
||||
static inline LLVMValueRef gencontext_emit_initializer_list_expr(GenContext *context, Expr *expr, LLVMValueRef optional_ref)
|
||||
static inline LLVMValueRef gencontext_emit_initializer_list_expr_addr(GenContext *context, Expr *expr, LLVMValueRef optional_ref)
|
||||
{
|
||||
LLVMTypeRef type = llvm_type(expr->type);
|
||||
LLVMValueRef ref = optional_ref ?: gencontext_emit_alloca(context, type, "literal");
|
||||
@@ -321,7 +294,7 @@ static inline LLVMValueRef gencontext_emit_initializer_list_expr(GenContext *co
|
||||
|
||||
if (expr->expr_initializer.init_type == INITIALIZER_ZERO)
|
||||
{
|
||||
return LLVMBuildLoad2(context->builder, type, ref, "");
|
||||
return ref;
|
||||
}
|
||||
|
||||
Expr **elements = expr->expr_initializer.initializer_expr;
|
||||
@@ -335,7 +308,7 @@ static inline LLVMValueRef gencontext_emit_initializer_list_expr(GenContext *co
|
||||
LLVMValueRef init_value = gencontext_emit_expr(context, elements[0]);
|
||||
LLVMValueRef u = LLVMBuildBitCast(context->builder, ref, LLVMPointerType(llvm_type(elements[0]->type->canonical), 0), "");
|
||||
LLVMBuildStore(context->builder, init_value, u);
|
||||
return LLVMBuildLoad2(context->builder, type, ref, "");
|
||||
return ref;
|
||||
}
|
||||
VECEACH(elements, i)
|
||||
{
|
||||
@@ -344,7 +317,7 @@ static inline LLVMValueRef gencontext_emit_initializer_list_expr(GenContext *co
|
||||
LLVMValueRef subref = LLVMBuildStructGEP2(context->builder, type, ref, i, "");
|
||||
LLVMBuildStore(context->builder, init_value, subref);
|
||||
}
|
||||
return LLVMBuildLoad2(context->builder, type, ref, "");
|
||||
return ref;
|
||||
}
|
||||
|
||||
VECEACH(elements, i)
|
||||
@@ -379,7 +352,7 @@ static inline LLVMValueRef gencontext_emit_initializer_list_expr(GenContext *co
|
||||
};
|
||||
sub_ref = LLVMBuildInBoundsGEP2(context->builder,
|
||||
llvm_type(parent_type),
|
||||
sub_ref, indices, 2, "[x]");
|
||||
sub_ref, indices, 2, "arrsub");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -391,19 +364,20 @@ static inline LLVMValueRef gencontext_emit_initializer_list_expr(GenContext *co
|
||||
}
|
||||
LLVMBuildStore(context->builder, sub_value, sub_ref);
|
||||
}
|
||||
return LLVMBuildLoad2(context->builder, type, ref, "");
|
||||
return ref;
|
||||
}
|
||||
|
||||
static inline LLVMValueRef gencontext_emit_inc_dec_change(GenContext *context, bool use_mod, LLVMValueRef current_value, Expr *expr, int diff)
|
||||
{
|
||||
Type *type = type_reduced_from_expr(expr);
|
||||
LLVMTypeRef llvm_type = llvm_type(type);
|
||||
|
||||
|
||||
if (type->type_kind == TYPE_POINTER)
|
||||
{
|
||||
LLVMValueRef add = LLVMConstInt(diff < 0 ? llvm_type(type_isize) : llvm_type(type_usize), diff, diff < 0);
|
||||
return LLVMBuildGEP2(context->builder, llvm_type, current_value, &add, 1, "ptrincdec");
|
||||
return LLVMBuildGEP2(context->builder, llvm_type(type->pointer), current_value, &add, 1, "ptrincdec");
|
||||
}
|
||||
LLVMTypeRef llvm_type = llvm_type(type);
|
||||
|
||||
if (type_is_float(type))
|
||||
{
|
||||
@@ -420,7 +394,7 @@ static inline LLVMValueRef gencontext_emit_inc_dec_change(GenContext *context, b
|
||||
static inline LLVMValueRef gencontext_emit_pre_inc_dec(GenContext *context, Expr *expr, int diff, bool use_mod)
|
||||
{
|
||||
LLVMValueRef addr = gencontext_emit_address(context, expr);
|
||||
LLVMValueRef value = LLVMBuildLoad2(context->builder, llvm_type(expr->type), addr, "");
|
||||
LLVMValueRef value = gencontext_emit_load(context, expr->type, addr);
|
||||
LLVMValueRef result = gencontext_emit_inc_dec_change(context, use_mod, value, expr, diff);
|
||||
LLVMBuildStore(context->builder, result, addr);
|
||||
return result;
|
||||
@@ -429,7 +403,7 @@ static inline LLVMValueRef gencontext_emit_pre_inc_dec(GenContext *context, Expr
|
||||
static inline LLVMValueRef gencontext_emit_post_inc_dec(GenContext *context, Expr *expr, int diff, bool use_mod)
|
||||
{
|
||||
LLVMValueRef addr = gencontext_emit_address(context, expr);
|
||||
LLVMValueRef value = LLVMBuildLoad2(context->builder, llvm_type(expr->type), addr, "");
|
||||
LLVMValueRef value = gencontext_emit_load(context, expr->type, addr);
|
||||
LLVMValueRef result = gencontext_emit_inc_dec_change(context, use_mod, value, expr, diff);
|
||||
LLVMBuildStore(context->builder, result, addr);
|
||||
return value;
|
||||
@@ -473,7 +447,7 @@ LLVMValueRef gencontext_emit_unary_expr(GenContext *context, Expr *expr)
|
||||
case UNARYOP_ADDR:
|
||||
return gencontext_emit_address(context, expr->unary_expr.expr);
|
||||
case UNARYOP_DEREF:
|
||||
return LLVMBuildLoad2(context->builder, llvm_type(type), gencontext_emit_expr(context, expr->unary_expr.expr), "deref");
|
||||
return gencontext_emit_load(context, expr->type, gencontext_emit_expr(context, expr->unary_expr.expr));
|
||||
case UNARYOP_INC:
|
||||
return gencontext_emit_pre_inc_dec(context, expr->unary_expr.expr, 1, false);
|
||||
case UNARYOP_DEC:
|
||||
@@ -523,18 +497,6 @@ static LLVMValueRef gencontext_emit_logical_and_or(GenContext *context, Expr *ex
|
||||
return phi;
|
||||
}
|
||||
|
||||
static inline LLVMValueRef gencontext_emit_initialization_from_expr(GenContext *context, LLVMValueRef strukt, Expr *expr)
|
||||
{
|
||||
assert(expr->expr_kind == EXPR_INITIALIZER_LIST);
|
||||
// TODO
|
||||
return strukt;
|
||||
}
|
||||
|
||||
static inline LLVMValueRef gencontext_emit_struct_value_expr(GenContext *context, Expr *expr)
|
||||
{
|
||||
LLVMValueRef temp_alloc = gencontext_emit_alloca(context, llvm_type(expr->type), "temp");
|
||||
return gencontext_emit_initialization_from_expr(context, temp_alloc, expr->struct_value_expr.init_expr);
|
||||
}
|
||||
|
||||
|
||||
static LLVMValueRef gencontext_emit_int_comparison(GenContext *context, Type *lhs_type, Type *rhs_type, LLVMValueRef lhs_value, LLVMValueRef rhs_value, BinaryOp binary_op)
|
||||
@@ -674,7 +636,7 @@ static LLVMValueRef gencontext_emit_binary(GenContext *context, Expr *expr, LLVM
|
||||
LLVMValueRef rhs_value;
|
||||
if (lhs_addr)
|
||||
{
|
||||
lhs_value = LLVMBuildLoad2(context->builder, llvm_type(lhs->type), lhs_addr, "");
|
||||
lhs_value = gencontext_emit_load(context, lhs->type, lhs_addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -729,7 +691,7 @@ static LLVMValueRef gencontext_emit_binary(GenContext *context, Expr *expr, LLVM
|
||||
{
|
||||
if (lhs->type->canonical == rhs->type->canonical) return LLVMBuildPtrDiff(context->builder, lhs_value, rhs_value, "ptrdiff");
|
||||
rhs_value = LLVMBuildNeg(context->builder, rhs_value, "");
|
||||
return LLVMBuildGEP2(context->builder, llvm_type(lhs->type), lhs_value, &rhs_value, 1, "ptrsub");
|
||||
return LLVMBuildGEP2(context->builder, llvm_type(lhs_type->canonical->pointer), lhs_value, &rhs_value, 1, "ptrsub");
|
||||
}
|
||||
if (is_float) return LLVMBuildFSub(context->builder, lhs_value, rhs_value, "fsub");
|
||||
return gencontext_emit_sub_int(context, lhs->type->canonical, binary_op == BINARYOP_SUB_MOD, lhs_value, rhs_value);
|
||||
@@ -738,7 +700,7 @@ static LLVMValueRef gencontext_emit_binary(GenContext *context, Expr *expr, LLVM
|
||||
if (lhs_type->type_kind == TYPE_POINTER)
|
||||
{
|
||||
assert(type_is_integer(rhs->type->canonical));
|
||||
return LLVMBuildGEP2(context->builder, llvm_type(lhs_type), lhs_value, &rhs_value, 1, "ptradd");
|
||||
return LLVMBuildGEP2(context->builder, llvm_type(lhs_type->canonical->pointer), lhs_value, &rhs_value, 1, "ptradd");
|
||||
}
|
||||
if (is_float) return LLVMBuildFAdd(context->builder, lhs_value, rhs_value, "fadd");
|
||||
return gencontext_emit_add_int(context, lhs_type, binary_op == BINARYOP_ADD_MOD, lhs_value, rhs_value);
|
||||
@@ -826,7 +788,7 @@ LLVMValueRef gencontext_emit_try_expr(GenContext *context, Expr *expr)
|
||||
LLVMBuildStore(context->builder, catch_value, res);
|
||||
gencontext_emit_br(context, after_catch);
|
||||
gencontext_emit_block(context, after_catch);
|
||||
return LLVMBuildLoad2(context->builder, llvm_type(expr->try_expr.else_expr->type), res, "");
|
||||
return gencontext_emit_load(context, expr->try_expr.else_expr->type, res);
|
||||
}
|
||||
TODO
|
||||
}
|
||||
@@ -1013,7 +975,7 @@ LLVMValueRef gencontext_emit_call_expr(GenContext *context, Expr *expr)
|
||||
{
|
||||
if (error_param)
|
||||
{
|
||||
LLVMValueRef maybe_error = LLVMBuildLoad2(context->builder, llvm_type(type_error_union), error_param, "");
|
||||
LLVMValueRef maybe_error = gencontext_emit_load(context, type_error_union, error_param);
|
||||
TODO // Incorrect, must get subset if this is 128 bits
|
||||
gencontext_emit_throw_branch(context, maybe_error);
|
||||
}
|
||||
@@ -1025,7 +987,7 @@ LLVMValueRef gencontext_emit_call_expr(GenContext *context, Expr *expr)
|
||||
// If we used a return param, then load that info here.
|
||||
if (return_param)
|
||||
{
|
||||
call = LLVMBuildLoad2(context->builder, llvm_type(signature->rtype->type), return_param, "");
|
||||
call = gencontext_emit_load(context, signature->rtype->type, return_param);
|
||||
}
|
||||
/*
|
||||
if (function->func.function_signature.convention)
|
||||
@@ -1093,7 +1055,9 @@ LLVMValueRef gencontext_emit_assign_expr(GenContext *context, LLVMValueRef ref,
|
||||
switch (expr->expr_kind)
|
||||
{
|
||||
case EXPR_INITIALIZER_LIST:
|
||||
return gencontext_emit_initializer_list_expr(context, expr, ref);
|
||||
return gencontext_emit_load(context,
|
||||
expr->type,
|
||||
gencontext_emit_initializer_list_expr_addr(context, expr, ref));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1114,6 +1078,12 @@ LLVMValueRef gencontext_emit_expr(GenContext *context, Expr *expr)
|
||||
case EXPR_DESIGNATED_INITIALIZER:
|
||||
// Should only appear when generating designated initializers.
|
||||
UNREACHABLE
|
||||
case EXPR_COMPOUND_LITERAL:
|
||||
return gencontext_emit_load(context,
|
||||
expr->type,
|
||||
gencontext_emit_initializer_list_expr_addr(context,
|
||||
expr->expr_compound_literal.initializer,
|
||||
NULL));
|
||||
case EXPR_EXPR_BLOCK:
|
||||
return gencontext_emit_expr_block(context, expr);
|
||||
case EXPR_SCOPED_EXPR:
|
||||
@@ -1139,13 +1109,15 @@ LLVMValueRef gencontext_emit_expr(GenContext *context, Expr *expr)
|
||||
case EXPR_IDENTIFIER:
|
||||
case EXPR_SUBSCRIPT:
|
||||
case EXPR_ACCESS:
|
||||
return gencontext_load_expr(context, gencontext_emit_address(context, expr));
|
||||
return gencontext_emit_load(context, expr->type, gencontext_emit_address(context, expr));
|
||||
case EXPR_CALL:
|
||||
return gencontext_emit_call_expr(context, expr);
|
||||
case EXPR_GROUP:
|
||||
return gencontext_emit_expr(context, expr->group_expr);
|
||||
case EXPR_INITIALIZER_LIST:
|
||||
return gencontext_emit_initializer_list_expr(context, expr, NULL);
|
||||
return gencontext_emit_load(context,
|
||||
expr->type,
|
||||
gencontext_emit_initializer_list_expr_addr(context, expr, NULL));
|
||||
case EXPR_EXPRESSION_LIST:
|
||||
return gencontext_emit_expression_list_expr(context, expr);
|
||||
case EXPR_CAST:
|
||||
|
||||
Reference in New Issue
Block a user