Skip to content

Commit 25efdd3

Browse files
committed
[SYCL] Support BYTE_ARRAY property in the offload wrapper.
Signed-off-by: Konstantin S Bobrovsky <[email protected]>
1 parent 29dea8d commit 25efdd3

File tree

2 files changed

+120
-25
lines changed

2 files changed

+120
-25
lines changed

clang/test/Driver/clang-offload-wrapper-exe.cpp

Lines changed: 103 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,22 @@
44
// works, and that the tool generates data properly accessible at runtime.
55

66
// --- Prepare test data
7-
// RUN: echo -e -n 'device binary image\n' > %t.bin
7+
// - create the first binary image
8+
// RUN: echo -e -n 'device binary image1\n' > %t.bin
89
// RUN: echo -e -n '[Category1]\nint_prop1=1|10\n[Category2]\nint_prop2=1|20\n' > %t.props
910
// RUN: echo -e -n 'kernel1\nkernel2\n' > %t.sym
1011
// RUN: echo -e -n 'Manifest file - arbitrary data generated by the toolchain\n' > %t.mnf
12+
13+
// - create the second binary image with byte array property values
14+
// RUN: echo -e -n 'device binary image2\n' > %t_1.bin
15+
// RUN: echo -e -n '[Category3]\n' > %t_1.props
16+
// RUN: echo -e -n 'kernel1=2|IAAAAAAAAAQA\n' >> %t_1.props
17+
// RUN: echo -e -n 'kernel2=2|oAAAAAAAAAw///3/wB\n' >> %t_1.props
18+
19+
// - create the batch file input for the wrapper
1120
// RUN: echo '[Code|Properties|Symbols|Manifest]' > %t.batch
1221
// RUN: echo %t.bin"|"%t.props"|"%t.sym"|"%t.mnf >> %t.batch
22+
// RUN: echo %t_1.bin"|"%t_1.props"|""|" >> %t.batch
1323
// --- Generate "gold" output
1424
// RUN: cat %t.bin %t.mnf %t.props %t.sym > %t.all
1525
// --- Create the wrapper object
@@ -22,6 +32,8 @@
2232
// RUN: %t.batch.exe > %t.batch.exe.out
2333
// RUN: diff -b %t.batch.exe.out %t.all
2434

35+
#include <assert.h>
36+
#include <cstring>
2537
#include <iostream>
2638
#include <string>
2739

@@ -105,31 +117,97 @@ static int getInt(void *Addr) {
105117
return Ptr[0] | (Ptr[1] << 8) | (Ptr[2] << 16) | (Ptr[3] << 24);
106118
}
107119

108-
int main(int argc, char **argv) {
109-
ASSERT(BinDesc->NumDeviceBinaries == 1, "BinDesc->NumDeviceBinaries");
110-
ASSERT(BinDesc->Version == 1, "BinDesc->Version");
120+
using byte = unsigned char;
121+
122+
static void printProp(const pi_device_binary_property &Prop) {
123+
std::cerr << "Property " << Prop->Name << " {\n";
124+
std::cerr << " Type: " << Prop->Type << "\n";
125+
if (Prop->Type != 1)
126+
std::cerr << " Size = " << Prop->ValSize << "\n";
127+
128+
std::cerr << " Value = ";
129+
if (Prop->Type == 1)
130+
std::cerr << getInt(&Prop->ValSize);
131+
else {
132+
std::cerr << " {\n ";
111133

112-
for (int I = 0; I < BinDesc->NumDeviceBinaries; ++I) {
113-
pi_device_binary Bin = &BinDesc->DeviceBinaries[I];
114-
ASSERT(Bin->Kind == 4, "Bin->Kind");
115-
ASSERT(Bin->Format == 1, "Bin->Format");
116-
117-
// dump code
118-
std::cout << getString(Bin->BinaryStart, Bin->BinaryEnd);
119-
// dump manifest
120-
std::cout << std::string(Bin->ManifestStart, Bin->ManifestEnd - Bin->ManifestStart);
121-
// dump properties
122-
for (pi_device_binary_property_set PropSet = Bin->PropertySetsBegin; PropSet != Bin->PropertySetsEnd; ++PropSet) {
123-
std::cout << "[" << PropSet->Name << "]"
124-
<< "\n";
125-
126-
for (pi_device_binary_property Prop = PropSet->PropertiesBegin; Prop != PropSet->PropertiesEnd; ++Prop)
127-
// values fitting into 64 bits are written into the 'ValAddr' field:
128-
std::cout << Prop->Name << "=" << Prop->Type << "|" << getInt(&Prop->ValSize) << "\n";
134+
byte *Ptr = (byte *)Prop->ValAddr;
135+
136+
for (auto I = 0; I < Prop->ValSize && I < 100; ++I) {
137+
std::cerr << " 0x" << std::hex << (unsigned int)Ptr[I];
138+
std::cerr << std::dec;
139+
}
140+
std::cerr << "\n }";
141+
}
142+
std::cerr << "\n";
143+
std::cerr << "}\n";
144+
}
145+
146+
static int dumpBinary0() {
147+
pi_device_binary Bin = &BinDesc->DeviceBinaries[0];
148+
ASSERT(Bin->Kind == 4, "Bin->Kind");
149+
ASSERT(Bin->Format == 1, "Bin->Format");
150+
151+
// dump code
152+
std::cout << getString(Bin->BinaryStart, Bin->BinaryEnd);
153+
// dump manifest
154+
std::cout << std::string(Bin->ManifestStart, Bin->ManifestEnd - Bin->ManifestStart);
155+
// dump properties
156+
for (pi_device_binary_property_set PropSet = Bin->PropertySetsBegin; PropSet != Bin->PropertySetsEnd; ++PropSet) {
157+
std::cout << "[" << PropSet->Name << "]"
158+
<< "\n";
159+
160+
for (pi_device_binary_property Prop = PropSet->PropertiesBegin; Prop != PropSet->PropertiesEnd; ++Prop) {
161+
ASSERT(Prop->Type == 1, "Prop->Type");
162+
std::cout << Prop->Name << "=" << Prop->Type << "|" << getInt(&Prop->ValSize) << "\n";
129163
}
130-
// dump symbols
131-
for (_pi_offload_entry Entry = Bin->EntriesBegin; Entry != Bin->EntriesEnd; ++Entry)
132-
std::cout << Entry->name << "\n";
133164
}
165+
// dump symbols
166+
for (_pi_offload_entry Entry = Bin->EntriesBegin; Entry != Bin->EntriesEnd; ++Entry)
167+
std::cout << Entry->name << "\n";
134168
return 0;
135-
}
169+
}
170+
171+
// Clang offload wrapper does Base64 decoding on byte array property values, so
172+
// they can't be dumped as is and compared to the original. Instead, this
173+
// testcase checks that the byte array in the property value is equal to the
174+
// pre-decoded byte array.
175+
static int checkBinary1() {
176+
// Decoded from "IAAAAAAAAAQA":
177+
const byte Arr0[] = {8, 0, 0, 0, 0, 0, 0, 0, 0x1};
178+
// Decoded from "oAAAAAAAAAw///3/wB":
179+
const byte Arr1[] = {40, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0x7F, 0xFF, 0x70};
180+
181+
struct {
182+
const byte *Ptr;
183+
const size_t Size;
184+
} GoldArrays[] = {
185+
{Arr0, sizeof(Arr0)},
186+
{Arr1, sizeof(Arr1)}};
187+
pi_device_binary Bin = &BinDesc->DeviceBinaries[1];
188+
ASSERT(Bin->Kind == 4, "Bin->Kind");
189+
ASSERT(Bin->Format == 1, "Bin->Format");
190+
191+
for (pi_device_binary_property_set PropSet = Bin->PropertySetsBegin; PropSet != Bin->PropertySetsEnd; ++PropSet) {
192+
int Cnt = 0;
193+
194+
for (pi_device_binary_property Prop = PropSet->PropertiesBegin; Prop != PropSet->PropertiesEnd; ++Prop, ++Cnt) {
195+
ASSERT(Prop->Type == 2, "Prop->Type"); // must be a byte array
196+
char *Ptr = reinterpret_cast<char *>(Prop->ValAddr);
197+
int Cmp = std::memcmp(Prop->ValAddr, GoldArrays[Cnt].Ptr, GoldArrays[Cnt].Size);
198+
ASSERT(Cmp == 0, "byte array property");
199+
}
200+
}
201+
return 0;
202+
}
203+
204+
int main(int argc, char **argv) {
205+
ASSERT(BinDesc->NumDeviceBinaries == 2, "BinDesc->NumDeviceBinaries");
206+
ASSERT(BinDesc->Version == 1, "BinDesc->Version");
207+
208+
if (dumpBinary0() != 0)
209+
return 1;
210+
if (checkBinary1() != 0)
211+
return 1;
212+
return 0;
213+
}

clang/tools/clang-offload-wrapper/ClangOffloadWrapper.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,15 @@ class BinaryWrapper {
610610
return std::make_pair(ImageB, ImageE);
611611
}
612612

613+
// Adds given data buffer as constant byte array and returns a constant
614+
// pointer to it. The pointer type does not carry size information.
615+
Constant *addRawDataToModule(ArrayRef<char> Data, const Twine &Name) {
616+
auto *Var = addGlobalArrayVariable(Name, Data);
617+
auto *DataPtr = ConstantExpr::getGetElementPtr(Var->getValueType(), Var,
618+
getSizetConstPair(0u, 0u));
619+
return DataPtr;
620+
}
621+
613622
// Creates all necessary data objects for the given image and returns a pair
614623
// of pointers that point to the beginning and end of the global variable that
615624
// contains the image data.
@@ -718,6 +727,14 @@ class BinaryWrapper {
718727
ConstantInt::get(Type::getInt64Ty(C), Prop.second.asUint32());
719728
break;
720729
}
730+
case llvm::util::PropertyValue::BYTE_ARRAY: {
731+
const char *Ptr =
732+
reinterpret_cast<const char *>(Prop.second.asRawByteArray());
733+
uint64_t Size = Prop.second.getRawByteArraySize();
734+
PropValSize = ConstantInt::get(Type::getInt64Ty(C), Size);
735+
PropValAddr = addRawDataToModule(ArrayRef<char>(Ptr, Size), "prop_val");
736+
break;
737+
}
721738
default:
722739
llvm_unreachable_internal("unsupported property");
723740
}

0 commit comments

Comments
 (0)