$path_root = split-path -Path $PSScriptRoot -Parent $misc = join-path $PSScriptRoot 'helpers/misc.ps1' . $misc $path_toolchain = join-path $path_root 'toolchain' $path_rad = join-path $path_toolchain 'rad' # --- Toolchain Executable Paths --- $compiler = 'clang' $optimizer = 'opt.exe' $linker = 'lld-link.exe' $archiver = 'llvm-lib.exe' $radbin = join-path $path_rad 'radbin.exe' $radlink = join-path $path_rad 'radlink.exe' # https://clang.llvm.org/docs/ClangCommandLineReference.html $flag_all_c = @('-x', 'c') $flag_c11 = '-std=c11' $flag_c23 = '-std=c23' $flag_all_cpp = '-x c++' $flag_charset_utf8 = '-fexec-charset=utf-8' $flag_compile = '-c' $flag_color_diagnostics = '-fcolor-diagnostics' $flag_no_builtin_includes = '-nobuiltininc' $flag_no_color_diagnostics = '-fno-color-diagnostics' $flag_debug = '-g' $flag_debug_codeview = '-gcodeview' $flag_define = '-D' $flag_emit_llvm = '-emit-llvm' $flag_stop_after_gen = '-S' $flag_exceptions_disabled = '-fno-exceptions' $flag_rtti_disabled = '-fno-rtti' $flag_diagnostics_absolute_paths = '-fdiagnostics-absolute-paths' $flag_preprocess = '-E' $flag_include = '-I' $flag_section_data = '-fdata-sections' $flag_section_functions = '-ffunction-sections' $flag_library = '-l' $flag_library_path = '-L' $flag_linker = '-Wl,' $flag_link_dll = '/DLL' $flag_link_mapfile = '/MAP:' $flag_link_optimize_references = '/OPT:REF' $flag_link_win_subsystem_console = '/SUBSYSTEM:CONSOLE' $flag_link_win_subsystem_windows = '/SUBSYSTEM:WINDOWS' $flag_link_win_machine_32 = '/MACHINE:X86' $flag_link_win_machine_64 = '/MACHINE:X64' $flag_link_win_debug = '/DEBUG' $flag_link_win_pdb = '/PDB:' $flag_link_win_path_output = '/OUT:' $flag_link_no_incremental = '/INCREMENTAL:NO' $flag_no_optimization = '-O0' $flag_optimize_fast = '-O2' $flag_optimize_size = '-O1' $flag_optimize_intrinsics = '-Oi' $flag_path_output = '-o' $flag_preprocess_non_intergrated = '-no-integrated-cpp' $flag_profiling_debug = '-fdebug-info-for-profiling' $flag_set_stack_size = '-stack=' $flag_syntax_only = '-fsyntax-only' $flag_target_arch = '-target' $flag_time_trace = '-ftime-trace' $flag_verbose = '-v' $flag_wall = '-Wall' $flag_warning = '-W' $flag_warnings_as_errors = '-Werror' $flag_nologo = '/nologo' $path_build = join-path $path_root 'build' if ( -not(test-path -Path $path_build) ) { new-item -ItemType Directory -Path $path_build } push-location $path_build # --- File Paths --- $unit_name = "simple" $unit_source = join-path $path_root "code\C\$unit_name.c" $ir_unoptimized = join-path $path_build "$unit_name.ll" $ir_optimized = join-path $path_build "$unit_name.opt.ll" $object = join-path $path_build "$unit_name.obj" $binary = join-path $path_build "$unit_name.exe" $pdb = join-path $path_build "$unit_name.pdb" $map = join-path $path_build "$unit_name.map" # --- Stage 1: Compile C to LLVM IR --- write-host "Stage 1: Compiling C to LLVM IR" $compiler_args = @() # $compiler_args += $flag_stop_after_gen # $compiler_args += $flag_emit_llvm $compiler_args += ($flag_define + 'BUILD_DEBUG=1') $compiler_args += $flag_debug # $compiler_args += $flag_debug_codeview $compiler_args += $flag_wall # $compiler_args += $flag_charset_utf8 $compiler_args += $flag_c23 $compiler_args += $flag_no_optimization # $compiler_args += $flag_no_builtin_includes $compiler_args += $flag_diagnostics_absolute_paths $compiler_args += $flag_rtti_disabled $compiler_args += $flag_exceptions_disabled $compiler_args += ($flag_include + $path_root) $compiler_args += $flag_compile $compiler_args += $flag_path_output, $object $compiler_args += $unit_source $compiler_args | ForEach-Object { Write-Host $_ } $stage1_time = Measure-Command { & $compiler $compiler_args } write-host "Compilation took $($stage1_time.TotalMilliseconds)ms" # write-host "IR generation took $($stage1_time.TotalMilliseconds)ms" write-host # --- Stage 2: Manually Optimize LLVM IR --- if ($false) { write-host "Manually Optimizing LLVM IR with 'opt'" $optimization_passes = @( '-sroa', # Scalar Replacement Of Aggregates '-early-cse', # Early Common Subexpression Elimination '-instcombine' # Instruction Combining ) $optimizer_args = @( $optimization_passes, $ir_unoptimized, $flag_path_output, $ir_optimized ) $optimizer_args | ForEach-Object { Write-Host $_ } $stage2_time = Measure-Command { & $optimizer $optimizer_args } write-host "Optimization took $($stage2_time.TotalMilliseconds)ms" write-hosts write-host "Compiling LLVM IR to Object File with 'clang'" $ir_to_obj_args = @() $ir_to_obj_args += $flag_compile $ir_to_obj_args += $flag_path_output, $object $ir_to_obj_args += $ir_optimized $ir_to_obj_args | ForEach-Object { Write-Host $_ } $stage3_time = Measure-Command { & $compiler $ir_to_obj_args } write-host "Object file generation took $($stage3_time.TotalMilliseconds)ms" write-host } if ($true) { # write-host "Linking with lld-link" $linker_args = @() $linker_args += $flag_nologo $linker_args += $flag_link_win_machine_64 $linker_args += $flag_link_no_incremental $linker_args += ($flag_link_win_path_output + $binary) $linker_args += "$flag_link_win_debug" $linker_args += $flag_link_win_pdb + $pdb $linker_args += $flag_link_mapfile + $map $linker_args += $flag_link_win_subsystem_console $linker_args += $object # Diagnoistc print for the args $linker_args | ForEach-Object { Write-Host $_ } $linking_time = Measure-Command { & $linker $linker_args } write-host "Linking took $($linking_time.TotalMilliseconds)ms" write-host } if ($false) { write-host "Dumping Debug Info" $rbin_out = '--out:' $rbin_dump = '--dump' $rdi = join-path $path_build "$unit_name.rdi" $rdi_listing = join-path $path_build "$unit_name.rdi.list" $nargs = @($pdb, ($rbin_out + $rdi)) & $radbin $nargs $nargs = @($rbin_dump, $rdi) $dump = & $radbin $nargs $dump > $rdi_listing } Pop-Location