mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 03:51:18 +00:00
Set stdlib library for testing and profit. Fix bugs when using void* to step. Make constants private linkage. Compare pointers using unsigned comparison without conversion. Use manual ptrdiff code. Fix issue returning "void!". Unify pointers when doing Foo* - void*. Allow comparing for example void* < Foo*
This commit is contained in:
committed by
Christoffer Lerno
parent
01f7343945
commit
0e076234ca
@@ -1,9 +1,118 @@
|
||||
module std::mem;
|
||||
|
||||
extern func void* _malloc(usize bytes) @cname("malloc");
|
||||
extern func void* _realloc(void* ptr, usize bytes) @cname("realloc");
|
||||
extern func void* _calloc(usize bytes, usize elements) @cname("calloc");
|
||||
extern func void _free(void* ptr) @cname("free");
|
||||
|
||||
public enum AllocationKind
|
||||
{
|
||||
ALLOC,
|
||||
REALLOC,
|
||||
FREE,
|
||||
}
|
||||
|
||||
public enum AllocationFailureKind
|
||||
{
|
||||
OUT_OF_MEMORY
|
||||
}
|
||||
|
||||
public error AllocationFailure
|
||||
{
|
||||
AllocationFailureKind failureKind;
|
||||
}
|
||||
|
||||
public typedef func void!(void *data, void** pointer, usize bytes, usize alignment, AllocationKind kind) as AllocatorFunction;
|
||||
|
||||
public struct Allocator
|
||||
{
|
||||
AllocatorFunction allocation_function;
|
||||
void *data;
|
||||
}
|
||||
|
||||
public func void! system_malloc_function(void *unused, void** pointer, usize bytes, usize alignment, AllocationKind kind) @inline
|
||||
{
|
||||
switch (kind)
|
||||
{
|
||||
case ALLOC:
|
||||
void* data = _malloc(bytes);
|
||||
if (!data) return AllocationFailure({ OUT_OF_MEMORY })!;
|
||||
*pointer = data;
|
||||
return;
|
||||
case REALLOC:
|
||||
void* data = _realloc(*pointer, bytes);
|
||||
if (!data) return AllocationFailure({ OUT_OF_MEMORY })!;
|
||||
*pointer = data;
|
||||
return;
|
||||
case FREE:
|
||||
_free(*pointer);
|
||||
*pointer = null;
|
||||
return;
|
||||
}
|
||||
$unreachable;
|
||||
}
|
||||
|
||||
public struct RingAllocator
|
||||
{
|
||||
char *data;
|
||||
usize size;
|
||||
usize offset;
|
||||
}
|
||||
|
||||
|
||||
public func void* RingAllocator.alloc(RingAllocator *allocator, usize size)
|
||||
{
|
||||
if (size > allocator.size) return null;
|
||||
// Wraparound? If so, start at the beginning.
|
||||
if (allocator.offset + size > allocator.size)
|
||||
{
|
||||
allocator.offset = size;
|
||||
return allocator.data;
|
||||
}
|
||||
void* data = allocator.offset + allocator.data;
|
||||
allocator.offset = (allocator.offset + size) & allocator.size;
|
||||
return data;
|
||||
}
|
||||
|
||||
public func void* RingAllocator.realloc(RingAllocator *allocator, void* ptr, usize size)
|
||||
{
|
||||
if (size > allocator.size) return null;
|
||||
assert(allocator.data >= ptr && ptr < allocator.data + size, "Realloc on other allocator.");
|
||||
// 1. The pointer is before the allocator
|
||||
if (allocator.data + allocator.offset > ptr)
|
||||
{
|
||||
if (allocator.data + allocator.size < ptr + size)
|
||||
{
|
||||
// 1a. There is not enough space, we need to copy to the start.
|
||||
usize pointer_offset = ptr - allocator.data;
|
||||
usize copy_len = pointer_offset + size > allocator.offset ? allocator.offset - pointer_offset : size;
|
||||
//memcpy(allocator.data, ptr, copy_len);
|
||||
allocator.offset = size;
|
||||
return allocator.data;
|
||||
}
|
||||
// 1b. There is enough space, so we just change the offset:
|
||||
allocator.offset = ptr - allocator.data + size;
|
||||
return ptr;
|
||||
}
|
||||
// 2. The pointer is after the allocator
|
||||
// 2a. Is there sufficient space?
|
||||
if (ptr + size <= allocator.data + allocator.size)
|
||||
{
|
||||
// Good, if so we simply change the offset and return the pointer.
|
||||
allocator.offset = ptr - allocator.data + size;
|
||||
return ptr;
|
||||
}
|
||||
// 2b. Not sufficient space, we copy to the beginning.
|
||||
usize pointer_offset = ptr - allocator.data;
|
||||
usize copy_len = allocator.size - (ptr - allocator.data);
|
||||
if (copy_len > size) copy_len = size;
|
||||
//memcpy(allocator.data, ptr, copy_len);
|
||||
allocator.offset = size;
|
||||
return allocator.data;
|
||||
}
|
||||
|
||||
public Allocator main_allocator = { &system_malloc_function, null };
|
||||
|
||||
public macro malloc($Type)
|
||||
{
|
||||
// TODO: return cast(_malloc($Type.sizeof) as $Type*);
|
||||
|
||||
32
resources/lib/std/runtime.c3
Normal file
32
resources/lib/std/runtime.c3
Normal file
@@ -0,0 +1,32 @@
|
||||
module std::runtime;
|
||||
|
||||
struct VirtualAny
|
||||
{
|
||||
void* ptr;
|
||||
typeid type_id;
|
||||
}
|
||||
|
||||
struct VirtualContainer
|
||||
{
|
||||
void* ptr;
|
||||
void* impl_ptr;
|
||||
}
|
||||
|
||||
struct SubArrayContainer
|
||||
{
|
||||
void* ptr;
|
||||
usize len;
|
||||
}
|
||||
|
||||
struct VarArrayHeader
|
||||
{
|
||||
usize size;
|
||||
usize capacity;
|
||||
void *allocator;
|
||||
|
||||
}
|
||||
|
||||
struct VarArrayContainer
|
||||
{
|
||||
|
||||
}
|
||||
@@ -63,7 +63,8 @@ static void usage(void)
|
||||
OUTPUT(" headers <file1> [<file2> ...] Analyse files and generate C headers for public methods.");
|
||||
OUTPUT("");
|
||||
OUTPUT("Options:");
|
||||
OUTPUT(" --lib <dir> - Use this directory as the c3 library path.");
|
||||
OUTPUT(" --stdlib <dir> - Use this directory as the C3 standard library path.");
|
||||
OUTPUT(" --lib <dir> - Use this directory as the C3 library path.");
|
||||
OUTPUT(" --path <dir> - Use this as the base directory for the current command.");
|
||||
OUTPUT(" --template <template> - Use a different template: \"lib\", \"staticlib\" or a path.");
|
||||
OUTPUT(" --about - Prints a short description of C3.");
|
||||
@@ -354,6 +355,12 @@ static void parse_option(BuildOptions *options)
|
||||
options->emit_llvm = true;
|
||||
return;
|
||||
}
|
||||
if (match_longopt("stdlib"))
|
||||
{
|
||||
if (at_end() || next_is_opt()) error_exit("error: --stdlib needs a directory.");
|
||||
options->std_lib_dir = check_dir(next_arg());
|
||||
return;
|
||||
}
|
||||
if (match_longopt("lib"))
|
||||
{
|
||||
if (at_end() || next_is_opt()) error_exit("error: --lib needs a directory.");
|
||||
|
||||
@@ -164,6 +164,7 @@ typedef enum
|
||||
typedef struct BuildOptions_
|
||||
{
|
||||
const char* lib_dir[MAX_LIB_DIRS];
|
||||
const char* std_lib_dir;
|
||||
int lib_count;
|
||||
const char** files;
|
||||
const char* project_name;
|
||||
|
||||
@@ -16,7 +16,7 @@ Vmem tokdata_arena;
|
||||
Vmem decl_arena;
|
||||
Vmem type_info_arena;
|
||||
|
||||
void compiler_init(void)
|
||||
void compiler_init(const char *std_lib_dir)
|
||||
{
|
||||
// Skip library detection.
|
||||
//compiler.lib_dir = find_lib_dir();
|
||||
@@ -34,7 +34,14 @@ void compiler_init(void)
|
||||
(void) sourceloc_calloc();
|
||||
(void) toktype_calloc();
|
||||
(void) tokdata_calloc();
|
||||
compiler.lib_dir = find_lib_dir();
|
||||
if (std_lib_dir)
|
||||
{
|
||||
compiler.lib_dir = std_lib_dir;
|
||||
}
|
||||
else
|
||||
{
|
||||
compiler.lib_dir = find_lib_dir();
|
||||
}
|
||||
}
|
||||
|
||||
static void compiler_lex(BuildTarget *target)
|
||||
@@ -79,6 +86,7 @@ void compiler_compile(BuildTarget *target)
|
||||
diag_setup(target->test_output);
|
||||
if (compiler.lib_dir)
|
||||
{
|
||||
vec_add(target->sources, strformat("%s/std/runtime.c3", compiler.lib_dir));
|
||||
vec_add(target->sources, strformat("%s/std/builtin.c3", compiler.lib_dir));
|
||||
vec_add(target->sources, strformat("%s/std/io.c3", compiler.lib_dir));
|
||||
vec_add(target->sources, strformat("%s/std/mem.c3", compiler.lib_dir));
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
// Use of this source code is governed by the GNU LGPLv3.0 license
|
||||
// a copy of which can be found in the LICENSE file.
|
||||
|
||||
void compiler_init();
|
||||
void compiler_init(const char *std_lib_dir);
|
||||
void compile_files(BuildTarget *target);
|
||||
void init_build_target(BuildTarget *build_target, BuildOptions *build_options);
|
||||
void init_default_build_target(BuildTarget *target, BuildOptions *options, const char *name);
|
||||
|
||||
@@ -136,7 +136,7 @@ static inline LLVMValueRef llvm_emit_subscript_addr_with_base(GenContext *c, Typ
|
||||
{
|
||||
case TYPE_POINTER:
|
||||
return LLVMBuildInBoundsGEP2(c->builder,
|
||||
llvm_get_type(c, type->pointer),
|
||||
llvm_get_pointee_type(c, type),
|
||||
parent_value, &index_value, 1, "ptridx");
|
||||
case TYPE_ARRAY:
|
||||
{
|
||||
@@ -605,7 +605,8 @@ static inline void llvm_emit_initialize_reference_temporary_const(GenContext *c,
|
||||
|
||||
// Create a global const.
|
||||
LLVMTypeRef type = modified ? LLVMTypeOf(value) : llvm_get_type(c, expr->type);
|
||||
LLVMValueRef global_copy = LLVMAddGlobal(c->module, type, "");
|
||||
LLVMValueRef global_copy = LLVMAddGlobal(c->module, type, ".__const");
|
||||
LLVMSetLinkage(global_copy, LLVMPrivateLinkage);
|
||||
|
||||
// Set a nice alignment
|
||||
unsigned alignment = type_alloca_alignment(expr->type);
|
||||
@@ -972,7 +973,7 @@ static inline void llvm_emit_inc_dec_change(GenContext *c, bool use_mod, BEValue
|
||||
{
|
||||
// Use byte here, we don't need a big offset.
|
||||
LLVMValueRef add = LLVMConstInt(diff < 0 ? llvm_get_type(c, type_ichar) : llvm_get_type(c, type_char), diff, diff < 0);
|
||||
after_value = LLVMBuildGEP2(c->builder, llvm_get_type(c, type->pointer), value.value, &add, 1, "ptrincdec");
|
||||
after_value = LLVMBuildGEP2(c->builder, llvm_get_pointee_type(c, type), value.value, &add, 1, "ptrincdec");
|
||||
break;
|
||||
}
|
||||
case ALL_FLOATS:
|
||||
@@ -1387,7 +1388,7 @@ static void gencontext_emit_slice(GenContext *context, BEValue *be_value, Expr *
|
||||
// Change pointer from Foo[x] to Foo*
|
||||
parent_base = llvm_emit_bitcast(context, parent_base, pointer_type);
|
||||
// Move pointer
|
||||
start_pointer = LLVMBuildInBoundsGEP2(context->builder, llvm_get_type(context, pointer_type->pointer), parent_base, &start_index, 1, "offset");
|
||||
start_pointer = LLVMBuildInBoundsGEP2(context->builder, llvm_get_pointee_type(context, pointer_type), parent_base, &start_index, 1, "offset");
|
||||
break;
|
||||
}
|
||||
case TYPE_SUBARRAY:
|
||||
@@ -1398,7 +1399,7 @@ static void gencontext_emit_slice(GenContext *context, BEValue *be_value, Expr *
|
||||
case TYPE_POINTER:
|
||||
{
|
||||
// Move pointer
|
||||
start_pointer = LLVMBuildInBoundsGEP2(context->builder, llvm_get_type(context, parent_type->pointer), parent_base, &start_index, 1, "offset");
|
||||
start_pointer = LLVMBuildInBoundsGEP2(context->builder, llvm_get_pointee_type(context, parent_type), parent_base, &start_index, 1, "offset");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -1657,6 +1658,29 @@ LLVMValueRef llvm_emit_int_comparison(GenContext *c, Type *lhs_type, Type *rhs_t
|
||||
|
||||
}
|
||||
|
||||
static LLVMValueRef llvm_emit_ptr_comparison(GenContext *c, LLVMValueRef lhs_value, LLVMValueRef rhs_value, BinaryOp binary_op)
|
||||
{
|
||||
switch (binary_op)
|
||||
{
|
||||
case BINARYOP_EQ:
|
||||
return LLVMBuildICmp(c->builder, LLVMIntEQ, lhs_value, rhs_value, "eq");
|
||||
case BINARYOP_NE:
|
||||
return LLVMBuildICmp(c->builder, LLVMIntNE, lhs_value, rhs_value, "neq");
|
||||
case BINARYOP_GE:
|
||||
return LLVMBuildICmp(c->builder, LLVMIntUGE, lhs_value, rhs_value, "ge");
|
||||
case BINARYOP_GT:
|
||||
return LLVMBuildICmp(c->builder, LLVMIntUGT, lhs_value, rhs_value, "gt");
|
||||
case BINARYOP_LE:
|
||||
return LLVMBuildICmp(c->builder, LLVMIntULE, lhs_value, rhs_value, "le");
|
||||
case BINARYOP_LT:
|
||||
return LLVMBuildICmp(c->builder, LLVMIntULT, lhs_value, rhs_value, "lt");
|
||||
default:
|
||||
UNREACHABLE
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static inline LLVMValueRef llvm_fixup_shift_rhs(GenContext *c, LLVMValueRef left, LLVMValueRef right)
|
||||
{
|
||||
LLVMTypeRef left_type = LLVMTypeOf(left);
|
||||
@@ -1725,6 +1749,11 @@ static void gencontext_emit_binary(GenContext *c, BEValue *be_value, Expr *expr,
|
||||
llvm_value_set_bool(be_value, llvm_emit_int_comparison(c, lhs_type, rhs_type, lhs_value, rhs_value, binary_op));
|
||||
return;
|
||||
}
|
||||
if (type_is_pointer(lhs_type) && binary_op >= BINARYOP_GT && binary_op <= BINARYOP_EQ)
|
||||
{
|
||||
llvm_value_set_bool(be_value, llvm_emit_ptr_comparison(c, lhs_value, rhs_value, binary_op));
|
||||
return;
|
||||
}
|
||||
bool is_float = type_is_float(lhs_type);
|
||||
LLVMValueRef val;
|
||||
switch (binary_op)
|
||||
@@ -1744,11 +1773,14 @@ static void gencontext_emit_binary(GenContext *c, BEValue *be_value, Expr *expr,
|
||||
{
|
||||
if (lhs_type == rhs_type)
|
||||
{
|
||||
val = LLVMBuildPtrDiff(c->builder, lhs_value, rhs_value, "ptrdiff");
|
||||
LLVMTypeRef int_type = llvm_get_type(c, type_iptrdiff);
|
||||
val = LLVMBuildSub(c->builder, LLVMBuildPtrToInt(c->builder, lhs_value, int_type, ""),
|
||||
LLVMBuildPtrToInt(c->builder, rhs_value, int_type, ""), "");
|
||||
val = LLVMBuildExactSDiv(c->builder, val, llvm_const_int(c, type_iptrdiff, type_abi_alignment(lhs_type->pointer)), "");
|
||||
break;
|
||||
}
|
||||
rhs_value = LLVMBuildNeg(c->builder, rhs_value, "");
|
||||
val = LLVMBuildGEP2(c->builder, llvm_get_type(c, lhs_type->canonical->pointer), lhs_value, &rhs_value, 1, "ptrsub");
|
||||
val = LLVMBuildGEP2(c->builder, llvm_get_pointee_type(c, lhs_type), lhs_value, &rhs_value, 1, "ptrsub");
|
||||
break;
|
||||
}
|
||||
if (is_float)
|
||||
@@ -1762,7 +1794,7 @@ static void gencontext_emit_binary(GenContext *c, BEValue *be_value, Expr *expr,
|
||||
if (lhs_type->type_kind == TYPE_POINTER)
|
||||
{
|
||||
assert(type_is_integer(rhs_type));
|
||||
val = LLVMBuildGEP2(c->builder, llvm_get_type(c, lhs_type->pointer), lhs_value, &rhs_value, 1, "ptradd");
|
||||
val = LLVMBuildGEP2(c->builder, llvm_get_pointee_type(c, lhs_type), lhs_value, &rhs_value, 1, "ptradd");
|
||||
break;
|
||||
}
|
||||
if (is_float)
|
||||
@@ -2231,13 +2263,14 @@ static void llvm_emit_const_expr(GenContext *c, BEValue *be_value, Expr *expr)
|
||||
return;
|
||||
case TYPE_STRLIT:
|
||||
{
|
||||
LLVMValueRef global_name = LLVMAddGlobal(c->module, LLVMArrayType(llvm_get_type(c, type_char), expr->const_expr.string.len + 1), "");
|
||||
LLVMSetLinkage(global_name, LLVMInternalLinkage);
|
||||
LLVMValueRef global_name = LLVMAddGlobal(c->module, LLVMArrayType(llvm_get_type(c, type_char), expr->const_expr.string.len + 1), ".str");
|
||||
LLVMSetLinkage(global_name, LLVMPrivateLinkage);
|
||||
LLVMSetGlobalConstant(global_name, 1);
|
||||
LLVMSetInitializer(global_name, LLVMConstStringInContext(c->context,
|
||||
expr->const_expr.string.chars,
|
||||
expr->const_expr.string.len,
|
||||
0));
|
||||
llvm_set_alignment(global_name, 1);
|
||||
global_name = LLVMConstBitCast(global_name, LLVMPointerType(llvm_get_type(c, type_char), 0));
|
||||
llvm_value_set(be_value, global_name, type);
|
||||
return;
|
||||
@@ -2716,7 +2749,7 @@ void llvm_emit_call_expr(GenContext *c, BEValue *be_value, Expr *expr)
|
||||
else
|
||||
{
|
||||
// 9b. Otherwise we also need to allocate memory for the arguments:
|
||||
Type *pointee_type = vararg_param->type->pointer;
|
||||
Type *pointee_type = vararg_param->type->array.base;
|
||||
LLVMTypeRef llvm_pointee = llvm_get_type(c, pointee_type);
|
||||
Type *array = type_get_array(pointee_type, arguments - non_variadic_params);
|
||||
LLVMTypeRef llvm_array_type = llvm_get_type(c, array);
|
||||
|
||||
@@ -256,8 +256,9 @@ void llvm_emit_return_abi(GenContext *c, BEValue *return_value, BEValue *failabl
|
||||
// In this case we use the failable as the actual return.
|
||||
if (signature->failable)
|
||||
{
|
||||
if (return_value)
|
||||
if (return_value && return_value->value)
|
||||
{
|
||||
|
||||
llvm_store_bevalue_aligned(c, c->return_out, return_value, 0);
|
||||
}
|
||||
return_out = c->failable_out;
|
||||
|
||||
@@ -256,6 +256,7 @@ static inline LLVMBasicBlockRef llvm_get_current_block_if_in_use(GenContext *con
|
||||
LLVMMetadataRef llvm_get_debug_type(GenContext *c, Type *type);
|
||||
static inline LLVMTypeRef llvm_get_ptr_type(GenContext *c, Type *type);
|
||||
LLVMTypeRef llvm_get_type(GenContext *c, Type *any_type);
|
||||
LLVMTypeRef llvm_get_pointee_type(GenContext *c, Type *any_type);
|
||||
static inline LLVMValueRef llvm_get_zero(GenContext *c, Type *type);
|
||||
|
||||
void llvm_debug_scope_push(GenContext *context, LLVMMetadataRef debug_scope);
|
||||
|
||||
@@ -313,6 +313,13 @@ LLVMTypeRef llvm_func_type(GenContext *context, Type *type)
|
||||
}
|
||||
|
||||
|
||||
LLVMTypeRef llvm_get_pointee_type(GenContext *c, Type *any_type)
|
||||
{
|
||||
any_type = any_type->canonical;
|
||||
assert(any_type->type_kind == TYPE_POINTER);
|
||||
if (any_type == type_voidptr) return llvm_get_type(c, type_char);
|
||||
return llvm_get_type(c, any_type->pointer);
|
||||
}
|
||||
|
||||
LLVMTypeRef llvm_get_type(GenContext *c, Type *any_type)
|
||||
{
|
||||
|
||||
@@ -3351,6 +3351,20 @@ static bool sema_check_int_type_fit(Expr *expr, Type *target_type)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void unify_voidptr(Expr *left, Expr *right, Type **left_type_ref, Type **right_type_ref)
|
||||
{
|
||||
if (*left_type_ref == *right_type_ref) return;
|
||||
if (*left_type_ref == type_voidptr)
|
||||
{
|
||||
cast(left, *right_type_ref);
|
||||
*left_type_ref = *right_type_ref;
|
||||
}
|
||||
if (*right_type_ref == type_voidptr)
|
||||
{
|
||||
cast(right, *left_type_ref);
|
||||
*right_type_ref = *left_type_ref;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Analyse a - b
|
||||
* @return true if analysis succeeded
|
||||
@@ -3370,6 +3384,7 @@ static bool sema_expr_analyse_sub(Context *context, Type *to, Expr *expr, Expr *
|
||||
if (right_type->type_kind == TYPE_POINTER)
|
||||
{
|
||||
// 3a. Require that both types are the same.
|
||||
unify_voidptr(left, right, &left_type, &right_type);
|
||||
if (left_type != right_type)
|
||||
{
|
||||
SEMA_ERROR(expr, "'%s' - '%s' is not allowed. Subtracting pointers of different types from each other is not possible.", type_to_error_string(left_type), type_to_error_string(right_type));
|
||||
@@ -3466,6 +3481,8 @@ static bool sema_expr_analyse_add(Context *context, Type *to, Expr *expr, Expr *
|
||||
left = temp;
|
||||
right_type = left_type;
|
||||
left_type = left->type->canonical;
|
||||
expr->binary_expr.left = left;
|
||||
expr->binary_expr.right = right;
|
||||
}
|
||||
|
||||
// 3. The "left" will now always be the pointer.
|
||||
@@ -4006,7 +4023,7 @@ static bool sema_expr_analyse_comp(Context *context, Expr *expr, Expr *left, Exp
|
||||
break;
|
||||
case TYPE_POINTER:
|
||||
// Only comparisons between the same type is allowed. Subtypes not allowed.
|
||||
if (left_type != right_type)
|
||||
if (left_type != right_type && left_type != type_voidptr && right_type != type_voidptr)
|
||||
{
|
||||
SEMA_ERROR(expr, "Cannot compare pointers of different types.");
|
||||
return false;
|
||||
|
||||
@@ -15,12 +15,13 @@ int main(int argc, const char *argv[])
|
||||
|
||||
DEBUG_LOG("Version: %d", version);
|
||||
|
||||
// Init the compiler
|
||||
compiler_init();
|
||||
|
||||
// Parse arguments.
|
||||
BuildOptions build_options = parse_arguments(argc, argv);
|
||||
|
||||
// Init the compiler
|
||||
compiler_init(build_options.std_lib_dir);
|
||||
|
||||
BuildTarget build_target = { .name = NULL };
|
||||
|
||||
switch (build_options.command)
|
||||
|
||||
@@ -91,12 +91,14 @@ char *read_file(const char *path, size_t *return_size)
|
||||
|
||||
const char* find_lib_dir(void)
|
||||
{
|
||||
|
||||
const char *path = find_executable_path();
|
||||
|
||||
DEBUG_LOG("Detected executable path at %s", path);
|
||||
|
||||
struct stat info;
|
||||
char *lib_path = NULL;
|
||||
|
||||
asprintf(&lib_path, "%s../lib/std/", path);
|
||||
DEBUG_LOG("Checking %s", lib_path);
|
||||
int err = stat(lib_path, &info);
|
||||
|
||||
@@ -14,14 +14,14 @@ func double test(uint x)
|
||||
|
||||
// #expect: array_literal.ll
|
||||
|
||||
@0 = constant [30 x double] [double 0.000000e+00, double 1.270600e+01, double 4.303000e+00, double 3.182000e+00, double 2.776000e+00, double 2.571000e+00, double 2.447000e+00, double 2.365000e+00, double 2.306000e+00, double 2.262000e+00, double 2.228000e+00, double 2.201000e+00, double 2.179000e+00, double 2.160000e+00, double 2.145000e+00, double 2.131000e+00, double 2.120000e+00, double 2.110000e+00, double 2.101000e+00, double 2.093000e+00, double 2.086000e+00, double 2.080000e+00, double 2.074000e+00, double 2.069000e+00, double 2.064000e+00, double 2.060000e+00, double 2.056000e+00, double 2.052000e+00, double 2.048000e+00, double 2.045000e+00], align 16
|
||||
@.__const = private constant [30 x double] [double 0.000000e+00, double 1.270600e+01, double 4.303000e+00, double 3.182000e+00, double 2.776000e+00, double 2.571000e+00, double 2.447000e+00, double 2.365000e+00, double 2.306000e+00, double 2.262000e+00, double 2.228000e+00, double 2.201000e+00, double 2.179000e+00, double 2.160000e+00, double 2.145000e+00, double 2.131000e+00, double 2.120000e+00, double 2.110000e+00, double 2.101000e+00, double 2.093000e+00, double 2.086000e+00, double 2.080000e+00, double 2.074000e+00, double 2.069000e+00, double 2.064000e+00, double 2.060000e+00, double 2.056000e+00, double 2.052000e+00, double 2.048000e+00, double 2.045000e+00], align 16
|
||||
|
||||
entry:
|
||||
%x = alloca i32, align 4
|
||||
%student_t = alloca [30 x double], align 16
|
||||
store i32 %0, i32* %x, align 4
|
||||
%1 = bitcast [30 x double]* %student_t to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 %1, i8* align 16 bitcast ([30 x double]* @0 to i8*), i32 240, i1 false)
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 %1, i8* align 16 bitcast ([30 x double]* @.__const to i8*), i32 240, i1 false)
|
||||
%2 = load i32, i32* %x, align 4
|
||||
%uiuiext = zext i32 %2 to i64
|
||||
%arridx = getelementptr inbounds [30 x double], [30 x double]* %student_t, i64 0, i64 %uiuiext
|
||||
|
||||
@@ -15,7 +15,7 @@ Connection[3] link
|
||||
|
||||
// #expect: complex_array_const.ll
|
||||
|
||||
@0 = internal constant [6 x i8] c"link1\00"
|
||||
@1 = internal constant [6 x i8] c"link2\00"
|
||||
@2 = internal constant [6 x i8] c"link3\00"
|
||||
@link = protected global [3 x %test.Connection] [%test.Connection { i64 1, i8* getelementptr inbounds ([6 x i8], [6 x i8]* @0, i32 0, i32 0), i64 10 }, %test.Connection { i64 2, i8* getelementptr inbounds ([6 x i8], [6 x i8]* @1, i32 0, i32 0), i64 20 }, %test.Connection { i64 3, i8* getelementptr inbounds ([6 x i8], [6 x i8]* @2, i32 0, i32 0), i64 30 }], align 16
|
||||
@.str = private constant [6 x i8] c"link1\00"
|
||||
@.str.1 = private constant [6 x i8] c"link2\00"
|
||||
@.str.2 = private constant [6 x i8] c"link3\00"
|
||||
@link = protected global [3 x %test.Connection] [%test.Connection { i64 1, i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str, i32 0, i32 0), i64 10 }, %test.Connection { i64 2, i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.1, i32 0, i32 0), i64 20 }, %test.Connection { i64 3, i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.2, i32 0, i32 0), i64 30 }], align 16
|
||||
|
||||
@@ -94,5 +94,5 @@ entry:
|
||||
%34 = getelementptr inbounds %pointer_access.ExtraSimple, %pointer_access.ExtraSimple* %a, i32 0, i32 3
|
||||
%35 = getelementptr inbounds %pointer_access.anon, %pointer_access.anon* %34, i32 0, i32 1
|
||||
%36 = load i32, i32* %35, align 4
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([71 x i8], [71 x i8]* @0, i32 0, i32 0), i32 %16, double %19, double %22, double %25, i32 %27, double %30, i32 %33, i32 %36)
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([71 x i8], [71 x i8]* @.str, i32 0, i32 0), i32 %16, double %19, double %22, double %25, i32 %27, double %30, i32 %33, i32 %36)
|
||||
ret void
|
||||
|
||||
@@ -7,4 +7,4 @@ func char* foo()
|
||||
|
||||
// #expect: strings.ll
|
||||
|
||||
@0 = internal constant [32 x i8] c"*** Word \22%s\22 on line %d is not\00"
|
||||
@.str = private constant [32 x i8] c"*** Word \22%s\22 on line %d is not\00"
|
||||
@@ -20,19 +20,19 @@ func void test()
|
||||
%x1 = alloca i8, align 1
|
||||
%b = alloca i8, align 1
|
||||
%z1 = alloca float, align 4
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @0, i32 0, i32 0), i32 1)
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @1, i32 0, i32 0), i32 123)
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @2, i32 0, i32 0), double 1.230000e+01)
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 1)
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.1, i32 0, i32 0), i32 123)
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.2, i32 0, i32 0), double 1.230000e+01)
|
||||
store i8 -123, i8* %x1, align 1
|
||||
store i8 0, i8* %b, align 1
|
||||
store float 0x40289999A0000000, float* %z1, align 4
|
||||
%0 = load i8, i8* %b, align 1
|
||||
%1 = trunc i8 %0 to i1
|
||||
%boolsi = zext i1 %1 to i32
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @3, i32 0, i32 0), i32 %boolsi)
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.3, i32 0, i32 0), i32 %boolsi)
|
||||
%2 = load i8, i8* %x1, align 1
|
||||
%sisiext = sext i8 %2 to i32
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @4, i32 0, i32 0), i32 %sisiext)
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.4, i32 0, i32 0), i32 %sisiext)
|
||||
%3 = load float, float* %z1, align 4
|
||||
%fpfpext = fpext float %3 to double
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @5, i32 0, i32 0), double %fpfpext)
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.5, i32 0, i32 0), double %fpfpext)
|
||||
@@ -50,7 +50,7 @@ entry:
|
||||
%idx34 = alloca i64, align 8
|
||||
%a35 = alloca double, align 8
|
||||
%0 = bitcast [3 x float]* %foo to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %0, i8* align 4 bitcast ([3 x float]* @0 to i8*), i32 12, i1 false)
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %0, i8* align 4 bitcast ([3 x float]* @.__const to i8*), i32 12, i1 false)
|
||||
store i64 0, i64* %idx, align 8
|
||||
br label %foreach.cond
|
||||
|
||||
@@ -65,7 +65,7 @@ foreach.body:
|
||||
store float %3, float* %a, align 4
|
||||
%4 = load float, float* %a, align 4
|
||||
%fpfpext = fpext float %4 to double
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @1, i32 0, i32 0), double %fpfpext)
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str, i32 0, i32 0), double %fpfpext)
|
||||
br label %foreach.inc
|
||||
|
||||
foreach.inc:
|
||||
@@ -93,7 +93,7 @@ foreach.body5:
|
||||
%11 = load float*, float** %a2, align 8
|
||||
%12 = load float, float* %11, align 8
|
||||
%fpfpext6 = fpext float %12 to double
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @2, i32 0, i32 0), double %fpfpext6)
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.1, i32 0, i32 0), double %fpfpext6)
|
||||
br label %foreach.inc7
|
||||
|
||||
foreach.inc7:
|
||||
@@ -119,7 +119,7 @@ foreach.body13:
|
||||
%ptrptr14 = bitcast i8* %17 to float*
|
||||
%18 = load float, float* %ptrptr14, align 8
|
||||
%fpfpext15 = fpext float %18 to double
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @3, i32 0, i32 0), double %fpfpext15)
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.2, i32 0, i32 0), double %fpfpext15)
|
||||
br label %foreach.inc16
|
||||
|
||||
foreach.inc16:
|
||||
@@ -144,7 +144,7 @@ foreach.body21:
|
||||
%24 = load i64, i64* %i, align 8
|
||||
%25 = load float, float* %a18, align 4
|
||||
%fpfpext22 = fpext float %25 to double
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @4, i32 0, i32 0), i64 %24, double %fpfpext22)
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.3, i32 0, i32 0), i64 %24, double %fpfpext22)
|
||||
br label %foreach.inc23
|
||||
|
||||
foreach.inc23:
|
||||
@@ -173,7 +173,7 @@ foreach.body30:
|
||||
%32 = load i8, i8* %i25, align 1
|
||||
%uisiext = zext i8 %32 to i32
|
||||
%33 = load double, double* %a27, align 8
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([16 x i8], [16 x i8]* @5, i32 0, i32 0), i32 %uisiext, double %33)
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([16 x i8], [16 x i8]* @.str.4, i32 0, i32 0), i32 %uisiext, double %33)
|
||||
br label %foreach.inc32
|
||||
|
||||
foreach.inc32:
|
||||
@@ -197,7 +197,7 @@ foreach.body38:
|
||||
%fpfpext39 = fpext float %38 to double
|
||||
store double %fpfpext39, double* %a35, align 8
|
||||
%39 = load double, double* %a35, align 8
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @6, i32 0, i32 0), double %39)
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.5, i32 0, i32 0), double %39)
|
||||
br label %foreach.inc40
|
||||
|
||||
foreach.inc40:
|
||||
|
||||
@@ -31,8 +31,8 @@ func int main()
|
||||
// #expect: while_switch.ll
|
||||
|
||||
|
||||
@0 = internal constant [2 x i8] c"3\00"
|
||||
@1 = internal constant [2 x i8] c"4\00"
|
||||
@.str = private constant [2 x i8] c"3\00"
|
||||
@.str.1 = private constant [2 x i8] c"4\00"
|
||||
|
||||
entry:
|
||||
%switch = alloca i32, align 4
|
||||
@@ -57,10 +57,10 @@ switch.entry:
|
||||
i32 6, label %switch.default
|
||||
]
|
||||
switch.case:
|
||||
%3 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @0, i32 0, i32 0))
|
||||
%3 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str, i32 0, i32 0))
|
||||
br label %switch.case1
|
||||
switch.case1:
|
||||
%4 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @1, i32 0, i32 0))
|
||||
%4 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i32 0, i32 0))
|
||||
br label %switch.default
|
||||
switch.default:
|
||||
br label %switch.exit
|
||||
|
||||
@@ -20,5 +20,5 @@ func void test1()
|
||||
entry:
|
||||
%p = alloca %test.Point, align 4
|
||||
%0 = bitcast %test.Point* %p to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %0, i8* align 4 bitcast (%test.Point* @0 to i8*), i32 8, i1 false)
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %0, i8* align 4 bitcast (%test.Point* @.__const to i8*), i32 8, i1 false)
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ func void test()
|
||||
%x = alloca [3 x i32], align 4
|
||||
%y = alloca %"int[]", align 8
|
||||
%0 = bitcast [3 x i32]* %x to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %0, i8* align 4 bitcast ([3 x i32]* @0 to i8*), i32 12, i1 false)
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %0, i8* align 4 bitcast ([3 x i32]* @.__const to i8*), i32 12, i1 false)
|
||||
%1 = bitcast [3 x i32]* %x to i32*
|
||||
%offset = getelementptr inbounds i32, i32* %1, i64 1
|
||||
%2 = insertvalue %"int[]" undef, i32* %offset, 0
|
||||
|
||||
@@ -10,7 +10,7 @@ func void test()
|
||||
%x = alloca [3 x i32], align 4
|
||||
%y = alloca %"int[]", align 8
|
||||
%0 = bitcast [3 x i32]* %x to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %0, i8* align 4 bitcast ([3 x i32]* @0 to i8*), i32 12, i1 false)
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %0, i8* align 4 bitcast ([3 x i32]* @.__const to i8*), i32 12, i1 false)
|
||||
%1 = bitcast [3 x i32]* %x to i32*
|
||||
%offset = getelementptr inbounds i32, i32* %1, i64 1
|
||||
%2 = insertvalue %"int[]" undef, i32* %offset, 0
|
||||
|
||||
@@ -9,7 +9,7 @@ func void test()
|
||||
%x = alloca [3 x i32], align 4
|
||||
%y = alloca %"int[]", align 8
|
||||
%0 = bitcast [3 x i32]* %x to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %0, i8* align 4 bitcast ([3 x i32]* @0 to i8*), i32 12, i1 false)
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %0, i8* align 4 bitcast ([3 x i32]* @.__const to i8*), i32 12, i1 false)
|
||||
%1 = bitcast [3 x i32]* %x to i32*
|
||||
%offset = getelementptr inbounds i32, i32* %1, i64 1
|
||||
%2 = insertvalue %"int[]" undef, i32* %offset, 0
|
||||
|
||||
@@ -9,7 +9,7 @@ func void test()
|
||||
%x = alloca [3 x i32], align 4
|
||||
%y = alloca %"int[]", align 8
|
||||
%0 = bitcast [3 x i32]* %x to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %0, i8* align 4 bitcast ([3 x i32]* @0 to i8*), i32 12, i1 false)
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %0, i8* align 4 bitcast ([3 x i32]* @.__const to i8*), i32 12, i1 false)
|
||||
%1 = bitcast [3 x i32]* %x to i32*
|
||||
%offset = getelementptr inbounds i32, i32* %1, i64 0
|
||||
%2 = insertvalue %"int[]" undef, i32* %offset, 0
|
||||
|
||||
Reference in New Issue
Block a user