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 ;
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.
2016-04-15 12:56:31 +05:30
# HCC_HOME : Path to HCC SDK (default /opt/rocm/hcc). Used on AMD platforms only.
# HSA_PATH : Path to HSA dir (default /opt/rocm/hsa). 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 ){
print "No Arguments passed, exiting ...\n" ;
exit ( - 1 );
}
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 ;
2016-03-24 13:33:07 -05:00
# Verbose: 0x1=commands, 0x2=paths, 0x4=hippc args
2016-01-26 20:14:33 -06:00
2016-08-14 16:22:25 +05:30
$HIP_PATH = $ENV { 'HIP_PATH' } // dirname ( dirname $0 ); # use parent directory of hipcc
2016-01-26 20:14:33 -06: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 = ();
2016-10-11 11:13:41 +05:30
parse_config_file ( "$HIP_PATH/lib/.hipInfo" , \ %hipConfig );
2016-08-03 12:01:48 +05:30
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` ;
2016-09-22 12:27:07 +05:30
( $HIP_VERSION_MAJOR , $HIP_VERSION_MINOR , $HIP_VERSION_PATCH ) = split ( /\./ , $HIP_VERSION );
2016-05-02 11:33:22 -05: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
if ( $HIP_PLATFORM eq "hcc" ) {
2016-08-14 16:22:25 +05:30
$HSA_PATH = $ENV { 'HSA_PATH' } // "/opt/rocm/hsa" ;
$HCC_HOME = $ENV { 'HCC_HOME' } // $hipConfig { 'HCC_HOME' } // "/opt/rocm/hcc" ;
2016-08-11 16:13:44 -05:00
$HCC_VERSION = `${HCC_HOME}/bin/hcc --version | cut -d" " -f9 | tr -d "\n"` ;
2016-08-14 16:22:25 +05:30
$ROCM_PATH = $ENV { 'ROCM_PATH' } // "/opt/rocm" ;
2016-04-15 16:20:35 +05:30
2016-07-21 16:02:51 +05:30
$HIP_ATP_MARKER = $ENV { 'HIP_ATP_MARKER' };
2016-08-03 09:08:40 +05:30
$marker_path = "$ROCM_PATH/profiler/CXLActivityLogger" ;
2016-07-21 16:02:51 +05:30
2016-08-14 16:22:25 +05:30
$ROCM_TARGET = $ENV { 'ROCM_TARGET' } // "fiji" ;
2016-07-15 10:08:27 +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" ;
2016-04-11 13:04:13 -05:00
$HCCFLAGS = "-hc -I$HCC_HOME/include " ;
2016-01-26 20:14:33 -06:00
$HIPCC = $HCC ;
$HIPCXXFLAGS = $HCCFLAGS ;
2016-04-28 13:17:49 -05:00
2016-10-05 10:54:42 +05:30
$HIPCXXFLAGS .= " -I$HIP_PATH/include/hip/hcc_detail/cuda" ;
2016-03-23 12:59:52 -05:00
$HIPCXXFLAGS .= " -I$HSA_PATH/include" ;
2016-07-25 10:15:02 -05:00
$HIPCXXFLAGS .= " -Wno-deprecated-register" ;
2016-07-13 11:26:03 +05:30
$HIPLDFLAGS = "-hc -L$HCC_HOME/lib -Wl,--rpath=$HCC_HOME/lib -lc++ -ldl -lpthread -Wl,--whole-archive -lmcwamp -Wl,--no-whole-archive" ;
2016-04-02 22:32:05 +05:30
# Suppress linker warnings in case HCC distribution contains OpenCL/SPIR symbols
2016-07-15 10:40:56 +05:30
$HOST_OSNAME = `cat /etc/os-release | grep "^ID\=" | cut -d= -f2 | tr -d '\n'` ;
$HOST_OSVER = `cat /etc/os-release | grep "^VERSION_ID\=" | cut -d= -f2 | tr -d '\n'` ;
if ( $HOST_OSNAME eq "ubuntu" and $HOST_OSVER eq "\"16.04\"" ) {
# No additional flags required
} else {
2016-10-06 09:50:35 +05:30
$HIPLDFLAGS .= " -Wl,--defsym=_binary_kernel_spir_end=1 -Wl,--defsym=_binary_kernel_spir_start=1 -Wl,--defsym=_binary_kernel_cl_start=1 -Wl,--defsym=_binary_kernel_cl_end=1" ;
2016-07-15 10:40:56 +05:30
}
2016-07-13 11:26:03 +05:30
2016-04-02 22:32:05 +05:30
# Satisfy HCC dependencies
2016-08-26 10:35:30 +05:30
$HIPLDFLAGS .= " -lc++abi -lsupc++" ;
2016-07-13 11:26:03 +05:30
$HIPLDFLAGS .= " -L$HSA_PATH/lib -L$ROCM_PATH/lib -lhsa-runtime64 -lhc_am -lhsakmt" ;
2016-03-23 01:17:53 -05:00
2016-07-15 10:08:27 +05:30
# Handle ROCm target platform
if ( $ROCM_TARGET eq "fiji" ) {
$HIPLDFLAGS .= " -amdgpu-target=AMD:AMDGPU:8:0:3" ;
}
2016-08-14 16:22:25 +05:30
if ( $ROCM_TARGET eq "carrizo" ) {
$HIPLDFLAGS .= " -amdgpu-target=AMD:AMDGPU:8:0:1" ;
}
2016-07-15 10:08:27 +05:30
if ( $ROCM_TARGET eq "hawaii" ) {
$HIPLDFLAGS .= " -amdgpu-target=AMD:AMDGPU:7:0:1" ;
}
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 ) {
$HIPCXXFLAGS .= " -I$marker_inc_path" ;
}
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
2016-07-13 11:26:03 +05:30
# Add C++ libs for GCC.
$HIPLDFLAGS .= " -lstdc++" ;
$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" ) {
2016-05-02 11:33:22 -05:00
if ( $verbose & 0x2 ) {
print ( "CUDA_PATH=$CUDA_PATH\n" );
}
2016-08-14 16:22:25 +05:30
$CUDA_PATH = $ENV { 'CUDA_PATH' } // '/usr/local/cuda' ;
2016-01-26 20:14:33 -06:00
$HIPCC = "$CUDA_PATH/bin/nvcc" ;
$HIPCXXFLAGS .= " -I$CUDA_PATH/include" ;
2016-09-29 15:11:57 -05:00
$HIPLDFLAGS = "-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:
2016-09-22 12:27:07 +05:30
$HIPCXXFLAGS .= " -I$HIP_PATH/include -DHIP_VERSION_MAJOR=$HIP_VERSION_MAJOR -DHIP_VERSION_MINOR=$HIP_VERSION_MINOR -DHIP_VERSION_PATCH=$HIP_VERSION_PATCH" ;
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 ;
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" ){
2016-09-07 10:23:02 +05:30
$ISACMD .= "set ROCM_PATH=$ROCM_PATH && set ROCM_TARGET=$ROCM_TARGET && $HIP_PATH/bin/hccgenco.sh " ;
2016-09-01 10:39:14 -05:00
if ( $ARGV [ 0 ] eq "--genco" ){
2016-09-01 15:06:36 +05:30
foreach $isaarg ( @ARGV [ 1 .. $#ARGV ]){
2016-08-31 20:36:36 -05:00
$ISACMD .= " " ;
$ISACMD .= $isaarg ;
}
2016-09-01 15:06:36 +05:30
if ( $verbose & 0x1 ) {
print "hipcc-cmd: " , $ISACMD , "\n" ;
}
system ( $ISACMD ) and die ();
2016-08-31 20:36:36 -05:00
exit ( 0 );
}
}
2016-10-10 15:29:50 -05:00
if ( $HIP_PLATFORM eq "hcc" ){
$EXPORT_LL = " " ;
$ENV { HCC_EXTRA_LIBRARIES } = "$HIP_PATH/lib/hip_ir.ll\n" ;
}
2016-08-31 20:36:36 -05:00
if ( $HIP_PLATFORM eq "nvcc" ){
2016-09-01 15:06:36 +05:30
$ISACMD .= "$HIP_PATH/bin/hipcc -ptx " ;
2016-09-01 10:39:14 -05:00
if ( $ARGV [ 0 ] eq "--genco" ){
2016-09-01 15:06:36 +05:30
foreach $isaarg ( @ARGV [ 1 .. $#ARGV ]){
2016-08-31 20:36:36 -05:00
$ISACMD .= " " ;
2016-09-01 12:11:11 +05:30
$ISACMD .= $isaarg ;
2016-08-31 20:36:36 -05:00
}
2016-09-01 15:06:36 +05:30
if ( $verbose & 0x1 ) {
print "hipcc-cmd: " , $ISACMD , "\n" ;
}
system ( $ISACMD ) and die ();
2016-08-31 20:36:36 -05:00
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
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
{
2016-03-24 11:53:28 -05:00
my $swallowArg = 0 ;
2016-01-26 20:14:33 -06:00
if ( $arg eq '-c' ) {
$compileOnly = 1 ;
$needCXXFLAGS = 1 ;
$needLDFLAGS = 0 ;
}
if ( $arg eq '-o' ) {
$needLDFLAGS = 1 ;
}
2016-09-26 14:39:20 -05:00
if (( $arg 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 ;
}
2016-09-26 14:39:20 -05:00
if (( $arg eq '-stdlib=libstdc++' ) and ( $setStdLib eq 0 ))
2016-05-02 23:47:04 -05:00
{
$HIPCXXFLAGS .= " -stdlib=libstdc++" ;
$setStdLib = 1 ;
2016-04-06 14:18:51 -05:00
}
2016-06-14 14:51:03 +05:30
if ( $arg eq '--version' ) {
$printHipVersion = 1 ;
}
if ( $arg eq '--short-version' ) {
$printHipVersion = 1 ;
$runCmd = 0 ;
}
2016-09-02 15:07:33 +05:30
if ( $arg eq '-M' ) {
$compileOnly = 1 ;
$buildDeps = 1 ;
}
2016-01-26 20:14:33 -06:00
if ( $arg =~ m/^-/ ) {
# 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 ;
if ( $arg eq "--hipcc_explicit_lib" ) {
# Some environments (ie cmake tests) already link their own hip_hcc.o, so don't add here:
$needHipHcc = 0 ;
}
} else {
push ( @options , $arg );
}
2016-01-26 20:14:33 -06:00
#print "O: <$arg>\n";
} else {
2016-07-13 11:26:03 +05:30
# input files and libraries
2016-03-03 09:47:37 +05:30
if (( $arg =~ /\.cpp$/ ) or ( $arg =~ /\.c$/ ) or ( $arg =~ /\.cc$/ ) ) {
2016-01-26 20:14:33 -06:00
$hasC = 1 ;
$needCXXFLAGS = 1 ;
2016-07-13 11:26:03 +05:30
}
2016-03-03 09:47:37 +05:30
if (( $arg =~ /\.cu$/ ) or ( $arg =~ /\.cuh$/ )) {
2016-01-26 20:14:33 -06:00
$hasCU = 1 ;
$needCXXFLAGS = 1 ;
}
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
}
if ( $hasC and $HIP_PLATFORM eq 'nvcc' ) {
$HIPCXXFLAGS .= " -x cu" ;
}
if ( $hasCU and $HIP_PLATFORM eq 'hcc' ) {
$HIPCXXFLAGS .= " -x c++" ;
}
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
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-05-03 11:14:27 -05:00
$HIPCXXFLAGS .= " -stdlib=libstdc++" ;
2016-04-06 14:50:27 -05:00
}
2016-01-26 20:14:33 -06:00
if ( $needHipHcc ) {
2016-08-19 13:07:22 +05:30
$HIP_LIB_TYPE = $hipConfig { 'HIP_LIB_TYPE' } // 0 ;
2016-04-01 16:08:49 +05:30
2016-08-19 13:07:22 +05:30
if ( $HIP_LIB_TYPE eq 0 ) {
2016-09-23 10:43:09 +05:30
$HIPLDFLAGS .= " $HIP_PATH/lib/device_util.cpp.o $HIP_PATH/lib/hip_device.cpp.o $HIP_PATH/lib/hip_error.cpp.o $HIP_PATH/lib/hip_event.cpp.o $HIP_PATH/lib/hip_hcc.cpp.o $HIP_PATH/lib/hip_memory.cpp.o $HIP_PATH/lib/hip_peer.cpp.o $HIP_PATH/lib/hip_stream.cpp.o $HIP_PATH/lib/hip_ldg.cpp.o $HIP_PATH/lib/hip_fp16.cpp.o $HIP_PATH/lib/hip_context.cpp.o $HIP_PATH/lib/hip_module.cpp.o" ;
2016-08-19 13:07:22 +05:30
} elsif ( $HIP_LIB_TYPE eq 1 ) {
$HIPLDFLAGS .= " -L$HIP_PATH/lib -lhip_hcc" ;
} else {
$HIPLDFLAGS .= " -L$HIP_PATH/lib -Wl,--rpath=$HIP_PATH/lib -lhip_hcc" ;
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.
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' }) {
2016-09-22 17:51:52 -05:00
print ( "HIP ($HIP_PATH) was built using hcc $hipConfig{'HCC_VERSION'}, but you are using hcc $HCC_VERSION. Please rebuild HIP including cmake.\n" ) && die ();
2016-08-03 11:32:08 +05:30
}
2016-06-14 14:51:03 +05:30
system ( "$CMD" ) and die ();
}