|
|
|
@@ -0,0 +1,937 @@
|
|
|
|
|
/*
|
|
|
|
|
Copyright (c) 2015-2016 Advanced Micro Devices, Inc. All rights reserved.
|
|
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
|
|
|
in the Software without restriction, including without limitation the rights
|
|
|
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
|
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
|
|
|
all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
|
THE SOFTWARE.
|
|
|
|
|
*/
|
|
|
|
|
/**
|
|
|
|
|
* @file Cuda2Hip.cpp
|
|
|
|
|
*
|
|
|
|
|
* This file is compiled and linked into clang based hipify tool.
|
|
|
|
|
*/
|
|
|
|
|
#include "clang/ASTMatchers/ASTMatchFinder.h"
|
|
|
|
|
#include "clang/ASTMatchers/ASTMatchers.h"
|
|
|
|
|
#include "clang/Basic/SourceManager.h"
|
|
|
|
|
#include "clang/Frontend/CompilerInstance.h"
|
|
|
|
|
#include "clang/Frontend/FrontendActions.h"
|
|
|
|
|
#include "clang/Frontend/TextDiagnosticPrinter.h"
|
|
|
|
|
#include "clang/Lex/Lexer.h"
|
|
|
|
|
#include "clang/Lex/MacroArgs.h"
|
|
|
|
|
#include "clang/Lex/MacroInfo.h"
|
|
|
|
|
#include "clang/Lex/PPCallbacks.h"
|
|
|
|
|
#include "clang/Lex/Preprocessor.h"
|
|
|
|
|
#include "clang/Rewrite/Core/Rewriter.h"
|
|
|
|
|
#include "clang/Tooling/CommonOptionsParser.h"
|
|
|
|
|
#include "clang/Tooling/Refactoring.h"
|
|
|
|
|
#include "clang/Tooling/Tooling.h"
|
|
|
|
|
#include "llvm/Support/CommandLine.h"
|
|
|
|
|
#include "llvm/Support/Debug.h"
|
|
|
|
|
#include "llvm/Support/MemoryBuffer.h"
|
|
|
|
|
#include "llvm/Support/Signals.h"
|
|
|
|
|
|
|
|
|
|
#include <cstdio>
|
|
|
|
|
#include <fstream>
|
|
|
|
|
|
|
|
|
|
using namespace clang;
|
|
|
|
|
using namespace clang::ast_matchers;
|
|
|
|
|
using namespace clang::tooling;
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
|
|
#define DEBUG_TYPE "cuda2hip"
|
|
|
|
|
|
|
|
|
|
enum ConvTypes {
|
|
|
|
|
CONV_DEV = 0,
|
|
|
|
|
CONV_MEM,
|
|
|
|
|
CONV_KERN,
|
|
|
|
|
CONV_COORD_FUNC,
|
|
|
|
|
CONV_MATH_FUNC,
|
|
|
|
|
CONV_SPECIAL_FUNC,
|
|
|
|
|
CONV_STREAM,
|
|
|
|
|
CONV_EVENT,
|
|
|
|
|
CONV_ERR,
|
|
|
|
|
CONV_DEF,
|
|
|
|
|
CONV_TEX,
|
|
|
|
|
CONV_OTHER,
|
|
|
|
|
CONV_INCLUDE,
|
|
|
|
|
CONV_LITERAL,
|
|
|
|
|
CONV_LAST
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const char *counterNames[ConvTypes::CONV_LAST] = {
|
|
|
|
|
"dev", "mem", "kern", "coord_func", "math_func",
|
|
|
|
|
"special_func", "stream", "event", "err", "def",
|
|
|
|
|
"tex", "other", "include", "literal"};
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
struct cuda2hipMap {
|
|
|
|
|
cuda2hipMap() {
|
|
|
|
|
// defines
|
|
|
|
|
cuda2hipRename["__CUDACC__"] = {"__HIPCC__", CONV_DEF};
|
|
|
|
|
|
|
|
|
|
// includes
|
|
|
|
|
cuda2hipRename["cuda_runtime.h"] = {"hip_runtime.h", CONV_INCLUDE};
|
|
|
|
|
cuda2hipRename["cuda_runtime_api.h"] = {"hip_runtime_api.h", CONV_INCLUDE};
|
|
|
|
|
|
|
|
|
|
// Error codes and return types:
|
|
|
|
|
cuda2hipRename["cudaError_t"] = {"hipError_t", CONV_ERR};
|
|
|
|
|
cuda2hipRename["cudaError"] = {"hipError", CONV_ERR};
|
|
|
|
|
cuda2hipRename["cudaSuccess"] = {"hipSuccess", CONV_ERR};
|
|
|
|
|
|
|
|
|
|
cuda2hipRename["cudaErrorUnknown"] = {"hipErrorUnknown", CONV_ERR};
|
|
|
|
|
cuda2hipRename["cudaErrorMemoryAllocation"] = {"hipErrorMemoryAllocation",
|
|
|
|
|
CONV_ERR};
|
|
|
|
|
cuda2hipRename["cudaErrorMemoryFree"] = {"hipErrorMemoryFree", CONV_ERR};
|
|
|
|
|
cuda2hipRename["cudaErrorUnknownSymbol"] = {"hipErrorUnknownSymbol",
|
|
|
|
|
CONV_ERR};
|
|
|
|
|
cuda2hipRename["cudaErrorOutOfResources"] = {"hipErrorOutOfResources",
|
|
|
|
|
CONV_ERR};
|
|
|
|
|
cuda2hipRename["cudaErrorInvalidValue"] = {"hipErrorInvalidValue",
|
|
|
|
|
CONV_ERR};
|
|
|
|
|
cuda2hipRename["cudaErrorInvalidResourceHandle"] = {
|
|
|
|
|
"hipErrorInvalidResourceHandle", CONV_ERR};
|
|
|
|
|
cuda2hipRename["cudaErrorInvalidDevice"] = {"hipErrorInvalidDevice",
|
|
|
|
|
CONV_ERR};
|
|
|
|
|
cuda2hipRename["cudaErrorNoDevice"] = {"hipErrorNoDevice", CONV_ERR};
|
|
|
|
|
cuda2hipRename["cudaErrorNotReady"] = {"hipErrorNotReady", CONV_ERR};
|
|
|
|
|
cuda2hipRename["cudaErrorUnknown"] = {"hipErrorUnknown", CONV_ERR};
|
|
|
|
|
|
|
|
|
|
// error APIs:
|
|
|
|
|
cuda2hipRename["cudaGetLastError"] = {"hipGetLastError", CONV_ERR};
|
|
|
|
|
cuda2hipRename["cudaPeekAtLastError"] = {"hipPeekAtLastError", CONV_ERR};
|
|
|
|
|
cuda2hipRename["cudaGetErrorName"] = {"hipGetErrorName", CONV_ERR};
|
|
|
|
|
cuda2hipRename["cudaGetErrorString"] = {"hipGetErrorString", CONV_ERR};
|
|
|
|
|
|
|
|
|
|
// Memcpy
|
|
|
|
|
cuda2hipRename["cudaMemcpy"] = {"hipMemcpy", CONV_MEM};
|
|
|
|
|
cuda2hipRename["cudaMemcpyHostToHost"] = {"hipMemcpyHostToHost", CONV_MEM};
|
|
|
|
|
cuda2hipRename["cudaMemcpyHostToDevice"] = {"hipMemcpyHostToDevice",
|
|
|
|
|
CONV_MEM};
|
|
|
|
|
cuda2hipRename["cudaMemcpyDeviceToHost"] = {"hipMemcpyDeviceToHost",
|
|
|
|
|
CONV_MEM};
|
|
|
|
|
cuda2hipRename["cudaMemcpyDeviceToDevice"] = {"hipMemcpyDeviceToDevice",
|
|
|
|
|
CONV_MEM};
|
|
|
|
|
cuda2hipRename["cudaMemcpyDefault"] = {"hipMemcpyDefault", CONV_MEM};
|
|
|
|
|
cuda2hipRename["cudaMemcpyToSymbol"] = {"hipMemcpyToSymbol", CONV_MEM};
|
|
|
|
|
cuda2hipRename["cudaMemset"] = {"hipMemset", CONV_MEM};
|
|
|
|
|
cuda2hipRename["cudaMemsetAsync"] = {"hipMemsetAsync", CONV_MEM};
|
|
|
|
|
cuda2hipRename["cudaMemcpyAsync"] = {"hipMemcpyAsync", CONV_MEM};
|
|
|
|
|
cuda2hipRename["cudaMemGetInfo"] = {"hipMemGetInfo", CONV_MEM};
|
|
|
|
|
cuda2hipRename["cudaMemcpyKind"] = {"hipMemcpyKind", CONV_MEM};
|
|
|
|
|
|
|
|
|
|
// Memory management :
|
|
|
|
|
cuda2hipRename["cudaMalloc"] = {"hipMalloc", CONV_MEM};
|
|
|
|
|
cuda2hipRename["cudaMallocHost"] = {"hipHostAlloc", CONV_MEM};
|
|
|
|
|
cuda2hipRename["cudaFree"] = {"hipFree", CONV_MEM};
|
|
|
|
|
cuda2hipRename["cudaFreeHost"] = {"hipHostFree", CONV_MEM};
|
|
|
|
|
|
|
|
|
|
// Coordinate Indexing and Dimensions:
|
|
|
|
|
cuda2hipRename["threadIdx.x"] = {"hipThreadIdx_x", CONV_COORD_FUNC};
|
|
|
|
|
cuda2hipRename["threadIdx.y"] = {"hipThreadIdx_y", CONV_COORD_FUNC};
|
|
|
|
|
cuda2hipRename["threadIdx.z"] = {"hipThreadIdx_z", CONV_COORD_FUNC};
|
|
|
|
|
|
|
|
|
|
cuda2hipRename["blockIdx.x"] = {"hipBlockIdx_x", CONV_COORD_FUNC};
|
|
|
|
|
cuda2hipRename["blockIdx.y"] = {"hipBlockIdx_y", CONV_COORD_FUNC};
|
|
|
|
|
cuda2hipRename["blockIdx.z"] = {"hipBlockIdx_z", CONV_COORD_FUNC};
|
|
|
|
|
|
|
|
|
|
cuda2hipRename["blockDim.x"] = {"hipBlockDim_x", CONV_COORD_FUNC};
|
|
|
|
|
cuda2hipRename["blockDim.y"] = {"hipBlockDim_y", CONV_COORD_FUNC};
|
|
|
|
|
cuda2hipRename["blockDim.z"] = {"hipBlockDim_z", CONV_COORD_FUNC};
|
|
|
|
|
|
|
|
|
|
cuda2hipRename["gridDim.x"] = {"hipGridDim_x", CONV_COORD_FUNC};
|
|
|
|
|
cuda2hipRename["gridDim.y"] = {"hipGridDim_y", CONV_COORD_FUNC};
|
|
|
|
|
cuda2hipRename["gridDim.z"] = {"hipGridDim_z", CONV_COORD_FUNC};
|
|
|
|
|
|
|
|
|
|
cuda2hipRename["blockIdx.x"] = {"hipBlockIdx_x", CONV_COORD_FUNC};
|
|
|
|
|
cuda2hipRename["blockIdx.y"] = {"hipBlockIdx_y", CONV_COORD_FUNC};
|
|
|
|
|
cuda2hipRename["blockIdx.z"] = {"hipBlockIdx_z", CONV_COORD_FUNC};
|
|
|
|
|
|
|
|
|
|
cuda2hipRename["blockDim.x"] = {"hipBlockDim_x", CONV_COORD_FUNC};
|
|
|
|
|
cuda2hipRename["blockDim.y"] = {"hipBlockDim_y", CONV_COORD_FUNC};
|
|
|
|
|
cuda2hipRename["blockDim.z"] = {"hipBlockDim_z", CONV_COORD_FUNC};
|
|
|
|
|
|
|
|
|
|
cuda2hipRename["gridDim.x"] = {"hipGridDim_x", CONV_COORD_FUNC};
|
|
|
|
|
cuda2hipRename["gridDim.y"] = {"hipGridDim_y", CONV_COORD_FUNC};
|
|
|
|
|
cuda2hipRename["gridDim.z"] = {"hipGridDim_z", CONV_COORD_FUNC};
|
|
|
|
|
|
|
|
|
|
cuda2hipRename["warpSize"] = {"hipWarpSize", CONV_SPECIAL_FUNC};
|
|
|
|
|
|
|
|
|
|
// Events
|
|
|
|
|
cuda2hipRename["cudaEvent_t"] = {"hipEvent_t", CONV_EVENT};
|
|
|
|
|
cuda2hipRename["cudaEventCreate"] = {"hipEventCreate", CONV_EVENT};
|
|
|
|
|
cuda2hipRename["cudaEventCreateWithFlags"] = {"hipEventCreateWithFlags",
|
|
|
|
|
CONV_EVENT};
|
|
|
|
|
cuda2hipRename["cudaEventDestroy"] = {"hipEventDestroy", CONV_EVENT};
|
|
|
|
|
cuda2hipRename["cudaEventRecord"] = {"hipEventRecord", CONV_EVENT};
|
|
|
|
|
cuda2hipRename["cudaEventElapsedTime"] = {"hipEventElapsedTime",
|
|
|
|
|
CONV_EVENT};
|
|
|
|
|
cuda2hipRename["cudaEventSynchronize"] = {"hipEventSynchronize",
|
|
|
|
|
CONV_EVENT};
|
|
|
|
|
|
|
|
|
|
// Streams
|
|
|
|
|
cuda2hipRename["cudaStream_t"] = {"hipStream_t", CONV_STREAM};
|
|
|
|
|
cuda2hipRename["cudaStreamCreate"] = {"hipStreamCreate", CONV_STREAM};
|
|
|
|
|
cuda2hipRename["cudaStreamCreateWithFlags"] = {"hipStreamCreateWithFlags",
|
|
|
|
|
CONV_STREAM};
|
|
|
|
|
cuda2hipRename["cudaStreamDestroy"] = {"hipStreamDestroy", CONV_STREAM};
|
|
|
|
|
cuda2hipRename["cudaStreamWaitEvent"] = {"hipStreamWaitEven", CONV_STREAM};
|
|
|
|
|
cuda2hipRename["cudaStreamSynchronize"] = {"hipStreamSynchronize",
|
|
|
|
|
CONV_STREAM};
|
|
|
|
|
cuda2hipRename["cudaStreamDefault"] = {"hipStreamDefault", CONV_STREAM};
|
|
|
|
|
cuda2hipRename["cudaStreamNonBlocking"] = {"hipStreamNonBlocking",
|
|
|
|
|
CONV_STREAM};
|
|
|
|
|
|
|
|
|
|
// Other synchronization
|
|
|
|
|
cuda2hipRename["cudaDeviceSynchronize"] = {"hipDeviceSynchronize",
|
|
|
|
|
CONV_DEV};
|
|
|
|
|
cuda2hipRename["cudaThreadSynchronize"] = {
|
|
|
|
|
"hipDeviceSynchronize",
|
|
|
|
|
CONV_DEV}; // translate deprecated cudaThreadSynchronize
|
|
|
|
|
cuda2hipRename["cudaDeviceReset"] = {"hipDeviceReset", CONV_DEV};
|
|
|
|
|
cuda2hipRename["cudaThreadExit"] = {
|
|
|
|
|
"hipDeviceReset", CONV_DEV}; // translate deprecated cudaThreadExit
|
|
|
|
|
cuda2hipRename["cudaSetDevice"] = {"hipSetDevice", CONV_DEV};
|
|
|
|
|
cuda2hipRename["cudaGetDevice"] = {"hipGetDevice", CONV_DEV};
|
|
|
|
|
|
|
|
|
|
// Attribute
|
|
|
|
|
cuda2hipRename["bcudaDeviceAttr"] = {"hipDeviceAttribute_t", CONV_DEV};
|
|
|
|
|
cuda2hipRename["bcudaDeviceGetAttribute"] = {"hipDeviceGetAttribute",
|
|
|
|
|
CONV_DEV};
|
|
|
|
|
|
|
|
|
|
// Device
|
|
|
|
|
cuda2hipRename["cudaDeviceProp"] = {"hipDeviceProp_t", CONV_DEV};
|
|
|
|
|
cuda2hipRename["cudaGetDeviceProperties"] = {"hipGetDeviceProperties",
|
|
|
|
|
CONV_DEV};
|
|
|
|
|
|
|
|
|
|
// Cache config
|
|
|
|
|
cuda2hipRename["cudaDeviceSetCacheConfig"] = {"hipDeviceSetCacheConfig",
|
|
|
|
|
CONV_DEV};
|
|
|
|
|
cuda2hipRename["cudaThreadSetCacheConfig"] = {
|
|
|
|
|
"hipDeviceSetCacheConfig", CONV_DEV}; // translate deprecated
|
|
|
|
|
cuda2hipRename["cudaDeviceGetCacheConfig"] = {"hipDeviceGetCacheConfig",
|
|
|
|
|
CONV_DEV};
|
|
|
|
|
cuda2hipRename["cudaThreadGetCacheConfig"] = {
|
|
|
|
|
"hipDeviceGetCacheConfig", CONV_DEV}; // translate deprecated
|
|
|
|
|
cuda2hipRename["cudaFuncCache"] = {"hipFuncCache", CONV_DEV};
|
|
|
|
|
cuda2hipRename["cudaFuncCachePreferNone"] = {"hipFuncCachePreferNone",
|
|
|
|
|
CONV_DEV};
|
|
|
|
|
cuda2hipRename["cudaFuncCachePreferShared"] = {"hipFuncCachePreferShared",
|
|
|
|
|
CONV_DEV};
|
|
|
|
|
cuda2hipRename["cudaFuncCachePreferL1"] = {"hipFuncCachePreferL1",
|
|
|
|
|
CONV_DEV};
|
|
|
|
|
cuda2hipRename["cudaFuncCachePreferEqual"] = {"hipFuncCachePreferEqual",
|
|
|
|
|
CONV_DEV};
|
|
|
|
|
// function
|
|
|
|
|
cuda2hipRename["cudaFuncSetCacheConfig"] = {"hipFuncSetCacheConfig",
|
|
|
|
|
CONV_DEV};
|
|
|
|
|
|
|
|
|
|
cuda2hipRename["cudaDriverGetVersion"] = {"hipDriverGetVersion", CONV_DEV};
|
|
|
|
|
// cuda2hipRename["cudaRuntimeGetVersion"] = {"hipRuntimeGetVersion",
|
|
|
|
|
// CONV_DEV};
|
|
|
|
|
|
|
|
|
|
// Peer2Peer
|
|
|
|
|
cuda2hipRename["cudaDeviceCanAccessPeer"] = {"hipDeviceCanAccessPeer",
|
|
|
|
|
CONV_DEV};
|
|
|
|
|
cuda2hipRename["cudaDeviceDisablePeerAccess"] = {
|
|
|
|
|
"hipDeviceDisablePeerAccess", CONV_DEV};
|
|
|
|
|
cuda2hipRename["cudaDeviceEnablePeerAccess"] = {"hipDeviceEnablePeerAccess",
|
|
|
|
|
CONV_DEV};
|
|
|
|
|
cuda2hipRename["cudaMemcpyPeerAsync"] = {"hipMemcpyPeerAsync", CONV_MEM};
|
|
|
|
|
cuda2hipRename["cudaMemcpyPeer"] = {"hipMemcpyPeer", CONV_MEM};
|
|
|
|
|
|
|
|
|
|
// Shared mem:
|
|
|
|
|
cuda2hipRename["cudaDeviceSetSharedMemConfig"] = {
|
|
|
|
|
"hipDeviceSetSharedMemConfig", CONV_DEV};
|
|
|
|
|
cuda2hipRename["cudaThreadSetSharedMemConfig"] = {
|
|
|
|
|
"hipDeviceSetSharedMemConfig", CONV_DEV}; // translate deprecated
|
|
|
|
|
cuda2hipRename["cudaDeviceGetSharedMemConfig"] = {
|
|
|
|
|
"hipDeviceGetSharedMemConfig", CONV_DEV};
|
|
|
|
|
cuda2hipRename["cudaThreadGetSharedMemConfig"] = {
|
|
|
|
|
"hipDeviceGetSharedMemConfig", CONV_DEV}; // translate deprecated
|
|
|
|
|
cuda2hipRename["cudaSharedMemConfig"] = {"hipSharedMemConfig", CONV_DEV};
|
|
|
|
|
cuda2hipRename["cudaSharedMemBankSizeDefault"] = {
|
|
|
|
|
"hipSharedMemBankSizeDefault", CONV_DEV};
|
|
|
|
|
cuda2hipRename["cudaSharedMemBankSizeFourByte"] = {
|
|
|
|
|
"hipSharedMemBankSizeFourByte", CONV_DEV};
|
|
|
|
|
cuda2hipRename["cudaSharedMemBankSizeEightByte"] = {
|
|
|
|
|
"hipSharedMemBankSizeEightByte", CONV_DEV};
|
|
|
|
|
|
|
|
|
|
cuda2hipRename["cudaGetDeviceCount"] = {"hipGetDeviceCount", CONV_DEV};
|
|
|
|
|
|
|
|
|
|
// Profiler
|
|
|
|
|
// cuda2hipRename["cudaProfilerInitialize"] = "hipProfilerInitialize"; //
|
|
|
|
|
// see if these are called anywhere.
|
|
|
|
|
cuda2hipRename["cudaProfilerStart"] = {"hipProfilerStart", CONV_OTHER};
|
|
|
|
|
cuda2hipRename["cudaProfilerStop"] = {"hipProfilerStop", CONV_OTHER};
|
|
|
|
|
|
|
|
|
|
cuda2hipRename["cudaChannelFormatDesc"] = {"hipChannelFormatDesc",
|
|
|
|
|
CONV_TEX};
|
|
|
|
|
cuda2hipRename["cudaFilterModePoint"] = {"hipFilterModePoint", CONV_TEX};
|
|
|
|
|
cuda2hipRename["cudaReadModeElementType"] = {"hipReadModeElementType",
|
|
|
|
|
CONV_TEX};
|
|
|
|
|
|
|
|
|
|
cuda2hipRename["cudaCreateChannelDesc"] = {"hipCreateChannelDesc",
|
|
|
|
|
CONV_TEX};
|
|
|
|
|
cuda2hipRename["cudaBindTexture"] = {"hipBindTexture", CONV_TEX};
|
|
|
|
|
cuda2hipRename["cudaUnbindTexture"] = {"hipUnbindTexture", CONV_TEX};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct HipNames {
|
|
|
|
|
StringRef hipName;
|
|
|
|
|
ConvTypes countType;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
SmallDenseMap<StringRef, HipNames> cuda2hipRename;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
StringRef unquoteStr(StringRef s) {
|
|
|
|
|
if (s.size() > 1 && s.front() == '"' && s.back() == '"')
|
|
|
|
|
return s.substr(1, s.size() - 2);
|
|
|
|
|
return s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void processString(StringRef s, const cuda2hipMap &map,
|
|
|
|
|
Replacements *Replace, SourceManager &SM,
|
|
|
|
|
SourceLocation start,
|
|
|
|
|
int64_t countReps[ConvTypes::CONV_LAST]) {
|
|
|
|
|
size_t begin = 0;
|
|
|
|
|
while ((begin = s.find("cuda", begin)) != StringRef::npos) {
|
|
|
|
|
const size_t end = s.find_first_of(" ", begin + 4);
|
|
|
|
|
StringRef name = s.slice(begin, end);
|
|
|
|
|
const auto found = map.cuda2hipRename.find(name);
|
|
|
|
|
if (found != map.cuda2hipRename.end()) {
|
|
|
|
|
countReps[CONV_LITERAL]++;
|
|
|
|
|
StringRef repName = found->second.hipName;
|
|
|
|
|
SourceLocation sl = start.getLocWithOffset(begin + 1);
|
|
|
|
|
Replacement Rep(SM, sl, name.size(), repName);
|
|
|
|
|
Replace->insert(Rep);
|
|
|
|
|
}
|
|
|
|
|
if (end == StringRef::npos)
|
|
|
|
|
break;
|
|
|
|
|
begin = end + 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct HipifyPPCallbacks : public PPCallbacks, public SourceFileCallbacks {
|
|
|
|
|
HipifyPPCallbacks(Replacements *R)
|
|
|
|
|
: SeenEnd(false), _sm(nullptr), _pp(nullptr), Replace(R) {}
|
|
|
|
|
|
|
|
|
|
virtual bool handleBeginSource(CompilerInstance &CI,
|
|
|
|
|
StringRef Filename) override {
|
|
|
|
|
Preprocessor &PP = CI.getPreprocessor();
|
|
|
|
|
SourceManager &SM = CI.getSourceManager();
|
|
|
|
|
setSourceManager(&SM);
|
|
|
|
|
PP.addPPCallbacks(std::unique_ptr<HipifyPPCallbacks>(this));
|
|
|
|
|
PP.Retain();
|
|
|
|
|
setPreprocessor(&PP);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void InclusionDirective(SourceLocation hash_loc,
|
|
|
|
|
const Token &include_token,
|
|
|
|
|
StringRef file_name, bool is_angled,
|
|
|
|
|
CharSourceRange filename_range,
|
|
|
|
|
const FileEntry *file, StringRef search_path,
|
|
|
|
|
StringRef relative_path,
|
|
|
|
|
const clang::Module *imported) override {
|
|
|
|
|
if (_sm->isWrittenInMainFile(hash_loc)) {
|
|
|
|
|
if (is_angled) {
|
|
|
|
|
const auto found = N.cuda2hipRename.find(file_name);
|
|
|
|
|
if (found != N.cuda2hipRename.end()) {
|
|
|
|
|
countReps[found->second.countType]++;
|
|
|
|
|
StringRef repName = found->second.hipName;
|
|
|
|
|
DEBUG(dbgs() << "Include file found: " << file_name << "\n"
|
|
|
|
|
<< "SourceLocation:"
|
|
|
|
|
<< filename_range.getBegin().printToString(*_sm) << "\n"
|
|
|
|
|
<< "Will be replaced with " << repName << "\n");
|
|
|
|
|
SourceLocation sl = filename_range.getBegin();
|
|
|
|
|
SourceLocation sle = filename_range.getEnd();
|
|
|
|
|
const char *B = _sm->getCharacterData(sl);
|
|
|
|
|
const char *E = _sm->getCharacterData(sle);
|
|
|
|
|
SmallString<128> tmpData;
|
|
|
|
|
Replacement Rep(*_sm, sl, E - B,
|
|
|
|
|
Twine("<" + repName + ">").toStringRef(tmpData));
|
|
|
|
|
Replace->insert(Rep);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void MacroDefined(const Token &MacroNameTok,
|
|
|
|
|
const MacroDirective *MD) override {
|
|
|
|
|
if (_sm->isWrittenInMainFile(MD->getLocation()) &&
|
|
|
|
|
MD->getKind() == MacroDirective::MD_Define) {
|
|
|
|
|
for (auto T : MD->getMacroInfo()->tokens()) {
|
|
|
|
|
if (T.isAnyIdentifier()) {
|
|
|
|
|
StringRef name = T.getIdentifierInfo()->getName();
|
|
|
|
|
const auto found = N.cuda2hipRename.find(name);
|
|
|
|
|
if (found != N.cuda2hipRename.end()) {
|
|
|
|
|
countReps[found->second.countType]++;
|
|
|
|
|
StringRef repName = found->second.hipName;
|
|
|
|
|
SourceLocation sl = T.getLocation();
|
|
|
|
|
DEBUG(dbgs() << "Identifier " << name
|
|
|
|
|
<< " found in definition of macro "
|
|
|
|
|
<< MacroNameTok.getIdentifierInfo()->getName() << "\n"
|
|
|
|
|
<< "will be replaced with: " << repName << "\n"
|
|
|
|
|
<< "SourceLocation: " << sl.printToString(*_sm)
|
|
|
|
|
<< "\n");
|
|
|
|
|
Replacement Rep(*_sm, sl, name.size(), repName);
|
|
|
|
|
Replace->insert(Rep);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void MacroExpands(const Token &MacroNameTok,
|
|
|
|
|
const MacroDefinition &MD, SourceRange Range,
|
|
|
|
|
const MacroArgs *Args) override {
|
|
|
|
|
if (_sm->isWrittenInMainFile(MacroNameTok.getLocation())) {
|
|
|
|
|
for (unsigned int i = 0; Args && i < MD.getMacroInfo()->getNumArgs();
|
|
|
|
|
i++) {
|
|
|
|
|
StringRef macroName = MacroNameTok.getIdentifierInfo()->getName();
|
|
|
|
|
std::vector<Token> toks;
|
|
|
|
|
// Code below is a kind of stolen from 'MacroArgs::getPreExpArgument'
|
|
|
|
|
// to workaround the 'const' MacroArgs passed into this hook.
|
|
|
|
|
const Token *start = Args->getUnexpArgument(i);
|
|
|
|
|
size_t len = Args->getArgLength(start) + 1;
|
|
|
|
|
#if (LLVM_VERSION_MAJOR >= 3) && (LLVM_VERSION_MINOR >= 9)
|
|
|
|
|
_pp->EnterTokenStream(ArrayRef<Token>(start, len), false);
|
|
|
|
|
#else
|
|
|
|
|
_pp->EnterTokenStream(start, len, false, false);
|
|
|
|
|
#endif
|
|
|
|
|
do {
|
|
|
|
|
toks.push_back(Token());
|
|
|
|
|
Token &tk = toks.back();
|
|
|
|
|
_pp->Lex(tk);
|
|
|
|
|
} while (toks.back().isNot(tok::eof));
|
|
|
|
|
_pp->RemoveTopOfLexerStack();
|
|
|
|
|
// end of stolen code
|
|
|
|
|
for (auto tok : toks) {
|
|
|
|
|
if (tok.isAnyIdentifier()) {
|
|
|
|
|
StringRef name = tok.getIdentifierInfo()->getName();
|
|
|
|
|
const auto found = N.cuda2hipRename.find(name);
|
|
|
|
|
if (found != N.cuda2hipRename.end()) {
|
|
|
|
|
countReps[found->second.countType]++;
|
|
|
|
|
StringRef repName = found->second.hipName;
|
|
|
|
|
DEBUG(dbgs()
|
|
|
|
|
<< "Identifier " << name
|
|
|
|
|
<< " found as an actual argument in expansion of macro "
|
|
|
|
|
<< macroName << "\n"
|
|
|
|
|
<< "will be replaced with: " << repName << "\n");
|
|
|
|
|
SourceLocation sl = tok.getLocation();
|
|
|
|
|
Replacement Rep(*_sm, sl, name.size(), repName);
|
|
|
|
|
Replace->insert(Rep);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (tok.is(tok::string_literal)) {
|
|
|
|
|
StringRef s(tok.getLiteralData(), tok.getLength());
|
|
|
|
|
processString(unquoteStr(s), N, Replace, *_sm, tok.getLocation(),
|
|
|
|
|
countReps);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EndOfMainFile() override {}
|
|
|
|
|
|
|
|
|
|
bool SeenEnd;
|
|
|
|
|
void setSourceManager(SourceManager *sm) { _sm = sm; }
|
|
|
|
|
void setPreprocessor(Preprocessor *pp) { _pp = pp; }
|
|
|
|
|
|
|
|
|
|
int64_t countReps[ConvTypes::CONV_LAST] = {0};
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
SourceManager *_sm;
|
|
|
|
|
Preprocessor *_pp;
|
|
|
|
|
|
|
|
|
|
Replacements *Replace;
|
|
|
|
|
struct cuda2hipMap N;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class Cuda2HipCallback : public MatchFinder::MatchCallback {
|
|
|
|
|
public:
|
|
|
|
|
Cuda2HipCallback(Replacements *Replace, ast_matchers::MatchFinder *parent)
|
|
|
|
|
: Replace(Replace), owner(parent) {}
|
|
|
|
|
|
|
|
|
|
void convertKernelDecl(const FunctionDecl *kernelDecl,
|
|
|
|
|
const MatchFinder::MatchResult &Result) {
|
|
|
|
|
SourceManager *SM = Result.SourceManager;
|
|
|
|
|
LangOptions DefaultLangOptions;
|
|
|
|
|
|
|
|
|
|
SmallString<40> XStr;
|
|
|
|
|
raw_svector_ostream OS(XStr);
|
|
|
|
|
StringRef initialParamList;
|
|
|
|
|
OS << "hipLaunchParm lp";
|
|
|
|
|
size_t replacementLength = OS.str().size();
|
|
|
|
|
SourceLocation sl = kernelDecl->getNameInfo().getEndLoc();
|
|
|
|
|
SourceLocation kernelArgListStart = clang::Lexer::findLocationAfterToken(
|
|
|
|
|
sl, clang::tok::l_paren, *SM, DefaultLangOptions, true);
|
|
|
|
|
DEBUG(dbgs() << kernelArgListStart.printToString(*SM));
|
|
|
|
|
if (kernelDecl->getNumParams() > 0) {
|
|
|
|
|
const ParmVarDecl *pvdFirst = kernelDecl->getParamDecl(0);
|
|
|
|
|
const ParmVarDecl *pvdLast =
|
|
|
|
|
kernelDecl->getParamDecl(kernelDecl->getNumParams() - 1);
|
|
|
|
|
SourceLocation kernelArgListStart(pvdFirst->getLocStart());
|
|
|
|
|
SourceLocation kernelArgListEnd(pvdLast->getLocEnd());
|
|
|
|
|
SourceLocation stop = clang::Lexer::getLocForEndOfToken(
|
|
|
|
|
kernelArgListEnd, 0, *SM, DefaultLangOptions);
|
|
|
|
|
replacementLength +=
|
|
|
|
|
SM->getCharacterData(stop) - SM->getCharacterData(kernelArgListStart);
|
|
|
|
|
initialParamList = StringRef(SM->getCharacterData(kernelArgListStart),
|
|
|
|
|
replacementLength);
|
|
|
|
|
OS << ", " << initialParamList;
|
|
|
|
|
}
|
|
|
|
|
DEBUG(dbgs() << "initial paramlist: " << initialParamList << "\n"
|
|
|
|
|
<< "new paramlist: " << OS.str() << "\n");
|
|
|
|
|
Replacement Rep0(*(Result.SourceManager), kernelArgListStart,
|
|
|
|
|
replacementLength, OS.str());
|
|
|
|
|
Replace->insert(Rep0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void run(const MatchFinder::MatchResult &Result) override {
|
|
|
|
|
SourceManager *SM = Result.SourceManager;
|
|
|
|
|
LangOptions DefaultLangOptions;
|
|
|
|
|
|
|
|
|
|
if (const CallExpr *call =
|
|
|
|
|
Result.Nodes.getNodeAs<clang::CallExpr>("cudaCall")) {
|
|
|
|
|
const FunctionDecl *funcDcl = call->getDirectCallee();
|
|
|
|
|
StringRef name = funcDcl->getDeclName().getAsString();
|
|
|
|
|
const auto found = N.cuda2hipRename.find(name);
|
|
|
|
|
if (found != N.cuda2hipRename.end()) {
|
|
|
|
|
countReps[found->second.countType]++;
|
|
|
|
|
StringRef repName = found->second.hipName;
|
|
|
|
|
SourceLocation sl = call->getLocStart();
|
|
|
|
|
Replacement Rep(*SM, SM->isMacroArgExpansion(sl)
|
|
|
|
|
? SM->getImmediateSpellingLoc(sl)
|
|
|
|
|
: sl,
|
|
|
|
|
name.size(), repName);
|
|
|
|
|
Replace->insert(Rep);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (const CUDAKernelCallExpr *launchKernel =
|
|
|
|
|
Result.Nodes.getNodeAs<clang::CUDAKernelCallExpr>(
|
|
|
|
|
"cudaLaunchKernel")) {
|
|
|
|
|
SmallString<40> XStr;
|
|
|
|
|
raw_svector_ostream OS(XStr);
|
|
|
|
|
StringRef calleeName;
|
|
|
|
|
const FunctionDecl *kernelDecl = launchKernel->getDirectCallee();
|
|
|
|
|
if (kernelDecl) {
|
|
|
|
|
calleeName = kernelDecl->getName();
|
|
|
|
|
convertKernelDecl(kernelDecl, Result);
|
|
|
|
|
} else {
|
|
|
|
|
const Expr *e = launchKernel->getCallee();
|
|
|
|
|
if (const UnresolvedLookupExpr *ule =
|
|
|
|
|
dyn_cast<UnresolvedLookupExpr>(e)) {
|
|
|
|
|
calleeName = ule->getName().getAsIdentifierInfo()->getName();
|
|
|
|
|
owner->addMatcher(functionTemplateDecl(hasName(calleeName))
|
|
|
|
|
.bind("unresolvedTemplateName"),
|
|
|
|
|
this);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
XStr.clear();
|
|
|
|
|
OS << "hipLaunchKernel(HIP_KERNEL_NAME(" << calleeName << "),";
|
|
|
|
|
|
|
|
|
|
const CallExpr *config = launchKernel->getConfig();
|
|
|
|
|
DEBUG(dbgs() << "Kernel config arguments:"
|
|
|
|
|
<< "\n");
|
|
|
|
|
for (unsigned argno = 0; argno < config->getNumArgs(); argno++) {
|
|
|
|
|
const Expr *arg = config->getArg(argno);
|
|
|
|
|
if (!isa<CXXDefaultArgExpr>(arg)) {
|
|
|
|
|
const ParmVarDecl *pvd =
|
|
|
|
|
config->getDirectCallee()->getParamDecl(argno);
|
|
|
|
|
|
|
|
|
|
SourceLocation sl(arg->getLocStart());
|
|
|
|
|
SourceLocation el(arg->getLocEnd());
|
|
|
|
|
SourceLocation stop =
|
|
|
|
|
clang::Lexer::getLocForEndOfToken(el, 0, *SM, DefaultLangOptions);
|
|
|
|
|
StringRef outs(SM->getCharacterData(sl),
|
|
|
|
|
SM->getCharacterData(stop) - SM->getCharacterData(sl));
|
|
|
|
|
DEBUG(dbgs() << "args[ " << argno << "]" << outs << " <"
|
|
|
|
|
<< pvd->getType().getAsString() << ">"
|
|
|
|
|
<< "\n");
|
|
|
|
|
if (pvd->getType().getAsString().compare("dim3") == 0)
|
|
|
|
|
OS << " dim3(" << outs << "),";
|
|
|
|
|
else
|
|
|
|
|
OS << " " << outs << ",";
|
|
|
|
|
} else
|
|
|
|
|
OS << " 0,";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (unsigned argno = 0; argno < launchKernel->getNumArgs(); argno++) {
|
|
|
|
|
const Expr *arg = launchKernel->getArg(argno);
|
|
|
|
|
SourceLocation sl(arg->getLocStart());
|
|
|
|
|
SourceLocation el(arg->getLocEnd());
|
|
|
|
|
SourceLocation stop =
|
|
|
|
|
clang::Lexer::getLocForEndOfToken(el, 0, *SM, DefaultLangOptions);
|
|
|
|
|
std::string outs(SM->getCharacterData(sl),
|
|
|
|
|
SM->getCharacterData(stop) - SM->getCharacterData(sl));
|
|
|
|
|
DEBUG(dbgs() << outs << "\n");
|
|
|
|
|
OS << " " << outs << ",";
|
|
|
|
|
}
|
|
|
|
|
XStr.pop_back();
|
|
|
|
|
OS << ")";
|
|
|
|
|
size_t length =
|
|
|
|
|
SM->getCharacterData(clang::Lexer::getLocForEndOfToken(
|
|
|
|
|
launchKernel->getLocEnd(), 0, *SM, DefaultLangOptions)) -
|
|
|
|
|
SM->getCharacterData(launchKernel->getLocStart());
|
|
|
|
|
Replacement Rep(*SM, launchKernel->getLocStart(), length, OS.str());
|
|
|
|
|
Replace->insert(Rep);
|
|
|
|
|
countReps[ConvTypes::CONV_KERN]++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (const FunctionTemplateDecl *templateDecl =
|
|
|
|
|
Result.Nodes.getNodeAs<clang::FunctionTemplateDecl>(
|
|
|
|
|
"unresolvedTemplateName")) {
|
|
|
|
|
FunctionDecl *kernelDecl = templateDecl->getTemplatedDecl();
|
|
|
|
|
convertKernelDecl(kernelDecl, Result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (const MemberExpr *threadIdx =
|
|
|
|
|
Result.Nodes.getNodeAs<clang::MemberExpr>("cudaBuiltin")) {
|
|
|
|
|
if (const OpaqueValueExpr *refBase =
|
|
|
|
|
dyn_cast<OpaqueValueExpr>(threadIdx->getBase())) {
|
|
|
|
|
if (const DeclRefExpr *declRef =
|
|
|
|
|
dyn_cast<DeclRefExpr>(refBase->getSourceExpr())) {
|
|
|
|
|
StringRef name = declRef->getDecl()->getName();
|
|
|
|
|
StringRef memberName = threadIdx->getMemberDecl()->getName();
|
|
|
|
|
size_t pos = memberName.find_first_not_of("__fetch_builtin_");
|
|
|
|
|
memberName = memberName.slice(pos, memberName.size());
|
|
|
|
|
SmallString<128> tmpData;
|
|
|
|
|
name = Twine(name + "." + memberName).toStringRef(tmpData);
|
|
|
|
|
const auto found = N.cuda2hipRename.find(name);
|
|
|
|
|
if (found != N.cuda2hipRename.end()) {
|
|
|
|
|
countReps[found->second.countType]++;
|
|
|
|
|
StringRef repName = found->second.hipName;
|
|
|
|
|
SourceLocation sl = threadIdx->getLocStart();
|
|
|
|
|
Replacement Rep(*SM, sl, name.size(), repName);
|
|
|
|
|
Replace->insert(Rep);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (const DeclRefExpr *cudaEnumConstantRef =
|
|
|
|
|
Result.Nodes.getNodeAs<clang::DeclRefExpr>("cudaEnumConstantRef")) {
|
|
|
|
|
StringRef name = cudaEnumConstantRef->getDecl()->getNameAsString();
|
|
|
|
|
const auto found = N.cuda2hipRename.find(name);
|
|
|
|
|
if (found != N.cuda2hipRename.end()) {
|
|
|
|
|
countReps[found->second.countType]++;
|
|
|
|
|
StringRef repName = found->second.hipName;
|
|
|
|
|
SourceLocation sl = cudaEnumConstantRef->getLocStart();
|
|
|
|
|
Replacement Rep(*SM, sl, name.size(), repName);
|
|
|
|
|
Replace->insert(Rep);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (const VarDecl *cudaEnumConstantDecl =
|
|
|
|
|
Result.Nodes.getNodeAs<clang::VarDecl>("cudaEnumConstantDecl")) {
|
|
|
|
|
StringRef name =
|
|
|
|
|
cudaEnumConstantDecl->getType()->getAsTagDecl()->getNameAsString();
|
|
|
|
|
const auto found = N.cuda2hipRename.find(name);
|
|
|
|
|
if (found != N.cuda2hipRename.end()) {
|
|
|
|
|
countReps[found->second.countType]++;
|
|
|
|
|
StringRef repName = found->second.hipName;
|
|
|
|
|
SourceLocation sl = cudaEnumConstantDecl->getLocStart();
|
|
|
|
|
Replacement Rep(*SM, sl, name.size(), repName);
|
|
|
|
|
Replace->insert(Rep);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (const VarDecl *cudaStructVar =
|
|
|
|
|
Result.Nodes.getNodeAs<clang::VarDecl>("cudaStructVar")) {
|
|
|
|
|
StringRef name = cudaStructVar->getType()
|
|
|
|
|
->getAsStructureType()
|
|
|
|
|
->getDecl()
|
|
|
|
|
->getNameAsString();
|
|
|
|
|
const auto found = N.cuda2hipRename.find(name);
|
|
|
|
|
if (found != N.cuda2hipRename.end()) {
|
|
|
|
|
countReps[found->second.countType]++;
|
|
|
|
|
StringRef repName = found->second.hipName;
|
|
|
|
|
TypeLoc TL = cudaStructVar->getTypeSourceInfo()->getTypeLoc();
|
|
|
|
|
SourceLocation sl = TL.getUnqualifiedLoc().getLocStart();
|
|
|
|
|
Replacement Rep(*SM, sl, name.size(), repName);
|
|
|
|
|
Replace->insert(Rep);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (const VarDecl *cudaStructVarPtr =
|
|
|
|
|
Result.Nodes.getNodeAs<clang::VarDecl>("cudaStructVarPtr")) {
|
|
|
|
|
const Type *t = cudaStructVarPtr->getType().getTypePtrOrNull();
|
|
|
|
|
if (t) {
|
|
|
|
|
StringRef name = t->getPointeeCXXRecordDecl()->getName();
|
|
|
|
|
const auto found = N.cuda2hipRename.find(name);
|
|
|
|
|
if (found != N.cuda2hipRename.end()) {
|
|
|
|
|
countReps[found->second.countType]++;
|
|
|
|
|
StringRef repName = found->second.hipName;
|
|
|
|
|
TypeLoc TL = cudaStructVarPtr->getTypeSourceInfo()->getTypeLoc();
|
|
|
|
|
SourceLocation sl = TL.getUnqualifiedLoc().getLocStart();
|
|
|
|
|
Replacement Rep(*SM, sl, name.size(), repName);
|
|
|
|
|
Replace->insert(Rep);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (const ParmVarDecl *cudaParamDecl =
|
|
|
|
|
Result.Nodes.getNodeAs<clang::ParmVarDecl>("cudaParamDecl")) {
|
|
|
|
|
QualType QT = cudaParamDecl->getOriginalType().getUnqualifiedType();
|
|
|
|
|
StringRef name = QT.getAsString();
|
|
|
|
|
const Type *t = QT.getTypePtr();
|
|
|
|
|
if (t->isStructureOrClassType()) {
|
|
|
|
|
name = t->getAsCXXRecordDecl()->getName();
|
|
|
|
|
}
|
|
|
|
|
const auto found = N.cuda2hipRename.find(name);
|
|
|
|
|
if (found != N.cuda2hipRename.end()) {
|
|
|
|
|
countReps[found->second.countType]++;
|
|
|
|
|
StringRef repName = found->second.hipName;
|
|
|
|
|
TypeLoc TL = cudaParamDecl->getTypeSourceInfo()->getTypeLoc();
|
|
|
|
|
SourceLocation sl = TL.getUnqualifiedLoc().getLocStart();
|
|
|
|
|
Replacement Rep(*SM, sl, name.size(), repName);
|
|
|
|
|
Replace->insert(Rep);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (const ParmVarDecl *cudaParamDeclPtr =
|
|
|
|
|
Result.Nodes.getNodeAs<clang::ParmVarDecl>("cudaParamDeclPtr")) {
|
|
|
|
|
const Type *pt = cudaParamDeclPtr->getType().getTypePtrOrNull();
|
|
|
|
|
if (pt) {
|
|
|
|
|
QualType QT = pt->getPointeeType();
|
|
|
|
|
const Type *t = QT.getTypePtr();
|
|
|
|
|
StringRef name = t->isStructureOrClassType()
|
|
|
|
|
? t->getAsCXXRecordDecl()->getName()
|
|
|
|
|
: StringRef(QT.getAsString());
|
|
|
|
|
const auto found = N.cuda2hipRename.find(name);
|
|
|
|
|
if (found != N.cuda2hipRename.end()) {
|
|
|
|
|
countReps[found->second.countType]++;
|
|
|
|
|
StringRef repName = found->second.hipName;
|
|
|
|
|
TypeLoc TL = cudaParamDeclPtr->getTypeSourceInfo()->getTypeLoc();
|
|
|
|
|
SourceLocation sl = TL.getUnqualifiedLoc().getLocStart();
|
|
|
|
|
Replacement Rep(*SM, sl, name.size(), repName);
|
|
|
|
|
Replace->insert(Rep);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (const StringLiteral *stringLiteral =
|
|
|
|
|
Result.Nodes.getNodeAs<clang::StringLiteral>("stringLiteral")) {
|
|
|
|
|
if (stringLiteral->getCharByteWidth() == 1) {
|
|
|
|
|
StringRef s = stringLiteral->getString();
|
|
|
|
|
processString(s, N, Replace, *SM, stringLiteral->getLocStart(),
|
|
|
|
|
countReps);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (const UnaryExprOrTypeTraitExpr *expr =
|
|
|
|
|
Result.Nodes.getNodeAs<clang::UnaryExprOrTypeTraitExpr>(
|
|
|
|
|
"cudaStructSizeOf")) {
|
|
|
|
|
TypeSourceInfo *typeInfo = expr->getArgumentTypeInfo();
|
|
|
|
|
QualType QT = typeInfo->getType().getUnqualifiedType();
|
|
|
|
|
const Type *type = QT.getTypePtr();
|
|
|
|
|
StringRef name = type->getAsCXXRecordDecl()->getName();
|
|
|
|
|
const auto found = N.cuda2hipRename.find(name);
|
|
|
|
|
if (found != N.cuda2hipRename.end()) {
|
|
|
|
|
countReps[found->second.countType]++;
|
|
|
|
|
StringRef repName = found->second.hipName;
|
|
|
|
|
TypeLoc TL = typeInfo->getTypeLoc();
|
|
|
|
|
SourceLocation sl = TL.getUnqualifiedLoc().getLocStart();
|
|
|
|
|
Replacement Rep(*SM, sl, name.size(), repName);
|
|
|
|
|
Replace->insert(Rep);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int64_t countReps[ConvTypes::CONV_LAST] = {0};
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
Replacements *Replace;
|
|
|
|
|
ast_matchers::MatchFinder *owner;
|
|
|
|
|
struct cuda2hipMap N;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
} // end anonymous namespace
|
|
|
|
|
|
|
|
|
|
// Set up the command line options
|
|
|
|
|
static cl::OptionCategory
|
|
|
|
|
ToolTemplateCategory("CUDA to HIP source translator options");
|
|
|
|
|
static cl::extrahelp MoreHelp("<source0> specify the path of source file\n\n");
|
|
|
|
|
|
|
|
|
|
static cl::opt<std::string> OutputFilename("o", cl::desc("Output filename"),
|
|
|
|
|
cl::value_desc("filename"),
|
|
|
|
|
cl::cat(ToolTemplateCategory));
|
|
|
|
|
|
|
|
|
|
static cl::opt<bool>
|
|
|
|
|
Inplace("inplace",
|
|
|
|
|
cl::desc("Modify input file inplace, replacing input with hipified "
|
|
|
|
|
"output, save backup in .prehip file. "),
|
|
|
|
|
cl::value_desc("inplace"), cl::cat(ToolTemplateCategory));
|
|
|
|
|
|
|
|
|
|
static cl::opt<bool>
|
|
|
|
|
NoOutput("no-output",
|
|
|
|
|
cl::desc("don't write any translated output to stdout"),
|
|
|
|
|
cl::value_desc("no-output"), cl::cat(ToolTemplateCategory));
|
|
|
|
|
static cl::opt<bool>
|
|
|
|
|
PrintStats("print-stats", cl::desc("print the command-line, like a header"),
|
|
|
|
|
cl::value_desc("print-stats"), cl::cat(ToolTemplateCategory));
|
|
|
|
|
|
|
|
|
|
int main(int argc, const char **argv) {
|
|
|
|
|
|
|
|
|
|
llvm::sys::PrintStackTraceOnErrorSignal();
|
|
|
|
|
|
|
|
|
|
int Result;
|
|
|
|
|
|
|
|
|
|
CommonOptionsParser OptionsParser(argc, argv, ToolTemplateCategory,
|
|
|
|
|
llvm::cl::Required);
|
|
|
|
|
std::string dst = OutputFilename;
|
|
|
|
|
std::vector<std::string> fileSources = OptionsParser.getSourcePathList();
|
|
|
|
|
if (dst.empty()) {
|
|
|
|
|
dst = fileSources[0];
|
|
|
|
|
if (!Inplace) {
|
|
|
|
|
size_t pos = dst.rfind(".cu");
|
|
|
|
|
if (pos != std::string::npos) {
|
|
|
|
|
dst = dst.substr(0, pos) + ".hip.cu";
|
|
|
|
|
} else {
|
|
|
|
|
llvm::errs() << "Input .cu file was not specified.\n";
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (Inplace) {
|
|
|
|
|
llvm::errs() << "Conflict: both -o and -inplace options are specified.";
|
|
|
|
|
}
|
|
|
|
|
dst += ".cu";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// copy source file since tooling makes changes "inplace"
|
|
|
|
|
std::ifstream source(fileSources[0], std::ios::binary);
|
|
|
|
|
std::ofstream dest(Inplace ? dst + ".prehip" : dst, std::ios::binary);
|
|
|
|
|
dest << source.rdbuf();
|
|
|
|
|
source.close();
|
|
|
|
|
dest.close();
|
|
|
|
|
|
|
|
|
|
RefactoringTool Tool(OptionsParser.getCompilations(), dst);
|
|
|
|
|
ast_matchers::MatchFinder Finder;
|
|
|
|
|
Cuda2HipCallback Callback(&Tool.getReplacements(), &Finder);
|
|
|
|
|
HipifyPPCallbacks PPCallbacks(&Tool.getReplacements());
|
|
|
|
|
Finder.addMatcher(callExpr(isExpansionInMainFile(),
|
|
|
|
|
callee(functionDecl(matchesName("cuda.*"))))
|
|
|
|
|
.bind("cudaCall"),
|
|
|
|
|
&Callback);
|
|
|
|
|
Finder.addMatcher(cudaKernelCallExpr().bind("cudaLaunchKernel"), &Callback);
|
|
|
|
|
Finder.addMatcher(memberExpr(isExpansionInMainFile(),
|
|
|
|
|
hasObjectExpression(hasType(cxxRecordDecl(
|
|
|
|
|
matchesName("__cuda_builtin_")))))
|
|
|
|
|
.bind("cudaBuiltin"),
|
|
|
|
|
&Callback);
|
|
|
|
|
Finder.addMatcher(declRefExpr(isExpansionInMainFile(),
|
|
|
|
|
to(enumConstantDecl(matchesName("cuda.*"))))
|
|
|
|
|
.bind("cudaEnumConstantRef"),
|
|
|
|
|
&Callback);
|
|
|
|
|
Finder.addMatcher(
|
|
|
|
|
varDecl(isExpansionInMainFile(), hasType(enumDecl(matchesName("cuda.*"))))
|
|
|
|
|
.bind("cudaEnumConstantDecl"),
|
|
|
|
|
&Callback);
|
|
|
|
|
Finder.addMatcher(varDecl(isExpansionInMainFile(),
|
|
|
|
|
hasType(cxxRecordDecl(matchesName("cuda.*"))))
|
|
|
|
|
.bind("cudaStructVar"),
|
|
|
|
|
&Callback);
|
|
|
|
|
Finder.addMatcher(
|
|
|
|
|
varDecl(isExpansionInMainFile(),
|
|
|
|
|
hasType(pointsTo(cxxRecordDecl(matchesName("cuda.*")))))
|
|
|
|
|
.bind("cudaStructVarPtr"),
|
|
|
|
|
&Callback);
|
|
|
|
|
Finder.addMatcher(parmVarDecl(isExpansionInMainFile(),
|
|
|
|
|
hasType(namedDecl(matchesName("cuda.*"))))
|
|
|
|
|
.bind("cudaParamDecl"),
|
|
|
|
|
&Callback);
|
|
|
|
|
Finder.addMatcher(
|
|
|
|
|
parmVarDecl(isExpansionInMainFile(),
|
|
|
|
|
hasType(pointsTo(namedDecl(matchesName("cuda.*")))))
|
|
|
|
|
.bind("cudaParamDeclPtr"),
|
|
|
|
|
&Callback);
|
|
|
|
|
Finder.addMatcher(expr(isExpansionInMainFile(),
|
|
|
|
|
sizeOfExpr(hasArgumentOfType(recordType(hasDeclaration(
|
|
|
|
|
cxxRecordDecl(matchesName("cuda.*")))))))
|
|
|
|
|
.bind("cudaStructSizeOf"),
|
|
|
|
|
&Callback);
|
|
|
|
|
Finder.addMatcher(
|
|
|
|
|
stringLiteral(isExpansionInMainFile()).bind("stringLiteral"), &Callback);
|
|
|
|
|
|
|
|
|
|
auto action = newFrontendActionFactory(&Finder, &PPCallbacks);
|
|
|
|
|
|
|
|
|
|
std::vector<const char *> compilationStages;
|
|
|
|
|
compilationStages.push_back("--cuda-host-only");
|
|
|
|
|
//compilationStages.push_back("--cuda-device-only");
|
|
|
|
|
|
|
|
|
|
for (auto Stage : compilationStages) {
|
|
|
|
|
Tool.appendArgumentsAdjuster(
|
|
|
|
|
getInsertArgumentAdjuster(Stage, ArgumentInsertPosition::BEGIN));
|
|
|
|
|
Tool.appendArgumentsAdjuster(getInsertArgumentAdjuster("-std=c++11"));
|
|
|
|
|
#if defined(HIPIFY_CLANG_RES)
|
|
|
|
|
Tool.appendArgumentsAdjuster(
|
|
|
|
|
getInsertArgumentAdjuster("-resource-dir=" HIPIFY_CLANG_RES));
|
|
|
|
|
#endif
|
|
|
|
|
Tool.appendArgumentsAdjuster(getClangSyntaxOnlyAdjuster());
|
|
|
|
|
Result = Tool.run(action.get());
|
|
|
|
|
|
|
|
|
|
Tool.clearArgumentsAdjusters();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LangOptions DefaultLangOptions;
|
|
|
|
|
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
|
|
|
|
|
TextDiagnosticPrinter DiagnosticPrinter(llvm::errs(), &*DiagOpts);
|
|
|
|
|
DiagnosticsEngine Diagnostics(
|
|
|
|
|
IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts,
|
|
|
|
|
&DiagnosticPrinter, false);
|
|
|
|
|
SourceManager Sources(Diagnostics, Tool.getFiles());
|
|
|
|
|
|
|
|
|
|
DEBUG(dbgs() << "Replacements collected by the tool:\n");
|
|
|
|
|
for (const auto &r : Tool.getReplacements()) {
|
|
|
|
|
DEBUG(dbgs() << r.toString() << "\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Rewriter Rewrite(Sources, DefaultLangOptions);
|
|
|
|
|
|
|
|
|
|
if (!Tool.applyAllReplacements(Rewrite)) {
|
|
|
|
|
DEBUG(dbgs() << "Skipped some replacements.\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Result = Rewrite.overwriteChangedFiles();
|
|
|
|
|
|
|
|
|
|
if (!Inplace) {
|
|
|
|
|
size_t pos = dst.rfind(".cu");
|
|
|
|
|
if (pos != std::string::npos) {
|
|
|
|
|
rename(dst.c_str(), dst.substr(0, pos).c_str());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (PrintStats) {
|
|
|
|
|
int64_t sum = 0;
|
|
|
|
|
for (int i = 0; i < ConvTypes::CONV_LAST; i++) {
|
|
|
|
|
sum += Callback.countReps[i] + PPCallbacks.countReps[i];
|
|
|
|
|
}
|
|
|
|
|
llvm::outs() << "info: converted " << sum << " CUDA->HIP refs ( ";
|
|
|
|
|
for (int i = 0; i < ConvTypes::CONV_LAST; i++) {
|
|
|
|
|
llvm::outs() << counterNames[i] << ':'
|
|
|
|
|
<< Callback.countReps[i] + PPCallbacks.countReps[i] << ' ';
|
|
|
|
|
}
|
|
|
|
|
llvm::outs() << ") in \'" << fileSources[0] << "\'\n";
|
|
|
|
|
}
|
|
|
|
|
return Result;
|
|
|
|
|
}
|