17cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines/*
27cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines * Copyright 2012, The Android Open Source Project
37cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines *
47cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines * Licensed under the Apache License, Version 2.0 (the "License");
57cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines * you may not use this file except in compliance with the License.
67cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines * You may obtain a copy of the License at
77cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines *
87cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines *     http://www.apache.org/licenses/LICENSE-2.0
97cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines *
107cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines * Unless required by applicable law or agreed to in writing, software
117cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines * distributed under the License is distributed on an "AS IS" BASIS,
127cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines * See the License for the specific language governing permissions and
147cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines * limitations under the License.
157cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines */
167cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines
177cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines#ifndef LLVM_WRAP_BCHEADER_FIELD_H__
187cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines#define LLVM_WRAP_BCHEADER_FIELD_H__
197cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines
207cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines#include <stdint.h>
217cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines#include <stdio.h>
227cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines#include <string.h>
237cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines
247cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines// Class representing a variable-size metadata field in the bitcode header.
257cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines// Also contains the list of known Tag IDs.
267cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines// Contains a pointer to the data but does not own the data, so it can be
277cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines// copied with the trivial copy constructor/assignment operator.
287cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines
297cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines// The serialized format has 2 fixed subfields (ID and length) and the
307cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines// variable-length data subfield
317cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hinesclass BCHeaderField {
327cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines public:
337cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines  typedef enum {
347cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    kInvalid = 0,
357cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    kBitcodeHash = 1,
367cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    kAndroidCompilerVersion = 0x4001,
377cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    kAndroidOptimizationLevel = 0x4002
387cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines  } Tag;
397cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines  typedef uint16_t FixedSubfield;
407cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines
417cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines  BCHeaderField(Tag ID, size_t len, uint8_t* data) :
427cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines      ID_(ID), len_(len), data_(data) {}
437cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines  size_t GetTotalSize() {
447cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    // Round up to 4 byte alignment
457cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    return (kTagLenSize + len_ + 3) & ~3;
467cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines  }
477cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines
487cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines  bool Write(uint8_t* buf, size_t buf_len) {
497cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    size_t fields_len = kTagLenSize + len_;
507cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    size_t pad_len = (4 - (fields_len & 3)) & 3;
517cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    // Ensure buffer is large enough and that length can be represented
527cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    // in 16 bits
5326218cebf31dd9d0ec3c677fec91e1847a87a6d2Stephen Hines    const size_t max_uint16_t = 65535;
547cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    if (buf_len < fields_len + pad_len ||
5526218cebf31dd9d0ec3c677fec91e1847a87a6d2Stephen Hines        len_ > max_uint16_t) return false;
567cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines
577cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    WriteFixedSubfield(static_cast<FixedSubfield>(ID_), buf);
587cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    WriteFixedSubfield(static_cast<FixedSubfield>(len_),
597cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines                       buf + sizeof(FixedSubfield));
607cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    memcpy(buf + kTagLenSize, data_, len_);
617cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    // Pad out to 4 byte alignment
627cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    if (pad_len) {
637cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines      memset(buf + fields_len, 0, pad_len);
647cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    }
657cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    return true;
667cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines  }
677cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines
687cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines  bool Read(const uint8_t* buf, size_t buf_len) {
697cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    if (buf_len < kTagLenSize) return false;
707cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    FixedSubfield field;
717cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    ReadFixedSubfield(&field, buf);
727cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    ID_ = static_cast<Tag>(field);
737cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    ReadFixedSubfield(&field, buf + sizeof(FixedSubfield));
747cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    len_ = static_cast<size_t>(field);
757cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    if (buf_len < kTagLenSize + len_) return false;
767cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    memcpy(data_, buf + kTagLenSize, len_);
777cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    return true;
787cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines  }
797cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines
807cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines  void Print() {
817cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    fprintf(stderr, "Field ID: %d, data length %d, total length %d\n",
827cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines            ID_, static_cast<int>(len_), static_cast<int>(GetTotalSize()));
837cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    fprintf(stderr, "Data:");
847cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    for (size_t i = 0; i < len_; i++) fprintf(stderr, "0x%x ", data_[i]);
857cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    fprintf(stderr, "\n");
867cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines  }
877cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines
887cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines  // Get the data size from a serialized field to allow allocation
897cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines  static size_t GetDataSizeFromSerialized(const uint8_t* buf) {
907cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    FixedSubfield len;
917cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    ReadFixedSubfield(&len, buf + sizeof(FixedSubfield));
927cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    return len;
937cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines  }
947cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines
957cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines  Tag getID() const {
967cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    return ID_;
977cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines  }
987cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines
997cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines  size_t getLen() const {
1007cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    return len_;
1017cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines  }
1027cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines
1037cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines private:
1047cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines // Combined size of the fixed subfields
1057cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines const static size_t kTagLenSize = 2 * sizeof(FixedSubfield);
1067cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines  static void WriteFixedSubfield(FixedSubfield value, uint8_t* buf) {
1077cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    buf[0] = value & 0xFF;
1087cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    buf[1] = (value >> 8) & 0xFF;
1097cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines  }
1107cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines  static void ReadFixedSubfield(FixedSubfield* value, const uint8_t* buf) {
1117cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines    *value = buf[0] | buf[1] << 8;
1127cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines  }
1137cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines  Tag ID_;
1147cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines  size_t len_;
1157cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines  uint8_t *data_;
1167cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines};
1177cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines
1187cd4c49d575478b2380f129dcd376a4e5e37939cStephen Hines#endif  // LLVM_WRAP_BCHEADER_FIELD_H__
119