| /* |
| * Copyright 2012, The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #ifndef LLVM_WRAP_BCHEADER_FIELD_H__ |
| #define LLVM_WRAP_BCHEADER_FIELD_H__ |
| |
| #include <limits> |
| #include <stdint.h> |
| #include <stdio.h> |
| #include <string.h> |
| |
| // Class representing a variable-size metadata field in the bitcode header. |
| // Also contains the list of known Tag IDs. |
| // Contains a pointer to the data but does not own the data, so it can be |
| // copied with the trivial copy constructor/assignment operator. |
| |
| // The serialized format has 2 fixed subfields (ID and length) and the |
| // variable-length data subfield |
| class BCHeaderField { |
| public: |
| typedef enum { |
| kInvalid = 0, |
| kBitcodeHash = 1, |
| kAndroidCompilerVersion = 0x4001, |
| kAndroidOptimizationLevel = 0x4002 |
| } Tag; |
| typedef uint16_t FixedSubfield; |
| |
| BCHeaderField(Tag ID, size_t len, uint8_t* data) : |
| ID_(ID), len_(len), data_(data) {} |
| size_t GetTotalSize() { |
| // Round up to 4 byte alignment |
| return (kTagLenSize + len_ + 3) & ~3; |
| } |
| |
| bool Write(uint8_t* buf, size_t buf_len) { |
| size_t fields_len = kTagLenSize + len_; |
| size_t pad_len = (4 - (fields_len & 3)) & 3; |
| // Ensure buffer is large enough and that length can be represented |
| // in 16 bits |
| if (buf_len < fields_len + pad_len || |
| len_ > std::numeric_limits<FixedSubfield>::max()) return false; |
| |
| WriteFixedSubfield(static_cast<FixedSubfield>(ID_), buf); |
| WriteFixedSubfield(static_cast<FixedSubfield>(len_), |
| buf + sizeof(FixedSubfield)); |
| memcpy(buf + kTagLenSize, data_, len_); |
| // Pad out to 4 byte alignment |
| if (pad_len) { |
| memset(buf + fields_len, 0, pad_len); |
| } |
| return true; |
| } |
| |
| bool Read(const uint8_t* buf, size_t buf_len) { |
| if (buf_len < kTagLenSize) return false; |
| FixedSubfield field; |
| ReadFixedSubfield(&field, buf); |
| ID_ = static_cast<Tag>(field); |
| ReadFixedSubfield(&field, buf + sizeof(FixedSubfield)); |
| len_ = static_cast<size_t>(field); |
| if (buf_len < kTagLenSize + len_) return false; |
| memcpy(data_, buf + kTagLenSize, len_); |
| return true; |
| } |
| |
| void Print() { |
| fprintf(stderr, "Field ID: %d, data length %d, total length %d\n", |
| ID_, static_cast<int>(len_), static_cast<int>(GetTotalSize())); |
| fprintf(stderr, "Data:"); |
| for (size_t i = 0; i < len_; i++) fprintf(stderr, "0x%x ", data_[i]); |
| fprintf(stderr, "\n"); |
| } |
| |
| // Get the data size from a serialized field to allow allocation |
| static size_t GetDataSizeFromSerialized(const uint8_t* buf) { |
| FixedSubfield len; |
| ReadFixedSubfield(&len, buf + sizeof(FixedSubfield)); |
| return len; |
| } |
| |
| Tag getID() const { |
| return ID_; |
| } |
| |
| size_t getLen() const { |
| return len_; |
| } |
| |
| private: |
| // Combined size of the fixed subfields |
| const static size_t kTagLenSize = 2 * sizeof(FixedSubfield); |
| static void WriteFixedSubfield(FixedSubfield value, uint8_t* buf) { |
| buf[0] = value & 0xFF; |
| buf[1] = (value >> 8) & 0xFF; |
| } |
| static void ReadFixedSubfield(FixedSubfield* value, const uint8_t* buf) { |
| *value = buf[0] | buf[1] << 8; |
| } |
| Tag ID_; |
| size_t len_; |
| uint8_t *data_; |
| }; |
| |
| #endif // LLVM_WRAP_BCHEADER_FIELD_H__ |