yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
7b570feed
master
1// This file contains a definition of LLVMFileCheck, an implementaion for 2// IFileCheck. 3 4#include "slang-com-helper.h" 5#include "slang-com-ptr.h" 6#include "slang.h" 7 8#include <core/slang-com-object.h> 9#include <llvm/ADT/SmallString.h> 10#include <llvm/FileCheck/FileCheck.h> 11#include <llvm/Support/raw_ostream.h> 12#include <slang-test/filecheck.h> 13 14namespace slang_llvm 15{ 16 17using namespace llvm ; 18using namespace Slang ; 19 20class LLVMFileCheck :IFileCheck ,ComBaseObject 21{ 22public : 23// ICastable 24virtual SLANG_NO_THROW void * SLANG_MCALL castAs (const Guid & guid )override ; 25 26// IUnknown 27SLANG_COM_BASE_IUNKNOWN_ALL 28void * getInterface (const Guid & guid ); 29void * getObject (const Guid & guid ); 30 31// IFileCheck 32virtual TestResult SLANG_MCALL performTest ( 33const char * programName , 34const char * rulesFilePath , 35const char * fileCheckPrefix , 36const char * stringToCheck , 37const char * stringToCheckName , 38ReportDiagnostic testReporter , 39void * reporterData , 40bool colorDiagnosticOutput )noexcept override ; 41 42private : 43// Everything we need to pass through LLVM back to our diagnostic handler 44struct ReporterData 45 { 46ReportDiagnostic reportFun ; 47// User data from the caller of performTest 48void * data ; 49bool colorDiagnosticOutput ; 50const char * programName ; 51TestMessageType testMessageType ; 52 }; 53 54static void fileCheckDiagHandler (const SMDiagnostic & diag ,void * reporterData ); 55}; 56 57class DisplayedStringOStream :public raw_string_ostream 58{ 59public : 60DisplayedStringOStream (std::string & s ) 61 :raw_string_ostream (s ) 62 { 63 } 64virtual bool is_displayed ()const override {return true; }; 65}; 66 67void LLVMFileCheck ::fileCheckDiagHandler (const SMDiagnostic & diag ,void * dataPtr ) 68{ 69const ReporterData & reporterData = * reinterpret_cast < ReporterData *> (dataPtr ); 70 std::string s ; 71DisplayedStringOStream o (s ); 72o .enable_colors (reporterData .colorDiagnosticOutput ); 73diag .reporterData .programName ,o ); 74reporterData .reportFun (reporterData .data ,TestMessageType ::TestFailure ,s .c_str ()); 75} 76 77TestResult LLVMFileCheck ::performTest ( 78const char * const programName , 79const char * const rulesFilePath , 80const char * const fileCheckPrefix , 81const char * const stringToCheck , 82const char * const stringToCheckName , 83const ReportDiagnostic testReporter , 84void * const userReporterData , 85const bool colorDiagnosticOutput )noexcept 86{ 87// 88// Set up our FileCheck session 89// 90FileCheckRequest fcReq ; 91fcReq .CheckPrefixes = {fileCheckPrefix }; 92FileCheck fc (fcReq ); 93 94// 95// Set up the LLVM source manager for diagnostic output from our input buffers 96// 97SourceMgr sourceManager ; 98auto rulesTextOrError = MemoryBuffer ::getFile (rulesFilePath , true); 99if (std::error_code err = rulesTextOrError .getError ()) 100 { 101const std::string message = "Unable to load FileCheck rules file: " + err .message (); 102testReporter (userReporterData ,TestMessageType ::RunError ,message .c_str ()); 103return TestResult ::Fail ; 104 } 105SmallString < 4096 > rulesBuffer ; 106StringRef rulesStringRef = fc .CanonicalizeFile (* rulesTextOrError .get (),rulesBuffer ); 107sourceManager .AddNewSourceBuffer ( 108MemoryBuffer ::getMemBuffer (rulesStringRef ,rulesFilePath ), 109SMLoc ()); 110 111SmallString < 4096 > inputBuffer ; 112const auto inputStringMB = 113MemoryBuffer ::getMemBuffer (StringRef (stringToCheck ),stringToCheckName , false); 114const StringRef inputStringRef = fc .CanonicalizeFile (* inputStringMB .get (),inputBuffer ); 115sourceManager .AddNewSourceBuffer ( 116MemoryBuffer ::getMemBuffer (inputStringRef ,stringToCheckName ), 117SMLoc ()); 118 119// Initialize this with a 'RunError' failure type. We'll "downgrade" this to 120// 'TestFailure' once we've done the FileCheck setup. 121ReporterData reporterData { 122testReporter , 123userReporterData , 124colorDiagnosticOutput , 125programName , 126TestMessageType ::RunError }; 127sourceManager .setDiagHandler (fileCheckDiagHandler ,static_cast < void *> (& reporterData )); 128 129auto checkPrefix = fc .buildCheckPrefixRegex (); 130if (fc .readCheckFile (sourceManager ,rulesStringRef ,checkPrefix )) 131 { 132// FileCheck failed to find or understand any FileCheck rules in 133// the input file, automatic fail, and reported to the diag handler . 134return TestResult ::Fail ; 135 } 136 137// We've done the FileCheck setup, so make sure that any diagnostics 138// reported on from here are just a regular test failure. 139reporterData .testMessageType = TestMessageType ::TestFailure ; 140if (!fc .checkInput (sourceManager ,inputStringRef )) 141 { 142// An ordinary failure, the FileCheck rules didn't match 143return TestResult ::Fail ; 144 } 145 146return TestResult ::Pass ; 147} 148 149void * LLVMFileCheck ::castAs (const Guid & guid ) 150{ 151if (auto ptr = getInterface (guid )) 152 { 153return ptr ; 154 } 155return getObject (guid ); 156} 157 158void * LLVMFileCheck ::getInterface (const Guid & guid ) 159{ 160if (guid == ISlangUnknown ::getTypeGuid ()|| guid == ICastable ::getTypeGuid ()|| 161guid == IFileCheck ::getTypeGuid ()) 162 { 163return static_cast < IFileCheck *> (this ); 164 } 165return nullptr ; 166} 167 168void * LLVMFileCheck ::getObject (const Guid & guid ) 169{ 170SLANG_UNUSED (guid ); 171return nullptr ; 172} 173 174}// namespace slang_llvm 175 176extern "C" SLANG_DLL_EXPORT SlangResult 177createLLVMFileCheck_V1 (const SlangUUID & intfGuid ,void ** out ) 178{ 179Slang ::ComPtr < slang_llvm::LLVMFileCheck > fileCheck (new slang_llvm::LLVMFileCheck ); 180 181if (auto ptr = fileCheck -> castAs (intfGuid )) 182 { 183fileCheck .detach (); 184* out = ptr ; 185return SLANG_OK ; 186 } 187 188return SLANG_E_NO_INTERFACE ; 189}