1 // =================================
  2 // Copyright (c) 2021 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 #include <cmajor/cmsxi/Context.hpp>
  7 #include <cmajor/cmsxi/Instruction.hpp>
  8 #include <cmajor/cmsxi/BasicBlock.hpp>
  9 
 10 namespace cmsxi {
 11 
 12 Context::Context() : currentFunction(nullptr)currentBasicBlock(nullptr)metadata()currentLineNumber(0)
 13 {
 14 }
 15 
 16 void Context::AddValue(Value* value)
 17 {
 18     values.push_back(std::unique_ptr<Value>(value));
 19 }
 20 
 21 ConstantValue* Context::GetBoolValue(bool value)
 22 {
 23     ConstantValue* boolValue = new BoolValue(value);
 24     AddValue(boolValue);
 25     return boolValue;
 26 }
 27 
 28 ConstantValue* Context::GetSByteValue(int8_t value)
 29 {
 30     ConstantValue* sbyteValue = new SByteValue(value);
 31     AddValue(sbyteValue);
 32     return sbyteValue;
 33 }
 34 
 35 ConstantValue* Context::GetByteValue(uint8_t value)
 36 {
 37     ConstantValue* byteValue = new ByteValue(value);
 38     AddValue(byteValue);
 39     return byteValue;
 40 }
 41 
 42 ConstantValue* Context::GetShortValue(int16_t value)
 43 {
 44     ConstantValue* shortValue = new ShortValue(value);
 45     AddValue(shortValue);
 46     return shortValue;
 47 }
 48 
 49 ConstantValue* Context::GetUShortValue(uint16_t value)
 50 {
 51     ConstantValue* ushortValue = new UShortValue(value);
 52     AddValue(ushortValue);
 53     return ushortValue;
 54 }
 55 
 56 ConstantValue* Context::GetIntValue(int32_t value)
 57 {
 58     ConstantValue* intValue = new IntValue(value);
 59     AddValue(intValue);
 60     return intValue;
 61 }
 62 
 63 ConstantValue* Context::GetUIntValue(uint32_t value)
 64 {
 65     ConstantValue* uintValue = new UIntValue(value);
 66     AddValue(uintValue);
 67     return uintValue;
 68 }
 69 
 70 ConstantValue* Context::GetLongValue(int64_t value)
 71 {
 72     ConstantValue* longValue = new LongValue(value);
 73     AddValue(longValue);
 74     return longValue;
 75 }
 76 
 77 ConstantValue* Context::GetULongValue(uint64_t value)
 78 {
 79     ConstantValue* ulongValue = new ULongValue(value);
 80     AddValue(ulongValue);
 81     return ulongValue;
 82 }
 83 
 84 ConstantValue* Context::GetFloatValue(float value)
 85 {
 86     ConstantValue* floatValue = new FloatValue(value);
 87     AddValue(floatValue);
 88     return floatValue;
 89 }
 90 
 91 ConstantValue* Context::GetDoubleValue(double value)
 92 {
 93     ConstantValue* doubleValue = new DoubleValue(value);
 94     AddValue(doubleValue);
 95     return doubleValue;
 96 }
 97 
 98 ArrayValue* Context::GetArrayValue(Type* arrayTypeconst std::std::vector<ConstantValue*>&elementsconststd::string&prefix)
 99 {
100     ArrayValue* arrayValue = new ArrayValue(arrayTypeelementsprefix);
101     AddValue(arrayValue);
102     return arrayValue;
103 }
104 
105 StructureValue* Context::GetStructureValue(Type* structureTypeconst std::std::vector<ConstantValue*>&members)
106 {
107     StructureValue* structureValue = new StructureValue(structureTypemembers);
108     AddValue(structureValue);
109     return structureValue;
110 }
111 
112 StringValue* Context::GetStringValue(Type* stringTypeconst std::string& value)
113 {
114     StringValue* stringValue = new StringValue(stringTypevalue);
115     AddValue(stringValue);
116     return stringValue;
117 }
118 
119 ConversionValue* Context::GetConversionValue(Type* typeConstantValue* from)
120 {
121     ConversionValue* conversionValue = new ConversionValue(typefrom);
122     AddValue(conversionValue);
123     return conversionValue;
124 }
125 
126 ClsIdValue* Context::GetClsIdValue(const std::string& typeId)
127 {
128     ClsIdValue* clsIdValue = new ClsIdValue(typeId);
129     AddValue(clsIdValue);
130     return clsIdValue;
131 }
132 
133 Instruction* Context::CreateNot(Value* arg)
134 {
135     Instruction* inst = new NotInstruction(arg);
136     AddLineInfo(inst);
137     currentBasicBlock->AddInstruction(inst);
138     return inst;
139 }
140 
141 Instruction* Context::CreateNeg(Value* arg)
142 {
143     Instruction* inst = new NegInstruction(arg);
144     AddLineInfo(inst);
145     currentBasicBlock->AddInstruction(inst);
146     return inst;
147 }
148 
149 Instruction* Context::CreateAdd(Value* leftValue* right)
150 {
151     Instruction* inst = new AddInstruction(leftright);
152     AddLineInfo(inst);
153     currentBasicBlock->AddInstruction(inst);
154     return inst;
155 }
156 
157 Instruction* Context::CreateSub(Value* leftValue* right)
158 {
159     Instruction* inst = new SubInstruction(leftright);
160     AddLineInfo(inst);
161     currentBasicBlock->AddInstruction(inst);
162     return inst;
163 }
164 
165 Instruction* Context::CreateMul(Value* leftValue* right)
166 {
167     Instruction* inst = new MulInstruction(leftright);
168     AddLineInfo(inst);
169     currentBasicBlock->AddInstruction(inst);
170     return inst;
171 }
172 
173 Instruction* Context::CreateDiv(Value* leftValue* right)
174 {
175     Instruction* inst = new DivInstruction(leftright);
176     AddLineInfo(inst);
177     currentBasicBlock->AddInstruction(inst);
178     return inst;
179 }
180 
181 Instruction* Context::CreateMod(Value* leftValue* right)
182 {
183     Instruction* inst = new ModInstruction(leftright);
184     AddLineInfo(inst);
185     currentBasicBlock->AddInstruction(inst);
186     return inst;
187 }
188 
189 Instruction* Context::CreateAnd(Value* leftValue* right)
190 {
191     Instruction* inst = new AndInstruction(leftright);
192     AddLineInfo(inst);
193     currentBasicBlock->AddInstruction(inst);
194     return inst;
195 }
196 
197 Instruction* Context::CreateOr(Value* leftValue* right)
198 {
199     Instruction* inst = new OrInstruction(leftright);
200     AddLineInfo(inst);
201     currentBasicBlock->AddInstruction(inst);
202     return inst;
203 }
204 
205 Instruction* Context::CreateXor(Value* leftValue* right)
206 {
207     Instruction* inst = new XorInstruction(leftright);
208     AddLineInfo(inst);
209     currentBasicBlock->AddInstruction(inst);
210     return inst;
211 }
212 
213 Instruction* Context::CreateShl(Value* leftValue* right)
214 {
215     Instruction* inst = new ShlInstruction(leftright);
216     AddLineInfo(inst);
217     currentBasicBlock->AddInstruction(inst);
218     return inst;
219 }
220 
221 Instruction* Context::CreateShr(Value* leftValue* right)
222 {
223     Instruction* inst = new ShrInstruction(leftright);
224     AddLineInfo(inst);
225     currentBasicBlock->AddInstruction(inst);
226     return inst;
227 }
228 
229 Instruction* Context::CreateEqual(Value* leftValue* right)
230 {
231     Instruction* inst = new EqualInstruction(leftright);
232     AddLineInfo(inst);
233     currentBasicBlock->AddInstruction(inst);
234     return inst;
235 }
236 
237 Instruction* Context::CreateLess(Value* leftValue* right)
238 {
239     Instruction* inst = new LessInstruction(leftright);
240     AddLineInfo(inst);
241     currentBasicBlock->AddInstruction(inst);
242     return inst;
243 }
244 
245 Instruction* Context::CreateSignExtend(Value* argType* destType)
246 {
247     Instruction* inst = new SignExtendInstruction(argdestType);
248     AddLineInfo(inst);
249     currentBasicBlock->AddInstruction(inst);
250     return inst;
251 }
252 
253 Instruction* Context::CreateZeroExtend(Value* argType* destType)
254 {
255     Instruction* inst = new ZeroExtendInstruction(argdestType);
256     AddLineInfo(inst);
257     currentBasicBlock->AddInstruction(inst);
258     return inst;
259 }
260 
261 Instruction* Context::CreateTruncate(Value* argType* destType)
262 {
263     Instruction* inst = new TruncateInstruction(argdestType);
264     AddLineInfo(inst);
265     currentBasicBlock->AddInstruction(inst);
266     return inst;
267 }
268 
269 Instruction* Context::CreateBitCast(Value* argType* destType)
270 {
271     Instruction* inst = new BitCastInstruction(argdestType);
272     AddLineInfo(inst);
273     currentBasicBlock->AddInstruction(inst);
274     return inst;
275 }
276 
277 Instruction* Context::CreateIntToFloat(Value* argType* destType)
278 {
279     Instruction* inst = new IntToFloatInstruction(argdestType);
280     AddLineInfo(inst);
281     currentBasicBlock->AddInstruction(inst);
282     return inst;
283 }
284 
285 Instruction* Context::CreateFloatToInt(Value* argType* destType)
286 {
287     Instruction* inst = new FloatToIntInstruction(argdestType);
288     AddLineInfo(inst);
289     currentBasicBlock->AddInstruction(inst);
290     return inst;
291 }
292 
293 Instruction* Context::CreateIntToPtr(Value* argType* destType)
294 {
295     Instruction* inst = new IntToPtrInstruction(argdestType);
296     AddLineInfo(inst);
297     currentBasicBlock->AddInstruction(inst);
298     return inst;
299 }
300 
301 Instruction* Context::CreatePtrToInt(Value* argType* destType)
302 {
303     Instruction* inst = new PtrToIntInstruction(argdestType);
304     AddLineInfo(inst);
305     currentBasicBlock->AddInstruction(inst);
306     return inst;
307 }
308 
309 Instruction* Context::CreateParam(Type* type)
310 {
311     Instruction* inst = new ParamInstruction(type);
312     AddLineInfo(inst);
313     currentBasicBlock->AddInstruction(inst);
314     return inst;
315 }
316 
317 Instruction* Context::CreateLocal(Type* type)
318 {
319     Instruction* inst = new LocalInstruction(type);
320     AddLineInfo(inst);
321     currentBasicBlock->AddInstruction(inst);
322     return inst;
323 }
324 
325 Instruction* Context::CreateLoad(Value* ptr)
326 {
327     Instruction* inst = new LoadInstruction(ptr);
328     AddLineInfo(inst);
329     currentBasicBlock->AddInstruction(inst);
330     return inst;
331 }
332 
333 Instruction* Context::CreateStore(Value* valueValue* ptr)
334 {
335     Instruction* inst = new StoreInstruction(valueptr);
336     AddLineInfo(inst);
337     currentBasicBlock->AddInstruction(inst);
338     return inst;
339 }
340 
341 Instruction* Context::CreateArg(Value* arg)
342 {
343     Instruction* inst = new ArgInstruction(arg);
344     AddLineInfo(inst);
345     currentBasicBlock->AddInstruction(inst);
346     return inst;
347 }
348 
349 Instruction* Context::CreateElemAddr(Value* ptrValue* index)
350 {
351     Instruction* inst = new ElemAddrInstruction(ptrindex);
352     AddLineInfo(inst);
353     currentBasicBlock->AddInstruction(inst);
354     return inst;
355 }
356 
357 Instruction* Context::CreatePtrOffset(Value* ptrValue* offset)
358 {
359     Instruction* inst = new PtrOffsetInstruction(ptroffset);
360     AddLineInfo(inst);
361     currentBasicBlock->AddInstruction(inst);
362     return inst;
363 }
364 
365 Instruction* Context::CreatePtrDiff(Value* leftPtrValue* rightPtr)
366 {
367     Instruction* inst = new PtrDiffInstruction(leftPtrrightPtr);
368     AddLineInfo(inst);
369     currentBasicBlock->AddInstruction(inst);
370     return inst;
371 }
372 
373 Instruction* Context::CreateCall(Value* function)
374 {
375     Instruction* inst = new CallInstruction(function);
376     AddLineInfo(inst);
377     currentBasicBlock->AddInstruction(inst);
378     return inst;
379 }
380 
381 Instruction* Context::CreateRet(Value* value)
382 {
383     Instruction* inst = new RetInstruction(value);
384     AddLineInfo(inst);
385     currentBasicBlock->AddInstruction(inst);
386     return inst;
387 }
388 
389 Instruction* Context::CreateJump(BasicBlock* dest)
390 {
391     Instruction* inst = new JumpInstruction(dest);
392     AddLineInfo(inst);
393     currentBasicBlock->AddInstruction(inst);
394     return inst;
395 }
396 
397 Instruction* Context::CreateBranch(Value* condBasicBlock* trueDestBasicBlock* falseDest)
398 {
399     Instruction* inst = new BranchInstruction(condtrueDestfalseDest);
400     AddLineInfo(inst);
401     currentBasicBlock->AddInstruction(inst);
402     return inst;
403 }
404 
405 Instruction* Context::CreateSwitch(Value* condBasicBlock* defaultDest)
406 {
407     Instruction* inst = new SwitchInstruction(conddefaultDest);
408     AddLineInfo(inst);
409     currentBasicBlock->AddInstruction(inst);
410     return inst;
411 }
412 
413 Instruction* Context::CreateTrap(const std::std::vector<Value*>&args)
414 {
415     Value* b0 = nullptr;
416     Value* b1 = nullptr;
417     Value* b2 = nullptr;
418     int n = args.size();
419     for (int i = 0; i < n; ++i)
420     {
421         Value* arg = args[i];
422         if (i == 0)
423         {
424             b0 = arg;
425         }
426         else if (i == 1)
427         {
428             b1 = arg;
429         }
430         else if (i == 2)
431         {
432             b2 = arg;
433         }
434         else
435         {
436             CreateArg(arg);
437         }
438     }
439     Instruction* inst = new TrapInstruction(b0b1b2);
440     AddLineInfo(inst);
441     currentBasicBlock->AddInstruction(inst);
442     return inst;
443 }
444 
445 Instruction* Context::CreateNop()
446 {
447     Instruction* inst = new NoOperationInstruction();
448     currentBasicBlock->AddInstruction(inst);
449     return inst;
450 }
451 
452 Instruction* Context::CreateSave()
453 {
454     Instruction* inst = new SaveInstruction();
455     currentBasicBlock->AddInstruction(inst);
456     return inst;
457 }
458 
459 GlobalVariable* Context::GetOrInsertGlobal(const std::string& nameType* type)
460 {
461     return dataRepository.GetOrInsertGlobal(nametype);
462 }
463 
464 GlobalVariable* Context::CreateGlobalStringPtr(const std::string& stringValue)
465 {
466     return dataRepository.CreateGlobalStringPtr(*thisstringValue);
467 }
468 
469 void Context::SetCompileUnitId(const std::string& compileUnitId_)
470 {
471     dataRepository.SetCompileUnitId(compileUnitId_);
472 }
473 
474 void Context::AddMDStructItem(MDStruct* mdStructconst std::string& fieldNameMDItem* item)
475 {
476     mdStruct->AddItem(fieldNameitem);
477 }
478 
479 void Context::SetCurrentLineNumber(int lineNumber)
480 {
481     if (lineNumber != -1)
482     {
483         currentLineNumber = lineNumber;
484     }
485 }
486 
487 void Context::AddLineInfo(Instruction* inst)
488 {
489     if (currentLineNumber != 0 && !inst->IsNoOperation())
490     {
491         MDStructRef* lineNumberInfo = nullptr;
492         auto it = lineNumberInfoMap.find(currentLineNumber);
493         if (it != lineNumberInfoMap.cend())
494         {
495             lineNumberInfo = it->second;
496         }
497         else
498         {
499             MDStruct* lineNumberStruct = metadata.CreateMDStruct();
500             lineNumberStruct->AddItem("nodeType"metadata.CreateMDLong(lineInfoNodeType));
501             lineNumberStruct->AddItem("line"metadata.CreateMDLong(currentLineNumber));
502             lineNumberInfo = metadata.CreateMDStructRef(lineNumberStruct->Id());
503             lineNumberInfoMap[currentLineNumber] = lineNumberInfo;
504         }
505         inst->SetMetadataRef(lineNumberInfo);
506     }
507 }
508 
509 MDStructRef* Context::GetMDStructRefForSourceFile(const std::string& sourceFileName)
510 {
511     auto it = sourceFileMap.find(sourceFileName);
512     if (it != sourceFileMap.cend())
513     {
514         return it->second;
515     }
516     else
517     {
518         MDStruct* sourceFileStruct = metadata.CreateMDStruct();
519         sourceFileStruct->AddItem("nodeType"metadata.CreateMDLong(fileInfoNodeType));
520         sourceFileStruct->AddItem("sourceFileName"metadata.CreateMDString(sourceFileName));
521         MDStructRef* sourceFileNameRef = metadata.CreateMDStructRef(sourceFileStruct->Id());
522         sourceFileMap[sourceFileName] = sourceFileNameRef;
523         return sourceFileNameRef;
524     }
525 }
526 
527 void Context::SetMetadataRef(Instruction* instMDStructRef* metadataRef)
528 {
529     inst->SetMetadataRef(metadataRef);
530 }
531 
532 } // namespace cmsxi