2016-01-26 20:14:33 -06:00
#!/usr/bin/perl -w
2016-08-14 16:22:25 +05:30
# Need perl > 5.10 to use logic-defined or
use 5.006 ; use v5 .10.1 ;
2016-01-26 20:14:33 -06:00
use File::Basename ;
2018-06-08 07:43:25 -04:00
use File::Temp qw/ :mktemp / ;
use Cwd ;
use Cwd 'abs_path' ;
2016-01-26 20:14:33 -06:00
2016-07-13 11:26:03 +05:30
# HIP compiler driver
2016-01-26 20:14:33 -06:00
# Will call NVCC or HCC (depending on target) and pass the appropriate include and library options for
# the target compiler and HIP infrastructure.
# Will pass-through options to the target compiler. The tools calling HIPCC must ensure the compiler
# options are appropriate for the target compiler.
# Environment variable HIP_PLATFORM control compilation path:
# HIP_PLATFORM='nvcc' or HIP_PLATFORM='hcc'.
# If HIP_PLATFORM is not set hipcc will attempt auto-detect based on if nvcc is found.
#
# Other environment variable controls:
2016-07-13 11:26:03 +05:30
# HIP_PATH : Path to HIP directory, default is one dir level above location of this script
2016-01-26 20:14:33 -06:00
# CUDA_PATH : Path to CUDA SDK (default /usr/local/cuda). Used on NVIDIA platforms only.
2019-10-10 07:26:55 -07:00
# HCC_HOME : Path to HCC SDK (defaults to ../../hcc relative to this
# script's abs_path). Used on AMD platforms only.
# HSA_PATH : Path to HSA dir (defaults to ../../hsa relative to abs_path
# of this script). Used on AMD platforms only.
2018-07-20 13:11:13 -04:00
# HIP_VDI_HOME : Path to HIP/VDI directory. Used on AMD platforms only.
2016-01-26 20:14:33 -06:00
2016-02-26 13:47:58 -06:00
if ( scalar @ARGV == 0 ){
2017-03-14 14:25:34 +05:30
print "No Arguments passed, exiting ...\n" ;
exit ( - 1 );
2016-02-26 13:47:58 -06:00
}
2016-01-26 20:14:33 -06:00
2016-08-14 16:22:25 +05:30
#---
# Function to parse config file
sub parse_config_file {
my ( $file , $config ) = @_ ;
if ( open ( CONFIG , "$file" )) {
while ( <CONFIG> ) {
my $config_line = $_ ;
chop ( $config_line );
$config_line =~ s/^\s*// ;
$config_line =~ s/\s*$// ;
if (( $config_line !~ /^#/ ) && ( $config_line ne "" )) {
my ( $name , $value ) = split ( /=/ , $config_line );
$$config { $name } = $value ;
}
}
close ( CONFIG );
}
}
$verbose = $ENV { 'HIPCC_VERBOSE' } // 0 ;
2017-07-01 09:43:31 -05:00
# Verbose: 0x1=commands, 0x2=paths, 0x4=hipcc args
2016-01-26 20:14:33 -06:00
2019-02-07 11:07:50 -05:00
$isWindows = $^O eq 'MSWin32' ;
2018-09-28 11:05:27 -04:00
$HIPCC_COMPILE_FLAGS_APPEND = $ENV { 'HIPCC_COMPILE_FLAGS_APPEND' };
$HIPCC_LINK_FLAGS_APPEND = $ENV { 'HIPCC_LINK_FLAGS_APPEND' };
2020-02-03 22:26:16 -05:00
# Known HIP target names.
@knownTargets = ( 'gfx701' , 'gfx801' , 'gfx802' , 'gfx803' , 'gfx900' , 'gfx906' , 'gfx908' , 'gfx1010' , 'gfx1011' , 'gfx1012' );
2019-10-10 07:26:55 -07:00
#
# TODO: Fix rpath LDFLAGS settings
#
# Since this hipcc script gets installed at two uneven hierarchical levels,
# linked by symlink, the absolute path of this script should be used to
# derive HIP_PATH, as dirname $0 could be /opt/rocm/bin or /opt/rocm/hip/bin
# depending on how it gets invoked.
# ROCM_PATH which points to <rocm_install_dir> is determined based on whether
# we find .info/version in the parent of HIP_PATH or not. If it is found,
# ROCM_PATH is defined relative to HIP_PATH else it is hardcoded to /opt/rocm.
#
$HIP_PATH = $ENV { 'HIP_PATH' } // dirname ( Cwd:: abs_path ( "$0/../" )); # use parent directory of hipcc
if ( - e "$HIP_PATH/../.info/version" ) {
$ROCM_PATH = $ENV { 'ROCM_PATH' } // dirname ( "$HIP_PATH" ); # use parent directory of HIP_PATH
} else {
$ROCM_PATH = $ENV { 'ROCM_PATH' } // "/opt/rocm" ;
}
2018-07-20 13:11:13 -04:00
$HIP_VDI_HOME = $ENV { 'HIP_VDI_HOME' };
2019-02-08 13:50:13 -08:00
$HIP_LIB_PATH = $ENV { 'HIP_LIB_PATH' };
2019-02-01 19:44:26 +00:00
$HIP_CLANG_PATH = $ENV { 'HIP_CLANG_PATH' };
$DEVICE_LIB_PATH = $ENV { 'DEVICE_LIB_PATH' };
2018-07-31 18:20:13 -04:00
$HIP_CLANG_HCC_COMPAT_MODE = $ENV { 'HIP_CLANG_HCC_COMPAT_MODE' }; # HCC compatibility mode
2016-01-26 20:14:33 -06:00
2019-02-07 21:51:01 +00:00
if ( defined $HIP_VDI_HOME ) {
$HIP_INFO_PATH = "$HIP_VDI_HOME/lib/.hipInfo" ;
} else {
2019-10-10 07:26:55 -07:00
$HIP_INFO_PATH = "$HIP_PATH/lib/.hipInfo" ; # use actual file
2019-02-07 21:51:01 +00:00
}
2016-08-03 12:01:48 +05:30
#---
2016-10-11 11:13:41 +05:30
# Read .hipInfo
2016-08-03 12:01:48 +05:30
my %hipConfig = ();
2019-02-07 21:51:01 +00:00
parse_config_file ( "$HIP_INFO_PATH" , \ %hipConfig );
2016-08-03 12:01:48 +05:30
2018-06-08 07:43:25 -04:00
#---
# Temporary directories
my @tmpDirs = ();
#---
# Create a new temporary directory and return it
sub get_temp_dir {
my $tmpdir = mkdtemp ( "/tmp/hipccXXXXXXXX" );
push ( @tmpDirs , $tmpdir );
return $tmpdir ;
}
#---
# Delete all created temporary directories
sub delete_temp_dirs {
if ( @tmpDirs ) {
system ( 'rm -rf ' . join ( ' ' , @tmpDirs ));
}
return 0 ;
}
2016-01-26 20:14:33 -06:00
#---
#HIP_PLATFORM controls whether to use NVCC or HCC for compilation:
2016-08-14 16:22:25 +05:30
$HIP_PLATFORM = `$HIP_PATH/bin/hipconfig --platform` // "hcc" ;
2016-07-11 16:38:41 +05:30
$HIP_VERSION = `$HIP_PATH/bin/hipconfig --version` ;
2019-02-01 19:44:26 +00:00
$HIP_COMPILER = $hipConfig { 'HIP_COMPILER' };
$HIP_RUNTIME = $hipConfig { 'HIP_RUNTIME' };
# If using VDI runtime, need to find HIP_VDI_HOME
2019-08-20 17:36:22 +05:30
if ( defined $HIP_RUNTIME and $HIP_RUNTIME eq "VDI" and ! defined $HIP_VDI_HOME ) {
2019-05-28 00:10:34 -04:00
my $hipcc_dir = dirname ( $0 );
2019-05-31 23:58:59 -04:00
if ( - e "$hipcc_dir/../lib/bitcode" ) {
2019-05-28 00:10:34 -04:00
$HIP_VDI_HOME = abs_path ( $hipcc_dir . "/.." );
} else {
2019-10-10 07:26:55 -07:00
$HIP_VDI_HOME = $HIP_PATH ; # use HIP_PATH
2019-05-28 00:10:34 -04:00
}
2019-02-01 19:44:26 +00:00
}
2016-05-02 11:33:22 -05:00
2018-07-20 13:11:13 -04:00
if ( defined $HIP_VDI_HOME ) {
2019-05-28 09:38:17 -04:00
if ( ! defined $HIP_CLANG_PATH and ( - e "$HIP_VDI_HOME/bin/clang" or - e "$HIP_VDI_HOME/bin/clang.exe" )) {
2019-05-28 00:10:34 -04:00
$HIP_CLANG_PATH = "$HIP_VDI_HOME/bin" ;
2018-07-20 13:11:13 -04:00
}
2019-05-28 00:10:34 -04:00
if ( ! defined $DEVICE_LIB_PATH and - e "$HIP_VDI_HOME/lib/bitcode" ) {
$DEVICE_LIB_PATH = "$HIP_VDI_HOME/lib/bitcode" ;
2018-07-20 13:11:13 -04:00
}
$HIP_INCLUDE_PATH = "$HIP_VDI_HOME/include" ;
2019-02-08 13:50:13 -08:00
if ( ! defined $HIP_LIB_PATH ) {
2019-05-28 00:10:34 -04:00
$HIP_LIB_PATH = "$HIP_VDI_HOME/lib" ;
2019-02-08 13:50:13 -08:00
}
2018-07-20 13:11:13 -04:00
}
2019-08-20 17:36:22 +05:30
if ( defined $HIP_COMPILER and $HIP_COMPILER eq "clang" ) {
2019-02-01 19:44:26 +00:00
$HIP_PLATFORM = "clang" ;
if ( ! defined $HIP_CLANG_PATH ) {
2019-10-10 07:26:55 -07:00
$HIP_CLANG_PATH = "$ROCM_PATH/llvm/bin" ;
2019-02-01 19:44:26 +00:00
}
if ( ! defined $DEVICE_LIB_PATH ) {
2019-10-10 07:26:55 -07:00
$DEVICE_LIB_PATH = "$ROCM_PATH/lib" ;
2019-02-01 19:44:26 +00:00
}
2018-05-17 13:08:55 -04:00
}
2016-01-26 20:14:33 -06:00
if ( $verbose & 0x2 ) {
2016-07-13 11:26:03 +05:30
print ( "HIP_PATH=$HIP_PATH\n" );
print ( "HIP_PLATFORM=$HIP_PLATFORM\n" );
2016-01-26 20:14:33 -06:00
}
2016-04-28 13:17:49 -05:00
# set if user explicitly requests -stdlib=libc++. (else we default to libstdc++ for better interop with g++):
2016-05-02 23:47:04 -05:00
$setStdLib = 0 ; # TODO - set to 0
2016-01-26 20:14:33 -06:00
2017-07-28 16:18:15 +05:30
$default_amdgpu_target = 1 ;
2017-02-08 12:04:05 -06:00
2018-05-17 13:08:55 -04:00
if ( $HIP_PLATFORM eq "clang" ) {
$HIPCC = "$HIP_CLANG_PATH/clang++" ;
2018-06-21 18:12:55 +00:00
# If $HIPCC clang++ is not compiled, use clang instead
if ( ! - e $HIPCC ) {
$HIPCC = "$HIP_CLANG_PATH/clang" ;
2018-06-28 22:33:46 -04:00
$HIPLDFLAGS = "--driver-mode=g++" ;
2018-06-21 18:12:55 +00:00
}
2018-06-28 22:33:46 -04:00
$HIP_CLANG_VERSION = `$HIPCC --version` ;
$HIP_CLANG_VERSION =~ /.*clang version ([^ ]+).*/ ;
$HIP_CLANG_VERSION = $1 ;
2018-07-20 13:11:13 -04:00
if ( ! defined $HIP_CLANG_INCLUDE_PATH ) {
2019-05-28 00:10:34 -04:00
$HIP_CLANG_INCLUDE_PATH = abs_path ( "$HIP_CLANG_PATH/../lib/clang/$HIP_CLANG_VERSION/include" );
2018-07-20 13:11:13 -04:00
}
if ( ! defined $HIP_INCLUDE_PATH ) {
$HIP_INCLUDE_PATH = "$HIP_PATH/include" ;
}
if ( ! defined $HIP_LIB_PATH ) {
$HIP_LIB_PATH = "$HIP_PATH/lib" ;
}
if ( $verbose & 0x2 ) {
if ( defined $HIP_VDI_HOME ) {
print ( "HIP_VDI_HOME=$HIP_VDI_HOME\n" );
}
print ( "HIP_CLANG_PATH=$HIP_CLANG_PATH\n" );
print ( "HIP_CLANG_INCLUDE_PATH=$HIP_CLANG_INCLUDE_PATH\n" );
print ( "HIP_INCLUDE_PATH=$HIP_INCLUDE_PATH\n" );
print ( "HIP_LIB_PATH=$HIP_LIB_PATH\n" );
print ( "DEVICE_LIB_PATH=$DEVICE_LIB_PATH\n" );
}
2019-07-31 16:25:15 -04:00
if ( $isWindows ) {
$HIPCXXFLAGS .= " -std=c++14 -fms-extensions -fms-compatibility" ;
} else {
$HIPCXXFLAGS .= " -std=c++11" ;
}
$HIPCXXFLAGS .= " -isystem $HIP_CLANG_INCLUDE_PATH" ;
2019-04-09 22:31:13 -04:00
$HIPLDFLAGS .= " -L$HIP_LIB_PATH" ;
2019-02-07 11:07:50 -05:00
if ( not $isWindows ) {
2019-04-29 14:17:11 -04:00
$HIPLDFLAGS .= " -Wl,--rpath-link=$HIP_LIB_PATH" ;
2019-03-19 16:25:07 -04:00
$HIPLDFLAGS .= " -lhip_hcc" ;
} else {
$HIPLDFLAGS .= " -lamdhip64" ;
2019-02-07 11:07:50 -05:00
}
2018-07-31 18:20:13 -04:00
if ( $HIP_CLANG_HCC_COMPAT_MODE ) {
## Allow __fp16 as function parameter and return type.
$HIPCXXFLAGS .= " -Xclang -fallow-half-arguments-and-returns -D__HIP_HCC_COMPAT_MODE__=1" ;
}
2019-04-09 15:01:50 -04:00
2020-02-12 23:30:01 -05:00
$HSA_PATH = $ENV { 'HSA_PATH' } // "$ROCM_PATH/hsa" ;
$HIPCXXFLAGS .= " -isystem $HSA_PATH/include" ;
2020-03-04 20:23:06 +05:30
if ( ! ( $HIP_RUNTIME eq "HCC" )) {
$HIPCXXFLAGS .= " -D__HIP_VDI__ -fhip-new-launch-api" ;
2019-04-09 15:01:50 -04:00
}
2018-05-17 13:08:55 -04:00
} elsif ( $HIP_PLATFORM eq "hcc" ) {
2018-07-20 13:11:13 -04:00
$HIP_INCLUDE_PATH = "$HIP_PATH/include" ;
2019-02-13 09:57:21 +05:30
if ( ! defined $HIP_LIB_PATH ) {
$HIP_LIB_PATH = "$HIP_PATH/lib" ;
}
2019-10-10 07:26:55 -07:00
$HSA_PATH = $ENV { 'HSA_PATH' } // "$ROCM_PATH/hsa" ;
2016-08-14 16:22:25 +05:30
2019-10-10 07:26:55 -07:00
$HCC_HOME = $ENV { 'HCC_HOME' } // $hipConfig { 'HCC_HOME' } // "$ROCM_PATH/hcc" ;
2016-08-11 16:13:44 -05:00
2017-03-03 04:27:54 -05:00
$HCC_VERSION = `${HCC_HOME}/bin/hcc --version` ;
$HCC_VERSION =~ /.*based on HCC ([^ ]+).*/ ;
$HCC_VERSION = $1 ;
$HCC_VERSION_MAJOR = $HCC_VERSION ;
$HCC_VERSION_MAJOR =~ s/\..*// ;
2016-08-11 16:13:44 -05:00
2016-10-27 20:38:32 -05:00
$HIP_ATP_MARKER = $ENV { 'HIP_ATP_MARKER' } // 1 ;
2016-08-03 09:08:40 +05:30
$marker_path = "$ROCM_PATH/profiler/CXLActivityLogger" ;
2016-07-21 16:02:51 +05:30
2016-01-26 20:14:33 -06:00
# HCC* may be used to compile src/hip_hcc.o (and also feed the HIPCXXFLAGS below)
$HCC = "$HCC_HOME/bin/hcc" ;
2019-02-04 15:07:06 +01:00
$HCCFLAGS = "-hc -D__HIPCC__ -isystem $HCC_HOME/include " ;
2016-01-26 20:14:33 -06:00
$HIPCC = $HCC ;
$HIPCXXFLAGS = $HCCFLAGS ;
2016-04-28 13:17:49 -05:00
2017-02-13 11:50:45 -05:00
$HIPLDFLAGS = `${HCC_HOME}/bin/hcc-config --ldflags` ;
2016-10-18 22:38:04 +03:00
#### GCC system includes workaround ####
2016-12-01 12:51:58 +05:30
$HCC_WA_FLAGS = " " ;
2017-09-08 11:46:10 -04:00
$HOST_OSNAME = `cat /etc/os-release | grep "^ID\=" | cut -d= -f2 | tr -d '\n'` ;
2016-12-01 12:51:58 +05:30
if ( $HCC_VERSION_MAJOR eq 1 ) {
2016-10-18 22:38:04 +03:00
my $GCC_CUR_VER = `gcc -dumpversion` ;
my $GPP_CUR_VER = `g++ -dumpversion` ;
$GCC_CUR_VER =~ s/\R//g ;
$GPP_CUR_VER =~ s/\R//g ;
2017-02-13 11:50:45 -05:00
my @GPP_VER_FIELDS = split ( '\.' , $GPP_CUR_VER );
# Only include the libstdc++ headers and libraries flags explicitly if the g++ is older than version 5.
# That's because HCC already uses libstdc++ by default if a newer g++/libstdc++ is available
2017-09-13 14:21:43 -04:00
# Cent OS 7 and RHEL 7.4 cannot use libstdc++ for compilation, default to libc++
if ( $ { GCC_CUR_VER } eq $ { GPP_CUR_VER } and $GPP_VER_FIELDS [ 0 ] < 5 and ( $HOST_OSNAME ne "\"centos\"" ) and ( $HOST_OSNAME ne "\"rhel\"" )) {
2019-02-04 15:07:06 +01:00
$HCC_WA_FLAGS .= " -stdlib=libstdc++ -isystem /usr/include/x86_64-linux-gnu -isystem /usr/include/x86_64-linux-gnu/c++/${GCC_CUR_VER} -isystem /usr/include/c++/${GCC_CUR_VER} " ;
2017-02-13 11:50:45 -05:00
# Add C++ libs for GCC.
$HIPLDFLAGS .= " -lstdc++" ;
2016-10-18 22:38:04 +03:00
}
}
2017-04-03 15:09:31 +05:30
# Force -stdlib=libc++ on UB14.04
$HOST_OSVER = `cat /etc/os-release | grep "^VERSION_ID\=" | cut -d= -f2 | tr -d '\n'` ;
2018-03-15 16:46:01 -04:00
if ( $HOST_OSNAME eq "ubuntu" and $HOST_OSVER eq "\"14.04\"" ) {
2017-04-03 15:09:31 +05:30
$HIPCXXFLAGS .= " -stdlib=libc++" ;
$setStdLib = 1 ;
}
2019-02-04 15:07:06 +01:00
$HIPCXXFLAGS .= " -isystem $HIP_PATH/include/hip/hcc_detail/cuda" ;
$HIPCXXFLAGS .= " -isystem $HSA_PATH/include" ;
2016-07-25 10:15:02 -05:00
$HIPCXXFLAGS .= " -Wno-deprecated-register" ;
2016-07-13 11:26:03 +05:30
2018-08-14 15:31:04 +05:30
$HIPLDFLAGS .= " -L$HSA_PATH/lib -L$ROCM_PATH/lib -lhsa-runtime64 -lhc_am " ;
2017-03-28 10:46:31 -05:00
# $HIPLDFLAGS .= " -L$HCC_HOME/compiler/lib -lLLVMAMDGPUDesc -lLLVMAMDGPUUtils -lLLVMMC -lLLVMCore -lLLVMSupport ";
2016-03-23 01:17:53 -05:00
# Add trace marker library:
2016-03-29 17:26:44 -05:00
# TODO - once we cleanly separate the HIP API headers from HIP library headers this logic should move to CMakebuild option - apps do not need to see the marker library.
2016-07-21 16:02:51 +05:30
if ( $HIP_ATP_MARKER ) {
$marker_inc_path = "$marker_path/include" ;
if ( - e $marker_inc_path ) {
2019-02-04 15:07:06 +01:00
$HIPCXXFLAGS .= " -isystem $marker_inc_path" ;
2016-07-21 16:02:51 +05:30
}
2016-08-03 09:08:40 +05:30
}
2016-07-21 16:02:51 +05:30
2016-08-03 09:08:40 +05:30
$marker_lib_path = "$marker_path/bin/x86_64" ;
if ( - e $marker_lib_path ) {
$HIPLDFLAGS .= " -L$marker_lib_path -lCXLActivityLogger -Wl,--rpath=$marker_lib_path" ;
2016-03-22 09:27:10 -05:00
}
2016-03-23 01:17:53 -05:00
2019-02-07 11:07:50 -05:00
if ( not $isWindows ) {
$HIPLDFLAGS .= " -lm" ;
}
2016-01-26 20:14:33 -06:00
if ( $verbose & 0x2 ) {
print ( "HSA_PATH=$HSA_PATH\n" );
print ( "HCC_HOME=$HCC_HOME\n" );
}
} elsif ( $HIP_PLATFORM eq "nvcc" ) {
2018-07-25 15:29:57 +05:30
$CUDA_PATH = $ENV { 'CUDA_PATH' } // '/usr/local/cuda' ;
2018-07-20 13:11:13 -04:00
$HIP_INCLUDE_PATH = "$HIP_PATH/include" ;
2016-05-02 11:33:22 -05:00
if ( $verbose & 0x2 ) {
print ( "CUDA_PATH=$CUDA_PATH\n" );
}
2016-01-26 20:14:33 -06:00
$HIPCC = "$CUDA_PATH/bin/nvcc" ;
2017-12-12 16:00:14 +05:30
$HIPCXXFLAGS .= " -Wno-deprecated-gpu-targets " ;
2019-02-04 15:07:06 +01:00
$HIPCXXFLAGS .= " -isystem $CUDA_PATH/include" ;
2016-01-26 20:14:33 -06:00
2017-12-12 16:00:14 +05:30
$HIPLDFLAGS = " -Wno-deprecated-gpu-targets -lcuda -lcudart -L$CUDA_PATH/lib64" ;
2016-01-26 20:14:33 -06:00
} else {
2016-07-13 11:26:03 +05:30
printf ( "error: unknown HIP_PLATFORM = '$HIP_PLATFORM'" );
exit ( - 1 );
2016-01-26 20:14:33 -06:00
}
2016-09-01 15:06:36 +05:30
# Add paths to common HIP includes:
2019-12-30 12:44:24 +05:30
$HIPCXXFLAGS .= " -isystem $HIP_INCLUDE_PATH" ;
2016-09-01 15:06:36 +05:30
my $compileOnly = 0 ;
my $needCXXFLAGS = 0 ; # need to add CXX flags to compile step
my $needLDFLAGS = 1 ; # need to add LDFLAGS to compile step.
my $hasC = 0 ; # options contain a c-style file (NVCC must force recognition as GPU file)
my $hasCU = 0 ; # options contain a cu-style file (HCC must force recognition as GPU file)
my $needHipHcc = ( $HIP_PLATFORM eq 'hcc' ); # set if we need to link hip_hcc.o from src tree. (some builds, ie cmake, provide their own)
my $printHipVersion = 0 ; # print HIP version
my $runCmd = 1 ;
2016-09-02 15:07:33 +05:30
my $buildDeps = 0 ;
2017-01-04 12:39:09 +05:30
my $linkType = 1 ;
2016-12-01 15:33:12 +05:30
my $setLinkType = 0 ;
2020-02-05 10:26:33 -05:00
my $coFormatv3 = 1 ;
2016-09-01 15:06:36 +05:30
my @options = ();
my @inputs = ();
if ( $verbose & 0x4 ) {
print "hipcc-args: " , join ( " " , @ARGV ), "\n" ;
}
2016-08-31 20:36:36 -05:00
2016-09-01 15:06:36 +05:30
# Handle code object generation
my $ISACMD = "" ;
2016-08-31 20:36:36 -05:00
if ( $HIP_PLATFORM eq "hcc" ){
2017-12-08 04:22:57 +00:00
$ISACMD .= "$HIP_PATH/bin/lpl " ;
2017-03-14 14:25:34 +05:30
if ( $ARGV [ 0 ] eq "--genco" ){
foreach $isaarg ( @ARGV [ 1 .. $#ARGV ]){
$ISACMD .= " " ;
$ISACMD .= $isaarg ;
}
if ( $verbose & 0x1 ) {
print "hipcc-cmd: " , $ISACMD , "\n" ;
}
system ( $ISACMD ) and die ();
exit ( 0 );
}
2016-08-31 20:36:36 -05:00
}
2017-01-12 11:30:20 -06:00
if (( $HIP_PLATFORM eq "hcc" )){
2018-06-19 21:09:44 +00:00
$ENV { HCC_EXTRA_LIBRARIES } = "\n" ;
2016-10-10 15:29:50 -05:00
}
2016-08-31 20:36:36 -05:00
if ( $HIP_PLATFORM eq "nvcc" ){
2017-03-14 14:25:34 +05:30
$ISACMD .= "$HIP_PATH/bin/hipcc -ptx " ;
if ( $ARGV [ 0 ] eq "--genco" ){
foreach $isaarg ( @ARGV [ 1 .. $#ARGV ]){
$ISACMD .= " " ;
$ISACMD .= $isaarg ;
}
if ( $verbose & 0x1 ) {
print "hipcc-cmd: " , $ISACMD , "\n" ;
}
system ( $ISACMD ) and die ();
exit ( 0 );
}
2016-08-31 13:05:57 -05:00
}
2016-01-26 20:14:33 -06:00
2016-03-24 11:53:28 -05:00
my $toolArgs = "" ; # arguments to pass to the hcc or nvcc tool
2019-04-09 22:31:13 -04:00
my $optArg = "" ; # -O args
2020-02-03 22:26:16 -05:00
my $targetOpt = '--amdgpu-target=' ;
my $targetsStr = "" ;
2016-08-31 13:05:57 -05:00
2016-07-13 11:26:03 +05:30
foreach $arg ( @ARGV )
2016-01-26 20:14:33 -06:00
{
2017-01-03 22:17:16 -06:00
$trimarg = $arg ;
$trimarg =~ s/^\s+|\s+$//g ; # Remive whitespace
2016-03-24 11:53:28 -05:00
my $swallowArg = 0 ;
2018-11-13 22:28:00 -05:00
if ( $arg eq '-c' or $arg eq '--genco' ) {
2016-01-26 20:14:33 -06:00
$compileOnly = 1 ;
$needCXXFLAGS = 1 ;
$needLDFLAGS = 0 ;
}
if ( $arg eq '-o' ) {
$needLDFLAGS = 1 ;
}
2017-01-03 22:17:16 -06:00
if (( $trimarg eq '-stdlib=libc++' ) and ( $setStdLib eq 0 ))
2016-04-06 14:18:51 -05:00
{
2016-04-28 13:17:49 -05:00
$HIPCXXFLAGS .= " -stdlib=libc++" ;
2016-05-02 23:47:04 -05:00
$setStdLib = 1 ;
}
2017-07-28 16:18:15 +05:30
2020-02-03 22:26:16 -05:00
# Check target selection option: --amdgpu-target=...
if ( substr ( $arg , 0 , length ( $targetOpt )) eq $targetOpt ) {
# If targets string is not empty, add a comma before adding new target option value.
$targetsStr .= ( $targetsStr ? ',' : '' );
$targetsStr .= substr ( $arg , length ( $targetOpt ));
$default_amdgpu_target = 0 ;
# hip-clang does not accept --amdgpu-target= options.
if ( $HIP_PLATFORM eq 'clang' ) {
$swallowArg = 1 ;
}
2018-05-28 10:46:23 -04:00
}
2017-03-14 14:25:34 +05:30
2020-02-05 10:26:33 -05:00
# code object format parsing
if ( $trimarg eq '-mcode-object-v3' ) {
$coFormatv3 = 1 ;
}
if ( $trimarg eq '-mno-code-object-v3' ) {
$coFormatv3 = 0 ;
}
2018-11-13 22:28:00 -05:00
if (( $arg =~ /--genco/ ) and $HIP_PLATFORM eq 'clang' ) {
$arg = "--cuda-device-only" ;
}
2017-01-03 22:17:16 -06:00
if (( $trimarg eq '-stdlib=libstdc++' ) and ( $setStdLib eq 0 ))
2016-05-02 23:47:04 -05:00
{
2016-12-01 12:51:58 +05:30
$HIPCXXFLAGS .= $HCC_WA_FLAGS ;
2016-05-02 23:47:04 -05:00
$setStdLib = 1 ;
2016-04-06 14:18:51 -05:00
}
2017-01-03 22:17:16 -06:00
if ( $trimarg eq '--version' ) {
2016-06-14 14:51:03 +05:30
$printHipVersion = 1 ;
}
2017-01-03 22:17:16 -06:00
if ( $trimarg eq '--short-version' ) {
2016-06-14 14:51:03 +05:30
$printHipVersion = 1 ;
$runCmd = 0 ;
}
2017-01-03 22:17:16 -06:00
if ( $trimarg eq '-M' ) {
2016-09-02 15:07:33 +05:30
$compileOnly = 1 ;
$buildDeps = 1 ;
}
2017-01-03 22:17:16 -06:00
if ( $trimarg eq '-use_fast_math' ) {
2016-11-23 11:19:15 -06:00
$HIPCXXFLAGS .= " -DHIP_FAST_MATH " ;
}
2017-01-03 22:17:16 -06:00
if (( $trimarg eq '-use-staticlib' ) and ( $setLinkType eq 0 ))
2016-12-01 15:33:12 +05:30
{
$linkType = 0 ;
$setLinkType = 1 ;
}
2017-01-03 22:17:16 -06:00
if (( $trimarg eq '-use-sharedlib' ) and ( $setLinkType eq 0 ))
2016-12-01 15:33:12 +05:30
{
$linkType = 1 ;
$setLinkType = 1 ;
}
2019-04-09 22:31:13 -04:00
if ( $arg =~ m/^-O/ )
{
$optArg = $arg ;
}
2016-11-23 11:19:15 -06:00
2019-10-16 01:21:28 -04:00
## This is a temporary workaround for CMake detection of OpenMP support.
## It should be removed when the OpenMP detection c++ test in CMake is updated
## and corrected CMake version is available.
if (( defined $HIP_COMPILER ) and ( $HIP_COMPILER eq "clang" ) and ( $arg eq '-fopenmp' )) {
$HIPCXXFLAGS .= " -D_OPENMP "
}
2018-06-08 07:43:25 -04:00
## process linker response file for hip-clang
## extract object files from static library and pass them directly to
## hip-clang in command line.
## ToDo: Remove this after hip-clang switch to lto and lld is able to
## handle clang-offload-bundler bundles.
if ( $arg =~ m/^-Wl,@/ and $HIP_PLATFORM eq 'clang' ) {
my $file = substr $arg , 5 ;
open my $in , "<:encoding(utf8)" , $file or die "$file: $!" ;
my $new_arg = "" ;
my $tmpdir = get_temp_dir ();
my $new_file = "$tmpdir/response_file" ;
open my $out , ">" , $new_file or die "$new_file: $!" ;
while ( my $line = <$in> ) {
chomp $line ;
2018-06-18 21:43:24 -04:00
if ( $line =~ m/\.a$/ || $line =~ m/\.lo$/ ) {
2018-06-13 10:01:14 -04:00
my $libFile = $line ;
2018-06-08 07:43:25 -04:00
my $path = abs_path ( $line );
my @objs = split ( '\n' , `cd $tmpdir; ar xv $path` );
2018-06-13 10:01:14 -04:00
## Check if all files in .a are object files.
my $allIsObj = 1 ;
my $realObjs = "" ;
2018-06-08 07:43:25 -04:00
foreach my $obj ( @objs ) {
chomp $obj ;
$obj =~ s/^x - // ;
$obj = "$tmpdir/$obj" ;
2018-06-13 10:01:14 -04:00
my $fileType = `file $obj` ;
my $isObj = ( $fileType =~ m/ELF/ or $fileType =~ m/COFF/ );
$allIsObj = ( $allIsObj and $isObj );
if ( $isObj ) {
2018-06-17 12:18:37 -04:00
$realObjs = ( $realObjs . " " . $obj );
2018-06-13 10:01:14 -04:00
} else {
push ( @inputs , $obj );
$new_arg = "$new_arg $obj" ;
}
}
2018-06-17 12:18:37 -04:00
chomp $realObjs ;
2018-06-13 10:01:14 -04:00
if ( $allIsObj ) {
print $out "$line\n" ;
2018-06-17 12:18:37 -04:00
} elsif ( $realObjs ) {
2018-06-18 21:43:24 -04:00
my ( $libBaseName , $libDir , $libExt ) = fileparse ( $libFile );
$libBaseName = mktemp ( $libBaseName . "XXXX" ) . $libExt ;
2018-06-17 12:18:37 -04:00
system ( "cd $tmpdir; ar c $libBaseName $realObjs" );
print $out "$tmpdir/$libBaseName\n" ;
2018-06-08 07:43:25 -04:00
}
2018-08-22 15:42:54 -04:00
} elsif ( $line =~ m/\.o$/ ) {
my $fileType = `file $line` ;
my $isObj = ( $fileType =~ m/ELF/ or $fileType =~ m/COFF/ );
if ( $isObj ) {
print $out "$line\n" ;
} else {
push ( @inputs , $line );
$new_arg = "$new_arg $line" ;
}
2018-06-08 07:43:25 -04:00
} else {
print $out "$line\n" ;
}
}
close $in ;
close $out ;
$arg = "$new_arg -Wl,\@$new_file" ;
2018-08-01 17:01:39 -04:00
} elsif (( $arg =~ m/\.a$/ || $arg =~ m/\.lo$/ ) &&
$HIP_PLATFORM eq 'clang' ) {
## process static library for hip-clang
## extract object files from static library and pass them directly to
## hip-clang.
## ToDo: Remove this after hip-clang switch to lto and lld is able to
## handle clang-offload-bundler bundles.
my $new_arg = "" ;
my $tmpdir = get_temp_dir ();
my $libFile = $arg ;
my $path = abs_path ( $arg );
my @objs = split ( '\n' , `cd $tmpdir; ar xv $path` );
## Check if all files in .a are object files.
my $allIsObj = 1 ;
my $realObjs = "" ;
foreach my $obj ( @objs ) {
chomp $obj ;
$obj =~ s/^x - // ;
$obj = "$tmpdir/$obj" ;
my $fileType = `file $obj` ;
my $isObj = ( $fileType =~ m/ELF/ or $fileType =~ m/COFF/ );
2018-11-08 11:28:47 -05:00
if ( $fileType =~ m/ELF/ ) {
my $sections = `readelf -e -W $obj` ;
$isObj = ! ( $sections =~ m/__CLANG_OFFLOAD_BUNDLE__/ );
}
2018-08-01 17:01:39 -04:00
$allIsObj = ( $allIsObj and $isObj );
if ( $isObj ) {
$realObjs = ( $realObjs . " " . $obj );
} else {
push ( @inputs , $obj );
if ( $new_arg ne "" ) {
$new_arg .= " " ;
}
$new_arg .= "$obj" ;
}
}
chomp $realObjs ;
if ( $allIsObj ) {
$new_arg = $arg ;
} elsif ( $realObjs ) {
my ( $libBaseName , $libDir , $libExt ) = fileparse ( $libFile );
$libBaseName = mktemp ( $libBaseName . "XXXX" ) . $libExt ;
system ( "cd $tmpdir; ar c $libBaseName $realObjs" );
$new_arg .= " $tmpdir/$libBaseName" ;
}
$arg = "$new_arg" ;
if ( $toolArgs =~ m/-Xlinker$/ ) {
$toolArgs = substr $toolArgs , 0 , - 8 ;
chomp $toolArgs ;
}
2018-06-08 07:43:25 -04:00
} elsif ( $arg =~ m/^-/ ) {
2016-01-26 20:14:33 -06:00
# options start with -
2016-07-13 11:26:03 +05:30
2016-03-24 11:53:28 -05:00
# Process HIPCC options here:
if ( $arg =~ m/^--hipcc/ ) {
$swallowArg = 1 ;
2016-10-27 20:38:32 -05:00
#if $arg eq "--hipcc_profile") { # Example argument here, hipcc
#
#}
2016-03-24 11:53:28 -05:00
} else {
push ( @options , $arg );
}
2016-01-26 20:14:33 -06:00
#print "O: <$arg>\n";
2018-06-08 07:43:25 -04:00
} else {
2016-07-13 11:26:03 +05:30
# input files and libraries
2019-08-07 19:11:12 +02:00
if (( $arg =~ /\.cpp$/ ) or ( $arg =~ /\.cxx$/ ) or ( $arg =~ /\.c$/ ) or ( $arg =~ /\.cc$/ ) ) {
2016-01-26 20:14:33 -06:00
$hasC = 1 ;
$needCXXFLAGS = 1 ;
2018-05-17 13:08:55 -04:00
if ( $HIP_PLATFORM eq 'clang' ) {
$toolArgs .= " -x hip"
}
2016-07-13 11:26:03 +05:30
}
2018-06-28 22:33:46 -04:00
if (( $arg =~ /\.cu$/ ) or ( $arg =~ /\.cuh$/ ) or ( $arg =~ /\.hip$/ )) {
2016-01-26 20:14:33 -06:00
$hasCU = 1 ;
$needCXXFLAGS = 1 ;
2018-05-17 13:08:55 -04:00
if ( $HIP_PLATFORM eq 'clang' ) {
$toolArgs .= " -x hip"
}
2016-01-26 20:14:33 -06:00
}
push ( @inputs , $arg );
#print "I: <$arg>\n";
}
2016-03-24 11:53:28 -05:00
$toolArgs .= " $arg" unless $swallowArg ;
2016-01-26 20:14:33 -06:00
}
2017-07-28 16:18:15 +05:30
2018-05-17 13:08:55 -04:00
if ( $HIP_PLATFORM eq "hcc" or $HIP_PLATFORM eq "clang" ){
2017-07-31 10:11:19 +05:30
# No AMDGPU target specified at commandline. So look for HCC_AMDGPU_TARGET
2020-02-03 22:26:16 -05:00
if ( $default_amdgpu_target eq 1 ) {
if ( defined $ENV { HCC_AMDGPU_TARGET }) {
$targetsStr = $ENV { HCC_AMDGPU_TARGET };
} else {
# Else try using rocm_agent_enumerator
$ROCM_AGENT_ENUM = "${ROCM_PATH}/bin/rocm_agent_enumerator" ;
$targetsStr = `${ROCM_AGENT_ENUM} -t GPU` ;
$targetsStr =~ s/\n/,/g ;
2017-03-15 12:03:05 +05:30
}
2020-02-03 22:26:16 -05:00
$default_amdgpu_target = 0 ;
2017-07-28 16:18:15 +05:30
}
2017-02-08 14:06:01 -06:00
2020-02-03 22:26:16 -05:00
# Parse the targets collected in targetStr and set corresponding compiler options.
my @targets = split ( ',' , $targetsStr );
2017-02-08 14:06:01 -06:00
2018-05-17 13:08:55 -04:00
if ( $HIP_PLATFORM eq "hcc" ) {
$GPU_ARCH_OPT = " --amdgpu-target=" ;
} else {
$GPU_ARCH_OPT = " --cuda-gpu-arch=" ;
}
2020-02-03 22:26:16 -05:00
foreach my $val ( @targets ) {
# Ignore 'gfx000' target reported by rocm_agent_enumerator.
if ( $val ne 'gfx000' ) {
# Construct an arch macro to be passed to the compiler.
# Example: gfx900 --> -D__HIP_ARCH_GFX900__=1
my $archMacro = ' -D__HIP_ARCH_' . uc ( $val ) . '__=1 ' ;
# Add the arch option and macro to the compiler options.
$GPU_ARCH_ARG = $GPU_ARCH_OPT . $val ;
$HIPLDFLAGS .= $GPU_ARCH_ARG ;
$HIPCXXFLAGS .= $archMacro ;
if ( $HIP_PLATFORM eq 'clang' ) {
$HIPCXXFLAGS .= $GPU_ARCH_ARG ;
}
2020-02-06 16:50:09 -05:00
# If the specified target is not in the list of known target names, emit a warning.
if ( grep ( /$val/ , @knownTargets ) eq 0 ) {
print "Warning: The specified HIP target: $val is unknown. Correct compilation is not guaranteed.\n" ;
}
2019-07-11 23:13:35 -04:00
}
}
2020-02-03 22:26:16 -05:00
# rocm_agent_enumerator failed! Throw an error and die if linking is required
if ( $default_amdgpu_target eq 1 and $compileOnly eq 0 ) {
print "No valid AMD GPU target was either specified or found. Please specify a valid target using --amdgpu-target=" and die ();
2019-07-11 23:13:35 -04:00
}
2020-02-03 22:26:16 -05:00
$ENV { HCC_EXTRA_LIBRARIES } = "\n" ;
2017-02-08 14:06:01 -06:00
}
2020-02-05 10:26:33 -05:00
# hcc defaults to v2, so we need to convert to the appropriate flag
# hip-clang defaults to v3, so we don't need to do anything
if ( $coFormatv3 and $HIP_PLATFORM eq 'hcc' ) {
$HIPLDFLAGS .= " -mcode-object-v3" ;
$HIPCXXFLAGS .= " -mcode-object-v3" ;
}
2016-01-26 20:14:33 -06:00
if ( $hasC and $HIP_PLATFORM eq 'nvcc' ) {
$HIPCXXFLAGS .= " -x cu" ;
}
if ( $hasCU and $HIP_PLATFORM eq 'hcc' ) {
$HIPCXXFLAGS .= " -x c++" ;
}
2018-05-17 13:08:55 -04:00
2016-09-02 15:07:33 +05:30
if ( $buildDeps and $HIP_PLATFORM eq 'nvcc' ) {
$HIPCXXFLAGS .= " -M -D__CUDACC__" ;
}
2016-01-26 20:14:33 -06:00
2018-07-20 15:16:27 -04:00
if ( $buildDeps and $HIP_PLATFORM eq 'clang' ) {
$HIPCXXFLAGS .= " --cuda-host-only" ;
}
2018-07-23 14:55:07 -04:00
# Add --hip-link only if there are no source files.
if ( ! $needCXXFLAGS and $HIP_PLATFORM eq 'clang' ) {
$HIPLDFLAGS .= " --hip-link" ;
}
2016-05-02 23:47:04 -05:00
if ( $setStdLib eq 0 and $HIP_PLATFORM eq 'hcc' )
2016-04-06 14:50:27 -05:00
{
2016-12-01 12:51:58 +05:30
$HIPCXXFLAGS .= $HCC_WA_FLAGS ;
2016-04-06 14:50:27 -05:00
}
2016-01-26 20:14:33 -06:00
if ( $needHipHcc ) {
2016-12-01 15:33:12 +05:30
if ( $linkType eq 0 ) {
2019-02-08 13:50:13 -08:00
substr ( $HIPLDFLAGS , 0 , 0 ) = " $HIP_LIB_PATH/libhip_hcc_static.a " ;
2016-08-19 13:07:22 +05:30
} else {
2020-01-21 00:47:35 -08:00
substr ( $HIPLDFLAGS , 0 , 0 ) = " -Wl,--enable-new-dtags -Wl,--rpath=$HIP_LIB_PATH:$ROCM_PATH/lib $HIP_LIB_PATH/libhip_hcc.so " ;
2016-04-01 16:08:49 +05:30
}
2016-01-26 20:14:33 -06:00
}
# hipcc currrently requires separate compilation of source files, ie it is not possible to pass
# CPP files combined with .O files
2016-07-13 11:26:03 +05:30
# Reason is that NVCC uses the file extension to determine whether to compile in CUDA mode or
2016-01-26 20:14:33 -06:00
# pass-through CPP mode.
2018-09-28 11:05:27 -04:00
if ( $HIP_PLATFORM eq "clang" ) {
2019-04-09 22:31:13 -04:00
# Set default optimization level to -O3 for hip-clang.
2019-08-28 21:03:11 -04:00
if ( $optArg eq "" ) {
2019-04-09 22:31:13 -04:00
$HIPCXXFLAGS .= " -O3" ;
$HIPLDFLAGS .= " -O3" ;
}
2020-03-10 13:01:28 -04:00
# Do not pass -mllvm on Windows since there is a clang bug causing duplicate -mllvm options in clang -cc1 on Windows.
# ToDo : remove restriction for Windows after clang bug is fixed.
if ( $optArg ne "-O0" and not $isWindows ) {
$HIPCXXFLAGS .= " -mllvm -amdgpu-early-inline-all=true -mllvm -amdgpu-function-calls=false" ;
if ( $needLDFLAGS and not $needCXXFLAGS ) {
$HIPLDFLAGS .= " -mllvm -amdgpu-early-inline-all=true -mllvm -amdgpu-function-calls=false" ;
2020-02-26 02:23:43 -08:00
}
2020-02-17 09:19:26 -08:00
}
2019-04-09 22:31:13 -04:00
$HIP_DEVLIB_FLAGS = " --hip-device-lib-path=$DEVICE_LIB_PATH" ;
2019-05-23 15:11:02 -04:00
$HIPCXXFLAGS .= " $HIP_DEVLIB_FLAGS" ;
2019-07-31 16:25:15 -04:00
if ( not $isWindows ) {
2019-02-07 11:07:50 -05:00
$HIPLDFLAGS .= " -lgcc_s -lgcc -lpthread -lm" ;
}
2018-09-28 11:05:27 -04:00
}
2016-01-26 20:14:33 -06:00
2019-02-05 14:27:57 -05:00
2018-09-28 11:05:27 -04:00
if ( $HIPCC_COMPILE_FLAGS_APPEND ) {
$HIPCXXFLAGS .= " $HIPCC_COMPILE_FLAGS_APPEND" ;
}
if ( $HIPCC_LINK_FLAGS_APPEND ) {
$HIPLDFLAGS .= " $HIPCC_LINK_FLAGS_APPEND" ;
}
2016-01-26 20:14:33 -06:00
my $CMD = "$HIPCC" ;
if ( $needCXXFLAGS ) {
$CMD .= " $HIPCXXFLAGS" ;
2016-07-13 11:26:03 +05:30
}
2016-01-26 20:14:33 -06:00
if ( $needLDFLAGS and not $compileOnly ) {
$CMD .= " $HIPLDFLAGS" ;
}
2016-03-24 11:53:28 -05:00
$CMD .= " $toolArgs" ;
2016-01-26 20:14:33 -06:00
if ( $verbose & 0x1 ) {
print "hipcc-cmd: " , $CMD , "\n" ;
}
2016-06-14 14:51:03 +05:30
if ( $printHipVersion ) {
if ( $runCmd ) {
print "HIP version: "
}
2016-07-11 16:38:41 +05:30
print $HIP_VERSION , "\n" ;
2016-06-14 14:51:03 +05:30
}
if ( $runCmd ) {
2016-08-14 16:22:25 +05:30
if ( $HIP_PLATFORM eq "hcc" and exists ( $hipConfig { 'HCC_VERSION' }) and $HCC_VERSION ne $hipConfig { 'HCC_VERSION' }) {
2017-01-20 14:37:39 -06:00
print ( "HIP ($HIP_PATH) was built using hcc $hipConfig{'HCC_VERSION'}, but you are using $HCC_HOME/hcc with version $HCC_VERSION from hipcc. Please rebuild HIP including cmake or update HCC_HOME variable.\n" ) ;
die unless $ENV { 'HIP_IGNORE_HCC_VERSION' };
2016-08-03 11:32:08 +05:30
}
2019-05-16 20:36:51 +00:00
system ( "$CMD" );
if ( $? == - 1 ) {
print "failed to execute: $!\n" ;
exit ( $? );
}
elsif ( $? & 127 ) {
printf "child died with signal %d, %s coredump\n" ,
( $? & 127 ), ( $? & 128 ) ? 'with' : 'without' ;
exit ( $? );
}
else {
$CMD_EXIT_CODE = $? >> 8 ;
}
$? or delete_temp_dirs ();
exit ( $CMD_EXIT_CODE );
2016-06-14 14:51:03 +05:30
}
2017-03-14 14:25:34 +05:30
# vim: ts=4:sw=4:expandtab:smartindent