96704ddd00
Change-Id: If5cbdd1e5d36d2d8b83f3eadd0598162691167aa
902 satır
31 KiB
Perl
Çalıştırılabilir Dosya
902 satır
31 KiB
Perl
Çalıştırılabilir Dosya
#!/usr/bin/perl -w
|
|
|
|
|
|
# Need perl > 5.10 to use logic-defined or
|
|
use 5.006; use v5.10.1;
|
|
use File::Basename;
|
|
use File::Temp qw/ :mktemp /;
|
|
use Cwd;
|
|
use Cwd 'abs_path';
|
|
|
|
# HIP compiler driver
|
|
# 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:
|
|
# HIP_PATH : Path to HIP directory, default is one dir level above location of this script.
|
|
# CUDA_PATH : Path to CUDA SDK (default /usr/local/cuda). Used on NVIDIA platforms only.
|
|
# 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.
|
|
# HIP_ROCCLR_HOME : Path to HIP/ROCclr directory. Used on AMD platforms only.
|
|
# HIP_CLANG_PATH : Path to HIP-Clang (default to ../../llvm/bin relative to this
|
|
# script's abs_path). Used on AMD platforms only.
|
|
|
|
if(scalar @ARGV == 0){
|
|
print "No Arguments passed, exiting ...\n";
|
|
exit(-1);
|
|
}
|
|
|
|
#---
|
|
# 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;
|
|
# Verbose: 0x1=commands, 0x2=paths, 0x4=hipcc args
|
|
|
|
$isWindows = $^O eq 'MSWin32';
|
|
|
|
$HIPCC_COMPILE_FLAGS_APPEND=$ENV{'HIPCC_COMPILE_FLAGS_APPEND'};
|
|
$HIPCC_LINK_FLAGS_APPEND=$ENV{'HIPCC_LINK_FLAGS_APPEND'};
|
|
|
|
# Known HIP target names.
|
|
@knownTargets = ('gfx701', 'gfx801', 'gfx802', 'gfx803', 'gfx900', 'gfx906', 'gfx908', 'gfx1010', 'gfx1011', 'gfx1012');
|
|
|
|
#
|
|
# 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";
|
|
}
|
|
$HIP_ROCCLR_HOME=$ENV{'HIP_ROCCLR_HOME'};
|
|
$HIP_LIB_PATH=$ENV{'HIP_LIB_PATH'};
|
|
$HIP_CLANG_PATH=$ENV{'HIP_CLANG_PATH'};
|
|
$DEVICE_LIB_PATH=$ENV{'DEVICE_LIB_PATH'};
|
|
$HIP_CLANG_HCC_COMPAT_MODE=$ENV{'HIP_CLANG_HCC_COMPAT_MODE'}; # HCC compatibility mode
|
|
$HIP_COMPILE_CXX_AS_HIP=$ENV{'HIP_COMPILE_CXX_AS_HIP'} // "1";
|
|
|
|
if (defined $HIP_ROCCLR_HOME) {
|
|
$HIP_INFO_PATH= "$HIP_ROCCLR_HOME/lib/.hipInfo";
|
|
} else {
|
|
$HIP_INFO_PATH= "$HIP_PATH/lib/.hipInfo"; # use actual file
|
|
}
|
|
|
|
#---
|
|
# Read .hipInfo
|
|
my %hipConfig = ();
|
|
parse_config_file("$HIP_INFO_PATH", \%hipConfig);
|
|
|
|
#---
|
|
# 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;
|
|
}
|
|
|
|
#---
|
|
#HIP_PLATFORM controls whether to use hcc (AMD) or nvcc as the platform:
|
|
#HIP_COMPILER controls whether to use hcc, clang or nvcc for compilation:
|
|
#HIP_RUNTIME controls whether to use HCC, ROCclr, or NVCC as the runtime:
|
|
if ($isWindows) {
|
|
# Windows cannot run perl natively, so hipcc will explicitly call perl
|
|
$HIP_PLATFORM= `perl $HIP_PATH/bin/hipconfig --platform`;
|
|
$HIP_VERSION= `perl $HIP_PATH/bin/hipconfig --version`;
|
|
$HIP_COMPILER= `perl $HIP_PATH/bin/hipconfig --compiler`;
|
|
$HIP_RUNTIME= `perl $HIP_PATH/bin/hipconfig --runtime`;
|
|
} else {
|
|
$HIP_PLATFORM= `$HIP_PATH/bin/hipconfig --platform`;
|
|
$HIP_VERSION= `$HIP_PATH/bin/hipconfig --version`;
|
|
$HIP_COMPILER= `$HIP_PATH/bin/hipconfig --compiler`;
|
|
$HIP_RUNTIME= `$HIP_PATH/bin/hipconfig --runtime`;
|
|
}
|
|
|
|
# If using ROCclr runtime, need to find HIP_ROCCLR_HOME
|
|
if (defined $HIP_RUNTIME and $HIP_RUNTIME eq "ROCclr" and !defined $HIP_ROCCLR_HOME) {
|
|
my $hipcc_dir = dirname($0);
|
|
if (-e "$hipcc_dir/../lib/bitcode") {
|
|
$HIP_ROCCLR_HOME = abs_path($hipcc_dir . "/..");
|
|
} else {
|
|
$HIP_ROCCLR_HOME = $HIP_PATH; # use HIP_PATH
|
|
}
|
|
$HIPCXXFLAGS .= "-D__HIP_ROCclr__";
|
|
$HIPCFLAGS .= "-D__HIP_ROCclr__";
|
|
}
|
|
|
|
if (defined $HIP_ROCCLR_HOME) {
|
|
if (!defined $HIP_CLANG_PATH and (-e "$HIP_ROCCLR_HOME/bin/clang" or -e "$HIP_ROCCLR_HOME/bin/clang.exe")) {
|
|
$HIP_CLANG_PATH = "$HIP_ROCCLR_HOME/bin";
|
|
}
|
|
if (!defined $DEVICE_LIB_PATH and -e "$HIP_ROCCLR_HOME/lib/bitcode") {
|
|
$DEVICE_LIB_PATH = "$HIP_ROCCLR_HOME/lib/bitcode";
|
|
}
|
|
$HIP_INCLUDE_PATH = "$HIP_ROCCLR_HOME/include";
|
|
if (!defined $HIP_LIB_PATH) {
|
|
$HIP_LIB_PATH = "$HIP_ROCCLR_HOME/lib";
|
|
}
|
|
}
|
|
|
|
if (defined $HIP_COMPILER and $HIP_PLATFORM eq "hcc" and $HIP_COMPILER eq "clang") {
|
|
if (!defined $HIP_CLANG_PATH) {
|
|
$HIP_CLANG_PATH = "$ROCM_PATH/llvm/bin";
|
|
}
|
|
if (!defined $DEVICE_LIB_PATH) {
|
|
$DEVICE_LIB_PATH = "$ROCM_PATH/lib";
|
|
}
|
|
}
|
|
|
|
if ($verbose & 0x2) {
|
|
print ("HIP_PATH=$HIP_PATH\n");
|
|
print ("HIP_PLATFORM=$HIP_PLATFORM\n");
|
|
print ("HIP_COMPILER=$HIP_COMPILER\n");
|
|
print ("HIP_RUNTIME=$HIP_RUNTIME\n");
|
|
}
|
|
|
|
# set if user explicitly requests -stdlib=libc++. (else we default to libstdc++ for better interop with g++):
|
|
$setStdLib = 0; # TODO - set to 0
|
|
|
|
$default_amdgpu_target = 1;
|
|
|
|
if ($HIP_PLATFORM eq "hcc" and $HIP_COMPILER eq "clang") {
|
|
$HIPCC="$HIP_CLANG_PATH/clang++";
|
|
|
|
# If $HIPCC clang++ is not compiled, use clang instead
|
|
if ( ! -e $HIPCC ) {
|
|
$HIPCC="$HIP_CLANG_PATH/clang";
|
|
$HIPLDFLAGS = "--driver-mode=g++";
|
|
}
|
|
|
|
$HIP_CLANG_VERSION = `$HIPCC --version`;
|
|
$HIP_CLANG_VERSION=~/.*clang version ([^ ]+).*/;
|
|
$HIP_CLANG_VERSION=$1;
|
|
|
|
if (! defined $HIP_CLANG_INCLUDE_PATH) {
|
|
$HIP_CLANG_INCLUDE_PATH = abs_path("$HIP_CLANG_PATH/../lib/clang/$HIP_CLANG_VERSION/include");
|
|
}
|
|
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_ROCCLR_HOME) {
|
|
print ("HIP_ROCCLR_HOME=$HIP_ROCCLR_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");
|
|
}
|
|
|
|
if ($isWindows) {
|
|
$HIPCXXFLAGS .= " -std=c++14 -fms-extensions -fms-compatibility";
|
|
} else {
|
|
$HIPCXXFLAGS .= " -std=c++11";
|
|
}
|
|
$HIPCXXFLAGS .= " -isystem $HIP_CLANG_INCLUDE_PATH/..";
|
|
$HIPCFLAGS .= " -isystem $HIP_CLANG_INCLUDE_PATH/..";
|
|
$HIPLDFLAGS .= " -L$HIP_LIB_PATH";
|
|
if ($isWindows) {
|
|
$HIPLDFLAGS .= " -lamdhip64";
|
|
}
|
|
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";
|
|
}
|
|
|
|
$HSA_PATH=$ENV{'HSA_PATH'} // "$ROCM_PATH/hsa";
|
|
$HIPCXXFLAGS .= " -isystem $HSA_PATH/include";
|
|
$HIPCFLAGS .= " -isystem $HSA_PATH/include";
|
|
if ($HIP_RUNTIME ne "HCC" ) {
|
|
$HIPCXXFLAGS .= " -D__HIP_ROCclr__";
|
|
$HIPCFLAGS .= " -D__HIP_ROCclr__";
|
|
}
|
|
|
|
} elsif ($HIP_PLATFORM eq "hcc" and $HIP_COMPILER eq "hcc") {
|
|
$HIP_INCLUDE_PATH = "$HIP_PATH/include";
|
|
if (! defined $HIP_LIB_PATH) {
|
|
$HIP_LIB_PATH = "$HIP_PATH/lib";
|
|
}
|
|
$HSA_PATH=$ENV{'HSA_PATH'} // "$ROCM_PATH/hsa";
|
|
|
|
$HCC_HOME=$ENV{'HCC_HOME'} // $hipConfig{'HCC_HOME'} // "$ROCM_PATH/hcc";
|
|
|
|
$HCC_VERSION=`${HCC_HOME}/bin/hcc --version`;
|
|
$HCC_VERSION=~/.*based on HCC ([^ ]+).*/;
|
|
$HCC_VERSION=$1;
|
|
$HCC_VERSION_MAJOR=$HCC_VERSION;
|
|
$HCC_VERSION_MAJOR=~s/\..*//;
|
|
|
|
# HCC* may be used to compile src/hip_hcc.o (and also feed the HIPCXXFLAGS below)
|
|
$HCC = "$HCC_HOME/bin/hcc";
|
|
$HCCFLAGS = "-hc -D__HIPCC__ -isystem $HCC_HOME/include ";
|
|
|
|
$HIPCC=$HCC;
|
|
$HIPCXXFLAGS = $HCCFLAGS;
|
|
|
|
$HIPLDFLAGS = `${HCC_HOME}/bin/hcc-config --ldflags`;
|
|
|
|
#### GCC system includes workaround ####
|
|
$HCC_WA_FLAGS = " ";
|
|
$HOST_OSNAME= `cat /etc/os-release | grep "^ID\=" | cut -d= -f2 | tr -d '\n'`;
|
|
if ($HCC_VERSION_MAJOR eq 1) {
|
|
my $GCC_CUR_VER = `gcc -dumpversion`;
|
|
my $GPP_CUR_VER = `g++ -dumpversion`;
|
|
$GCC_CUR_VER =~ s/\R//g;
|
|
$GPP_CUR_VER =~ s/\R//g;
|
|
|
|
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
|
|
# 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\"")) {
|
|
$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} ";
|
|
# Add C++ libs for GCC.
|
|
$HIPLDFLAGS .= " -lstdc++";
|
|
}
|
|
}
|
|
|
|
# Force -stdlib=libc++ on UB14.04
|
|
$HOST_OSVER= `cat /etc/os-release | grep "^VERSION_ID\=" | cut -d= -f2 | tr -d '\n'`;
|
|
if ($HOST_OSNAME eq "ubuntu" and $HOST_OSVER eq "\"14.04\"") {
|
|
$HIPCXXFLAGS .= " -stdlib=libc++";
|
|
$setStdLib = 1;
|
|
}
|
|
|
|
$HIPCXXFLAGS .= " -isystem $HIP_PATH/include/hip/hcc_detail/cuda";
|
|
$HIPCFLAGS .= " -isystem $HIP_PATH/include/hip/hcc_detail/cuda";
|
|
$HIPCXXFLAGS .= " -isystem $HSA_PATH/include";
|
|
$HIPCFLAGS .= " -isystem $HSA_PATH/include";
|
|
$HIPCXXFLAGS .= " -Wno-deprecated-register";
|
|
$HIPCFLAGS .= " -Wno-deprecated-register";
|
|
|
|
$HIPLDFLAGS .= " -L$HSA_PATH/lib -L$ROCM_PATH/lib -lhsa-runtime64 -lhc_am ";
|
|
# $HIPLDFLAGS .= " -L$HCC_HOME/compiler/lib -lLLVMAMDGPUDesc -lLLVMAMDGPUUtils -lLLVMMC -lLLVMCore -lLLVMSupport ";
|
|
|
|
if (not $isWindows) {
|
|
$HIPLDFLAGS .= " -lm";
|
|
}
|
|
|
|
if ($verbose & 0x2) {
|
|
print ("HSA_PATH=$HSA_PATH\n");
|
|
print ("HCC_HOME=$HCC_HOME\n");
|
|
}
|
|
|
|
} elsif ($HIP_PLATFORM eq "nvcc") {
|
|
$CUDA_PATH=$ENV{'CUDA_PATH'} // '/usr/local/cuda';
|
|
$HIP_INCLUDE_PATH = "$HIP_PATH/include";
|
|
if ($verbose & 0x2) {
|
|
print ("CUDA_PATH=$CUDA_PATH\n");
|
|
}
|
|
|
|
$HIPCC="$CUDA_PATH/bin/nvcc";
|
|
$HIPCXXFLAGS .= " -Wno-deprecated-gpu-targets ";
|
|
$HIPCXXFLAGS .= " -isystem $CUDA_PATH/include";
|
|
$HIPCFLAGS .= " -isystem $CUDA_PATH/include";
|
|
|
|
$HIPLDFLAGS = " -Wno-deprecated-gpu-targets -lcuda -lcudart -L$CUDA_PATH/lib64";
|
|
} else {
|
|
printf ("error: unknown HIP_PLATFORM = '$HIP_PLATFORM'");
|
|
printf (" or HIP_COMPILER = '$HIP_COMPILER'");
|
|
exit (-1);
|
|
}
|
|
|
|
# Add paths to common HIP includes:
|
|
$HIPCXXFLAGS .= " -isystem $HIP_INCLUDE_PATH" ;
|
|
$HIPCFLAGS .= " -isystem $HIP_INCLUDE_PATH" ;
|
|
|
|
my $compileOnly = 0;
|
|
my $needCXXFLAGS = 0; # need to add CXX flags to compile step
|
|
my $needCFLAGS = 0; # need to add C flags to compile step
|
|
my $needLDFLAGS = 1; # need to add LDFLAGS to compile step.
|
|
my $hasC = 0; # options contain a c-style file
|
|
my $hasCXX = 0; # options contain a cpp-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 $hasHIP = 0; # options contain a hip-style file (HIP-Clang must pass offloading options)
|
|
my $needHipHcc = ($HIP_PLATFORM eq 'hcc' and $HIP_COMPILER 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 $printCXXFlags = 0; # print HIPCXXFLAGS
|
|
my $printLDFlags = 0; # print HIPLDFLAGS
|
|
my $runCmd = 1;
|
|
my $buildDeps = 0;
|
|
my $linkType = 1;
|
|
my $setLinkType = 0;
|
|
my $coFormatv3 = 1;
|
|
if(defined $HIP_COMPILER and $HIP_COMPILER eq "hcc") {
|
|
$coFormatv3 = 0;
|
|
}
|
|
my $funcSupp = 0; # enable function support
|
|
my $rdc = 0; # whether -fgpu-rdc is on
|
|
|
|
my @options = ();
|
|
my @inputs = ();
|
|
|
|
if ($verbose & 0x4) {
|
|
print "hipcc-args: ", join (" ", @ARGV), "\n";
|
|
}
|
|
|
|
# Handle code object generation
|
|
my $ISACMD="";
|
|
if($HIP_PLATFORM eq "hcc" and $HIP_COMPILER eq "hcc"){
|
|
$ISACMD .= "$HIP_PATH/bin/lpl ";
|
|
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);
|
|
}
|
|
}
|
|
|
|
if(($HIP_PLATFORM eq "hcc" and $HIP_COMPILER eq "hcc")){
|
|
$ENV{HCC_EXTRA_LIBRARIES}="\n";
|
|
}
|
|
|
|
if($HIP_PLATFORM eq "nvcc"){
|
|
$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);
|
|
}
|
|
}
|
|
|
|
# TODO: convert toolArgs to an array rather than a string
|
|
my $toolArgs = ""; # arguments to pass to the hcc or nvcc tool
|
|
my $optArg = ""; # -O args
|
|
my $targetOpt = '--amdgpu-target=';
|
|
my $targetsStr = "";
|
|
my $skipOutputFile = 0; # file followed by -o should not contibute in picking compiler flags
|
|
my $prevArg = ""; # previous argument
|
|
|
|
foreach $arg (@ARGV)
|
|
{
|
|
# Save $arg, it can get changed in the loop.
|
|
$trimarg = $arg;
|
|
# TODO: figure out why this space removal is wanted.
|
|
# TODO: If someone has gone to the effort of quoting the spaces to the shell
|
|
# TODO: why are we removing it here?
|
|
$trimarg =~ s/^\s+|\s+$//g; # Remive whitespace
|
|
my $swallowArg = 0;
|
|
if ($arg eq '-c' or $arg eq '--genco' or $arg eq '-E') {
|
|
$compileOnly = 1;
|
|
$needLDFLAGS = 0;
|
|
}
|
|
|
|
if ($skipOutputFile) {
|
|
# TODO: handle filename with shell metacharacters
|
|
$toolArgs .= " $arg";
|
|
$prevArg = $arg;
|
|
$skipOutputFile = 0;
|
|
next;
|
|
}
|
|
|
|
if ($arg eq '-o') {
|
|
$needLDFLAGS = 1;
|
|
$skipOutputFile = 1;
|
|
}
|
|
|
|
if(($trimarg eq '-stdlib=libc++') and ($setStdLib eq 0))
|
|
{
|
|
$HIPCXXFLAGS .= " -stdlib=libc++";
|
|
$setStdLib = 1;
|
|
}
|
|
|
|
# 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 "hcc" and $HIP_COMPILER eq "clang") {
|
|
$swallowArg = 1;
|
|
}
|
|
}
|
|
|
|
# code object format parsing
|
|
if ($trimarg eq '-mcode-object-v3') {
|
|
$coFormatv3 = 1;
|
|
}
|
|
if ($trimarg eq '-mno-code-object-v3') {
|
|
$coFormatv3 = 0;
|
|
}
|
|
|
|
if (($arg =~ /--genco/) and $HIP_PLATFORM eq 'hcc' and $HIP_COMPILER eq 'clang' ) {
|
|
$arg = "--cuda-device-only";
|
|
}
|
|
|
|
if(($trimarg eq '-stdlib=libstdc++') and ($setStdLib eq 0) and $HIP_PLATFORM eq 'hcc' and $HIP_COMPILER eq 'hcc')
|
|
{
|
|
$HIPCXXFLAGS .= $HCC_WA_FLAGS;
|
|
$setStdLib = 1;
|
|
}
|
|
if($trimarg eq '--version') {
|
|
$printHipVersion = 1;
|
|
}
|
|
if($trimarg eq '--short-version') {
|
|
$printHipVersion = 1;
|
|
$runCmd = 0;
|
|
}
|
|
if($trimarg eq '--cxxflags') {
|
|
$printCXXFlags = 1;
|
|
$runCmd = 0;
|
|
}
|
|
if($trimarg eq '--ldflags') {
|
|
$printLDFlags = 1;
|
|
$runCmd = 0;
|
|
}
|
|
if($trimarg eq '-M') {
|
|
$compileOnly = 1;
|
|
$buildDeps = 1;
|
|
}
|
|
if($trimarg eq '-use_fast_math') {
|
|
$HIPCXXFLAGS .= " -DHIP_FAST_MATH ";
|
|
$HIPCFLAGS .= " -DHIP_FAST_MATH ";
|
|
}
|
|
if(($trimarg eq '-use-staticlib') and ($setLinkType eq 0))
|
|
{
|
|
$linkType = 0;
|
|
$setLinkType = 1;
|
|
$swallowArg = 1;
|
|
}
|
|
if(($trimarg eq '-use-sharedlib') and ($setLinkType eq 0))
|
|
{
|
|
$linkType = 1;
|
|
$setLinkType = 1;
|
|
}
|
|
if($arg =~ m/^-O/)
|
|
{
|
|
$optArg = $arg;
|
|
}
|
|
|
|
## 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 'hcc' and $HIP_COMPILER 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;
|
|
if ($line =~ m/\.a$/ || $line =~ m/\.lo$/) {
|
|
my $libFile = $line;
|
|
my $path = abs_path($line);
|
|
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/);
|
|
$allIsObj = ($allIsObj and $isObj);
|
|
if ($isObj) {
|
|
$realObjs = ($realObjs . " " . $obj);
|
|
} else {
|
|
push (@inputs, $obj);
|
|
$new_arg = "$new_arg $obj";
|
|
}
|
|
}
|
|
chomp $realObjs;
|
|
if ($allIsObj) {
|
|
print $out "$line\n";
|
|
} elsif ($realObjs) {
|
|
my($libBaseName, $libDir, $libExt) = fileparse($libFile);
|
|
$libBaseName = mktemp($libBaseName . "XXXX") . $libExt;
|
|
system("cd $tmpdir; ar c $libBaseName $realObjs");
|
|
print $out "$tmpdir/$libBaseName\n";
|
|
}
|
|
} 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";
|
|
}
|
|
} else {
|
|
print $out "$line\n";
|
|
}
|
|
}
|
|
close $in;
|
|
close $out;
|
|
$arg = "$new_arg -Wl,\@$new_file";
|
|
} elsif (($arg =~ m/\.a$/ || $arg =~ m/\.lo$/) &&
|
|
$HIP_PLATFORM eq 'hcc' and $HIP_COMPILER 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/);
|
|
if ($fileType =~ m/ELF/) {
|
|
my $sections = `readelf -e -W $obj`;
|
|
$isObj = !($sections =~ m/__CLANG_OFFLOAD_BUNDLE__/);
|
|
}
|
|
$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;
|
|
}
|
|
} elsif ($arg eq 'c' and $prevArg eq '-x') {
|
|
$hasC = 1;
|
|
$hasCXX = 0;
|
|
$hasHIP = 0;
|
|
} elsif ($arg eq 'c++' and $prevArg eq '-x') {
|
|
$hasC = 0;
|
|
$hasCXX = 1;
|
|
$hasHIP = 0;
|
|
} elsif ($arg eq 'hip' and $prevArg eq '-x') {
|
|
$hasC = 0;
|
|
$hasCXX = 0;
|
|
$hasHIP = 1;
|
|
} elsif ($arg =~ m/^-/) {
|
|
# options start with -
|
|
if ($arg eq '-fgpu-rdc') {
|
|
$rdc = 1;
|
|
} elsif ($arg eq '-fno-gpu-rdc') {
|
|
$rdc = 0;
|
|
}
|
|
|
|
# Process HIPCC options here:
|
|
if ($arg =~ m/^--hipcc/) {
|
|
$swallowArg = 1;
|
|
#if $arg eq "--hipcc_profile") { # Example argument here, hipcc
|
|
#
|
|
#}
|
|
if ($arg eq "--hipcc-func-supp") {
|
|
$funcSupp = 1;
|
|
} elsif ($arg eq "--hipcc-no-func-supp") {
|
|
$funcSupp = 0;
|
|
}
|
|
} else {
|
|
push (@options, $arg);
|
|
}
|
|
#print "O: <$arg>\n";
|
|
} elsif ($prevArg ne '-o') {
|
|
# input files and libraries
|
|
# Skip guessing if `-x {c|c++|hip}` is already specified.
|
|
if (not ($hasC or $hasCXX or $hasHIP)) {
|
|
if ($arg =~ /\.c$/) {
|
|
$hasC = 1;
|
|
$needCFLAGS = 1;
|
|
$toolArgs .= " -x c"
|
|
} elsif (($arg =~ /\.cpp$/) or ($arg =~ /\.cxx$/) or ($arg =~ /\.cc$/) ) {
|
|
$needCXXFLAGS = 1;
|
|
if ($HIP_COMPILE_CXX_AS_HIP eq '0' or $HIP_COMPILER ne "clang") {
|
|
$hasCXX = 1;
|
|
} else {
|
|
$hasHIP = 1;
|
|
$toolArgs .= " -x hip";
|
|
}
|
|
} elsif ((($arg =~ /\.cu$/ or $arg =~ /\.cuh$/) and $HIP_COMPILE_CXX_AS_HIP ne '0') or ($arg =~ /\.hip$/)) {
|
|
$needCXXFLAGS = 1;
|
|
if ($HIP_PLATFORM eq "hcc" and $HIP_COMPILER eq "clang") {
|
|
$hasHIP = 1;
|
|
$toolArgs .= " -x hip";
|
|
} else {
|
|
$hasCU = 1;
|
|
}
|
|
}
|
|
} elsif ($hasC) {
|
|
$needCFLAGS = 1;
|
|
} elsif ($hasCXX) {
|
|
$needCXXFLAGS = 1;
|
|
} else {
|
|
$needCXXFLAGS = 1;
|
|
}
|
|
push (@inputs, $arg);
|
|
#print "I: <$arg>\n";
|
|
}
|
|
# Produce a version of $arg where characters significant to the shell are
|
|
# quoted. One could quote everything of course but don't bother for
|
|
# common characters such as alphanumerics.
|
|
# Do the quoting here because sometimes the $arg is changed in the loop
|
|
# Important to have all of '-Xlinker' in the set of unquoted characters.
|
|
if (not $isWindows) { # Windows needs different quoting, ignore for now
|
|
$arg =~ s/[^-a-zA-Z0-9_=+,.\/]/\\$&/g;
|
|
}
|
|
$toolArgs .= " $arg" unless $swallowArg;
|
|
$prevArg = $arg;
|
|
}
|
|
|
|
if($HIP_PLATFORM eq "hcc"){
|
|
# No AMDGPU target specified at commandline. So look for HCC_AMDGPU_TARGET
|
|
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;
|
|
}
|
|
$default_amdgpu_target = 0;
|
|
}
|
|
|
|
# Parse the targets collected in targetStr and set corresponding compiler options.
|
|
my @targets = split(',', $targetsStr);
|
|
|
|
if($HIP_COMPILER eq "hcc") {
|
|
$GPU_ARCH_OPT = " --amdgpu-target=";
|
|
} else {
|
|
$GPU_ARCH_OPT = " --cuda-gpu-arch=";
|
|
}
|
|
|
|
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;
|
|
$HIPLDARCHFLAGS .= $GPU_ARCH_ARG;
|
|
$HIPCXXFLAGS .= $archMacro;
|
|
if ($HIP_COMPILER eq 'clang' and $hasHIP) {
|
|
$HIPCXXFLAGS .= $GPU_ARCH_ARG;
|
|
}
|
|
|
|
# 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";
|
|
}
|
|
}
|
|
}
|
|
|
|
# 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();
|
|
}
|
|
|
|
$ENV{HCC_EXTRA_LIBRARIES}="\n";
|
|
}
|
|
|
|
# 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' and $HIP_COMPILER eq 'hcc') {
|
|
$HIPLDFLAGS .= " -mcode-object-v3";
|
|
$HIPCXXFLAGS .= " -mcode-object-v3";
|
|
}
|
|
|
|
if ($hasCXX and $HIP_PLATFORM eq 'nvcc') {
|
|
$HIPCXXFLAGS .= " -x cu";
|
|
}
|
|
if ($hasCU and $HIP_PLATFORM eq 'hcc' and $HIP_COMPILER eq 'hcc') {
|
|
$HIPCXXFLAGS .= " -x c++";
|
|
}
|
|
|
|
if ($buildDeps and $HIP_PLATFORM eq 'nvcc') {
|
|
$HIPCXXFLAGS .= " -M -D__CUDACC__";
|
|
$HIPCFLAGS .= " -M -D__CUDACC__";
|
|
}
|
|
|
|
if ($buildDeps and $HIP_PLATFORM eq 'hcc' and $HIP_COMPILER eq 'clang') {
|
|
$HIPCXXFLAGS .= " --cuda-host-only";
|
|
}
|
|
|
|
# Add --hip-link only if it is compile only and -fgpu-rdc is on.
|
|
if ($rdc and !$compileOnly and $HIP_PLATFORM eq 'hcc' and $HIP_COMPILER eq 'clang') {
|
|
$HIPLDFLAGS .= " --hip-link";
|
|
$HIPLDFLAGS .= $HIPLDARCHFLAGS;
|
|
}
|
|
|
|
if ($setStdLib eq 0 and $HIP_PLATFORM eq 'hcc' and $HIP_COMPILER eq 'hcc')
|
|
{
|
|
$HIPCXXFLAGS .= $HCC_WA_FLAGS;
|
|
}
|
|
|
|
if ($needHipHcc) {
|
|
if ($linkType eq 0) {
|
|
substr($HIPLDFLAGS,0,0) = " $HIP_LIB_PATH/libhip_hcc_static.a " ;
|
|
} else {
|
|
substr($HIPLDFLAGS,0,0) = " -Wl,--enable-new-dtags -Wl,--rpath=$HIP_LIB_PATH:$ROCM_PATH/lib $HIP_LIB_PATH/libhip_hcc.so ";
|
|
}
|
|
}
|
|
|
|
# hipcc currrently requires separate compilation of source files, ie it is not possible to pass
|
|
# CPP files combined with .O files
|
|
# Reason is that NVCC uses the file extension to determine whether to compile in CUDA mode or
|
|
# pass-through CPP mode.
|
|
|
|
if ($HIP_PLATFORM eq "hcc" and $HIP_COMPILER eq "clang") {
|
|
# Set default optimization level to -O3 for hip-clang.
|
|
if ($optArg eq "") {
|
|
$HIPCXXFLAGS .= " -O3";
|
|
$HIPCFLAGS .= " -O3";
|
|
$HIPLDFLAGS .= " -O3";
|
|
}
|
|
# 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 (!$funcSupp and $optArg ne "-O0" and not $isWindows and $hasHIP) {
|
|
$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";
|
|
}
|
|
}
|
|
$HIP_DEVLIB_FLAGS = " --hip-device-lib-path=$DEVICE_LIB_PATH";
|
|
if ($hasHIP) {
|
|
$HIPCXXFLAGS .= " $HIP_DEVLIB_FLAGS";
|
|
if ($HIP_RUNTIME ne "HCC") {
|
|
$HIPCXXFLAGS .= " -fhip-new-launch-api";
|
|
}
|
|
}
|
|
if (not $isWindows) {
|
|
$HIPLDFLAGS .= " -lgcc_s -lgcc -lpthread -lm";
|
|
}
|
|
|
|
if (not $isWindows and not $compileOnly) {
|
|
if ($linkType eq 0) {
|
|
$toolArgs .= " -L$HIP_LIB_PATH -lamdhip64_static -L$ROCM_PATH/lib -lhsa-runtime64 -ldl ";
|
|
} else {
|
|
$toolArgs .= " -Wl,--enable-new-dtags -Wl,--rpath=$HIP_LIB_PATH:$ROCM_PATH/lib -lhip_hcc ";
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($HIPCC_COMPILE_FLAGS_APPEND) {
|
|
$HIPCXXFLAGS .= " $HIPCC_COMPILE_FLAGS_APPEND";
|
|
$HIPCFLAGS .= " $HIPCC_COMPILE_FLAGS_APPEND";
|
|
}
|
|
if ($HIPCC_LINK_FLAGS_APPEND) {
|
|
$HIPLDFLAGS .= " $HIPCC_LINK_FLAGS_APPEND";
|
|
}
|
|
|
|
# TODO: convert CMD to an array rather than a string
|
|
my $CMD="$HIPCC";
|
|
|
|
if ($needCFLAGS) {
|
|
$CMD .= " $HIPCFLAGS";
|
|
}
|
|
|
|
if ($needCXXFLAGS) {
|
|
$CMD .= " $HIPCXXFLAGS";
|
|
}
|
|
|
|
if ($needLDFLAGS and not $compileOnly) {
|
|
$CMD .= " $HIPLDFLAGS";
|
|
}
|
|
$CMD .= " $toolArgs";
|
|
|
|
if ($verbose & 0x1) {
|
|
print "hipcc-cmd: ", $CMD, "\n";
|
|
}
|
|
|
|
if ($printHipVersion) {
|
|
if ($runCmd) {
|
|
print "HIP version: "
|
|
}
|
|
print $HIP_VERSION, "\n";
|
|
}
|
|
if ($printCXXFlags) {
|
|
print $HIPCXXFLAGS;
|
|
}
|
|
if ($printLDFlags) {
|
|
print $HIPLDFLAGS;
|
|
}
|
|
if ($runCmd) {
|
|
if ($HIP_PLATFORM eq "hcc" and $HIP_COMPILER eq "hcc" and exists($hipConfig{'HCC_VERSION'}) and $HCC_VERSION ne $hipConfig{'HCC_VERSION'}) {
|
|
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'};
|
|
}
|
|
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);
|
|
}
|
|
|
|
# vim: ts=4:sw=4:expandtab:smartindent
|