• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "obj_emit.h"
17 
18 namespace maplebe {
19 using namespace maple;
20 using namespace namemangler;
21 
Run(FuncEmitInfo & funcEmitInfo)22 void ObjEmitter::Run(FuncEmitInfo &funcEmitInfo)
23 {
24     InsertNopInsn(static_cast<ObjFuncEmitInfo &>(funcEmitInfo));
25     EmitFuncBinaryCode(static_cast<ObjFuncEmitInfo &>(funcEmitInfo));
26 }
27 
28 /* traverse insns, get the binary code and saved in buffer */
EmitFuncBinaryCode(ObjFuncEmitInfo & objFuncEmitInfo)29 void ObjEmitter::EmitFuncBinaryCode(ObjFuncEmitInfo &objFuncEmitInfo)
30 {
31     CGFunc &cgFunc = objFuncEmitInfo.GetCGFunc();
32     objFuncEmitInfo.SetFuncName(cgFunc.GetName());
33 
34     int labelSize = static_cast<int>(cgFunc.GetLab2BBMap().size()) +
35                     static_cast<int>(cgFunc.GetLabelAndValueMap().size()) + 1;
36     std::vector<uint32> label2Offset(labelSize, 0xFFFFFFFFULL);
37     EmitInstructions(objFuncEmitInfo, label2Offset);
38     objFuncEmitInfo.UpdateMethodCodeSize();
39 
40     int symbolSize = static_cast<int>(cgFunc.GetLabelIdx() + 1);
41     std::vector<uint32> symbol2Offset(symbolSize, 0xFFFFFFFFULL);
42     EmitFunctionSymbolTable(objFuncEmitInfo, symbol2Offset);
43     EmitSwitchTable(objFuncEmitInfo, symbol2Offset);
44 
45     /* local float variable */
46     for (const auto &mpPair : cgFunc.GetLabelAndValueMap()) {
47         CHECK_FATAL(mpPair.first < label2Offset.size(), "label2Offset");
48         label2Offset[mpPair.first] = objFuncEmitInfo.GetTextDataSize();
49         objFuncEmitInfo.AppendTextData(&(mpPair.second), k8ByteSize);
50     }
51 
52     /* handle branch fixup here */
53     objFuncEmitInfo.HandleLocalBranchFixup(label2Offset, symbol2Offset);
54 }
55 
EmitInstructions(ObjFuncEmitInfo & objFuncEmitInfo,std::vector<uint32> & label2Offset)56 void ObjEmitter::EmitInstructions(ObjFuncEmitInfo &objFuncEmitInfo, std::vector<uint32> &label2Offset)
57 {
58     CGFunc &cgFunc = objFuncEmitInfo.GetCGFunc();
59     FOR_ALL_BB(bb, &cgFunc) {
60         if (bb->GetLabIdx() != 0) {
61             CHECK_FATAL(bb->GetLabIdx() < label2Offset.size(), "label2Offset");
62             label2Offset[bb->GetLabIdx()] = objFuncEmitInfo.GetTextDataSize();
63             objFuncEmitInfo.AppendLabel2Order(bb->GetLabIdx());
64         }
65 
66         FOR_BB_INSNS(insn, bb) {
67             if (!insn->IsMachineInstruction() || insn->IsAsmInsn() || insn->IsPseudo()) {
68                 continue;
69             }
70 
71             /* get binary code and save in buffer */
72             if (insn->GetDesc()->IsIntrinsic()) {
73                 EmitIntrinsicInsn(*insn, label2Offset, objFuncEmitInfo);
74             } else if (insn->GetDesc()->IsSpecialIntrinsic()) {
75                 EmitSpinIntrinsicInsn(*insn, objFuncEmitInfo);
76             } else {
77                 EncodeInstruction(*insn, label2Offset, objFuncEmitInfo);
78             }
79         }
80     }
81 }
82 
EmitSwitchTable(ObjFuncEmitInfo & objFuncEmitInfo,const std::vector<uint32> & symbol2Offset)83 void ObjEmitter::EmitSwitchTable(ObjFuncEmitInfo &objFuncEmitInfo, const std::vector<uint32> &symbol2Offset)
84 {
85     CGFunc &cgFunc = objFuncEmitInfo.GetCGFunc();
86     if (cgFunc.GetEmitStVec().size() == 0) {
87         return;
88     }
89     uint32 tmpOffset = GetBeforeTextDataSize(objFuncEmitInfo);
90     /* align is 8 push padding to objFuncEmitInfo.data */
91     uint32 startOffset = Alignment::Align<uint32>(tmpOffset, k8ByteSize);
92     uint32 padding = startOffset - tmpOffset;
93     objFuncEmitInfo.FillTextDataNop(padding);
94 
95     uint32 curOffset = objFuncEmitInfo.GetTextDataSize();
96     for (std::pair<uint32, MIRSymbol *> st : cgFunc.GetEmitStVec()) {
97         objFuncEmitInfo.SetSwitchTableOffset(st.second->GetName(), curOffset);
98         MIRAggConst *arrayConst = safe_cast<MIRAggConst>(st.second->GetKonst());
99         DEBUG_ASSERT(arrayConst != nullptr, "null ptr check");
100         for (size_t i = 0; i < arrayConst->GetConstVec().size(); ++i) {
101             MIRLblConst *lblConst = safe_cast<MIRLblConst>(arrayConst->GetConstVecItem(i));
102             DEBUG_ASSERT(lblConst != nullptr, "null ptr check");
103             CHECK_FATAL(lblConst->GetValue() <= symbol2Offset.size(), "symbol2Offset");
104             uint64 offset = static_cast<uint64>(symbol2Offset[lblConst->GetValue()]) - static_cast<uint64>(curOffset);
105             objFuncEmitInfo.AppendTextData(offset, k8ByteSize);
106         }
107 
108         curOffset += arrayConst->GetConstVec().size() * k8ByteSize;
109     }
110 }
111 
WriteObjFile()112 void ObjEmitter::WriteObjFile()
113 {
114     const auto &emitMemorymanager = CGOptions::GetInstance().GetEmitMemoryManager();
115     if (emitMemorymanager.codeSpace != nullptr) {
116         DEBUG_ASSERT(textSection != nullptr, "textSection has not been initialized");
117         uint8 *codeSpace = emitMemorymanager.allocateDataSection(emitMemorymanager.codeSpace,
118             textSection->GetDataSize(), textSection->GetAlign(), textSection->GetName().c_str());
119         memcpy_s(codeSpace, textSection->GetDataSize(), textSection->GetData().data(), textSection->GetDataSize());
120         if (CGOptions::addFuncSymbol()) {
121             uint8 *symtabSpace = emitMemorymanager.allocateDataSection(emitMemorymanager.codeSpace,
122                 symbolTabSection->GetDataSize(), symbolTabSection->GetAlign(), symbolTabSection->GetName().c_str());
123             memcpy_s(symtabSpace, symbolTabSection->GetDataSize(),
124                 symbolTabSection->GetAddr(), symbolTabSection->GetDataSize());
125             uint8 *stringTabSpace = emitMemorymanager.allocateDataSection(emitMemorymanager.codeSpace,
126                 strTabSection->GetDataSize(), strTabSection->GetAlign(), strTabSection->GetName().c_str());
127             memcpy_s(stringTabSpace, strTabSection->GetDataSize(),
128                 strTabSection->GetData().data(), strTabSection->GetDataSize());
129         }
130 
131         return;
132     }
133     /* write header */
134     Emit(&header, sizeof(header));
135 
136     /* write sections */
137     for (auto *section : sections) {
138         if (section->GetType() == SHT_NOBITS) {
139             continue;
140         }
141 
142         SetFileOffset(section->GetOffset());
143         section->WriteSection(outStream);
144     }
145 
146     /* write section table */
147     SetFileOffset(header.e_shoff);
148     for (auto section : sections) {
149         Emit(&section->GetSectionHeader(), sizeof(section->GetSectionHeader()));
150     }
151 }
152 
AddFuncSymbol(const MapleString & name,Word size,Address value)153 void ObjEmitter::AddFuncSymbol(const MapleString &name, Word size, Address value)
154 {
155     auto symbolStrIndex = strTabSection->AddString(name);
156     symbolTabSection->AppendSymbol({static_cast<Word>(symbolStrIndex),
157                                     static_cast<uint8>((STB_GLOBAL << k4BitSize) + (STT_FUNC & 0xf)), 0,
158                                     textSection->GetIndex(), value, size});
159 }
160 
ClearData()161 void ObjEmitter::ClearData()
162 {
163     globalLabel2Offset.clear();
164     for (auto *section : sections) {
165         if (section != nullptr) {
166             section->ClearData();
167         }
168     }
169 }
170 
InitELFHeader()171 void ObjEmitter::InitELFHeader()
172 {
173     header.e_ident[EI_MAG0] = ELFMAG0;
174     header.e_ident[EI_MAG1] = ELFMAG1;
175     header.e_ident[EI_MAG2] = ELFMAG2;
176     header.e_ident[EI_MAG3] = ELFMAG3;
177     header.e_ident[EI_CLASS] = ELFCLASS64;
178     header.e_ident[EI_DATA] = ELFDATA2LSB;
179     header.e_ident[EI_VERSION] = EV_CURRENT;
180     header.e_ident[EI_OSABI] = ELFOSABI_LINUX;
181     header.e_ident[EI_ABIVERSION] = 0;
182     std::fill_n(&header.e_ident[EI_PAD], EI_NIDENT - EI_PAD, 0);
183     header.e_type = ET_REL;
184     header.e_version = 1;
185     UpdateMachineAndFlags(header);
186     header.e_entry = 0;
187     header.e_ehsize = sizeof(FileHeader);
188     header.e_phentsize = sizeof(SegmentHeader);
189     header.e_shentsize = sizeof(SectionHeader);
190     header.e_shstrndx = shStrSection->GetIndex();
191     header.e_shoff = 0;
192     header.e_phoff = 0;
193     header.e_shnum = sections.size();
194     header.e_phnum = 0;
195 }
196 
EmitFunctionSymbolTable(ObjFuncEmitInfo & objFuncEmitInfo,std::vector<uint32> & symbol2Offset)197 void ObjEmitter::EmitFunctionSymbolTable(ObjFuncEmitInfo &objFuncEmitInfo, std::vector<uint32> &symbol2Offset)
198 {
199     CGFunc &cgFunc = objFuncEmitInfo.GetCGFunc();
200     MIRFunction *func = &cgFunc.GetFunction();
201 
202     size_t size =
203         (func == nullptr) ? GlobalTables::GetGsymTable().GetTable().size() : func->GetSymTab()->GetTable().size();
204     for (size_t i = 0; i < size; ++i) {
205         const MIRSymbol *st = nullptr;
206         if (func == nullptr) {
207             auto &symTab = GlobalTables::GetGsymTable();
208             st = symTab.GetSymbol(i);
209         } else {
210             auto &symTab = *func->GetSymTab();
211             st = symTab.GetSymbolAt(i);
212         }
213         if (st == nullptr) {
214             continue;
215         }
216         MIRStorageClass storageClass = st->GetStorageClass();
217         MIRSymKind symKind = st->GetSKind();
218         if (storageClass == kScPstatic && symKind == kStConst) {
219             // align
220             size_t tmpOffset = GetBeforeTextDataSize(objFuncEmitInfo);
221             uint32 offset = Alignment::Align<uint32>(tmpOffset, k8ByteSize);
222             uint32 padding = offset - tmpOffset;
223             objFuncEmitInfo.FillTextDataNop(padding);
224             CHECK_FATAL(cgFunc.GetLocalSymLabelIndex(*st) <= symbol2Offset.size(), "symbol2Offset");
225             symbol2Offset[cgFunc.GetLocalSymLabelIndex(*st)] = static_cast<uint32>(objFuncEmitInfo.GetTextDataSize());
226             if (st->GetKonst()->GetKind() == kConstStr16Const) {
227                 EmitStr16Const(objFuncEmitInfo, *st);
228                 continue;
229             }
230 
231             if (st->GetKonst()->GetKind() == kConstStrConst) {
232                 EmitStrConst(objFuncEmitInfo, *st);
233                 continue;
234             }
235 
236             switch (st->GetKonst()->GetType().GetPrimType()) {
237                 case PTY_u32: {
238                     MIRIntConst *intConst = safe_cast<MIRIntConst>(st->GetKonst());
239                     DEBUG_ASSERT(intConst != nullptr, "intConst should not be nullptr");
240                     uint32 value = static_cast<uint32>(intConst->GetValue().GetExtValue());
241                     objFuncEmitInfo.AppendTextData(&value, sizeof(value));
242                     break;
243                 }
244                 case PTY_f32: {
245                     MIRFloatConst *floatConst = safe_cast<MIRFloatConst>(st->GetKonst());
246                     uint32 value = static_cast<uint32>(floatConst->GetIntValue());
247                     objFuncEmitInfo.AppendTextData(&value, sizeof(value));
248                     break;
249                 }
250                 case PTY_f64: {
251                     MIRDoubleConst *doubleConst = safe_cast<MIRDoubleConst>(st->GetKonst());
252                     uint32 value = doubleConst->GetIntLow32();
253                     objFuncEmitInfo.AppendTextData(&value, sizeof(value));
254                     value = doubleConst->GetIntHigh32();
255                     objFuncEmitInfo.AppendTextData(&value, sizeof(value));
256                     break;
257                 }
258                 default:
259                     break;
260             }
261         }
262     }
263 }
264 
EmitStr16Const(ObjFuncEmitInfo & objFuncEmitInfo,const MIRSymbol & str16Symbol)265 void ObjEmitter::EmitStr16Const(ObjFuncEmitInfo &objFuncEmitInfo, const MIRSymbol &str16Symbol)
266 {
267     MIRStr16Const *mirStr16Const = safe_cast<MIRStr16Const>(str16Symbol.GetKonst());
268     DEBUG_ASSERT(mirStr16Const != nullptr, "nullptr check");
269     const std::u16string &str16 = GlobalTables::GetU16StrTable().GetStringFromStrIdx(mirStr16Const->GetValue());
270 
271     uint32 len = str16.length();
272     for (uint32 i = 0; i < len; ++i) {
273         char16_t c = str16[i];
274         objFuncEmitInfo.AppendTextData(&c, sizeof(c));
275     }
276     if ((str16.length() & 0x1) == 1) {
277         uint16 value = 0;
278         objFuncEmitInfo.AppendTextData(&value, sizeof(value));
279     }
280 }
281 
EmitStrConst(ObjFuncEmitInfo & objFuncEmitInfo,const MIRSymbol & strSymbol)282 void ObjEmitter::EmitStrConst(ObjFuncEmitInfo &objFuncEmitInfo, const MIRSymbol &strSymbol)
283 {
284     MIRStrConst *mirStrConst = safe_cast<MIRStrConst>(strSymbol.GetKonst());
285     DEBUG_ASSERT(mirStrConst != nullptr, "null ptr check");
286     auto str = GlobalTables::GetUStrTable().GetStringFromStrIdx(mirStrConst->GetValue());
287     size_t size = str.length();
288     /* 1 is tail 0 of the str string */
289     objFuncEmitInfo.AppendTextData(str.c_str(), size + 1);
290 }
291 } /* namespace maplebe */
292