Skip to content

Commit 9dd9c36

Browse files
committed
Repo Update
- Added libLLVMReset() to libLLVM.API. - Added Reset() class method to TLLVM class, which uses libLLVMReset() to reset LLVM back to a known state. - All the LinkXXX routines in TLLMetaLang class now call TLLVM.Reset() after calling LLDLink to clean up "dirty" global state left by LLD. - Add RunExe class method to TLLUtils class - Updated UTestbed until to allow you to test the dll/exe created from Test #17, which will be Tests #18, and #19 respectively - Other misc. fixes and enhancements
1 parent aeb3fdc commit 9dd9c36

File tree

7 files changed

+126
-19
lines changed

7 files changed

+126
-19
lines changed

examples/testbed/UTestbed.pas

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,20 +43,33 @@ implementation
4343
libLLVM.Test.ObjectCompilation,
4444
libLLVM.Test.MetaLang;
4545

46-
// Test add_two_numbers DLL created by Test #17, make sure you run it first
46+
// Test add_two_numbers.dll created by Test #17, make sure you run it first
4747
{$WARN SYMBOL_PLATFORM OFF}
4848
function add_two_numbers(a, b: int32): int32; cdecl; external 'simple_math.dll' delayed;
4949
{$WARN SYMBOL_PLATFORM ON}
5050
procedure test_add_two_numbers_dll();
5151
begin
5252
if not TFile.Exists('simple_math.dll') then
5353
begin
54-
raise Exception.Create('You must run Test #17 first');
54+
raise Exception.Create('add_two_numbers.dll not found, you must run Test #17 first!');
5555
end;
5656

57+
TLLUtils.PrintLn('Running simple_math.dll...');
5758
TLLUtils.PrintLn('10 + 10 = %d', [add_two_numbers(10, 10)]);
5859
end;
5960

61+
// Test hello_world.exe created by Test #17, make sure you run it first
62+
procedure test_hello_world_exe();
63+
begin
64+
if not TFile.Exists('hello_world.exe') then
65+
begin
66+
raise Exception.Create('hello_world.exe not found, you must run Test #17 first!');
67+
end;
68+
69+
TLLUtils.PrintLn('Running hello_world.exe...');
70+
TLLUtils.RunExe('hello_world.exe', '', '')
71+
end;
72+
6073
procedure RunTests();
6174
var
6275
LNum: UInt32;
@@ -87,14 +100,15 @@ procedure RunTests();
87100
16: TTestObjectCompilation.RunAllTests();
88101
17: TTestMetaLang.RunAllTests();
89102
18: test_add_two_numbers_dll();
103+
19: test_hello_world_exe();
90104

91105
else
92106
TLLUtils.Print('Invalid test number.');
93107
end;
94108

95109
except
96110
on E: Exception do
97-
Writeln(E.ClassName, ': ', E.Message);
111+
TLLUtils.PrintLn('Fatal error: %s', [E.Message]);
98112
end;
99113

100114
TLLUtils.Pause();

src/libLLVM.API.pas

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{===============================================================================
1+
{===============================================================================
22
_ _ _ _ _ __ ____ __ ™
33
| (_) |__| | | |\ \ / / \/ |
44
| | | '_ \ |__| |_\ V /| |\/| |
@@ -2428,7 +2428,7 @@ LLVMOrcCLookupSetElement = record
24282428
LLVMDisposePassBuilderOptions: procedure(Options: LLVMPassBuilderOptionsRef); cdecl;
24292429
LLD_Link: function(argc: Integer; argv: PPUTF8Char; const flavor: PUTF8Char; canRunAgain: PInteger): Integer; cdecl;
24302430

2431-
procedure GetExports(const aDLLHandle: THandle);
2431+
procedure libLLVMReset();
24322432

24332433
implementation
24342434

@@ -3771,6 +3771,12 @@ procedure UnloadDLL();
37713771
end;
37723772
end;
37733773

3774+
procedure libLLVMReset();
3775+
begin
3776+
UnloadDLL();
3777+
LoadDLL();
3778+
end;
3779+
37743780
initialization
37753781
begin
37763782
// turn on memory leak detection

src/libLLVM.LLD.pas

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@ implementation
108108
WinApi.Windows,
109109
System.SysUtils,
110110
System.Classes,
111-
libLLVM.API;
111+
libLLVM.API,
112+
libLLVM;
112113

113114
type
114115
TPipeReader = class(TThread)
@@ -355,6 +356,7 @@ function LLDLink(const AArgs: array of string; const AFlavor: string;
355356
// Close read ends
356357
CloseHandle(OutRead);
357358
CloseHandle(ErrRead);
359+
358360
end;
359361
except
360362
on E: Exception do

src/libLLVM.MetaLang.pas

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1218,10 +1218,10 @@ function TLLMetaLang.LinkToDLL(
12181218
// Call LLD linker
12191219
LCan := False;
12201220
AResult := LLDLink(LArgs, 'coff', AStdOut, AStdErr, LCan);
1221-
1222-
// Reset JIT after linking to clear LLD's persistent state
1223-
//FLLVM.ResetJIT(AModuleId);
1224-
1221+
1222+
// clean up after LLD call
1223+
TLLVM.Reset();
1224+
12251225
Result := Self;
12261226
end;
12271227

@@ -1287,7 +1287,8 @@ function TLLMetaLang.LinkToExecutable(
12871287
LCan := False;
12881288
AResult := LLDLink(LArgs, 'coff', AStdOut, AStdErr, LCan);
12891289

1290-
writeln(LCan);
1290+
// clean up after LLD call
1291+
TLLVM.Reset();
12911292

12921293
Result := Self;
12931294
end;
@@ -1412,7 +1413,10 @@ function TLLMetaLang.LinkModuleToDLL(
14121413
// Call LLD linker
14131414
LCan := False;
14141415
AResult := LLDLink(LArgs, 'coff', AStdOut, AStdErr, LCan);
1415-
1416+
1417+
// clean up after LLD call
1418+
TLLVM.Reset();
1419+
14161420
Result := Self;
14171421
end;
14181422

@@ -1572,7 +1576,10 @@ function TLLMetaLang.LinkAllModulesToDLL(
15721576
// Call LLD linker
15731577
LCan := False;
15741578
AResult := LLDLink(LArgs, 'coff', AStdOut, AStdErr, LCan);
1575-
1579+
1580+
// clean up after LLD call
1581+
TLLVM.Reset();
1582+
15761583
Result := Self;
15771584
end;
15781585

src/libLLVM.Utils.pas

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,9 @@ TLLUtils = class
8787
class procedure Pause(); static;
8888

8989
class function AsUTF8(const AValue: string; ALength: PCardinal=nil): Pointer; static;
90+
91+
class function RunExe(const AExe, AParams, AWorkDir: string; const AWait: Boolean = True; const AShowCmd: Word = SW_SHOWNORMAL): Cardinal; static;
92+
9093
end;
9194

9295
implementation
@@ -537,6 +540,72 @@ class function TLLUtils.AsUTF8(const AValue: string; ALength: PCardinal): Pointe
537540
ALength^ := System.AnsiStrings.StrLen(PAnsiChar(Result));
538541
end;
539542

543+
class function TLLUtils.RunExe(const AExe, AParams, AWorkDir: string; const AWait: Boolean; const AShowCmd: Word): Cardinal;
544+
var
545+
LCmd: UnicodeString;
546+
LSI: STARTUPINFOW;
547+
LPI: PROCESS_INFORMATION;
548+
LWorkDir: PWideChar;
549+
LExit: DWORD;
550+
LCreationFlags: DWORD;
551+
begin
552+
Result := 0;
553+
554+
if AExe = '' then
555+
raise Exception.Create('RunExe: Executable path is empty');
556+
557+
if AParams <> '' then
558+
LCmd := '"' + AExe + '" ' + AParams
559+
else
560+
LCmd := '"' + AExe + '"';
561+
562+
UniqueString(LCmd); // CreateProcess may modify the buffer
563+
564+
ZeroMemory(@LSI, SizeOf(LSI));
565+
ZeroMemory(@LPI, SizeOf(LPI));
566+
LSI.cb := SizeOf(LSI);
567+
LSI.dwFlags := STARTF_USESHOWWINDOW;
568+
LSI.wShowWindow := AShowCmd;
569+
570+
if AWorkDir <> '' then
571+
LWorkDir := PWideChar(AWorkDir)
572+
else
573+
LWorkDir := nil;
574+
575+
LCreationFlags := CREATE_UNICODE_ENVIRONMENT;
576+
577+
if not CreateProcessW(
578+
nil, // lpApplicationName
579+
PWideChar(LCmd), // lpCommandLine (mutable)
580+
nil, // lpProcessAttributes
581+
nil, // lpThreadAttributes
582+
False, // bInheritHandles
583+
LCreationFlags, // dwCreationFlags
584+
nil, // lpEnvironment
585+
LWorkDir, // lpCurrentDirectory
586+
LSI, // lpStartupInfo
587+
LPI // lpProcessInformation
588+
) then
589+
raise Exception.CreateFmt('RunExe: CreateProcess failed (%d) %s', [GetLastError, SysErrorMessage(GetLastError)]);
590+
591+
try
592+
if AWait then
593+
begin
594+
WaitForSingleObject(LPI.hProcess, INFINITE);
595+
LExit := 0;
596+
if GetExitCodeProcess(LPI.hProcess, LExit) then
597+
Result := LExit
598+
else
599+
raise Exception.CreateFmt('RunExe: GetExitCodeProcess failed (%d) %s', [GetLastError, SysErrorMessage(GetLastError)]);
600+
end
601+
else
602+
Result := 0;
603+
finally
604+
CloseHandle(LPI.hThread);
605+
CloseHandle(LPI.hProcess);
606+
end;
607+
end;
608+
540609
initialization
541610
begin
542611
TLLUtils.InitConsole();

src/libLLVM.pas

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ TLLVM = class
199199
constructor Create();
200200
destructor Destroy(); override;
201201

202+
class procedure Reset(); static;
202203
class function GetVersionStr(): string; static;
203204
class function GetLLVMVersionStr(): string; static;
204205

@@ -433,6 +434,7 @@ class procedure TLLVM.Shutdown();
433434
LLVMShutdown();
434435
end;
435436

437+
436438
constructor TLLVM.Create;
437439
begin
438440
inherited Create();
@@ -490,6 +492,13 @@ destructor TLLVM.Destroy;
490492
inherited Destroy();
491493
end;
492494

495+
class procedure TLLVM.Reset();
496+
begin
497+
Shutdown();
498+
libLLVMReset();
499+
Startup();
500+
end;
501+
493502
class function TLLVM.GetVersionStr(): string;
494503
begin
495504
Result := Format('%d.%d.%d', [libLLVM_MAJOR, libLLVM_MINOR, libLLVM_PATCH])

src/tests/libLLVM.Test.MetaLang.pas

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ interface
2121
System.IOUtils,
2222
libLLVM.Utils,
2323
libLLVM,
24-
libLLVM.MetaLang;
24+
libLLVM.MetaLang,
25+
libLLVM.API;
2526

2627
type
2728
{ TTestMetaLang }
@@ -55,6 +56,10 @@ class procedure TTestMetaLang.RunAllTests();
5556
begin
5657
TLLUtils.PrintLn('Running libLLVM.Test.MetaLang...');
5758

59+
// Comprehensive examples
60+
TestComprehensiveMathDLL();
61+
TestComprehensiveHelloWorld();
62+
5863
// Simple focused tests
5964
TestModuleCreation();
6065
TestBasicFunction();
@@ -68,11 +73,6 @@ class procedure TTestMetaLang.RunAllTests();
6873
TestMemoryOperations();
6974
TestExportedFunction();
7075

71-
// Comprehensive examples
72-
TestComprehensiveMathDLL();
73-
TestComprehensiveHelloWorld();
74-
75-
7676
TLLUtils.PrintLn('libLLVM.Test.MetaLang completed.');
7777
end;
7878

0 commit comments

Comments
 (0)