1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <stdlib.h>
20 
21 #include <array>
22 #include <initializer_list>
23 #include <set>
24 #include <string>
25 
26 enum class Arch : size_t {
27   arm = 0,
28   arm64,
29   mips,
30   mips64,
31   x86,
32   x86_64,
33 };
34 
35 std::string to_string(const Arch& arch);
36 Arch arch_from_string(const std::string& name);
37 
38 template <typename T>
39 class ArchMapIterator;
40 
41 template <typename T>
42 class ArchMap {
43  public:
ArchMap()44   ArchMap() {
45   }
46 
ArchMap(std::initializer_list<std::pair<Arch,T>> initializer)47   ArchMap(std::initializer_list<std::pair<Arch, T>> initializer) {
48     for (auto& pair : initializer) {
49       this->operator[](pair.first) = pair.second;
50     }
51   }
52 
53   T& operator[](Arch arch) {
54     return data_[size_t(arch)];
55   }
56 
57   const T& operator[](Arch arch) const {
58     return data_[size_t(arch)];
59   }
60 
61   bool operator==(const ArchMap& other) const {
62     for (size_t i = 0; i < data_.size(); ++i) {
63       if (data_[i] != other.data_[i]) {
64         return false;
65       }
66     }
67     return true;
68   }
69 
begin()70   ArchMapIterator<T> begin() const {
71     return ArchMapIterator<T>(*this, Arch::arm);
72   }
73 
end()74   ArchMapIterator<T> end() const {
75     return ArchMapIterator<T>(*this, Arch(size_t(Arch::x86_64) + 1));
76   }
77 
78  private:
79   std::array<T, size_t(Arch::x86_64) + 1> data_ = {};
80 };
81 
82 template <typename T>
83 class ArchMapIterator {
84   const ArchMap<T>& map_;
85   Arch arch_ = Arch::arm;
86 
87  public:
88   ArchMapIterator() = delete;
89 
ArchMapIterator(const ArchMap<T> & map,Arch arch)90   ArchMapIterator(const ArchMap<T>& map, Arch arch) : map_(map), arch_(arch) {
91   }
92 
93   bool operator==(const ArchMapIterator<T>& rhs) const {
94     return map_ == rhs.map_ && arch_ == rhs.arch_;
95   }
96 
97   bool operator!=(const ArchMapIterator<T>& rhs) const {
98     return !(*this == rhs);
99   }
100 
101   ArchMapIterator& operator++() {
102     arch_ = Arch(size_t(arch_) + 1);
103     return *this;
104   }
105 
106   ArchMapIterator operator++(int) {
107     ArchMapIterator result = *this;
108     ++*this;
109     return result;
110   }
111 
112   std::pair<const Arch&, const T&> operator*() const {
113     return std::tie(arch_, map_[arch_]);
114   }
115 
116   std::pair<const Arch&, const T&> operator->() const {
117     return std::tie(arch_, map_[arch_]);
118   }
119 };
120 
121 static const std::set<Arch> supported_archs = {
122   Arch::arm,
123   Arch::arm64,
124   Arch::mips,
125   Arch::mips64,
126   Arch::x86,
127   Arch::x86_64,
128 };
129 
130 static ArchMap<std::string> arch_targets = {
131   { Arch::arm, "arm-linux-androideabi" },
132   { Arch::arm64, "aarch64-linux-android" },
133   { Arch::mips, "mipsel-linux-android" },
134   { Arch::mips64, "mips64el-linux-android" },
135   { Arch::x86, "i686-linux-android" },
136   { Arch::x86_64, "x86_64-linux-android" },
137 };
138 
139 static const std::set<int> supported_levels = { 9, 12, 13, 14, 15, 16, 17, 18, 19, 21, 23, 24 };
140 
141 static const ArchMap<int> arch_min_api = {
142   { Arch::arm, 9 },
143   { Arch::arm64, 21 },
144   { Arch::mips, 9 },
145   { Arch::mips64, 21 },
146   { Arch::x86, 9 },
147   { Arch::x86_64, 21 },
148 };
149