summaryrefslogtreecommitdiff
path: root/source/slang-record-replay/util
diff options
context:
space:
mode:
authorkaizhangNV <149626564+kaizhangNV@users.noreply.github.com>2024-07-23 10:45:26 -0500
committerGitHub <noreply@github.com>2024-07-23 08:45:26 -0700
commit986256ffb92ab7c8fc7cf9f2c424919a439a824f (patch)
tree260e37bd439275e3398d16fe238b20cd00d08cb7 /source/slang-record-replay/util
parentc28d8b6aec721fa3350fc52647f1572a353f6151 (diff)
Feature/capture (#4625)
* Add decoder * Add a replay executable to consume the decoded content Add file-processor.cpp/h where we implement the logic to process the captured file block by block. Each block is: function header + parameter buffer + function tailer + function output[optional]. After reading one block, the block of data is sent to decoder module to dispatch the corresponding API. Add slang-decoder.cpp/h where we implement the logic to dispatch the slang API according to the input block data. - Rename api_callId.h to capture-format.h - Renmae capture_utility.cpp to capture-utility.cpp - Renmae capture_utility.h to capture-utility.h - Change the #include file name accordingly. * Reorganize source files structure Move all the capture logic code into `capture` directory. - the capture code will be build with slang dll. Move all the replay logic code into `relay` directoy. - the replay code is not part of slang dll, it will be built as a stand alone binary and link against slang dll. Change the #include file names accordingly. Add tools/slang-replay/main.cpp for the slang-replay stand alone binary place holder. Will implement it later. Update premake5.lua accordingly. * Update cmake files Update cmake files to change the build process for capture and relay system. - capture component should be build with slang dll, so we should not include replay component. - replay component should be a separate executable tool, which should not include capture component. - In order to easy use our current cmake infrastructure, move the shared files to a `util` folder - change the header include path * Redesgin the interfaces of consumers Fix some issues in capture Finish implementing all slang-decoder functions * Fix the AppleClang build issue * Address few comments - Fix the weird indent issues. - Correct the function name for CreateGlobalSession() - Rename file-processor to captureFile-processor to be more specific. - Use Slang::List instead of std::vector * record/replay: name refactor change Refactor the naming. Change the name "encoder/capture" to "record".
Diffstat (limited to 'source/slang-record-replay/util')
-rw-r--r--source/slang-record-replay/util/record-format.h172
-rw-r--r--source/slang-record-replay/util/record-utility.cpp82
-rw-r--r--source/slang-record-replay/util/record-utility.h37
3 files changed, 291 insertions, 0 deletions
diff --git a/source/slang-record-replay/util/record-format.h b/source/slang-record-replay/util/record-format.h
new file mode 100644
index 000000000..d796abec6
--- /dev/null
+++ b/source/slang-record-replay/util/record-format.h
@@ -0,0 +1,172 @@
+#ifndef API_CALL_ID_H
+#define API_CALL_ID_H
+
+#include <cstdint>
+
+namespace SlangRecord
+{
+ constexpr uint32_t makeApiCallId(uint16_t classId, uint16_t memberFunctionId)
+ {
+ return ((static_cast<uint32_t>(classId) << 16) & 0xffff0000) | (static_cast<uint32_t>(memberFunctionId) & 0x0000ffff);
+ }
+
+ constexpr uint16_t getClassId(uint32_t callId)
+ {
+ return static_cast<uint16_t>((callId >> 16) & 0x0000ffff);
+ }
+
+ constexpr uint16_t getMemberFunctionId(uint32_t callId)
+ {
+ return static_cast<uint16_t>(callId & 0x0000ffff);
+ }
+
+ enum ApiClassId : uint16_t
+ {
+ GlobalFunction = 1,
+ Class_IGlobalSession = 2,
+ Class_ISession = 3,
+ Class_IModule = 4,
+ Class_IEntryPoint = 5,
+ Class_ICompositeComponentType = 6,
+ Class_ITypeConformance = 7,
+ };
+
+ // Store the pointer value in a 64-bit integer
+ typedef uint64_t AddressFormat;
+
+ // Use the address directly to represent the slang object.
+ typedef AddressFormat ObjectID;
+
+ constexpr uint64_t g_globalFunctionHandle = 0;
+ constexpr uint32_t MAGIC_HEADER = 0x44414548;
+ constexpr uint32_t MAGIC_TAILER = 0x4C494154;
+
+ enum ApiCallId : uint32_t
+ {
+ InvalidCallId = 0x00000000,
+ CreateGlobalSession = makeApiCallId(GlobalFunction, 0x0000),
+ IGlobalSession_createSession = makeApiCallId(Class_IGlobalSession, 0x0001),
+ IGlobalSession_findProfile = makeApiCallId(Class_IGlobalSession, 0x0002),
+ IGlobalSession_setDownstreamCompilerPath = makeApiCallId(Class_IGlobalSession, 0x0003),
+ IGlobalSession_setDownstreamCompilerPrelude = makeApiCallId(Class_IGlobalSession, 0x0004),
+ IGlobalSession_getDownstreamCompilerPrelude = makeApiCallId(Class_IGlobalSession, 0x0005),
+ IGlobalSession_getBuildTagString = makeApiCallId(Class_IGlobalSession, 0x0006),
+ IGlobalSession_setDefaultDownstreamCompiler = makeApiCallId(Class_IGlobalSession, 0x0007),
+ IGlobalSession_getDefaultDownstreamCompiler = makeApiCallId(Class_IGlobalSession, 0x0008),
+ IGlobalSession_setLanguagePrelude = makeApiCallId(Class_IGlobalSession, 0x0009),
+ IGlobalSession_getLanguagePrelude = makeApiCallId(Class_IGlobalSession, 0x000A),
+ IGlobalSession_createCompileRequest = makeApiCallId(Class_IGlobalSession, 0x000B),
+ IGlobalSession_addBuiltins = makeApiCallId(Class_IGlobalSession, 0x000C),
+ IGlobalSession_setSharedLibraryLoader = makeApiCallId(Class_IGlobalSession, 0x000D),
+ IGlobalSession_getSharedLibraryLoader = makeApiCallId(Class_IGlobalSession, 0x000E),
+ IGlobalSession_checkCompileTargetSupport = makeApiCallId(Class_IGlobalSession, 0x000F),
+ IGlobalSession_checkPassThroughSupport = makeApiCallId(Class_IGlobalSession, 0x0010),
+ IGlobalSession_compileStdLib = makeApiCallId(Class_IGlobalSession, 0x0011),
+ IGlobalSession_loadStdLib = makeApiCallId(Class_IGlobalSession, 0x0012),
+ IGlobalSession_saveStdLib = makeApiCallId(Class_IGlobalSession, 0x0013),
+ IGlobalSession_findCapability = makeApiCallId(Class_IGlobalSession, 0x0014),
+ IGlobalSession_setDownstreamCompilerForTransition = makeApiCallId(Class_IGlobalSession, 0x0015),
+ IGlobalSession_getDownstreamCompilerForTransition = makeApiCallId(Class_IGlobalSession, 0x0016),
+ IGlobalSession_getCompilerElapsedTime = makeApiCallId(Class_IGlobalSession, 0x0017),
+ IGlobalSession_setSPIRVCoreGrammar = makeApiCallId(Class_IGlobalSession, 0x0018),
+ IGlobalSession_parseCommandLineArguments = makeApiCallId(Class_IGlobalSession, 0x0019),
+ IGlobalSession_getSessionDescDigest = makeApiCallId(Class_IGlobalSession, 0x001A),
+
+ ISession_getGlobalSession = makeApiCallId(Class_ISession, 0x0001),
+ ISession_loadModule = makeApiCallId(Class_ISession, 0x0002),
+ ISession_loadModuleFromIRBlob = makeApiCallId(Class_ISession, 0x0004),
+ ISession_loadModuleFromSource = makeApiCallId(Class_ISession, 0x0005),
+ ISession_loadModuleFromSourceString = makeApiCallId(Class_ISession, 0x0006),
+ ISession_createCompositeComponentType = makeApiCallId(Class_ISession, 0x0007),
+ ISession_specializeType = makeApiCallId(Class_ISession, 0x0008),
+ ISession_getTypeLayout = makeApiCallId(Class_ISession, 0x0009),
+ ISession_getContainerType = makeApiCallId(Class_ISession, 0x000A),
+ ISession_getDynamicType = makeApiCallId(Class_ISession, 0x000B),
+ ISession_getTypeRTTIMangledName = makeApiCallId(Class_ISession, 0x000C),
+ ISession_getTypeConformanceWitnessMangledName = makeApiCallId(Class_ISession, 0x000D),
+ ISession_getTypeConformanceWitnessSequentialID = makeApiCallId(Class_ISession, 0x000E),
+ ISession_createTypeConformanceComponentType = makeApiCallId(Class_ISession, 0x000F),
+ ISession_createCompileRequest = makeApiCallId(Class_ISession, 0x0010),
+ ISession_getLoadedModuleCount = makeApiCallId(Class_ISession, 0x0011),
+ ISession_getLoadedModule = makeApiCallId(Class_ISession, 0x0012),
+ ISession_isBinaryModuleUpToDate = makeApiCallId(Class_ISession, 0x0013),
+
+ IModule_findEntryPointByName = makeApiCallId(Class_IModule, 0x0001),
+ IModule_getDefinedEntryPointCount = makeApiCallId(Class_IModule, 0x0002),
+ IModule_getDefinedEntryPoint = makeApiCallId(Class_IModule, 0x0003),
+ IModule_serialize = makeApiCallId(Class_IModule, 0x0004),
+ IModule_writeToFile = makeApiCallId(Class_IModule, 0x0005),
+ IModule_getName = makeApiCallId(Class_IModule, 0x0006),
+ IModule_getFilePath = makeApiCallId(Class_IModule, 0x0007),
+ IModule_getUniqueIdentity = makeApiCallId(Class_IModule, 0x0008),
+ IModule_findAndCheckEntryPoint = makeApiCallId(Class_IModule, 0x0009),
+ IModule_getSession = makeApiCallId(Class_IModule, 0x000A),
+ IModule_getLayout = makeApiCallId(Class_IModule, 0x000B),
+ IModule_getSpecializationParamCount = makeApiCallId(Class_IModule, 0x000C),
+ IModule_getEntryPointCode = makeApiCallId(Class_IModule, 0x000D),
+ IModule_getTargetCode = makeApiCallId(Class_IModule, 0x000E),
+ IModule_getResultAsFileSystem = makeApiCallId(Class_IModule, 0x000F),
+ IModule_getEntryPointHash = makeApiCallId(Class_IModule, 0x0010),
+ IModule_specialize = makeApiCallId(Class_IModule, 0x0011),
+ IModule_link = makeApiCallId(Class_IModule, 0x0012),
+ IModule_getEntryPointHostCallable = makeApiCallId(Class_IModule, 0x0013),
+ IModule_renameEntryPoint = makeApiCallId(Class_IModule, 0x0014),
+ IModule_linkWithOptions = makeApiCallId(Class_IModule, 0x0015),
+
+ IEntryPoint_getSession = makeApiCallId(Class_IEntryPoint, 0x0001),
+ IEntryPoint_getLayout = makeApiCallId(Class_IEntryPoint, 0x0002),
+ IEntryPoint_getSpecializationParamCount = makeApiCallId(Class_IEntryPoint, 0x0003),
+ IEntryPoint_getEntryPointCode = makeApiCallId(Class_IEntryPoint, 0x0004),
+ IEntryPoint_getTargetCode = makeApiCallId(Class_IEntryPoint, 0x0005),
+ IEntryPoint_getResultAsFileSystem = makeApiCallId(Class_IEntryPoint, 0x0006),
+ IEntryPoint_getEntryPointHash = makeApiCallId(Class_IEntryPoint, 0x0007),
+ IEntryPoint_specialize = makeApiCallId(Class_IEntryPoint, 0x0008),
+ IEntryPoint_link = makeApiCallId(Class_IEntryPoint, 0x0009),
+ IEntryPoint_getEntryPointHostCallable = makeApiCallId(Class_IEntryPoint, 0x000A),
+ IEntryPoint_renameEntryPoint = makeApiCallId(Class_IEntryPoint, 0x000B),
+ IEntryPoint_linkWithOptions = makeApiCallId(Class_IEntryPoint, 0x000C),
+
+ ICompositeComponentType_getSession = makeApiCallId(Class_ICompositeComponentType, 0x0001),
+ ICompositeComponentType_getLayout = makeApiCallId(Class_ICompositeComponentType, 0x0002),
+ ICompositeComponentType_getSpecializationParamCount = makeApiCallId(Class_ICompositeComponentType, 0x0003),
+ ICompositeComponentType_getEntryPointCode = makeApiCallId(Class_ICompositeComponentType, 0x0004),
+ ICompositeComponentType_getTargetCode = makeApiCallId(Class_ICompositeComponentType, 0x0005),
+ ICompositeComponentType_getResultAsFileSystem = makeApiCallId(Class_ICompositeComponentType, 0x0006),
+ ICompositeComponentType_getEntryPointHash = makeApiCallId(Class_ICompositeComponentType, 0x0007),
+ ICompositeComponentType_specialize = makeApiCallId(Class_ICompositeComponentType, 0x0008),
+ ICompositeComponentType_link = makeApiCallId(Class_ICompositeComponentType, 0x0009),
+ ICompositeComponentType_getEntryPointHostCallable = makeApiCallId(Class_ICompositeComponentType, 0x000A),
+ ICompositeComponentType_renameEntryPoint = makeApiCallId(Class_ICompositeComponentType, 0x000B),
+ ICompositeComponentType_linkWithOptions = makeApiCallId(Class_ICompositeComponentType, 0x000C),
+
+ ITypeConformance_getSession = makeApiCallId(Class_ITypeConformance, 0x0001),
+ ITypeConformance_getLayout = makeApiCallId(Class_ITypeConformance, 0x0002),
+ ITypeConformance_getSpecializationParamCount = makeApiCallId(Class_ITypeConformance, 0x0003),
+ ITypeConformance_getEntryPointCode = makeApiCallId(Class_ITypeConformance, 0x0004),
+ ITypeConformance_getTargetCode = makeApiCallId(Class_ITypeConformance, 0x0005),
+ ITypeConformance_getResultAsFileSystem = makeApiCallId(Class_ITypeConformance, 0x0006),
+ ITypeConformance_getEntryPointHash = makeApiCallId(Class_ITypeConformance, 0x0007),
+ ITypeConformance_specialize = makeApiCallId(Class_ITypeConformance, 0x0008),
+ ITypeConformance_link = makeApiCallId(Class_ITypeConformance, 0x0009),
+ ITypeConformance_getEntryPointHostCallable = makeApiCallId(Class_ITypeConformance, 0x000A),
+ ITypeConformance_renameEntryPoint = makeApiCallId(Class_ITypeConformance, 0x000B),
+ ITypeConformance_linkWithOptions = makeApiCallId(Class_ITypeConformance, 0x000C)
+ };
+
+ struct FunctionHeader
+ {
+ uint32_t magic {MAGIC_HEADER};
+ ApiCallId callId {InvalidCallId};
+ ObjectID handleId {0};
+ uint64_t dataSizeInBytes {0};
+ uint64_t threadId {0};
+ };
+
+ struct FunctionTailer
+ {
+ uint32_t magic {MAGIC_TAILER};
+ uint32_t dataSizeInBytes {0};
+ };
+
+}
+#endif
diff --git a/source/slang-record-replay/util/record-utility.cpp b/source/slang-record-replay/util/record-utility.cpp
new file mode 100644
index 000000000..8bf89ea67
--- /dev/null
+++ b/source/slang-record-replay/util/record-utility.cpp
@@ -0,0 +1,82 @@
+
+#include <cstring>
+#include <string>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <mutex>
+
+#include "record-utility.h"
+
+constexpr const char* kRecordLayerEnvVar = "SLANG_RECORD_LAYER";
+constexpr const char* kRecordLayerLogLevel = "SLANG_RECORD_LOG_LEVEL";
+
+namespace SlangRecord
+{
+ static thread_local unsigned int g_logLevel = LogLevel::Silent;
+
+ static bool getEnvironmentVariable(const char* name, std::string& out)
+ {
+#ifdef _WIN32
+ char* envVar = nullptr;
+ size_t sz = 0;
+ if (_dupenv_s(&envVar, &sz, name) == 0 && envVar != nullptr)
+ {
+ out = envVar;
+ free(envVar);
+ }
+#else
+ if (const char* envVar = std::getenv(name))
+ {
+ out = envVar;
+ }
+#endif
+ return out.empty() == false;
+ }
+
+ bool isRecordLayerEnabled()
+ {
+ std::string envVarStr;
+ if(getEnvironmentVariable(kRecordLayerEnvVar, envVarStr))
+ {
+ if (envVarStr == "1")
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ void setLogLevel()
+ {
+ // We only want to set the log level once
+ if (g_logLevel != LogLevel::Silent)
+ {
+ return;
+ }
+
+ std::string envVarStr;
+ if (getEnvironmentVariable(kRecordLayerLogLevel, envVarStr))
+ {
+ char* end = nullptr;
+ unsigned int logLevel = std::strtol(envVarStr.c_str(), &end, 10);
+ if (end && (*end == 0))
+ {
+ g_logLevel = std::min((unsigned int)(LogLevel::Verbose), logLevel);
+ return;
+ }
+ }
+ }
+
+ void slangRecordLog(LogLevel logLevel, const char* fmt, ...)
+ {
+ if (logLevel > g_logLevel)
+ {
+ return;
+ }
+
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(stdout, fmt, args);
+ va_end(args);
+ }
+}
diff --git a/source/slang-record-replay/util/record-utility.h b/source/slang-record-replay/util/record-utility.h
new file mode 100644
index 000000000..33156a1f6
--- /dev/null
+++ b/source/slang-record-replay/util/record-utility.h
@@ -0,0 +1,37 @@
+#ifndef RECORD_UTILITY_H
+#define RECORD_UTILITY_H
+
+// in gcc and clang, __PRETTY_FUNCTION__ is the function signature,
+// while MSVC uses __FUNCSIG__
+#ifdef _MSC_VER
+#define __PRETTY_FUNCTION__ __FUNCSIG__
+#endif
+
+namespace SlangRecord
+{
+ enum LogLevel: unsigned int
+ {
+ Silent = 0,
+ Error = 1,
+ Debug = 2,
+ Verbose = 3,
+ };
+
+ bool isRecordLayerEnabled();
+ void slangRecordLog(LogLevel logLevel, const char* fmt, ...);
+ void setLogLevel();
+}
+
+#define SLANG_RECORD_ASSERT(VALUE) \
+ do { \
+ if (!(VALUE)) { \
+ SlangRecord::slangRecordLog(SlangRecord::LogLevel::Error, "Assertion failed: %s, %s, %d\n", #VALUE, __FILE__, __LINE__);\
+ std::abort(); \
+ } \
+ } while(0)
+
+#define SLANG_RECORD_CHECK(VALUE) \
+ do { \
+ SLANG_RECORD_ASSERT((VALUE) == SLANG_OK); \
+ } while(0)
+#endif // RECORD_UTILITY_H