#!/bin/bash usage(){ cat << EOF Usage: $0 [-c ] [-d] -s|--asm Option: -c : optional if not specify clang path, use default: llvm/bin/clang in repository gemmPerf. -s|--asm : required assembly file path must end with .s EOF } gen_amdgcn_target(){ amdgcn_target=$(grep -nr "\.amdgcn_target" $s_abs_path | awk '{print $NF}' | awk -F "\"" '{print $2}') amdgcn_target=${amdgcn_target#*--} [[ -n ${amdgcn_target} ]] || { echo "target-id null, exit"; exit -1; } [[ $DEBUG_MODE = true ]] && echo -e "\n--- amdgcn_target: $amdgcn_target" } gen_co_from_s(){ local co_dir=${PWD}/hsaco_kernel local o_dir=${PWD}/o_kernel [[ -d ${co_dir} ]] || mkdir -p ${co_dir} [[ -d ${o_dir} ]] || mkdir -p ${o_dir} local o_abs_dir_path local name_prefix local o_name local co_name o_abs_dir_path=$(dirname ${s_abs_path}) name_prefix=$(basename ${s_abs_path}) name_prefix=${name_prefix%.s} [[ $DEBUG_MODE = true ]] && echo -e "\n--- name prefix: $name_prefix" o_name="${name_prefix}.o" co_name="${name_prefix}.co" ### Command: generate .o from .s: #grep "$2" $s_abs_path || { echo -e "\n*** Fatal: .amdgcn_target in .s not contain specified target-id: $2\n*** .s: $(grep ".amdgcn_target" $s_abs_path)"; exit -1; } [[ $DEBUG_MODE = true ]] && echo -e "\n--- .s -> .o:\n $ ${ASM_COMPILER} -x assembler -target amdgcn-amd-amdhsa -mcpu=${amdgcn_target} -c -o ${o_dir}/${o_name} ${s_abs_path}" ${ASM_COMPILER} -x assembler -target amdgcn-amd-amdhsa -mcpu=${amdgcn_target} -c -o ${o_dir}/${o_name} ${s_abs_path} [[ $? -eq 0 ]] || { echo -e "\n*** Fatal: $(basename $0) failure .s -> .o\n $ ${ASM_COMPILER} -x assembler -target amdgcn-amd-amdhsa -mcpu=${amdgcn_target} -c -o ${o_dir}/${o_name} ${s_abs_path} "; exit -1; } o_abs_path=$(realpath -e ${o_dir}/${o_name}) [[ $DEBUG_MODE = true ]] && echo -e "\n--- .o dir: ${o_dir}\n--- .o path:\n $(realpath -e ${o_dir}/${o_name})" ### Command: generate .hsaco/.co from .o: [[ $DEBUG_MODE = true ]] && echo -e "\n--- .o -> .co:\n $ ${ASM_COMPILER} -target amdgcn-amd-amdhsa -o ${co_dir}/${co_name} ${o_abs_path}" ${ASM_COMPILER} -target amdgcn-amd-amdhsa -o ${co_dir}/${co_name} ${o_abs_path} [[ $? -eq 0 ]] || { echo -e "\n*** Fatal: $(basename $0) failure .o -> .co\n $ ${ASM_COMPILER} -target amdgcn-amd-amdhsa -o ${co_dir}/${co_name} ${o_abs_path}"; exit -1; } co_abs_path=$(realpath -e ${co_dir}/${co_name}) || exit -1 [[ $DEBUG_MODE = true ]] && echo -e "\n--- .co dir: ${co_dir}\n--- .co path:\n ${co_abs_path}" echo "${co_abs_path}" } check_getopt_exit_status(){ local exit_status=$1 if [[ $exit_status -eq 0 ]] && [[ $DEBUG_MODE = true ]]; then echo -e "--- Parsing Successfully." elif [[ $exit_status -eq 1 ]]; then echo -e "*** getopt(3) returns errors." exit -1 elif [[ $exit_status -eq 2 ]]; then echo -e "*** Don't understand its own parameters" exit -1 elif [[ $exit_status -eq 3 ]]; then echo -e "*** an internal error occurs like out-of-memory" exit -1 elif [[ $exit_status -eq 4 ]] && [[ $DEBUG_MODE = true ]]; then echo -e "--- called with -T" fi } parse_option(){ getopt -T if [[ $? -eq 4 ]]; then GETOPT_PARSE=$(getopt --name "${0}" --longoptions help,compiler:,asm:,debug --options hc:ds: -- "$@" 2>getopt_stderr.log) GETOPT_RET=$? if [[ -s getopt_stderr.log ]]; then echo -e "\n*** Fatal:" echo "*** $(cat getopt_stderr.log)" rm getopt_stderr.log fi check_getopt_exit_status $GETOPT_RET #if [[ $GETOPT_RET -eq 0 ]] ; then # echo -e "--- option: ${GETOPT_PARSE}" #fi else echo -e "\n*** Fatal:" echo "*** getopt is an old version, Need enhanced version" exit -1 fi eval set -- ${GETOPT_PARSE} while true; do case "$1" in -h|--help) usage exit 0 ;; -c|--compiler) ASM_COMPILER=$(realpath -e $2) || exit -1 shift 2 ;; -s|--asm) ASM_FILE_PATH=$(realpath -e $2) || exit -1 [[ $ASM_FILE_PATH =~ \.s$ ]] || { echo -e "\n*** Fatal: asm file not end with .s\n*** asm file: $ASM_FILE_PATH"; exit -1; } shift 2 ;; -d|--debug) DEBUG_MODE=true shift ;; --) shift break ;; *) echo "unrecognized parameter:[$1] received, exit" exit -1 ;; esac done if [[ -z $ASM_COMPILER ]]; then [[ $DEBUG_MODE = true ]] && echo -e "\n--- option no compiler option: -c/--compiler\n--- use default: /opt/rocm/llvm/bin/clang-18)" ASM_COMPILER=/opt/rocm/llvm/bin/clang-18 || exit -1 fi if [[ -z $ASM_FILE_PATH ]]; then usage exit -1 fi REMAIN_PARAMS_NUM=$# REMAIN_PARAMS=$@ if [[ $DEBUG_MODE = true ]]; then echo "--- remaining parameter number: $#" echo "--- remaining parameter option: $@" fi } ##### # main ##### # name # A word consisting only of alphanumeric characters and underscores, # and beginning with an alphabetic character or an underscore. # Also referred to as an identifier. ##### ASM_COMPILER= ASM_FILE_PATH= REMAIN_PARAMS_NUM= REMAIN_PARAMS= DEBUG_MODE=false parse_option $@ shift $(($#-$REMAIN_PARAMS_NUM)) #echo "\$@: $@" ##### # compile .s -> .co ##### s_abs_path=$ASM_FILE_PATH co_abs_path= gen_amdgcn_target gen_co_from_s