Merge pull request #26 from birth-software/compile-in-different-optimization-modes
Compile in different optimization modes
This commit is contained in:
commit
667597d38e
18
.github/workflows/ci.yml
vendored
18
.github/workflows/ci.yml
vendored
@ -18,12 +18,12 @@ jobs:
|
|||||||
- name: Build and test
|
- name: Build and test
|
||||||
run: |
|
run: |
|
||||||
./run_tests.sh 1
|
./run_tests.sh 1
|
||||||
# macos_build_and_test:
|
macos_build_and_test:
|
||||||
# runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
# timeout-minutes: 15
|
timeout-minutes: 15
|
||||||
# steps:
|
steps:
|
||||||
# - name: Checkout
|
- name: Checkout
|
||||||
# uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
# - name: Build and test
|
- name: Build and test
|
||||||
# run: |
|
run: |
|
||||||
# ./run_tests.sh
|
./run_tests.sh 1
|
||||||
|
101
bootstrap/main.c
101
bootstrap/main.c
@ -1,5 +1,6 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
@ -159,7 +160,7 @@ fn u64 strlen (const char* c_string)
|
|||||||
#define strlit(s) (String){ .pointer = (u8*)s, .length = sizeof(s) - 1, }
|
#define strlit(s) (String){ .pointer = (u8*)s, .length = sizeof(s) - 1, }
|
||||||
#define ch_to_str(ch) (String){ .pointer = &ch, .length = 1 }
|
#define ch_to_str(ch) (String){ .pointer = &ch, .length = 1 }
|
||||||
#define array_to_slice(arr) { .pointer = (arr), .length = array_length(arr) }
|
#define array_to_slice(arr) { .pointer = (arr), .length = array_length(arr) }
|
||||||
#define pointer_to_bytes(p) Slice<u8>{ .pointer = (u8*)(p), .length = sizeof(*p) }
|
#define pointer_to_bytes(p) (String) { .pointer = (u8*)(p), .length = sizeof(*p) }
|
||||||
#define struct_to_bytes(s) pointer_to_bytes(&(s))
|
#define struct_to_bytes(s) pointer_to_bytes(&(s))
|
||||||
|
|
||||||
#define case_to_name(prefix, e) case prefix ## e: return strlit(#e)
|
#define case_to_name(prefix, e) case prefix ## e: return strlit(#e)
|
||||||
@ -2512,6 +2513,31 @@ fn u8 type_equal(Thread* thread, Type* a, Type* b)
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
fn Hash hash_type(Thread* thread, Type* type);
|
||||||
|
|
||||||
|
fn Hash node_get_hash_default(Thread* thread, Node* node)
|
||||||
|
{
|
||||||
|
return fnv_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn Hash node_get_hash_projection(Thread* thread, Node* node)
|
||||||
|
{
|
||||||
|
trap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn Hash node_get_hash_control_projection(Thread* thread, Node* node)
|
||||||
|
{
|
||||||
|
auto projection_index = node->control_projection.projection.index;
|
||||||
|
auto proj_index_bytes = struct_to_bytes(projection_index);
|
||||||
|
return hash_bytes(proj_index_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn Hash node_get_hash_constant(Thread* thread, Node* node)
|
||||||
|
{
|
||||||
|
auto* type = thread_type_get(thread, node->type);
|
||||||
|
auto type_hash = hash_type(thread, type);
|
||||||
|
return type_hash;
|
||||||
|
}
|
||||||
|
|
||||||
typedef NodeIndex NodeIdealize(Thread* thread, NodeIndex node_index);
|
typedef NodeIndex NodeIdealize(Thread* thread, NodeIndex node_index);
|
||||||
typedef TypeIndex NodeComputeType(Thread* thread, NodeIndex node_index);
|
typedef TypeIndex NodeComputeType(Thread* thread, NodeIndex node_index);
|
||||||
@ -2573,11 +2599,6 @@ fn Hash type_get_hash_tuple(Thread* thread, Type* type)
|
|||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn Hash node_get_hash_constant(Thread* thread, Node* node)
|
|
||||||
{
|
|
||||||
trap();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn u8 is_projection(Node* n)
|
fn u8 is_projection(Node* n)
|
||||||
{
|
{
|
||||||
return (n->id == NODE_CONTROL_PROJECTION) | (n->id == NODE_PROJECTION);
|
return (n->id == NODE_CONTROL_PROJECTION) | (n->id == NODE_PROJECTION);
|
||||||
@ -2921,22 +2942,27 @@ global const NodeVirtualTable node_functions[NODE_COUNT] = {
|
|||||||
[NODE_START] = {
|
[NODE_START] = {
|
||||||
.compute_type = &compute_type_start,
|
.compute_type = &compute_type_start,
|
||||||
.idealize = &idealize_null,
|
.idealize = &idealize_null,
|
||||||
|
.get_hash = &node_get_hash_default,
|
||||||
},
|
},
|
||||||
[NODE_STOP] = {
|
[NODE_STOP] = {
|
||||||
.compute_type = &compute_type_bottom,
|
.compute_type = &compute_type_bottom,
|
||||||
.idealize = &idealize_stop,
|
.idealize = &idealize_stop,
|
||||||
|
.get_hash = &node_get_hash_default,
|
||||||
},
|
},
|
||||||
[NODE_CONTROL_PROJECTION] = {
|
[NODE_CONTROL_PROJECTION] = {
|
||||||
.compute_type = &compute_type_projection,
|
.compute_type = &compute_type_projection,
|
||||||
.idealize = &idealize_control_projection,
|
.idealize = &idealize_control_projection,
|
||||||
|
.get_hash = &node_get_hash_control_projection,
|
||||||
},
|
},
|
||||||
[NODE_DEAD_CONTROL] = {
|
[NODE_DEAD_CONTROL] = {
|
||||||
.compute_type = &compute_type_dead_control,
|
.compute_type = &compute_type_dead_control,
|
||||||
.idealize = &idealize_null,
|
.idealize = &idealize_null,
|
||||||
|
.get_hash = &node_get_hash_default,
|
||||||
},
|
},
|
||||||
[NODE_RETURN] = {
|
[NODE_RETURN] = {
|
||||||
.compute_type = &compute_type_return,
|
.compute_type = &compute_type_return,
|
||||||
.idealize = &idealize_return,
|
.idealize = &idealize_return,
|
||||||
|
.get_hash = &node_get_hash_default,
|
||||||
},
|
},
|
||||||
[NODE_CONSTANT] = {
|
[NODE_CONSTANT] = {
|
||||||
.compute_type = &compute_type_constant,
|
.compute_type = &compute_type_constant,
|
||||||
@ -2954,7 +2980,7 @@ fn Hash hash_type(Thread* thread, Type* type)
|
|||||||
hash = type_functions[type->id].get_hash(thread, type);
|
hash = type_functions[type->id].get_hash(thread, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(hash);
|
assert(hash != 0);
|
||||||
type->hash = hash;
|
type->hash = hash;
|
||||||
|
|
||||||
return hash;
|
return hash;
|
||||||
@ -3032,20 +3058,33 @@ fn s32 intern_pool_find_node_slot(Thread* thread, u32 original_index, NodeIndex
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn Hash hash_node(Node* node)
|
fn Hash hash_node(Thread* thread, Node* node)
|
||||||
{
|
{
|
||||||
auto hash = node->hash;
|
auto hash = node->hash;
|
||||||
if (!hash)
|
if (!hash)
|
||||||
{
|
{
|
||||||
hash = fnv_offset;
|
hash = node_functions[node->id].get_hash(thread, node);
|
||||||
for (auto* it = (u8*)node; it < (u8*)(node + 1); it += 1)
|
|
||||||
|
hash = hash_byte(hash, node->id);
|
||||||
|
|
||||||
|
auto inputs = node_get_inputs(thread, node);
|
||||||
|
for (u32 i = 0; i < inputs.length; i += 1)
|
||||||
{
|
{
|
||||||
hash = hash_byte(hash, *it);
|
auto input_index = inputs.pointer[i];
|
||||||
|
if (validi(input_index))
|
||||||
|
{
|
||||||
|
for (u8* it = (u8*)&input_index; it < (u8*)(&input_index + 1); it += 1)
|
||||||
|
{
|
||||||
|
hash = hash_byte(hash, *it);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
node->hash = hash;
|
node->hash = hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(hash);
|
||||||
|
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3053,7 +3092,7 @@ fn NodeGetOrPut intern_pool_get_or_put_node(Thread* thread, NodeIndex node_index
|
|||||||
{
|
{
|
||||||
auto existing_capacity = thread->interned.nodes.capacity;
|
auto existing_capacity = thread->interned.nodes.capacity;
|
||||||
auto* node = &thread->buffer.nodes.pointer[geti(node_index)];
|
auto* node = &thread->buffer.nodes.pointer[geti(node_index)];
|
||||||
auto hash = hash_node(node);
|
auto hash = hash_node(thread, node);
|
||||||
auto original_index = hash & (existing_capacity - 1);
|
auto original_index = hash & (existing_capacity - 1);
|
||||||
|
|
||||||
auto slot = intern_pool_find_node_slot(thread, original_index, node_index);
|
auto slot = intern_pool_find_node_slot(thread, original_index, node_index);
|
||||||
@ -3092,23 +3131,47 @@ fn NodeIndex intern_pool_remove_node(Thread* thread, NodeIndex node_index)
|
|||||||
{
|
{
|
||||||
auto existing_capacity = thread->interned.nodes.capacity;
|
auto existing_capacity = thread->interned.nodes.capacity;
|
||||||
auto* node = thread_node_get(thread, node_index);
|
auto* node = thread_node_get(thread, node_index);
|
||||||
auto hash = hash_node(node);
|
auto hash = hash_node(thread, node);
|
||||||
|
|
||||||
auto original_index = hash & (existing_capacity - 1);
|
auto original_index = hash & (existing_capacity - 1);
|
||||||
auto slot = intern_pool_find_node_slot(thread, original_index, node_index);
|
auto slot = intern_pool_find_node_slot(thread, original_index, node_index);
|
||||||
if (slot != -1)
|
if (slot != -1)
|
||||||
{
|
{
|
||||||
auto index = (u32)slot;
|
auto slot_index = (u32)slot;
|
||||||
auto* slot_pointer = &thread->interned.nodes.pointer[index];
|
auto* slot_pointer = &thread->interned.nodes.pointer[slot_index];
|
||||||
auto old_node_index = *(NodeIndex*)slot_pointer;
|
auto old_node_index = *(NodeIndex*)slot_pointer;
|
||||||
*slot_pointer = 0;
|
*slot_pointer = 0;
|
||||||
|
|
||||||
|
auto index = slot_index;
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
index = (index + 1) & (existing_capacity - 1);
|
index = (index + 1) & (existing_capacity - 1);
|
||||||
if (thread->interned.nodes.pointer[index] == 0)
|
auto existing = thread->interned.nodes.pointer[index];
|
||||||
|
if (existing == 0)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
auto existing_node_index = *(NodeIndex*)&existing;
|
||||||
|
auto* existing_node = thread_node_get(thread, existing_node_index);
|
||||||
|
auto existing_node_hash = hash_node(thread, existing_node);
|
||||||
|
auto existing_index = existing_node_hash & (existing_capacity - 1);
|
||||||
|
|
||||||
|
if (slot_index <= existing_index)
|
||||||
|
{
|
||||||
|
if ((slot_index < existing_index) & (existing_index <= index))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((slot_index <= index) | (slot_index < existing_index))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
trap();
|
trap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4630,9 +4693,9 @@ fn String c_lower(Thread* thread)
|
|||||||
|
|
||||||
fn void thread_init(Thread* thread)
|
fn void thread_init(Thread* thread)
|
||||||
{
|
{
|
||||||
*thread = (Thread) {
|
memset(thread, 0, sizeof(Thread));
|
||||||
.arena = arena_init_default(KB(64)),
|
thread->arena = arena_init_default(KB(64));
|
||||||
};
|
|
||||||
Type top, bot, live_control, dead_control;
|
Type top, bot, live_control, dead_control;
|
||||||
memset(&top, 0, sizeof(Type));
|
memset(&top, 0, sizeof(Type));
|
||||||
top.id = TYPE_TOP;
|
top.id = TYPE_TOP;
|
||||||
|
10
compile.sh
10
compile.sh
@ -2,13 +2,19 @@
|
|||||||
|
|
||||||
function compile()
|
function compile()
|
||||||
{
|
{
|
||||||
|
mkdir -p $build_dir
|
||||||
|
|
||||||
build_dir=$1
|
build_dir=$1
|
||||||
exe_name=$2
|
exe_name=$2
|
||||||
debug_info=$3
|
debug_info=$3
|
||||||
optimizations=$4
|
optimizations=$4
|
||||||
static=0
|
static=$5
|
||||||
|
|
||||||
mkdir -p $build_dir
|
echo "BUILD_DIR: $build_dir"
|
||||||
|
echo "EXE_NAME: $exe_name"
|
||||||
|
echo "DEBUG_INFO: $debug_info"
|
||||||
|
echo "OPTIMIZATIONS: $optimizations"
|
||||||
|
echo "STATIC: $static"
|
||||||
|
|
||||||
compile_command="clang bootstrap/main.c -o $build_dir/$exe_name $debug_info $optimizations -std=gnu2x -Wall -Wextra -Wpedantic -Wno-nested-anon-types -Wno-keyword-macro -Wno-gnu-auto-type -Wno-auto-decl-extensions -pedantic -fno-exceptions -fno-stack-protector -ferror-limit=1 -MJ $build_dir/compile_commands.json"
|
compile_command="clang bootstrap/main.c -o $build_dir/$exe_name $debug_info $optimizations -std=gnu2x -Wall -Wextra -Wpedantic -Wno-nested-anon-types -Wno-keyword-macro -Wno-gnu-auto-type -Wno-auto-decl-extensions -pedantic -fno-exceptions -fno-stack-protector -ferror-limit=1 -MJ $build_dir/compile_commands.json"
|
||||||
|
|
||||||
|
15
debug.sh
15
debug.sh
@ -3,17 +3,26 @@
|
|||||||
set -e
|
set -e
|
||||||
|
|
||||||
path=$1
|
path=$1
|
||||||
echo $path
|
if [ "$path" == "" ]
|
||||||
|
then
|
||||||
|
echo "error: a valid binary path must be provided to debug"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
source ./compile.sh
|
source ./compile.sh
|
||||||
build_dir="build"
|
build_dir="build"
|
||||||
exe_name="nest"
|
exe_name="nest"
|
||||||
exe_path=$build_dir/$exe_name
|
exe_path=$build_dir/$exe_name
|
||||||
debug_flags="-g"
|
debug_flags="-g"
|
||||||
optimization_flags=""
|
optimization_flags="-O0"
|
||||||
bootstrap_args="$path"
|
bootstrap_args="$path"
|
||||||
|
case "$OSTYPE" in
|
||||||
|
darwin*) static=0;;
|
||||||
|
linux*) static=1;;
|
||||||
|
*) echo "unknown: $OSTYPE" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
compile $build_dir $exe_name $debug_flags $optimization_flags
|
compile $build_dir $exe_name $debug_flags $optimization_flags $static
|
||||||
|
|
||||||
case "$OSTYPE" in
|
case "$OSTYPE" in
|
||||||
darwin*) lldb -- $exe_path $bootstrap_args;;
|
darwin*) lldb -- $exe_path $bootstrap_args;;
|
||||||
|
64
run_tests.sh
64
run_tests.sh
@ -3,46 +3,62 @@
|
|||||||
set -e
|
set -e
|
||||||
source ./compile.sh
|
source ./compile.sh
|
||||||
all=$1
|
all=$1
|
||||||
|
all=$1
|
||||||
build_dir="build"
|
build_dir="build"
|
||||||
exe_name="nest"
|
base_exe_name="nest"
|
||||||
exe_path=$build_dir/$exe_name
|
|
||||||
debug_flags="-g"
|
debug_flags="-g"
|
||||||
no_optimization_flags=""
|
no_optimization_flags=""
|
||||||
test_names="first"
|
test_names="first"
|
||||||
|
|
||||||
if [ "$all" == "1" ]
|
if [ "$all" == "1" ]
|
||||||
then
|
then
|
||||||
optimization_modes=("" "-O1" "-O2 march=native", "-Os march=native" "-Oz march=native" "-O3 march=native")
|
optimization_modes=("-O0" "-O1" "-O2" "-Os" "-Oz" "-O3")
|
||||||
|
case "$OSTYPE" in
|
||||||
|
darwin*) linking_modes=("0") ;;
|
||||||
|
linux*) linking_modes=("0" "1") ;;
|
||||||
|
*) echo "unknown: $OSTYPE"; exit 1 ;;
|
||||||
|
esac
|
||||||
else
|
else
|
||||||
optimization_modes=("")
|
optimization_modes=("-O0")
|
||||||
|
case "$OSTYPE" in
|
||||||
|
darwin*) linking_modes=("0") ;;
|
||||||
|
linux*) linking_modes=("1") ;;
|
||||||
|
*) echo "unknown: $OSTYPE"; exit 1 ;;
|
||||||
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
for optimization_mode in "${optimization_modes[@]}"
|
for linking_mode in "${linking_modes[@]}"
|
||||||
do
|
do
|
||||||
|
for optimization_mode in "${optimization_modes[@]}"
|
||||||
printf "\n===========================\n"
|
|
||||||
echo "TESTS ($optimization_mode)"
|
|
||||||
printf "===========================\n\n"
|
|
||||||
|
|
||||||
compile $build_dir $exe_name $debug_flags $optimization_mode;
|
|
||||||
|
|
||||||
printf "\n===========================\n"
|
|
||||||
echo "COMPILER BUILD OK"
|
|
||||||
printf "===========================\n\n"
|
|
||||||
|
|
||||||
for test_name in "${test_names[@]}"
|
|
||||||
do
|
do
|
||||||
|
|
||||||
printf "\n===========================\n"
|
printf "\n===========================\n"
|
||||||
echo "$test_name..."
|
echo "TESTS (STATIC=$linking_mode, $optimization_mode)"
|
||||||
printf "===========================\n\n"
|
printf "===========================\n\n"
|
||||||
build/nest "tests/$test_name.nat"
|
|
||||||
|
exe_name="${base_exe_name}_${optimization_mode}_$linking_mode"
|
||||||
|
compile $build_dir $exe_name $debug_flags $optimization_mode $linking_mode;
|
||||||
|
|
||||||
printf "\n===========================\n"
|
printf "\n===========================\n"
|
||||||
echo "$test_name [COMPILATION] [OK]"
|
echo "COMPILER BUILD OK"
|
||||||
printf "===========================\n\n"
|
|
||||||
nest/$test_name
|
|
||||||
printf "\n===========================\n"
|
|
||||||
echo "$test_name [RUN] [OK]"
|
|
||||||
printf "===========================\n\n"
|
printf "===========================\n\n"
|
||||||
|
|
||||||
|
for test_name in "${test_names[@]}"
|
||||||
|
do
|
||||||
|
printf "\n===========================\n"
|
||||||
|
echo "$test_name..."
|
||||||
|
printf "===========================\n\n"
|
||||||
|
cmd="build/$exe_name tests/$test_name.nat"
|
||||||
|
echo "Run command: $cmd"
|
||||||
|
eval "$cmd"
|
||||||
|
printf "\n===========================\n"
|
||||||
|
echo "$test_name [COMPILATION] [OK]"
|
||||||
|
printf "===========================\n\n"
|
||||||
|
nest/$test_name
|
||||||
|
printf "\n===========================\n"
|
||||||
|
echo "$test_name [RUN] [OK]"
|
||||||
|
printf "===========================\n\n"
|
||||||
|
done
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user