LLVM: lib/ObjectYAML/GOFFEmitter.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
19
20using namespace llvm;
21
22namespace {
23
24
25enum {
26
27 Rec_Continued = 1,
28
29
30 Rec_Continuation = 1 << (8 - 6 - 1),
31};
32
33template struct BinaryBeImpl {
35 BinaryBeImpl(ValueType V) : Value(V) {}
36};
37
38template
40 char Buffer[sizeof(BBE.Value)];
43 OS.write(Buffer, sizeof(BBE.Value));
44 return OS;
45}
46
47template BinaryBeImpl binaryBe(ValueType V) {
48 return BinaryBeImpl(V);
49}
50
51struct ZerosImpl {
52 size_t NumBytes;
53};
54
57 return OS;
58}
59
60ZerosImpl zeros(const size_t NumBytes) { return ZerosImpl{NumBytes}; }
61
62
63
64
65
66
68public:
69 explicit GOFFOstream(raw_ostream &OS)
70 : OS(OS), LogicalRecords(0), RemainingSize(0), NewLogicalRecord(false) {
72 }
73
74 ~GOFFOstream() override { finalize(); }
75
77 fillRecord();
78 CurrentType = Type;
79 RemainingSize = Size;
82 NewLogicalRecord = true;
83 ++LogicalRecords;
84 }
85
86 void finalize() { fillRecord(); }
87
88 uint32_t logicalRecords() { return LogicalRecords; }
89
90private:
91
92 raw_ostream &OS;
93
94
95 uint32_t LogicalRecords;
96
97
98 size_t RemainingSize;
99
100
102
103
104 bool NewLogicalRecord;
105
106
107
108
109 size_t bytesToNextPhysicalRecord() {
112 }
113
114
115
117 size_t RemainingSize,
118 uint8_t Flags = Rec_Continuation) {
119 uint8_t TypeAndFlags = Flags | (Type << 4);
121 TypeAndFlags |= Rec_Continued;
122 OS << binaryBe(static_cast(GOFF::PTVPrefix))
123 << binaryBe(static_cast<unsigned char>(TypeAndFlags))
124 << binaryBe(static_cast<unsigned char>(0));
125 }
126
127
128 void fillRecord() {
129 assert((GetNumBytesInBuffer() <= RemainingSize) &&
130 "More bytes in buffer than expected");
131 size_t Remains = RemainingSize - GetNumBytesInBuffer();
132 if (Remains) {
134 "Attempting to fill more than one physical record");
136 }
137 flush();
138 assert(RemainingSize == 0 && "Not fully flushed");
139 assert(GetNumBytesInBuffer() == 0 && "Buffer not fully empty");
140 }
141
142
143 void write_impl(const char *Ptr, size_t Size) override {
144 assert((RemainingSize >= Size) && "Attempt to write too much data");
145 assert(RemainingSize && "Logical record overflow");
147 writeRecordPrefix(OS, CurrentType, RemainingSize,
148 NewLogicalRecord ? 0 : Rec_Continuation);
149 NewLogicalRecord = false;
150 }
151 assert(!NewLogicalRecord &&
152 "New logical record not on physical record boundary");
153
154 size_t Idx = 0;
155 while (Size > 0) {
156 size_t BytesToWrite = bytesToNextPhysicalRecord();
157 if (BytesToWrite > Size)
158 BytesToWrite = Size;
159 OS.write(Ptr + Idx, BytesToWrite);
160 Idx += BytesToWrite;
161 Size -= BytesToWrite;
162 RemainingSize -= BytesToWrite;
164 writeRecordPrefix(OS, CurrentType, RemainingSize);
165 }
166 }
167 }
168
169
170
171 uint64_t current_pos() const override { return OS.tell(); }
172};
173
174class GOFFState {
175 void writeHeader(GOFFYAML::FileHeader &FileHdr);
176 void writeEnd();
177
179 ErrHandler(Msg);
180 HasError = true;
181 }
182
183 GOFFState(raw_ostream &OS, GOFFYAML::Object &Doc,
185 : GW(OS), Doc(Doc), ErrHandler(ErrHandler), HasError(false) {}
186
187 ~GOFFState() { GW.finalize(); }
188
189 bool writeObject();
190
191public:
192 static bool writeGOFF(raw_ostream &OS, GOFFYAML::Object &Doc,
194
195private:
196 GOFFOstream GW;
197 GOFFYAML::Object &Doc;
199 bool HasError;
200};
201
203 SmallString<16> CCSIDName;
204 if (std::error_code EC =
207 if (CCSIDName.size() > 16) {
208 reportError("CharacterSetName too long");
209 CCSIDName.resize(16);
210 }
211 SmallString<16> LangProd;
215 if (LangProd.size() > 16) {
216 reportError("LanguageProductIdentifier too long");
218 }
219
223 << zeros(2)
224 << binaryBe(FileHdr.CCSID)
225 << CCSIDName
226 << zeros(16 - CCSIDName.size())
227 << LangProd
228 << zeros(16 - LangProd.size())
230
231 uint16_t ModPropLen = 0;
233 ModPropLen = 3;
235 ModPropLen = 2;
236 if (ModPropLen) {
237 GW << binaryBe(ModPropLen) << zeros(6);
238 if (ModPropLen >= 2)
239 GW << binaryBe(FileHdr.InternalCCSID.value_or(0));
240 if (ModPropLen >= 3)
242 }
243}
244
245void GOFFState::writeEnd() {
247 GW << binaryBe(uint8_t(0))
248 << binaryBe(uint8_t(0))
249 << zeros(3)
250 << binaryBe(GW.logicalRecords());
251
252 GW.finalize();
253}
254
255bool GOFFState::writeObject() {
256 writeHeader(Doc.Header);
257 if (HasError)
258 return false;
259 writeEnd();
260 return true;
261}
262
263bool GOFFState::writeGOFF(raw_ostream &OS, GOFFYAML::Object &Doc,
265 GOFFState State(OS, Doc, ErrHandler);
266 return State.writeObject();
267}
268}
269
270namespace llvm {
271namespace yaml {
272
275 return GOFFState::writeGOFF(Out, Doc, ErrHandler);
276}
277
278}
279}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Function Alias Analysis false
static Error reportError(StringRef Message)
zeros_impl< sizeof(T)> zeros(const T &)
This file provides utility functions for converting between EBCDIC-1047 and UTF-8.
This class implements an extremely fast bulk output stream that can only output to a stream.
raw_ostream & write_zeros(unsigned NumZeros)
write_zeros - Insert 'NumZeros' nulls.
raw_ostream & write(unsigned char C)
LLVM_ABI std::error_code convertToEBCDIC(StringRef Source, SmallVectorImpl< char > &Result)
constexpr uint8_t PayloadLength
constexpr uint8_t PTVPrefix
Prefix byte on every record. This indicates GOFF format.
constexpr uint8_t RecordLength
Length of the parts of a physical GOFF record.
void write(void *memory, value_type value, endianness endian)
Write a value to memory with a particular endianness.
LLVM_ABI bool yaml2goff(GOFFYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH)
Definition GOFFEmitter.cpp:273
llvm::function_ref< void(const Twine &Msg)> ErrorHandler
This is an optimization pass for GlobalISel generic memory operations.
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
PointerUnion< const Value *, const PseudoSourceValue * > ValueType
Common declarations for yaml2obj.