1*9880d681SAndroid Build Coastguard Worker //===- StreamWrite.cpp - Writes bytes and objects to a stream -------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker
10*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/CodeView/StreamWriter.h"
11*9880d681SAndroid Build Coastguard Worker
12*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/CodeView/CodeViewError.h"
13*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/CodeView/StreamReader.h"
14*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/CodeView/StreamRef.h"
15*9880d681SAndroid Build Coastguard Worker
16*9880d681SAndroid Build Coastguard Worker using namespace llvm;
17*9880d681SAndroid Build Coastguard Worker using namespace llvm::codeview;
18*9880d681SAndroid Build Coastguard Worker
StreamWriter(StreamRef S)19*9880d681SAndroid Build Coastguard Worker StreamWriter::StreamWriter(StreamRef S) : Stream(S), Offset(0) {}
20*9880d681SAndroid Build Coastguard Worker
writeBytes(ArrayRef<uint8_t> Buffer)21*9880d681SAndroid Build Coastguard Worker Error StreamWriter::writeBytes(ArrayRef<uint8_t> Buffer) {
22*9880d681SAndroid Build Coastguard Worker if (auto EC = Stream.writeBytes(Offset, Buffer))
23*9880d681SAndroid Build Coastguard Worker return EC;
24*9880d681SAndroid Build Coastguard Worker Offset += Buffer.size();
25*9880d681SAndroid Build Coastguard Worker return Error::success();
26*9880d681SAndroid Build Coastguard Worker }
27*9880d681SAndroid Build Coastguard Worker
writeInteger(uint16_t Int)28*9880d681SAndroid Build Coastguard Worker Error StreamWriter::writeInteger(uint16_t Int) {
29*9880d681SAndroid Build Coastguard Worker return writeObject(support::ulittle16_t(Int));
30*9880d681SAndroid Build Coastguard Worker }
31*9880d681SAndroid Build Coastguard Worker
writeInteger(uint32_t Int)32*9880d681SAndroid Build Coastguard Worker Error StreamWriter::writeInteger(uint32_t Int) {
33*9880d681SAndroid Build Coastguard Worker return writeObject(support::ulittle32_t(Int));
34*9880d681SAndroid Build Coastguard Worker }
35*9880d681SAndroid Build Coastguard Worker
writeZeroString(StringRef Str)36*9880d681SAndroid Build Coastguard Worker Error StreamWriter::writeZeroString(StringRef Str) {
37*9880d681SAndroid Build Coastguard Worker if (auto EC = writeFixedString(Str))
38*9880d681SAndroid Build Coastguard Worker return EC;
39*9880d681SAndroid Build Coastguard Worker if (auto EC = writeObject('\0'))
40*9880d681SAndroid Build Coastguard Worker return EC;
41*9880d681SAndroid Build Coastguard Worker
42*9880d681SAndroid Build Coastguard Worker return Error::success();
43*9880d681SAndroid Build Coastguard Worker }
44*9880d681SAndroid Build Coastguard Worker
writeFixedString(StringRef Str)45*9880d681SAndroid Build Coastguard Worker Error StreamWriter::writeFixedString(StringRef Str) {
46*9880d681SAndroid Build Coastguard Worker ArrayRef<uint8_t> Bytes(Str.bytes_begin(), Str.bytes_end());
47*9880d681SAndroid Build Coastguard Worker if (auto EC = Stream.writeBytes(Offset, Bytes))
48*9880d681SAndroid Build Coastguard Worker return EC;
49*9880d681SAndroid Build Coastguard Worker
50*9880d681SAndroid Build Coastguard Worker Offset += Str.size();
51*9880d681SAndroid Build Coastguard Worker return Error::success();
52*9880d681SAndroid Build Coastguard Worker }
53*9880d681SAndroid Build Coastguard Worker
writeStreamRef(StreamRef Ref)54*9880d681SAndroid Build Coastguard Worker Error StreamWriter::writeStreamRef(StreamRef Ref) {
55*9880d681SAndroid Build Coastguard Worker if (auto EC = writeStreamRef(Ref, Ref.getLength()))
56*9880d681SAndroid Build Coastguard Worker return EC;
57*9880d681SAndroid Build Coastguard Worker Offset += Ref.getLength();
58*9880d681SAndroid Build Coastguard Worker return Error::success();
59*9880d681SAndroid Build Coastguard Worker }
60*9880d681SAndroid Build Coastguard Worker
writeStreamRef(StreamRef Ref,uint32_t Length)61*9880d681SAndroid Build Coastguard Worker Error StreamWriter::writeStreamRef(StreamRef Ref, uint32_t Length) {
62*9880d681SAndroid Build Coastguard Worker Ref = Ref.slice(0, Length);
63*9880d681SAndroid Build Coastguard Worker
64*9880d681SAndroid Build Coastguard Worker StreamReader SrcReader(Ref);
65*9880d681SAndroid Build Coastguard Worker // This is a bit tricky. If we just call readBytes, we are requiring that it
66*9880d681SAndroid Build Coastguard Worker // return us the entire stream as a contiguous buffer. For large streams this
67*9880d681SAndroid Build Coastguard Worker // will allocate a huge amount of space from the pool. Instead, iterate over
68*9880d681SAndroid Build Coastguard Worker // each contiguous chunk until we've consumed the entire stream.
69*9880d681SAndroid Build Coastguard Worker while (SrcReader.bytesRemaining() > 0) {
70*9880d681SAndroid Build Coastguard Worker ArrayRef<uint8_t> Chunk;
71*9880d681SAndroid Build Coastguard Worker if (auto EC = SrcReader.readLongestContiguousChunk(Chunk))
72*9880d681SAndroid Build Coastguard Worker return EC;
73*9880d681SAndroid Build Coastguard Worker if (auto EC = writeBytes(Chunk))
74*9880d681SAndroid Build Coastguard Worker return EC;
75*9880d681SAndroid Build Coastguard Worker }
76*9880d681SAndroid Build Coastguard Worker return Error::success();
77*9880d681SAndroid Build Coastguard Worker }
78