diff --git a/src/llvm/expr.c b/src/llvm/expr.c new file mode 100644 index 0000000..959936b --- /dev/null +++ b/src/llvm/expr.c @@ -0,0 +1,82 @@ +// +// Created by servostar on 5/28/24. +// + +#include +#include + +BackendError impl_transmute(LLVMBackendCompileUnit* unit, LLVMLocalScope* scope, + LLVMBuilderRef builder, Transmute* transmute, + LLVMValueRef* llvm_result) { + // TODO: resolve sub expression + LLVMValueRef operand = NULL; + LLVMTypeRef target_type = NULL; + BackendError err = get_type_impl(unit, scope->func_scope->global_scope, + &transmute->targetType, &target_type); + // if target type is valid + if (err.kind == Success) { + *llvm_result = + LLVMBuildBitCast(builder, operand, target_type, "transmute"); + } + + return err; +} + +static LLVMBool is_type_signed(const Type* type) { + switch (type->kind) { + case TypeKindPrimitive: + return 1; + case TypeKindComposite: + return type->impl.composite.sign == Signed; + default: + return 0; + } +} + +BackendError impl_typecast(LLVMBackendCompileUnit* unit, LLVMLocalScope* scope, + LLVMBuilderRef builder, TypeCast* typecast, + LLVMValueRef* llvm_result) { + // TODO: resolve sub expression + LLVMValueRef operand = NULL; + LLVMTypeRef target_type = NULL; + BackendError err = get_type_impl(unit, scope->func_scope->global_scope, + &typecast->targetType, &target_type); + // if target type is valid + if (err.kind != Success) { + return err; + } + + LLVMBool dst_signed = is_type_signed(&typecast->targetType); + // TODO: derive source type sign + const LLVMOpcode opcode = + LLVMGetCastOpcode(operand, 0, target_type, dst_signed); + *llvm_result = + LLVMBuildCast(builder, opcode, operand, target_type, "transmute"); + + return err; +} +BackendError impl_expr(LLVMBackendCompileUnit* unit, LLVMLocalScope* scope, + LLVMBuilderRef builder, Expression* expr, + LLVMValueRef* llvm_result) { + BackendError err = SUCCESS; + + switch (expr->kind) { + case ExpressionKindConstant: + err = get_type_value(unit, scope->func_scope->global_scope, + &expr->impl.constant, llvm_result); + break; + case ExpressionKindTransmute: + err = impl_transmute(unit, scope, builder, &expr->impl.transmute, + llvm_result); + break; + case ExpressionKindTypeCast: + err = impl_typecast(unit, scope, builder, &expr->impl.typecast, + llvm_result); + break; + case ExpressionKindOperation: + + break; + } + + return err; +} \ No newline at end of file diff --git a/src/llvm/expr.h b/src/llvm/expr.h new file mode 100644 index 0000000..204b807 --- /dev/null +++ b/src/llvm/expr.h @@ -0,0 +1,16 @@ +// +// Created by servostar on 5/28/24. +// + +#ifndef LLVM_BACKEND_EXPR_H +#define LLVM_BACKEND_EXPR_H + +#include +#include +#include +#include + +BackendError impl_expr(LLVMBackendCompileUnit* unit, LLVMLocalScope* scope, + Expression* expr, LLVMValueRef* llvm_result); + +#endif // LLVM_BACKEND_EXPR_H diff --git a/src/llvm/stmt.c b/src/llvm/stmt.c index 98fec0f..471360c 100644 --- a/src/llvm/stmt.c +++ b/src/llvm/stmt.c @@ -6,10 +6,14 @@ #include #include #include +#include BackendError impl_assign_stmt(LLVMBackendCompileUnit* unit, - LLVMBuilderRef builder, LLVMLocalScope* scope, - Assignment* assignment) { + const LLVMBuilderRef builder, const LLVMLocalScope* scope, + const Assignment* assignment) { + BackendError err = SUCCESS; + DEBUG("implementing assignment for variabel: %s", assignment->variable->name); + // TODO: resolve expression to LLVMValueRef const LLVMValueRef llvm_value = NULL; @@ -18,11 +22,14 @@ BackendError impl_assign_stmt(LLVMBackendCompileUnit* unit, case VariableKindDefinition: const LLVMValueRef llvm_ptr = get_variable(scope, assignment->variable->name); - LLVMBuildStore(builder, llvm_value, llvm_ptr); - break; + LLVMBuildStore(builder, llvm_value, llvm_ptr); + break; case VariableKindBoxMember: - break; + // TODO: resolve LLVMValueRef from BoxAccess + break; } + + return err; } BackendError impl_stmt(LLVMBackendCompileUnit* unit, Statement* stmt) {} diff --git a/src/llvm/types.c b/src/llvm/types.c index bc95f83..65fd661 100644 --- a/src/llvm/types.c +++ b/src/llvm/types.c @@ -9,6 +9,71 @@ #define BASE_BYTES 4 #define BITS_PER_BYTE 8 +static BackendError get_const_primitive_value(PrimitiveType primitive, + LLVMTypeRef llvm_type, + const char* value, + LLVMValueRef* llvm_value) { + switch (primitive) { + case Int: + *llvm_value = LLVMConstIntOfString(llvm_type, value, 10); + break; + case Float: + *llvm_value = LLVMConstRealOfString(llvm_type, value); + break; + } + + return SUCCESS; +} + +static BackendError get_const_composite_value(CompositeType composite, + LLVMTypeRef llvm_type, + const char* value, + LLVMValueRef* llvm_value) { + return get_const_primitive_value(composite.primitive, llvm_type, value, + llvm_value); +} + +BackendError get_const_type_value(LLVMBackendCompileUnit* unit, + LLVMGlobalScope* scope, + TypeValue* gemstone_value, + LLVMValueRef* llvm_value) { + BackendError err = new_backend_impl_error( + Implementation, gemstone_value->nodePtr, "No default value for type"); + + LLVMTypeRef llvm_type = NULL; + err = get_type_impl(unit, scope, &gemstone_value->type, &llvm_type); + if (err.kind != Success) { + return err; + } + + switch (gemstone_value->type.kind) { + case TypeKindPrimitive: + err = get_const_primitive_value(gemstone_value->type.impl.primitive, + llvm_type, gemstone_value->value, + llvm_value); + break; + case TypeKindComposite: + err = get_const_composite_value(gemstone_value->type.impl.composite, + llvm_type, gemstone_value->value, + llvm_value); + break; + case TypeKindReference: + err = + new_backend_impl_error(Implementation, gemstone_value->nodePtr, + "reference cannot be constant value"); + break; + case TypeKindBox: + err = + new_backend_impl_error(Implementation, gemstone_value->nodePtr, + "boxes cannot be constant value"); + break; + default: + PANIC("invalid value kind: %ld", gemstone_value->type.kind); + } + + return err; +} + BackendError impl_primtive_type(LLVMBackendCompileUnit* unit, PrimitiveType primtive, LLVMTypeRef* llvm_type) { diff --git a/src/llvm/types.h b/src/llvm/types.h index c8a873b..edd8b66 100644 --- a/src/llvm/types.h +++ b/src/llvm/types.h @@ -18,4 +18,8 @@ BackendError get_type_default_value(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, Type* gemstone_type, LLVMValueRef* llvm_value); +BackendError get_type_value(LLVMBackendCompileUnit* unit, + LLVMGlobalScope* scope, TypeValue* gemstone_value, + LLVMValueRef* llvm_value); + #endif // LLVM_BACKEND_TYPES_H_