Skip to content

Commit f51d824

Browse files
authored
Merge pull request #426 from jmittert/FreeFileContents
Handling Memory Across the API Boundary
2 parents 06a2553 + a9ad54a commit f51d824

File tree

6 files changed

+81
-17
lines changed

6 files changed

+81
-17
lines changed

examples/c-api/buildsystem/main.c

+43-7
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
#include <string.h>
2323

2424
#include <sys/stat.h>
25+
#if defined(_WIN32)
26+
#include <windows.h>
27+
#endif
2528

2629
static const char* progname;
2730
static void usage() {
@@ -34,6 +37,27 @@ static const char* basename(const char* path) {
3437
return result ? result : path;
3538
}
3639

40+
#if defined(_WIN32)
41+
static wchar_t* convertToMultiByte(const char* s) {
42+
int numChars = MultiByteToWideChar(
43+
/*CodePage=*/CP_UTF8,
44+
/*dwFlags=*/0,
45+
/*lpMultibyteStr=*/s,
46+
/*cbMultiByte=*/-1,
47+
/*lpWideCharStr=*/NULL,
48+
/*ccWideChar=*/0);
49+
wchar_t* mbs = malloc(numChars * sizeof(wchar_t));
50+
MultiByteToWideChar(
51+
/*CodePage=*/CP_UTF8,
52+
/*dwFlags=*/0,
53+
/*lpMultibyteStr=*/s,
54+
/*cbMultiByte=*/-1,
55+
/*lpWideCharStr=*/mbs,
56+
/*ccWideChar=*/numChars);
57+
return mbs;
58+
}
59+
#endif
60+
3761
// "Fancy" Command Implementation
3862

3963
static bool
@@ -61,18 +85,30 @@ fancy_tool_create_command(void *context, const llb_data_t* name) {
6185

6286
static bool fs_get_file_contents(void* context, const char* path,
6387
llb_data_t* data_out) {
88+
89+
#if defined(_WIN32)
90+
wchar_t* wPath = convertToMultiByte(path);
91+
wprintf(L" -- read file contents: %ls\n", wPath);
92+
fflush(stdout);
93+
FILE* fp;
94+
if (_wfopen_s(&fp, wPath, L"rb")) {
95+
free(wPath);
96+
return false;
97+
}
98+
free(wPath);
99+
#else
64100
printf(" -- read file contents: %s\n", path);
65101
fflush(stdout);
66-
67102
FILE *fp = fopen(path, "rb");
68103
if (!fp) {
69104
return false;
70105
}
71-
106+
#endif
107+
72108
fseek(fp, 0, SEEK_END);
73109
long size = ftell(fp);
74110
fseek(fp, 0, SEEK_SET);
75-
uint8_t* buffer = malloc(size);
111+
uint8_t* buffer = (uint8_t*)llb_alloc(size);
76112
if (!buffer) {
77113
return false;
78114
}
@@ -107,7 +143,7 @@ static void fs_get_file_info(void* context, const char* path,
107143
static llb_buildsystem_tool_t* lookup_tool(void *context,
108144
const llb_data_t* name) {
109145
if (name->length == 5 && memcmp(name->data, "fancy", 5) == 0) {
110-
llb_buildsystem_tool_delegate_t delegate = {};
146+
llb_buildsystem_tool_delegate_t delegate = {0};
111147
delegate.create_command = fancy_tool_create_command;
112148
return llb_buildsystem_tool_create(name, delegate);
113149
}
@@ -136,7 +172,7 @@ static void command_started(void* context,
136172
llb_buildsystem_command_get_name(command, &name);
137173
printf("%s: %.*s -- %s\n", __FUNCTION__, (int)name.length, name.data,
138174
description);
139-
free(description);
175+
llb_free(description);
140176
fflush(stdout);
141177
}
142178

@@ -192,12 +228,12 @@ int main(int argc, char **argv) {
192228
const char* buildFilePath = argv[1];
193229

194230
// Create an invocation.
195-
llb_buildsystem_invocation_t invocation = {};
231+
llb_buildsystem_invocation_t invocation = {0};
196232
invocation.buildFilePath = buildFilePath;
197233
invocation.useSerialBuild = true;
198234

199235
// Create a build system delegate.
200-
llb_buildsystem_delegate_t delegate = {};
236+
llb_buildsystem_delegate_t delegate = {0};
201237
delegate.context = NULL;
202238
delegate.fs_get_file_contents = fs_get_file_contents;
203239
delegate.fs_get_file_info = fs_get_file_info;

lib/Basic/Subprocess.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,9 @@ void llbuild::basic::spawnProcess(
416416
// gets pulled in.
417417
std::for_each(std::begin(argsStorage) + 1, std::end(argsStorage),
418418
[&args](auto arg) { args += arg + " "; });
419-
args.pop_back();
419+
if (!args.empty()) {
420+
args.pop_back();
421+
}
420422
// Convert the command line string to utf16
421423
llvm::SmallVector<UTF16, 20> u16Executable;
422424
llvm::SmallVector<UTF16, 20> u16CmdLine;
@@ -603,6 +605,7 @@ void llbuild::basic::spawnProcess(
603605
if (!res.getError()) {
604606
argsStorage[0] = *res;
605607
#if defined(_WIN32)
608+
u16Executable.clear();
606609
llvm::convertUTF8ToUTF16String(argsStorage[0], u16Executable);
607610
#else
608611
args[0] = argsStorage[0].c_str();

products/libllbuild/BuildSystem-C-API.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -932,3 +932,5 @@ void llb_set_quality_of_service(llb_quality_of_service_t level) {
932932
}
933933
}
934934

935+
void* llb_alloc(size_t size) { return malloc(size); }
936+
void llb_free(void* ptr) { free(ptr); }

products/libllbuild/include/llbuild/buildsystem.h

+13-2
Original file line numberDiff line numberDiff line change
@@ -254,11 +254,11 @@ typedef struct llb_buildsystem_delegate_t_ {
254254
///
255255
/// \\returns True on success (the directory was created, or already exists).
256256
bool (*fs_create_directory)(void* context, const char* path);
257-
257+
258258
/// Get the file contents for the given path.
259259
///
260260
/// The contents *MUST* be returned in a new buffer allocated with \see
261-
/// malloc().
261+
/// llb_alloc().
262262
///
263263
/// Xparam path The path to provide the contents for.
264264
///
@@ -735,7 +735,18 @@ llb_get_scheduler_lane_width();
735735
/// be automatically translated into the number of cores detected on the host.
736736
LLBUILD_EXPORT void
737737
llb_set_scheduler_lane_width(uint32_t width);
738+
/// @}
738739

740+
/// @name Memory APIs
741+
// MARK: Allocating and freeing memory
742+
/// Allocate memory usable by the build system
743+
/// \param size The number bytes to allocate
744+
LLBUILD_EXPORT void*
745+
llb_alloc(size_t size);
746+
/// Free memory allocated for or by the build system
747+
/// \param ptr A pointer to the allocated memory to free
748+
LLBUILD_EXPORT void
749+
llb_free(void* ptr);
739750
/// @}
740751

741752
#endif

tests/Examples/buildsystem-capi.llbuild

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# RUN: env LD_LIBRARY_PATH=%{llbuild-lib-dir} %t.exe %s > %t.out
55
# RUN: %{FileCheck} %s --input-file %t.out
66
#
7-
# CHECK: -- read file contents: {{.*}}/buildsystem-capi.llbuild
7+
# CHECK: -- read file contents: {{.*[/\\]}}buildsystem-capi.llbuild
88
# CHECK: initial build:
99
# CHECK: -- stat: /
1010
# CHECK: command_started: <hello> -- HELLO

unittests/CAPI/BuildSystem-C-API.cpp

+18-6
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
#include "llbuild/llbuild.h"
1413
#include "llbuild/Basic/PlatformUtility.h"
14+
#include "llbuild/llbuild.h"
1515
#include "llbuild/buildsystem.h"
16+
#include "llvm/Support/ConvertUTF.h"
1617
#include <stdlib.h>
1718
#include <string.h>
1819

@@ -119,7 +120,7 @@ depinfo_tester_command_execute_command(void *context,
119120
writeFileContents(depInfoPath, depInfoContents);
120121

121122
// Clean up.
122-
free(desc);
123+
llb_free(desc);
123124
return true;
124125
}
125126

@@ -134,18 +135,29 @@ depinfo_tester_tool_create_command(void *context, const llb_data_t* name) {
134135

135136
static bool fs_get_file_contents(void* context, const char* path,
136137
llb_data_t* data_out) {
138+
#if defined(_WIN32)
139+
llvm::SmallVector<UTF16, 20> wPath;
140+
llvm::convertUTF8ToUTF16String(path, wPath);
141+
wprintf(L" -- read file contents: %ls\n", (LPCWSTR)wPath.data());
142+
fflush(stdout);
143+
FILE* fp;
144+
if (_wfopen_s(&fp, (LPCWSTR)wPath.data(), L"rb")) {
145+
return false;
146+
}
147+
#else
137148
printf(" -- read file contents: %s\n", path);
138149
fflush(stdout);
139-
150+
140151
FILE *fp = fopen(path, "rb");
141152
if (!fp) {
142153
return false;
143154
}
144-
155+
#endif
156+
145157
fseek(fp, 0, SEEK_END);
146158
long size = ftell(fp);
147159
fseek(fp, 0, SEEK_SET);
148-
uint8_t* buffer = (uint8_t *)malloc(size);
160+
uint8_t* buffer = (uint8_t*)llb_alloc(size);
149161
if (!buffer) {
150162
return false;
151163
}
@@ -209,7 +221,7 @@ static void command_started(void* context,
209221
llb_buildsystem_command_get_name(command, &name);
210222
printf("%s: %.*s -- %s\n", __FUNCTION__, (int)name.length, name.data,
211223
description);
212-
free(description);
224+
llb_free(description);
213225
fflush(stdout);
214226
}
215227

0 commit comments

Comments
 (0)