• 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 #include "namemangler.h"
18 #include "cg.h"
19 
20 namespace maplebe {
21 using namespace maple;
22 using namespace namemangler;
23 
Run(FuncEmitInfo & funcEmitInfo)24 void ObjEmitter::Run(FuncEmitInfo &funcEmitInfo)
25 {
26     InsertNopInsn(static_cast<ObjFuncEmitInfo &>(funcEmitInfo));
27     EmitFuncBinaryCode(static_cast<ObjFuncEmitInfo &>(funcEmitInfo));
28 }
29 
30 /* traverse insns, get the binary code and saved in buffer */
EmitFuncBinaryCode(ObjFuncEmitInfo & objFuncEmitInfo)31 void ObjEmitter::EmitFuncBinaryCode(ObjFuncEmitInfo &objFuncEmitInfo)
32 {
33     CGFunc &cgFunc = objFuncEmitInfo.GetCGFunc();
34     objFuncEmitInfo.SetFuncName(cgFunc.GetName());
35 
36     int labelSize = static_cast<int>(cgFunc.GetLab2BBMap().size()) +
37                     static_cast<int>(cgFunc.GetLabelAndValueMap().size()) + 1;
38     std::vector<uint32> label2Offset(labelSize, 0xFFFFFFFFULL);
39     EmitInstructions(objFuncEmitInfo, label2Offset);
40     objFuncEmitInfo.UpdateMethodCodeSize();
41 
42     int symbolSize = static_cast<int>(cgFunc.GetLabelIdx() + 1);
43     std::vector<uint32> symbol2Offset(symbolSize, 0xFFFFFFFFULL);
44     EmitFunctionSymbolTable(objFuncEmitInfo, symbol2Offset);
45     EmitSwitchTable(objFuncEmitInfo, symbol2Offset);
46 
47     /* local float variable */
48     for (const auto &mpPair : cgFunc.GetLabelAndValueMap()) {
49         CHECK_FATAL(mpPair.first < label2Offset.size(), "label2Offset");
50         label2Offset[mpPair.first] = objFuncEmitInfo.GetTextDataSize();
51         objFuncEmitInfo.AppendTextData(&(mpPair.second), k8ByteSize);
52     }
53 
54     /* handle branch fixup here */
55     objFuncEmitInfo.HandleLocalBranchFixup(label2Offset, symbol2Offset);
56 }
57 
EmitInstructions(ObjFuncEmitInfo & objFuncEmitInfo,std::vector<uint32> & label2Offset)58 void ObjEmitter::EmitInstructions(ObjFuncEmitInfo &objFuncEmitInfo, std::vector<uint32> &label2Offset)
59 {
60     CGFunc &cgFunc = objFuncEmitInfo.GetCGFunc();
61     FOR_ALL_BB(bb, &cgFunc) {
62         if (bb->GetLabIdx() != 0) {
63             CHECK_FATAL(bb->GetLabIdx() < label2Offset.size(), "label2Offset");
64             label2Offset[bb->GetLabIdx()] = objFuncEmitInfo.GetTextDataSize();
65             objFuncEmitInfo.AppendLabel2Order(bb->GetLabIdx());
66         }
67 
68         FOR_BB_INSNS(insn, bb) {
69             if (!insn->IsMachineInstruction() || insn->IsAsmInsn() || insn->IsPseudo()) {
70                 continue;
71             }
72 
73             /* get binary code and save in buffer */
74             if (insn->GetDesc()->IsIntrinsic()) {
75                 EmitIntrinsicInsn(*insn, objFuncEmitInfo);
76             } else if (insn->GetDesc()->IsSpecialIntrinsic()) {
77                 EmitSpinIntrinsicInsn(*insn, objFuncEmitInfo);
78             } else {
79                 EncodeInstruction(*insn, label2Offset, objFuncEmitInfo);
80             }
81         }
82     }
83 }
84 
EmitSwitchTable(ObjFuncEmitInfo & objFuncEmitInfo,const std::vector<uint32> & symbol2Offset)85 void ObjEmitter::EmitSwitchTable(ObjFuncEmitInfo &objFuncEmitInfo, const std::vector<uint32> &symbol2Offset)
86 {
87     CGFunc &cgFunc = objFuncEmitInfo.GetCGFunc();
88     if (cgFunc.GetEmitStVec().size() == 0) {
89         return;
90     }
91     uint32 tmpOffset = GetBeforeTextDataSize(objFuncEmitInfo);
92     /* align is 8 push padding to objFuncEmitInfo.data */
93     uint32 startOffset = Alignment::Align<uint32>(tmpOffset, k8ByteSize);
94     uint32 padding = startOffset - tmpOffset;
95     objFuncEmitInfo.FillTextDataNop(padding);
96 
97     uint32 curOffset = objFuncEmitInfo.GetTextDataSize();
98     for (std::pair<uint32, MIRSymbol *> st : cgFunc.GetEmitStVec()) {
99         objFuncEmitInfo.SetSwitchTableOffset(st.second->GetName(), curOffset);
100         MIRAggConst *arrayConst = safe_cast<MIRAggConst>(st.second->GetKonst());
101         DEBUG_ASSERT(arrayConst != nullptr, "null ptr check");
102         for (size_t i = 0; i < arrayConst->GetConstVec().size(); ++i) {
103             MIRLblConst *lblConst = safe_cast<MIRLblConst>(arrayConst->GetConstVecItem(i));
104             DEBUG_ASSERT(lblConst != nullptr, "null ptr check");
105             CHECK_FATAL(lblConst->GetValue() <= symbol2Offset.size(), "symbol2Offset");
106             uint64 offset = static_cast<uint64>(symbol2Offset[lblConst->GetValue()]) - static_cast<uint64>(curOffset);
107             objFuncEmitInfo.AppendTextData(offset, k8ByteSize);
108         }
109 
110         curOffset += arrayConst->GetConstVec().size() * k8ByteSize;
111     }
112 }
113 
WriteObjFile()114 void ObjEmitter::WriteObjFile()
115 {
116     const auto &emitMemorymanager = CGOptions::GetInstance().GetEmitMemoryManager();
117     if (emitMemorymanager.codeSpace != nullptr) {
118         DEBUG_ASSERT(textSection != nullptr, "textSection has not been initialized");
119         uint8 *codeSpace = emitMemorymanager.allocateDataSection(emitMemorymanager.codeSpace,
120             textSection->GetDataSize(), textSection->GetAlign(), textSection->GetName().c_str());
121         memcpy_s(codeSpace, textSection->GetDataSize(), textSection->GetData().data(), textSection->GetDataSize());
122         if (CGOptions::addFuncSymbol()) {
123             uint8 *symtabSpace = emitMemorymanager.allocateDataSection(emitMemorymanager.codeSpace,
124                 symbolTabSection->GetDataSize(), symbolTabSection->GetAlign(), symbolTabSection->GetName().c_str());
125             memcpy_s(symtabSpace, symbolTabSection->GetDataSize(),
126                 symbolTabSection->GetAddr(), symbolTabSection->GetDataSize());
127             uint8 *stringTabSpace = emitMemorymanager.allocateDataSection(emitMemorymanager.codeSpace,
128                 strTabSection->GetDataSize(), strTabSection->GetAlign(), strTabSection->GetName().c_str());
129             memcpy_s(stringTabSpace, strTabSection->GetDataSize(),
130                 strTabSection->GetData().data(), strTabSection->GetDataSize());
131         }
132 
133         return;
134     }
135     /* write header */
136     Emit(&header, sizeof(header));
137 
138     /* write sections */
139     for (auto *section : sections) {
140         if (section->GetType() == SHT_NOBITS) {
141             continue;
142         }
143 
144         SetFileOffset(section->GetOffset());
145         section->WriteSection(outStream);
146     }
147 
148     /* write section table */
149     SetFileOffset(header.e_shoff);
150     for (auto section : sections) {
151         Emit(&section->GetSectionHeader(), sizeof(section->GetSectionHeader()));
152     }
153 }
154 
AddSymbol(const std::string & name,Word size,const Section & section,Address value)155 void ObjEmitter::AddSymbol(const std::string &name, Word size, const Section &section, Address value)
156 {
157     auto nameIndex = strTabSection->AddString(name);
158     symbolTabSection->AppendSymbol({static_cast<Word>(nameIndex),
159                                     static_cast<uint8_t>((STB_GLOBAL << 4) + (STT_SECTION & 0xf)), 0,
160                                     section.GetIndex(), value, size});
161 }
162 
AddFuncSymbol(const MapleString & name,Word size,Address value)163 void ObjEmitter::AddFuncSymbol(const MapleString &name, Word size, Address value)
164 {
165     auto symbolStrIndex = strTabSection->AddString(name);
166     symbolTabSection->AppendSymbol({static_cast<Word>(symbolStrIndex),
167                                     static_cast<uint8>((STB_GLOBAL << k4BitSize) + (STT_FUNC & 0xf)), 0,
168                                     textSection->GetIndex(), value, size});
169 }
170 
ClearData()171 void ObjEmitter::ClearData()
172 {
173     globalLabel2Offset.clear();
174     for (auto *section : sections) {
175         if (section != nullptr) {
176             section->ClearData();
177         }
178     }
179 }
180 
InitELFHeader()181 void ObjEmitter::InitELFHeader()
182 {
183     header.e_ident[EI_MAG0] = ELFMAG0;
184     header.e_ident[EI_MAG1] = ELFMAG1;
185     header.e_ident[EI_MAG2] = ELFMAG2;
186     header.e_ident[EI_MAG3] = ELFMAG3;
187     header.e_ident[EI_CLASS] = ELFCLASS64;
188     header.e_ident[EI_DATA] = ELFDATA2LSB;
189     header.e_ident[EI_VERSION] = EV_CURRENT;
190     header.e_ident[EI_OSABI] = ELFOSABI_LINUX;
191     header.e_ident[EI_ABIVERSION] = 0;
192     std::fill_n(&header.e_ident[EI_PAD], EI_NIDENT - EI_PAD, 0);
193     header.e_type = ET_REL;
194     header.e_version = 1;
195     UpdateMachineAndFlags(header);
196     header.e_entry = 0;
197     header.e_ehsize = sizeof(FileHeader);
198     header.e_phentsize = sizeof(SegmentHeader);
199     header.e_shentsize = sizeof(SectionHeader);
200     header.e_shstrndx = shStrSection->GetIndex();
201     header.e_shoff = 0;
202     header.e_phoff = 0;
203     header.e_shnum = sections.size();
204     header.e_phnum = 0;
205 }
206 
EmitMIRIntConst(EmitInfo & emitInfo)207 void ObjEmitter::EmitMIRIntConst(EmitInfo &emitInfo)
208 {
209     DEBUG_ASSERT(IsPrimitiveScalar(emitInfo.elemConst.GetType().GetPrimType()), "must be primitive type!");
210     MIRIntConst &intConst = static_cast<MIRIntConst &>(emitInfo.elemConst);
211     size_t size = GetPrimTypeSize(emitInfo.elemConst.GetType().GetPrimType());
212     const IntVal &value = intConst.GetValue();
213     int64 val = value.GetExtValue();
214     dataSection->AppendData(&val, size);
215     emitInfo.offset += size;
216 #ifdef OBJ_DEBUG
217     LogInfo::MapleLogger() << val << " size: " << size << "\n";
218 #endif
219 }
220 
EmitMIRAddrofConstCommon(EmitInfo & emitInfo,uint64 specialOffset)221 void ObjEmitter::EmitMIRAddrofConstCommon(EmitInfo &emitInfo, uint64 specialOffset)
222 {
223     MIRAddrofConst &symAddr = static_cast<MIRAddrofConst &>(emitInfo.elemConst);
224     MIRSymbol *symAddrSym = GlobalTables::GetGsymTable().GetSymbolFromStidx(symAddr.GetSymbolIndex().Idx());
225     DEBUG_ASSERT(symAddrSym != nullptr, "null ptr check");
226     const std::string &symAddrName = symAddrSym->GetName();
227     LabelFixup labelFixup(symAddrName, emitInfo.offset, kLabelFixupDirect64);
228     if (specialOffset != 0) {
229         DataSection::AddLabelFixup(emitInfo.labelFixups, labelFixup);
230     }
231     uint64 value = specialOffset - emitInfo.offset;
232     size_t size = GetPrimTypeSize(emitInfo.elemConst.GetType().GetPrimType());
233     dataSection->AppendData(&value, size);
234     emitInfo.offset += size;
235 
236 #ifdef OBJ_DEBUG
237     LogInfo::MapleLogger() << symAddrName << " size: " << size << "\n";
238 #endif
239 }
240 
EmitMIRAddrofConst(EmitInfo & emitInfo)241 void ObjEmitter::EmitMIRAddrofConst(EmitInfo &emitInfo)
242 {
243     EmitMIRAddrofConstCommon(emitInfo, 0);
244 }
245 
EmitMIRAddrofConstOffset(EmitInfo & emitInfo)246 void ObjEmitter::EmitMIRAddrofConstOffset(EmitInfo &emitInfo)
247 {
248     /* 2 is fixed offset in runtime */
249     EmitMIRAddrofConstCommon(emitInfo, 2);
250 }
251 
EmitFunctionSymbolTable(ObjFuncEmitInfo & objFuncEmitInfo,std::vector<uint32> & symbol2Offset)252 void ObjEmitter::EmitFunctionSymbolTable(ObjFuncEmitInfo &objFuncEmitInfo, std::vector<uint32> &symbol2Offset)
253 {
254     CGFunc &cgFunc = objFuncEmitInfo.GetCGFunc();
255     MIRFunction *func = &cgFunc.GetFunction();
256 
257     size_t size =
258         (func == nullptr) ? GlobalTables::GetGsymTable().GetTable().size() : func->GetSymTab()->GetTable().size();
259     for (size_t i = 0; i < size; ++i) {
260         const MIRSymbol *st = nullptr;
261         if (func == nullptr) {
262             auto &symTab = GlobalTables::GetGsymTable();
263             st = symTab.GetSymbol(i);
264         } else {
265             auto &symTab = *func->GetSymTab();
266             st = symTab.GetSymbolAt(i);
267         }
268         if (st == nullptr) {
269             continue;
270         }
271         MIRStorageClass storageClass = st->GetStorageClass();
272         MIRSymKind symKind = st->GetSKind();
273         if (storageClass == kScPstatic && symKind == kStConst) {
274             // align
275             size_t tmpOffset = GetBeforeTextDataSize(objFuncEmitInfo);
276             uint32 offset = Alignment::Align<uint32>(tmpOffset, k8ByteSize);
277             uint32 padding = offset - tmpOffset;
278             objFuncEmitInfo.FillTextDataNop(padding);
279             CHECK_FATAL(cgFunc.GetLocalSymLabelIndex(*st) <= symbol2Offset.size(), "symbol2Offset");
280             symbol2Offset[cgFunc.GetLocalSymLabelIndex(*st)] = static_cast<uint32>(objFuncEmitInfo.GetTextDataSize());
281             if (st->GetKonst()->GetKind() == kConstStr16Const) {
282                 EmitStr16Const(objFuncEmitInfo, *st);
283                 continue;
284             }
285 
286             if (st->GetKonst()->GetKind() == kConstStrConst) {
287                 EmitStrConst(objFuncEmitInfo, *st);
288                 continue;
289             }
290 
291             switch (st->GetKonst()->GetType().GetPrimType()) {
292                 case PTY_u32: {
293                     MIRIntConst *intConst = safe_cast<MIRIntConst>(st->GetKonst());
294                     DEBUG_ASSERT(intConst != nullptr, "intConst should not be nullptr");
295                     uint32 value = static_cast<uint32>(intConst->GetValue().GetExtValue());
296                     objFuncEmitInfo.AppendTextData(&value, sizeof(value));
297                     break;
298                 }
299                 case PTY_f32: {
300                     MIRFloatConst *floatConst = safe_cast<MIRFloatConst>(st->GetKonst());
301                     uint32 value = static_cast<uint32>(floatConst->GetIntValue());
302                     objFuncEmitInfo.AppendTextData(&value, sizeof(value));
303                     break;
304                 }
305                 case PTY_f64: {
306                     MIRDoubleConst *doubleConst = safe_cast<MIRDoubleConst>(st->GetKonst());
307                     uint32 value = doubleConst->GetIntLow32();
308                     objFuncEmitInfo.AppendTextData(&value, sizeof(value));
309                     value = doubleConst->GetIntHigh32();
310                     objFuncEmitInfo.AppendTextData(&value, sizeof(value));
311                     break;
312                 }
313                 default:
314                     break;
315             }
316         }
317     }
318 }
319 
EmitStr16Const(ObjFuncEmitInfo & objFuncEmitInfo,const MIRSymbol & str16Symbol)320 void ObjEmitter::EmitStr16Const(ObjFuncEmitInfo &objFuncEmitInfo, const MIRSymbol &str16Symbol)
321 {
322     MIRStr16Const *mirStr16Const = safe_cast<MIRStr16Const>(str16Symbol.GetKonst());
323     DEBUG_ASSERT(mirStr16Const != nullptr, "nullptr check");
324     const std::u16string &str16 = GlobalTables::GetU16StrTable().GetStringFromStrIdx(mirStr16Const->GetValue());
325 
326     uint32 len = str16.length();
327     for (uint32 i = 0; i < len; ++i) {
328         char16_t c = str16[i];
329         objFuncEmitInfo.AppendTextData(&c, sizeof(c));
330     }
331     if ((str16.length() & 0x1) == 1) {
332         uint16 value = 0;
333         objFuncEmitInfo.AppendTextData(&value, sizeof(value));
334     }
335 }
336 
EmitStrConst(ObjFuncEmitInfo & objFuncEmitInfo,const MIRSymbol & strSymbol)337 void ObjEmitter::EmitStrConst(ObjFuncEmitInfo &objFuncEmitInfo, const MIRSymbol &strSymbol)
338 {
339     MIRStrConst *mirStrConst = safe_cast<MIRStrConst>(strSymbol.GetKonst());
340     DEBUG_ASSERT(mirStrConst != nullptr, "null ptr check");
341     auto str = GlobalTables::GetUStrTable().GetStringFromStrIdx(mirStrConst->GetValue());
342     size_t size = str.length();
343     /* 1 is tail 0 of the str string */
344     objFuncEmitInfo.AppendTextData(str.c_str(), size + 1);
345 }
346 } /* namespace maplebe */
347