blob: 6b572f35a53b5563024b843ad2f33a055b8fca5d [file] [log] [blame]
Chris Lattner31c2ec32007-05-06 20:31:17 +00001//===-- MSILWriter.cpp - Library for converting LLVM code to MSIL ---------===//
Anton Korobeynikov099883f2007-03-21 21:38:25 +00002//
Bill Wendling85db3a92008-02-26 10:57:23 +00003// The LLVM Compiler Infrastructure
Anton Korobeynikov099883f2007-03-21 21:38:25 +00004//
Chris Lattner4ee451d2007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Anton Korobeynikov099883f2007-03-21 21:38:25 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This library converts LLVM code to MSIL code.
11//
12//===----------------------------------------------------------------------===//
13
14#include "MSILWriter.h"
15#include "llvm/CallingConv.h"
16#include "llvm/DerivedTypes.h"
17#include "llvm/Intrinsics.h"
18#include "llvm/IntrinsicInst.h"
19#include "llvm/TypeSymbolTable.h"
20#include "llvm/Analysis/ConstantsScanner.h"
21#include "llvm/Support/CallSite.h"
22#include "llvm/Support/InstVisitor.h"
Anton Korobeynikovf13090c2007-05-06 20:13:33 +000023#include "llvm/Support/MathExtras.h"
Anton Korobeynikov099883f2007-03-21 21:38:25 +000024#include "llvm/Transforms/Scalar.h"
25#include "llvm/ADT/StringExtras.h"
Gordon Henriksence224772008-01-07 01:30:38 +000026#include "llvm/CodeGen/Passes.h"
Anton Korobeynikov099883f2007-03-21 21:38:25 +000027
28namespace {
29 // TargetMachine for the MSIL
30 struct VISIBILITY_HIDDEN MSILTarget : public TargetMachine {
31 const TargetData DataLayout; // Calculates type size & alignment
32
33 MSILTarget(const Module &M, const std::string &FS)
34 : DataLayout(&M) {}
35
36 virtual bool WantsWholeFile() const { return true; }
Owen Andersoncb371882008-08-21 00:14:44 +000037 virtual bool addPassesToEmitWholeFile(PassManager &PM, raw_ostream &Out,
Anton Korobeynikov099883f2007-03-21 21:38:25 +000038 CodeGenFileType FileType, bool Fast);
39
40 // This class always works, but shouldn't be the default in most cases.
41 static unsigned getModuleMatchQuality(const Module &M) { return 1; }
42
43 virtual const TargetData *getTargetData() const { return &DataLayout; }
44 };
45}
46
Oscar Fuentes92adc192008-11-15 21:36:30 +000047/// MSILTargetMachineModule - Note that this is used on hosts that
48/// cannot link in a library unless there are references into the
49/// library. In particular, it seems that it is not possible to get
50/// things to work on Win32 without this. Though it is unused, do not
51/// remove it.
52extern "C" int MSILTargetMachineModule;
53int MSILTargetMachineModule = 0;
Anton Korobeynikov099883f2007-03-21 21:38:25 +000054
Dan Gohmanb8cab922008-10-14 20:25:08 +000055static RegisterTarget<MSILTarget> X("msil", "MSIL backend");
Anton Korobeynikov099883f2007-03-21 21:38:25 +000056
57bool MSILModule::runOnModule(Module &M) {
58 ModulePtr = &M;
59 TD = &getAnalysis<TargetData>();
60 bool Changed = false;
61 // Find named types.
62 TypeSymbolTable& Table = M.getTypeSymbolTable();
63 std::set<const Type *> Types = getAnalysis<FindUsedTypes>().getTypes();
64 for (TypeSymbolTable::iterator I = Table.begin(), E = Table.end(); I!=E; ) {
65 if (!isa<StructType>(I->second) && !isa<OpaqueType>(I->second))
66 Table.remove(I++);
67 else {
68 std::set<const Type *>::iterator T = Types.find(I->second);
69 if (T==Types.end())
70 Table.remove(I++);
71 else {
72 Types.erase(T);
73 ++I;
74 }
75 }
76 }
77 // Find unnamed types.
78 unsigned RenameCounter = 0;
79 for (std::set<const Type *>::const_iterator I = Types.begin(),
80 E = Types.end(); I!=E; ++I)
81 if (const StructType *STy = dyn_cast<StructType>(*I)) {
82 while (ModulePtr->addTypeName("unnamed$"+utostr(RenameCounter), STy))
83 ++RenameCounter;
84 Changed = true;
85 }
86 // Pointer for FunctionPass.
87 UsedTypes = &getAnalysis<FindUsedTypes>().getTypes();
88 return Changed;
89}
90
Devang Patel19974732007-05-03 01:11:54 +000091char MSILModule::ID = 0;
92char MSILWriter::ID = 0;
Anton Korobeynikov099883f2007-03-21 21:38:25 +000093
94bool MSILWriter::runOnFunction(Function &F) {
95 if (F.isDeclaration()) return false;
Chris Lattner9062d9a2009-04-17 00:26:12 +000096
97 // Do not codegen any 'available_externally' functions at all, they have
98 // definitions outside the translation unit.
99 if (F.hasAvailableExternallyLinkage())
100 return false;
101
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000102 LInfo = &getAnalysis<LoopInfo>();
103 printFunction(F);
104 return false;
105}
106
107
108bool MSILWriter::doInitialization(Module &M) {
109 ModulePtr = &M;
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000110 Mang = new Mangler(M);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000111 Out << ".assembly extern mscorlib {}\n";
112 Out << ".assembly MSIL {}\n\n";
113 Out << "// External\n";
114 printExternals();
115 Out << "// Declarations\n";
116 printDeclarations(M.getTypeSymbolTable());
117 Out << "// Definitions\n";
118 printGlobalVariables();
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000119 Out << "// Startup code\n";
120 printModuleStartup();
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000121 return false;
122}
123
124
125bool MSILWriter::doFinalization(Module &M) {
126 delete Mang;
127 return false;
128}
129
130
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000131void MSILWriter::printModuleStartup() {
132 Out <<
133 ".method static public int32 $MSIL_Startup() {\n"
134 "\t.entrypoint\n"
135 "\t.locals (native int i)\n"
136 "\t.locals (native int argc)\n"
137 "\t.locals (native int ptr)\n"
138 "\t.locals (void* argv)\n"
139 "\t.locals (string[] args)\n"
140 "\tcall\tstring[] [mscorlib]System.Environment::GetCommandLineArgs()\n"
141 "\tdup\n"
142 "\tstloc\targs\n"
143 "\tldlen\n"
144 "\tconv.i4\n"
145 "\tdup\n"
146 "\tstloc\targc\n";
147 printPtrLoad(TD->getPointerSize());
148 Out <<
149 "\tmul\n"
150 "\tlocalloc\n"
151 "\tstloc\targv\n"
152 "\tldc.i4.0\n"
153 "\tstloc\ti\n"
154 "L_01:\n"
155 "\tldloc\ti\n"
156 "\tldloc\targc\n"
157 "\tceq\n"
158 "\tbrtrue\tL_02\n"
159 "\tldloc\targs\n"
160 "\tldloc\ti\n"
161 "\tldelem.ref\n"
162 "\tcall\tnative int [mscorlib]System.Runtime.InteropServices.Marshal::"
163 "StringToHGlobalAnsi(string)\n"
164 "\tstloc\tptr\n"
165 "\tldloc\targv\n"
166 "\tldloc\ti\n";
167 printPtrLoad(TD->getPointerSize());
168 Out <<
169 "\tmul\n"
170 "\tadd\n"
171 "\tldloc\tptr\n"
172 "\tstind.i\n"
173 "\tldloc\ti\n"
174 "\tldc.i4.1\n"
175 "\tadd\n"
176 "\tstloc\ti\n"
177 "\tbr\tL_01\n"
178 "L_02:\n"
179 "\tcall void $MSIL_Init()\n";
180
181 // Call user 'main' function.
182 const Function* F = ModulePtr->getFunction("main");
183 if (!F || F->isDeclaration()) {
184 Out << "\tldc.i4.0\n\tret\n}\n";
185 return;
186 }
Nick Lewycky9c0f1462009-03-19 05:51:39 +0000187 bool BadSig = true;
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000188 std::string Args("");
189 Function::const_arg_iterator Arg1,Arg2;
190
191 switch (F->arg_size()) {
192 case 0:
193 BadSig = false;
194 break;
195 case 1:
196 Arg1 = F->arg_begin();
197 if (Arg1->getType()->isInteger()) {
198 Out << "\tldloc\targc\n";
199 Args = getTypeName(Arg1->getType());
200 BadSig = false;
201 }
202 break;
203 case 2:
204 Arg1 = Arg2 = F->arg_begin(); ++Arg2;
205 if (Arg1->getType()->isInteger() &&
206 Arg2->getType()->getTypeID() == Type::PointerTyID) {
207 Out << "\tldloc\targc\n\tldloc\targv\n";
208 Args = getTypeName(Arg1->getType())+","+getTypeName(Arg2->getType());
209 BadSig = false;
210 }
211 break;
212 default:
213 BadSig = true;
214 }
215
216 bool RetVoid = (F->getReturnType()->getTypeID() == Type::VoidTyID);
Anton Korobeynikov7c1c2612008-02-20 11:22:39 +0000217 if (BadSig || (!F->getReturnType()->isInteger() && !RetVoid)) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000218 Out << "\tldc.i4.0\n";
219 } else {
220 Out << "\tcall\t" << getTypeName(F->getReturnType()) <<
221 getConvModopt(F->getCallingConv()) << "main(" << Args << ")\n";
222 if (RetVoid)
223 Out << "\tldc.i4.0\n";
224 else
225 Out << "\tconv.i4\n";
226 }
227 Out << "\tret\n}\n";
228}
229
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000230bool MSILWriter::isZeroValue(const Value* V) {
231 if (const Constant *C = dyn_cast<Constant>(V))
232 return C->isNullValue();
233 return false;
234}
235
236
237std::string MSILWriter::getValueName(const Value* V) {
238 // Name into the quotes allow control and space characters.
239 return "'"+Mang->getValueName(V)+"'";
240}
241
242
243std::string MSILWriter::getLabelName(const std::string& Name) {
244 if (Name.find('.')!=std::string::npos) {
245 std::string Tmp(Name);
246 // Replace unaccepable characters in the label name.
247 for (std::string::iterator I = Tmp.begin(), E = Tmp.end(); I!=E; ++I)
248 if (*I=='.') *I = '@';
249 return Tmp;
250 }
251 return Name;
252}
253
254
255std::string MSILWriter::getLabelName(const Value* V) {
256 return getLabelName(Mang->getValueName(V));
257}
258
259
260std::string MSILWriter::getConvModopt(unsigned CallingConvID) {
261 switch (CallingConvID) {
262 case CallingConv::C:
263 case CallingConv::Cold:
264 case CallingConv::Fast:
265 return "modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl) ";
266 case CallingConv::X86_FastCall:
267 return "modopt([mscorlib]System.Runtime.CompilerServices.CallConvFastcall) ";
268 case CallingConv::X86_StdCall:
269 return "modopt([mscorlib]System.Runtime.CompilerServices.CallConvStdcall) ";
270 default:
271 cerr << "CallingConvID = " << CallingConvID << '\n';
272 assert(0 && "Unsupported calling convention");
273 }
Chris Lattnerd27c9912008-03-30 18:22:13 +0000274 return ""; // Not reached
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000275}
276
277
278std::string MSILWriter::getArrayTypeName(Type::TypeID TyID, const Type* Ty) {
279 std::string Tmp = "";
280 const Type* ElemTy = Ty;
281 assert(Ty->getTypeID()==TyID && "Invalid type passed");
282 // Walk trought array element types.
283 for (;;) {
284 // Multidimensional array.
285 if (ElemTy->getTypeID()==TyID) {
286 if (const ArrayType* ATy = dyn_cast<ArrayType>(ElemTy))
287 Tmp += utostr(ATy->getNumElements());
288 else if (const VectorType* VTy = dyn_cast<VectorType>(ElemTy))
289 Tmp += utostr(VTy->getNumElements());
290 ElemTy = cast<SequentialType>(ElemTy)->getElementType();
291 }
292 // Base element type found.
293 if (ElemTy->getTypeID()!=TyID) break;
294 Tmp += ",";
295 }
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000296 return getTypeName(ElemTy, false, true)+"["+Tmp+"]";
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000297}
298
299
300std::string MSILWriter::getPrimitiveTypeName(const Type* Ty, bool isSigned) {
301 unsigned NumBits = 0;
302 switch (Ty->getTypeID()) {
303 case Type::VoidTyID:
304 return "void ";
305 case Type::IntegerTyID:
306 NumBits = getBitWidth(Ty);
307 if(NumBits==1)
308 return "bool ";
309 if (!isSigned)
310 return "unsigned int"+utostr(NumBits)+" ";
311 return "int"+utostr(NumBits)+" ";
312 case Type::FloatTyID:
313 return "float32 ";
314 case Type::DoubleTyID:
315 return "float64 ";
316 default:
317 cerr << "Type = " << *Ty << '\n';
318 assert(0 && "Invalid primitive type");
319 }
Chris Lattnerd27c9912008-03-30 18:22:13 +0000320 return ""; // Not reached
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000321}
322
323
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000324std::string MSILWriter::getTypeName(const Type* Ty, bool isSigned,
325 bool isNested) {
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000326 if (Ty->isPrimitiveType() || Ty->isInteger())
327 return getPrimitiveTypeName(Ty,isSigned);
328 // FIXME: "OpaqueType" support
329 switch (Ty->getTypeID()) {
330 case Type::PointerTyID:
331 return "void* ";
332 case Type::StructTyID:
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000333 if (isNested)
334 return ModulePtr->getTypeName(Ty);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000335 return "valuetype '"+ModulePtr->getTypeName(Ty)+"' ";
336 case Type::ArrayTyID:
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000337 if (isNested)
338 return getArrayTypeName(Ty->getTypeID(),Ty);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000339 return "valuetype '"+getArrayTypeName(Ty->getTypeID(),Ty)+"' ";
340 case Type::VectorTyID:
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000341 if (isNested)
342 return getArrayTypeName(Ty->getTypeID(),Ty);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000343 return "valuetype '"+getArrayTypeName(Ty->getTypeID(),Ty)+"' ";
344 default:
345 cerr << "Type = " << *Ty << '\n';
346 assert(0 && "Invalid type in getTypeName()");
347 }
Chris Lattnerd27c9912008-03-30 18:22:13 +0000348 return ""; // Not reached
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000349}
350
351
352MSILWriter::ValueType MSILWriter::getValueLocation(const Value* V) {
353 // Function argument
354 if (isa<Argument>(V))
355 return ArgumentVT;
356 // Function
357 else if (const Function* F = dyn_cast<Function>(V))
Rafael Espindolabb46f522009-01-15 20:18:42 +0000358 return F->hasLocalLinkage() ? InternalVT : GlobalVT;
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000359 // Variable
360 else if (const GlobalVariable* G = dyn_cast<GlobalVariable>(V))
Rafael Espindolabb46f522009-01-15 20:18:42 +0000361 return G->hasLocalLinkage() ? InternalVT : GlobalVT;
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000362 // Constant
363 else if (isa<Constant>(V))
364 return isa<ConstantExpr>(V) ? ConstExprVT : ConstVT;
365 // Local variable
366 return LocalVT;
367}
368
369
370std::string MSILWriter::getTypePostfix(const Type* Ty, bool Expand,
371 bool isSigned) {
372 unsigned NumBits = 0;
373 switch (Ty->getTypeID()) {
374 // Integer constant, expanding for stack operations.
375 case Type::IntegerTyID:
376 NumBits = getBitWidth(Ty);
377 // Expand integer value to "int32" or "int64".
378 if (Expand) return (NumBits<=32 ? "i4" : "i8");
379 if (NumBits==1) return "i1";
380 return (isSigned ? "i" : "u")+utostr(NumBits/8);
381 // Float constant.
382 case Type::FloatTyID:
383 return "r4";
384 case Type::DoubleTyID:
385 return "r8";
386 case Type::PointerTyID:
Duncan Sandsceb4d1a2009-01-12 20:38:59 +0000387 return "i"+utostr(TD->getTypePaddedSize(Ty));
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000388 default:
389 cerr << "TypeID = " << Ty->getTypeID() << '\n';
390 assert(0 && "Invalid type in TypeToPostfix()");
391 }
Chris Lattnerd27c9912008-03-30 18:22:13 +0000392 return ""; // Not reached
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000393}
394
395
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000396void MSILWriter::printConvToPtr() {
397 switch (ModulePtr->getPointerSize()) {
398 case Module::Pointer32:
399 printSimpleInstruction("conv.u4");
400 break;
401 case Module::Pointer64:
402 printSimpleInstruction("conv.u8");
403 break;
404 default:
405 assert(0 && "Module use not supporting pointer size");
406 }
407}
408
409
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000410void MSILWriter::printPtrLoad(uint64_t N) {
411 switch (ModulePtr->getPointerSize()) {
412 case Module::Pointer32:
413 printSimpleInstruction("ldc.i4",utostr(N).c_str());
414 // FIXME: Need overflow test?
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000415 if (!isUInt32(N)) {
416 cerr << "Value = " << utostr(N) << '\n';
417 assert(0 && "32-bit pointer overflowed");
418 }
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000419 break;
420 case Module::Pointer64:
421 printSimpleInstruction("ldc.i8",utostr(N).c_str());
422 break;
423 default:
424 assert(0 && "Module use not supporting pointer size");
425 }
426}
427
428
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000429void MSILWriter::printValuePtrLoad(const Value* V) {
430 printValueLoad(V);
431 printConvToPtr();
432}
433
434
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000435void MSILWriter::printConstLoad(const Constant* C) {
436 if (const ConstantInt* CInt = dyn_cast<ConstantInt>(C)) {
437 // Integer constant
438 Out << "\tldc." << getTypePostfix(C->getType(),true) << '\t';
439 if (CInt->isMinValue(true))
440 Out << CInt->getSExtValue();
441 else
442 Out << CInt->getZExtValue();
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000443 } else if (const ConstantFP* FP = dyn_cast<ConstantFP>(C)) {
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000444 // Float constant
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000445 uint64_t X;
446 unsigned Size;
447 if (FP->getType()->getTypeID()==Type::FloatTyID) {
Dale Johannesen7111b022008-10-09 18:53:47 +0000448 X = (uint32_t)FP->getValueAPF().bitcastToAPInt().getZExtValue();
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000449 Size = 4;
450 } else {
Dale Johannesen7111b022008-10-09 18:53:47 +0000451 X = FP->getValueAPF().bitcastToAPInt().getZExtValue();
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000452 Size = 8;
453 }
454 Out << "\tldc.r" << Size << "\t( " << utohexstr(X) << ')';
455 } else if (isa<UndefValue>(C)) {
456 // Undefined constant value = NULL.
457 printPtrLoad(0);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000458 } else {
459 cerr << "Constant = " << *C << '\n';
460 assert(0 && "Invalid constant value");
461 }
462 Out << '\n';
463}
464
465
466void MSILWriter::printValueLoad(const Value* V) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000467 MSILWriter::ValueType Location = getValueLocation(V);
468 switch (Location) {
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000469 // Global variable or function address.
470 case GlobalVT:
471 case InternalVT:
472 if (const Function* F = dyn_cast<Function>(V)) {
473 std::string Name = getConvModopt(F->getCallingConv())+getValueName(F);
474 printSimpleInstruction("ldftn",
475 getCallSignature(F->getFunctionType(),NULL,Name).c_str());
476 } else {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000477 std::string Tmp;
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000478 const Type* ElemTy = cast<PointerType>(V->getType())->getElementType();
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000479 if (Location==GlobalVT && cast<GlobalVariable>(V)->hasDLLImportLinkage()) {
480 Tmp = "void* "+getValueName(V);
481 printSimpleInstruction("ldsfld",Tmp.c_str());
482 } else {
483 Tmp = getTypeName(ElemTy)+getValueName(V);
484 printSimpleInstruction("ldsflda",Tmp.c_str());
485 }
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000486 }
487 break;
488 // Function argument.
489 case ArgumentVT:
490 printSimpleInstruction("ldarg",getValueName(V).c_str());
491 break;
492 // Local function variable.
493 case LocalVT:
494 printSimpleInstruction("ldloc",getValueName(V).c_str());
495 break;
496 // Constant value.
497 case ConstVT:
498 if (isa<ConstantPointerNull>(V))
499 printPtrLoad(0);
500 else
501 printConstLoad(cast<Constant>(V));
502 break;
503 // Constant expression.
504 case ConstExprVT:
505 printConstantExpr(cast<ConstantExpr>(V));
506 break;
507 default:
508 cerr << "Value = " << *V << '\n';
509 assert(0 && "Invalid value location");
510 }
511}
512
513
514void MSILWriter::printValueSave(const Value* V) {
515 switch (getValueLocation(V)) {
516 case ArgumentVT:
517 printSimpleInstruction("starg",getValueName(V).c_str());
518 break;
519 case LocalVT:
520 printSimpleInstruction("stloc",getValueName(V).c_str());
521 break;
522 default:
523 cerr << "Value = " << *V << '\n';
524 assert(0 && "Invalid value location");
525 }
526}
527
528
529void MSILWriter::printBinaryInstruction(const char* Name, const Value* Left,
530 const Value* Right) {
531 printValueLoad(Left);
532 printValueLoad(Right);
533 Out << '\t' << Name << '\n';
534}
535
536
537void MSILWriter::printSimpleInstruction(const char* Inst, const char* Operand) {
538 if(Operand)
539 Out << '\t' << Inst << '\t' << Operand << '\n';
540 else
541 Out << '\t' << Inst << '\n';
542}
543
544
545void MSILWriter::printPHICopy(const BasicBlock* Src, const BasicBlock* Dst) {
546 for (BasicBlock::const_iterator I = Dst->begin(), E = Dst->end();
547 isa<PHINode>(I); ++I) {
548 const PHINode* Phi = cast<PHINode>(I);
549 const Value* Val = Phi->getIncomingValueForBlock(Src);
550 if (isa<UndefValue>(Val)) continue;
551 printValueLoad(Val);
552 printValueSave(Phi);
553 }
554}
555
556
557void MSILWriter::printBranchToBlock(const BasicBlock* CurrBB,
558 const BasicBlock* TrueBB,
559 const BasicBlock* FalseBB) {
560 if (TrueBB==FalseBB) {
561 // "TrueBB" and "FalseBB" destination equals
562 printPHICopy(CurrBB,TrueBB);
563 printSimpleInstruction("pop");
564 printSimpleInstruction("br",getLabelName(TrueBB).c_str());
565 } else if (FalseBB==NULL) {
566 // If "FalseBB" not used the jump have condition
567 printPHICopy(CurrBB,TrueBB);
568 printSimpleInstruction("brtrue",getLabelName(TrueBB).c_str());
569 } else if (TrueBB==NULL) {
570 // If "TrueBB" not used the jump is unconditional
571 printPHICopy(CurrBB,FalseBB);
572 printSimpleInstruction("br",getLabelName(FalseBB).c_str());
573 } else {
574 // Copy PHI instructions for each block
575 std::string TmpLabel;
576 // Print PHI instructions for "TrueBB"
577 if (isa<PHINode>(TrueBB->begin())) {
578 TmpLabel = getLabelName(TrueBB)+"$phi_"+utostr(getUniqID());
579 printSimpleInstruction("brtrue",TmpLabel.c_str());
580 } else {
581 printSimpleInstruction("brtrue",getLabelName(TrueBB).c_str());
582 }
583 // Print PHI instructions for "FalseBB"
584 if (isa<PHINode>(FalseBB->begin())) {
585 printPHICopy(CurrBB,FalseBB);
586 printSimpleInstruction("br",getLabelName(FalseBB).c_str());
587 } else {
588 printSimpleInstruction("br",getLabelName(FalseBB).c_str());
589 }
590 if (isa<PHINode>(TrueBB->begin())) {
591 // Handle "TrueBB" PHI Copy
592 Out << TmpLabel << ":\n";
593 printPHICopy(CurrBB,TrueBB);
594 printSimpleInstruction("br",getLabelName(TrueBB).c_str());
595 }
596 }
597}
598
599
600void MSILWriter::printBranchInstruction(const BranchInst* Inst) {
601 if (Inst->isUnconditional()) {
602 printBranchToBlock(Inst->getParent(),NULL,Inst->getSuccessor(0));
603 } else {
604 printValueLoad(Inst->getCondition());
605 printBranchToBlock(Inst->getParent(),Inst->getSuccessor(0),
606 Inst->getSuccessor(1));
607 }
608}
609
610
611void MSILWriter::printSelectInstruction(const Value* Cond, const Value* VTrue,
612 const Value* VFalse) {
613 std::string TmpLabel = std::string("select$true_")+utostr(getUniqID());
614 printValueLoad(VTrue);
615 printValueLoad(Cond);
616 printSimpleInstruction("brtrue",TmpLabel.c_str());
617 printSimpleInstruction("pop");
618 printValueLoad(VFalse);
619 Out << TmpLabel << ":\n";
620}
621
622
623void MSILWriter::printIndirectLoad(const Value* V) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000624 const Type* Ty = V->getType();
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000625 printValueLoad(V);
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000626 if (const PointerType* P = dyn_cast<PointerType>(Ty))
627 Ty = P->getElementType();
628 std::string Tmp = "ldind."+getTypePostfix(Ty, false);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000629 printSimpleInstruction(Tmp.c_str());
630}
631
632
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000633void MSILWriter::printIndirectSave(const Value* Ptr, const Value* Val) {
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000634 printValueLoad(Ptr);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000635 printValueLoad(Val);
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000636 printIndirectSave(Val->getType());
637}
638
639
640void MSILWriter::printIndirectSave(const Type* Ty) {
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000641 // Instruction need signed postfix for any type.
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000642 std::string postfix = getTypePostfix(Ty, false);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000643 if (*postfix.begin()=='u') *postfix.begin() = 'i';
644 postfix = "stind."+postfix;
645 printSimpleInstruction(postfix.c_str());
646}
647
648
649void MSILWriter::printCastInstruction(unsigned int Op, const Value* V,
650 const Type* Ty) {
651 std::string Tmp("");
652 printValueLoad(V);
653 switch (Op) {
654 // Signed
655 case Instruction::SExt:
656 case Instruction::SIToFP:
657 case Instruction::FPToSI:
658 Tmp = "conv."+getTypePostfix(Ty,false,true);
659 printSimpleInstruction(Tmp.c_str());
660 break;
661 // Unsigned
662 case Instruction::FPTrunc:
663 case Instruction::FPExt:
664 case Instruction::UIToFP:
665 case Instruction::Trunc:
666 case Instruction::ZExt:
667 case Instruction::FPToUI:
668 case Instruction::PtrToInt:
669 case Instruction::IntToPtr:
670 Tmp = "conv."+getTypePostfix(Ty,false);
671 printSimpleInstruction(Tmp.c_str());
672 break;
673 // Do nothing
674 case Instruction::BitCast:
675 // FIXME: meaning that ld*/st* instruction do not change data format.
676 break;
677 default:
678 cerr << "Opcode = " << Op << '\n';
679 assert(0 && "Invalid conversion instruction");
680 }
681}
682
683
684void MSILWriter::printGepInstruction(const Value* V, gep_type_iterator I,
685 gep_type_iterator E) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000686 unsigned Size;
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000687 // Load address
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000688 printValuePtrLoad(V);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000689 // Calculate element offset.
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000690 for (; I!=E; ++I){
691 Size = 0;
692 const Value* IndexValue = I.getOperand();
693 if (const StructType* StrucTy = dyn_cast<StructType>(*I)) {
694 uint64_t FieldIndex = cast<ConstantInt>(IndexValue)->getZExtValue();
695 // Offset is the sum of all previous structure fields.
696 for (uint64_t F = 0; F<FieldIndex; ++F)
Duncan Sandsceb4d1a2009-01-12 20:38:59 +0000697 Size += TD->getTypePaddedSize(StrucTy->getContainedType((unsigned)F));
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000698 printPtrLoad(Size);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000699 printSimpleInstruction("add");
700 continue;
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000701 } else if (const SequentialType* SeqTy = dyn_cast<SequentialType>(*I)) {
Duncan Sandsceb4d1a2009-01-12 20:38:59 +0000702 Size = TD->getTypePaddedSize(SeqTy->getElementType());
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000703 } else {
Duncan Sandsceb4d1a2009-01-12 20:38:59 +0000704 Size = TD->getTypePaddedSize(*I);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000705 }
706 // Add offset of current element to stack top.
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000707 if (!isZeroValue(IndexValue)) {
708 // Constant optimization.
709 if (const ConstantInt* C = dyn_cast<ConstantInt>(IndexValue)) {
710 if (C->getValue().isNegative()) {
711 printPtrLoad(C->getValue().abs().getZExtValue()*Size);
712 printSimpleInstruction("sub");
713 continue;
714 } else
715 printPtrLoad(C->getZExtValue()*Size);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000716 } else {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000717 printPtrLoad(Size);
718 printValuePtrLoad(IndexValue);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000719 printSimpleInstruction("mul");
720 }
721 printSimpleInstruction("add");
722 }
723 }
724}
725
726
727std::string MSILWriter::getCallSignature(const FunctionType* Ty,
728 const Instruction* Inst,
729 std::string Name) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000730 std::string Tmp("");
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000731 if (Ty->isVarArg()) Tmp += "vararg ";
732 // Name and return type.
733 Tmp += getTypeName(Ty->getReturnType())+Name+"(";
734 // Function argument type list.
735 unsigned NumParams = Ty->getNumParams();
736 for (unsigned I = 0; I!=NumParams; ++I) {
737 if (I!=0) Tmp += ",";
738 Tmp += getTypeName(Ty->getParamType(I));
739 }
740 // CLR needs to know the exact amount of parameters received by vararg
741 // function, because caller cleans the stack.
742 if (Ty->isVarArg() && Inst) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000743 // Origin to function arguments in "CallInst" or "InvokeInst".
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000744 unsigned Org = isa<InvokeInst>(Inst) ? 3 : 1;
745 // Print variable argument types.
746 unsigned NumOperands = Inst->getNumOperands()-Org;
747 if (NumParams<NumOperands) {
748 if (NumParams!=0) Tmp += ", ";
749 Tmp += "... , ";
750 for (unsigned J = NumParams; J!=NumOperands; ++J) {
751 if (J!=NumParams) Tmp += ", ";
752 Tmp += getTypeName(Inst->getOperand(J+Org)->getType());
753 }
754 }
755 }
756 return Tmp+")";
757}
758
759
760void MSILWriter::printFunctionCall(const Value* FnVal,
761 const Instruction* Inst) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000762 // Get function calling convention.
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000763 std::string Name = "";
764 if (const CallInst* Call = dyn_cast<CallInst>(Inst))
765 Name = getConvModopt(Call->getCallingConv());
766 else if (const InvokeInst* Invoke = dyn_cast<InvokeInst>(Inst))
767 Name = getConvModopt(Invoke->getCallingConv());
768 else {
769 cerr << "Instruction = " << Inst->getName() << '\n';
770 assert(0 && "Need \"Invoke\" or \"Call\" instruction only");
771 }
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000772 if (const Function* F = dyn_cast<Function>(FnVal)) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000773 // Direct call.
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000774 Name += getValueName(F);
775 printSimpleInstruction("call",
776 getCallSignature(F->getFunctionType(),Inst,Name).c_str());
777 } else {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000778 // Indirect function call.
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000779 const PointerType* PTy = cast<PointerType>(FnVal->getType());
780 const FunctionType* FTy = cast<FunctionType>(PTy->getElementType());
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000781 // Load function address.
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000782 printValueLoad(FnVal);
783 printSimpleInstruction("calli",getCallSignature(FTy,Inst,Name).c_str());
784 }
785}
786
787
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000788void MSILWriter::printIntrinsicCall(const IntrinsicInst* Inst) {
789 std::string Name;
790 switch (Inst->getIntrinsicID()) {
791 case Intrinsic::vastart:
792 Name = getValueName(Inst->getOperand(1));
793 Name.insert(Name.length()-1,"$valist");
794 // Obtain the argument handle.
795 printSimpleInstruction("ldloca",Name.c_str());
796 printSimpleInstruction("arglist");
797 printSimpleInstruction("call",
798 "instance void [mscorlib]System.ArgIterator::.ctor"
799 "(valuetype [mscorlib]System.RuntimeArgumentHandle)");
800 // Save as pointer type "void*"
801 printValueLoad(Inst->getOperand(1));
802 printSimpleInstruction("ldloca",Name.c_str());
Christopher Lamb43ad6b32007-12-17 01:12:55 +0000803 printIndirectSave(PointerType::getUnqual(IntegerType::get(8)));
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000804 break;
805 case Intrinsic::vaend:
806 // Close argument list handle.
807 printIndirectLoad(Inst->getOperand(1));
808 printSimpleInstruction("call","instance void [mscorlib]System.ArgIterator::End()");
809 break;
810 case Intrinsic::vacopy:
811 // Copy "ArgIterator" valuetype.
812 printIndirectLoad(Inst->getOperand(1));
813 printIndirectLoad(Inst->getOperand(2));
814 printSimpleInstruction("cpobj","[mscorlib]System.ArgIterator");
815 break;
816 default:
817 cerr << "Intrinsic ID = " << Inst->getIntrinsicID() << '\n';
818 assert(0 && "Invalid intrinsic function");
819 }
820}
821
822
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000823void MSILWriter::printCallInstruction(const Instruction* Inst) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000824 if (isa<IntrinsicInst>(Inst)) {
825 // Handle intrinsic function.
826 printIntrinsicCall(cast<IntrinsicInst>(Inst));
827 } else {
828 // Load arguments to stack and call function.
829 for (int I = 1, E = Inst->getNumOperands(); I!=E; ++I)
830 printValueLoad(Inst->getOperand(I));
831 printFunctionCall(Inst->getOperand(0),Inst);
832 }
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000833}
834
835
836void MSILWriter::printICmpInstruction(unsigned Predicate, const Value* Left,
837 const Value* Right) {
838 switch (Predicate) {
839 case ICmpInst::ICMP_EQ:
840 printBinaryInstruction("ceq",Left,Right);
841 break;
842 case ICmpInst::ICMP_NE:
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000843 // Emulate = not neg (Op1 eq Op2)
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000844 printBinaryInstruction("ceq",Left,Right);
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000845 printSimpleInstruction("neg");
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000846 printSimpleInstruction("not");
847 break;
848 case ICmpInst::ICMP_ULE:
849 case ICmpInst::ICMP_SLE:
850 // Emulate = (Op1 eq Op2) or (Op1 lt Op2)
851 printBinaryInstruction("ceq",Left,Right);
852 if (Predicate==ICmpInst::ICMP_ULE)
853 printBinaryInstruction("clt.un",Left,Right);
854 else
855 printBinaryInstruction("clt",Left,Right);
856 printSimpleInstruction("or");
857 break;
858 case ICmpInst::ICMP_UGE:
859 case ICmpInst::ICMP_SGE:
860 // Emulate = (Op1 eq Op2) or (Op1 gt Op2)
861 printBinaryInstruction("ceq",Left,Right);
862 if (Predicate==ICmpInst::ICMP_UGE)
863 printBinaryInstruction("cgt.un",Left,Right);
864 else
865 printBinaryInstruction("cgt",Left,Right);
866 printSimpleInstruction("or");
867 break;
868 case ICmpInst::ICMP_ULT:
869 printBinaryInstruction("clt.un",Left,Right);
870 break;
871 case ICmpInst::ICMP_SLT:
872 printBinaryInstruction("clt",Left,Right);
873 break;
874 case ICmpInst::ICMP_UGT:
875 printBinaryInstruction("cgt.un",Left,Right);
876 case ICmpInst::ICMP_SGT:
877 printBinaryInstruction("cgt",Left,Right);
878 break;
879 default:
880 cerr << "Predicate = " << Predicate << '\n';
881 assert(0 && "Invalid icmp predicate");
882 }
883}
884
885
886void MSILWriter::printFCmpInstruction(unsigned Predicate, const Value* Left,
887 const Value* Right) {
888 // FIXME: Correct comparison
889 std::string NanFunc = "bool [mscorlib]System.Double::IsNaN(float64)";
890 switch (Predicate) {
891 case FCmpInst::FCMP_UGT:
892 // X > Y || llvm_fcmp_uno(X, Y)
893 printBinaryInstruction("cgt",Left,Right);
894 printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
895 printSimpleInstruction("or");
896 break;
897 case FCmpInst::FCMP_OGT:
898 // X > Y
899 printBinaryInstruction("cgt",Left,Right);
900 break;
901 case FCmpInst::FCMP_UGE:
902 // X >= Y || llvm_fcmp_uno(X, Y)
903 printBinaryInstruction("ceq",Left,Right);
904 printBinaryInstruction("cgt",Left,Right);
905 printSimpleInstruction("or");
906 printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
907 printSimpleInstruction("or");
908 break;
909 case FCmpInst::FCMP_OGE:
910 // X >= Y
911 printBinaryInstruction("ceq",Left,Right);
912 printBinaryInstruction("cgt",Left,Right);
913 printSimpleInstruction("or");
914 break;
915 case FCmpInst::FCMP_ULT:
916 // X < Y || llvm_fcmp_uno(X, Y)
917 printBinaryInstruction("clt",Left,Right);
918 printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
919 printSimpleInstruction("or");
920 break;
921 case FCmpInst::FCMP_OLT:
922 // X < Y
923 printBinaryInstruction("clt",Left,Right);
924 break;
925 case FCmpInst::FCMP_ULE:
926 // X <= Y || llvm_fcmp_uno(X, Y)
927 printBinaryInstruction("ceq",Left,Right);
928 printBinaryInstruction("clt",Left,Right);
929 printSimpleInstruction("or");
930 printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
931 printSimpleInstruction("or");
932 break;
933 case FCmpInst::FCMP_OLE:
934 // X <= Y
935 printBinaryInstruction("ceq",Left,Right);
936 printBinaryInstruction("clt",Left,Right);
937 printSimpleInstruction("or");
938 break;
939 case FCmpInst::FCMP_UEQ:
940 // X == Y || llvm_fcmp_uno(X, Y)
941 printBinaryInstruction("ceq",Left,Right);
942 printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
943 printSimpleInstruction("or");
944 break;
945 case FCmpInst::FCMP_OEQ:
946 // X == Y
947 printBinaryInstruction("ceq",Left,Right);
948 break;
949 case FCmpInst::FCMP_UNE:
950 // X != Y
951 printBinaryInstruction("ceq",Left,Right);
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000952 printSimpleInstruction("neg");
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000953 printSimpleInstruction("not");
954 break;
955 case FCmpInst::FCMP_ONE:
956 // X != Y && llvm_fcmp_ord(X, Y)
957 printBinaryInstruction("ceq",Left,Right);
958 printSimpleInstruction("not");
959 break;
960 case FCmpInst::FCMP_ORD:
961 // return X == X && Y == Y
962 printBinaryInstruction("ceq",Left,Left);
963 printBinaryInstruction("ceq",Right,Right);
964 printSimpleInstruction("or");
965 break;
966 case FCmpInst::FCMP_UNO:
967 // X != X || Y != Y
968 printBinaryInstruction("ceq",Left,Left);
969 printSimpleInstruction("not");
970 printBinaryInstruction("ceq",Right,Right);
971 printSimpleInstruction("not");
972 printSimpleInstruction("or");
973 break;
974 default:
975 assert(0 && "Illegal FCmp predicate");
976 }
977}
978
979
980void MSILWriter::printInvokeInstruction(const InvokeInst* Inst) {
981 std::string Label = "leave$normal_"+utostr(getUniqID());
982 Out << ".try {\n";
983 // Load arguments
984 for (int I = 3, E = Inst->getNumOperands(); I!=E; ++I)
985 printValueLoad(Inst->getOperand(I));
986 // Print call instruction
987 printFunctionCall(Inst->getOperand(0),Inst);
988 // Save function result and leave "try" block
989 printValueSave(Inst);
990 printSimpleInstruction("leave",Label.c_str());
991 Out << "}\n";
992 Out << "catch [mscorlib]System.Exception {\n";
993 // Redirect to unwind block
994 printSimpleInstruction("pop");
995 printBranchToBlock(Inst->getParent(),NULL,Inst->getUnwindDest());
996 Out << "}\n" << Label << ":\n";
997 // Redirect to continue block
998 printBranchToBlock(Inst->getParent(),NULL,Inst->getNormalDest());
999}
1000
1001
1002void MSILWriter::printSwitchInstruction(const SwitchInst* Inst) {
1003 // FIXME: Emulate with IL "switch" instruction
1004 // Emulate = if () else if () else if () else ...
1005 for (unsigned int I = 1, E = Inst->getNumCases(); I!=E; ++I) {
1006 printValueLoad(Inst->getCondition());
1007 printValueLoad(Inst->getCaseValue(I));
1008 printSimpleInstruction("ceq");
1009 // Condition jump to successor block
1010 printBranchToBlock(Inst->getParent(),Inst->getSuccessor(I),NULL);
1011 }
1012 // Jump to default block
1013 printBranchToBlock(Inst->getParent(),NULL,Inst->getDefaultDest());
1014}
1015
1016
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001017void MSILWriter::printVAArgInstruction(const VAArgInst* Inst) {
1018 printIndirectLoad(Inst->getOperand(0));
1019 printSimpleInstruction("call",
1020 "instance typedref [mscorlib]System.ArgIterator::GetNextArg()");
1021 printSimpleInstruction("refanyval","void*");
Christopher Lamb43ad6b32007-12-17 01:12:55 +00001022 std::string Name =
1023 "ldind."+getTypePostfix(PointerType::getUnqual(IntegerType::get(8)),false);
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001024 printSimpleInstruction(Name.c_str());
1025}
1026
1027
1028void MSILWriter::printAllocaInstruction(const AllocaInst* Inst) {
Duncan Sandsceb4d1a2009-01-12 20:38:59 +00001029 uint64_t Size = TD->getTypePaddedSize(Inst->getAllocatedType());
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001030 // Constant optimization.
1031 if (const ConstantInt* CInt = dyn_cast<ConstantInt>(Inst->getOperand(0))) {
1032 printPtrLoad(CInt->getZExtValue()*Size);
1033 } else {
1034 printPtrLoad(Size);
1035 printValueLoad(Inst->getOperand(0));
1036 printSimpleInstruction("mul");
1037 }
1038 printSimpleInstruction("localloc");
1039}
1040
1041
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001042void MSILWriter::printInstruction(const Instruction* Inst) {
1043 const Value *Left = 0, *Right = 0;
1044 if (Inst->getNumOperands()>=1) Left = Inst->getOperand(0);
1045 if (Inst->getNumOperands()>=2) Right = Inst->getOperand(1);
1046 // Print instruction
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001047 // FIXME: "ShuffleVector","ExtractElement","InsertElement" support.
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001048 switch (Inst->getOpcode()) {
1049 // Terminator
1050 case Instruction::Ret:
1051 if (Inst->getNumOperands()) {
1052 printValueLoad(Left);
1053 printSimpleInstruction("ret");
1054 } else
1055 printSimpleInstruction("ret");
1056 break;
1057 case Instruction::Br:
1058 printBranchInstruction(cast<BranchInst>(Inst));
1059 break;
1060 // Binary
1061 case Instruction::Add:
1062 printBinaryInstruction("add",Left,Right);
1063 break;
1064 case Instruction::Sub:
1065 printBinaryInstruction("sub",Left,Right);
1066 break;
1067 case Instruction::Mul:
1068 printBinaryInstruction("mul",Left,Right);
1069 break;
1070 case Instruction::UDiv:
1071 printBinaryInstruction("div.un",Left,Right);
1072 break;
1073 case Instruction::SDiv:
1074 case Instruction::FDiv:
1075 printBinaryInstruction("div",Left,Right);
1076 break;
1077 case Instruction::URem:
1078 printBinaryInstruction("rem.un",Left,Right);
1079 break;
1080 case Instruction::SRem:
1081 case Instruction::FRem:
1082 printBinaryInstruction("rem",Left,Right);
1083 break;
1084 // Binary Condition
1085 case Instruction::ICmp:
1086 printICmpInstruction(cast<ICmpInst>(Inst)->getPredicate(),Left,Right);
1087 break;
1088 case Instruction::FCmp:
1089 printFCmpInstruction(cast<FCmpInst>(Inst)->getPredicate(),Left,Right);
1090 break;
1091 // Bitwise Binary
1092 case Instruction::And:
1093 printBinaryInstruction("and",Left,Right);
1094 break;
1095 case Instruction::Or:
1096 printBinaryInstruction("or",Left,Right);
1097 break;
1098 case Instruction::Xor:
1099 printBinaryInstruction("xor",Left,Right);
1100 break;
1101 case Instruction::Shl:
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001102 printValueLoad(Left);
1103 printValueLoad(Right);
1104 printSimpleInstruction("conv.i4");
1105 printSimpleInstruction("shl");
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001106 break;
1107 case Instruction::LShr:
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001108 printValueLoad(Left);
1109 printValueLoad(Right);
1110 printSimpleInstruction("conv.i4");
1111 printSimpleInstruction("shr.un");
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001112 break;
1113 case Instruction::AShr:
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001114 printValueLoad(Left);
1115 printValueLoad(Right);
1116 printSimpleInstruction("conv.i4");
1117 printSimpleInstruction("shr");
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001118 break;
1119 case Instruction::Select:
1120 printSelectInstruction(Inst->getOperand(0),Inst->getOperand(1),Inst->getOperand(2));
1121 break;
1122 case Instruction::Load:
1123 printIndirectLoad(Inst->getOperand(0));
1124 break;
1125 case Instruction::Store:
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001126 printIndirectSave(Inst->getOperand(1), Inst->getOperand(0));
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001127 break;
1128 case Instruction::Trunc:
1129 case Instruction::ZExt:
1130 case Instruction::SExt:
1131 case Instruction::FPTrunc:
1132 case Instruction::FPExt:
1133 case Instruction::UIToFP:
1134 case Instruction::SIToFP:
1135 case Instruction::FPToUI:
1136 case Instruction::FPToSI:
1137 case Instruction::PtrToInt:
1138 case Instruction::IntToPtr:
1139 case Instruction::BitCast:
1140 printCastInstruction(Inst->getOpcode(),Left,
1141 cast<CastInst>(Inst)->getDestTy());
1142 break;
1143 case Instruction::GetElementPtr:
1144 printGepInstruction(Inst->getOperand(0),gep_type_begin(Inst),
1145 gep_type_end(Inst));
1146 break;
1147 case Instruction::Call:
1148 printCallInstruction(cast<CallInst>(Inst));
1149 break;
1150 case Instruction::Invoke:
1151 printInvokeInstruction(cast<InvokeInst>(Inst));
1152 break;
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001153 case Instruction::Unwind:
1154 printSimpleInstruction("newobj",
1155 "instance void [mscorlib]System.Exception::.ctor()");
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001156 printSimpleInstruction("throw");
1157 break;
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001158 case Instruction::Switch:
1159 printSwitchInstruction(cast<SwitchInst>(Inst));
1160 break;
1161 case Instruction::Alloca:
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001162 printAllocaInstruction(cast<AllocaInst>(Inst));
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001163 break;
1164 case Instruction::Malloc:
1165 assert(0 && "LowerAllocationsPass used");
1166 break;
1167 case Instruction::Free:
1168 assert(0 && "LowerAllocationsPass used");
1169 break;
1170 case Instruction::Unreachable:
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001171 printSimpleInstruction("ldstr", "\"Unreachable instruction\"");
1172 printSimpleInstruction("newobj",
1173 "instance void [mscorlib]System.Exception::.ctor(string)");
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001174 printSimpleInstruction("throw");
1175 break;
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001176 case Instruction::VAArg:
1177 printVAArgInstruction(cast<VAArgInst>(Inst));
1178 break;
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001179 default:
1180 cerr << "Instruction = " << Inst->getName() << '\n';
1181 assert(0 && "Unsupported instruction");
1182 }
1183}
1184
1185
1186void MSILWriter::printLoop(const Loop* L) {
1187 Out << getLabelName(L->getHeader()->getName()) << ":\n";
1188 const std::vector<BasicBlock*>& blocks = L->getBlocks();
1189 for (unsigned I = 0, E = blocks.size(); I!=E; I++) {
1190 BasicBlock* BB = blocks[I];
1191 Loop* BBLoop = LInfo->getLoopFor(BB);
1192 if (BBLoop == L)
1193 printBasicBlock(BB);
1194 else if (BB==BBLoop->getHeader() && BBLoop->getParentLoop()==L)
1195 printLoop(BBLoop);
1196 }
1197 printSimpleInstruction("br",getLabelName(L->getHeader()->getName()).c_str());
1198}
1199
1200
1201void MSILWriter::printBasicBlock(const BasicBlock* BB) {
1202 Out << getLabelName(BB) << ":\n";
1203 for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I!=E; ++I) {
1204 const Instruction* Inst = I;
1205 // Comment llvm original instruction
Owen Andersoncb371882008-08-21 00:14:44 +00001206 // Out << "\n//" << *Inst << "\n";
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001207 // Do not handle PHI instruction in current block
1208 if (Inst->getOpcode()==Instruction::PHI) continue;
1209 // Print instruction
1210 printInstruction(Inst);
1211 // Save result
1212 if (Inst->getType()!=Type::VoidTy) {
1213 // Do not save value after invoke, it done in "try" block
1214 if (Inst->getOpcode()==Instruction::Invoke) continue;
1215 printValueSave(Inst);
1216 }
1217 }
1218}
1219
1220
1221void MSILWriter::printLocalVariables(const Function& F) {
1222 std::string Name;
1223 const Type* Ty = NULL;
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001224 std::set<const Value*> Printed;
1225 const Value* VaList = NULL;
1226 unsigned StackDepth = 8;
1227 // Find local variables
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001228 for (const_inst_iterator I = inst_begin(&F), E = inst_end(&F); I!=E; ++I) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001229 if (I->getOpcode()==Instruction::Call ||
1230 I->getOpcode()==Instruction::Invoke) {
1231 // Test stack depth.
1232 if (StackDepth<I->getNumOperands())
1233 StackDepth = I->getNumOperands();
1234 }
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001235 const AllocaInst* AI = dyn_cast<AllocaInst>(&*I);
1236 if (AI && !isa<GlobalVariable>(AI)) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001237 // Local variable allocation.
Christopher Lamb43ad6b32007-12-17 01:12:55 +00001238 Ty = PointerType::getUnqual(AI->getAllocatedType());
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001239 Name = getValueName(AI);
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001240 Out << "\t.locals (" << getTypeName(Ty) << Name << ")\n";
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001241 } else if (I->getType()!=Type::VoidTy) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001242 // Operation result.
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001243 Ty = I->getType();
1244 Name = getValueName(&*I);
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001245 Out << "\t.locals (" << getTypeName(Ty) << Name << ")\n";
1246 }
1247 // Test on 'va_list' variable
1248 bool isVaList = false;
1249 if (const VAArgInst* VaInst = dyn_cast<VAArgInst>(&*I)) {
1250 // "va_list" as "va_arg" instruction operand.
1251 isVaList = true;
1252 VaList = VaInst->getOperand(0);
1253 } else if (const IntrinsicInst* Inst = dyn_cast<IntrinsicInst>(&*I)) {
1254 // "va_list" as intrinsic function operand.
1255 switch (Inst->getIntrinsicID()) {
1256 case Intrinsic::vastart:
1257 case Intrinsic::vaend:
1258 case Intrinsic::vacopy:
1259 isVaList = true;
1260 VaList = Inst->getOperand(1);
1261 break;
1262 default:
1263 isVaList = false;
1264 }
1265 }
1266 // Print "va_list" variable.
1267 if (isVaList && Printed.insert(VaList).second) {
1268 Name = getValueName(VaList);
1269 Name.insert(Name.length()-1,"$valist");
1270 Out << "\t.locals (valuetype [mscorlib]System.ArgIterator "
1271 << Name << ")\n";
1272 }
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001273 }
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001274 printSimpleInstruction(".maxstack",utostr(StackDepth*2).c_str());
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001275}
1276
1277
1278void MSILWriter::printFunctionBody(const Function& F) {
1279 // Print body
1280 for (Function::const_iterator I = F.begin(), E = F.end(); I!=E; ++I) {
1281 if (Loop *L = LInfo->getLoopFor(I)) {
1282 if (L->getHeader()==I && L->getParentLoop()==0)
1283 printLoop(L);
1284 } else {
1285 printBasicBlock(I);
1286 }
1287 }
1288}
1289
1290
1291void MSILWriter::printConstantExpr(const ConstantExpr* CE) {
1292 const Value *left = 0, *right = 0;
1293 if (CE->getNumOperands()>=1) left = CE->getOperand(0);
1294 if (CE->getNumOperands()>=2) right = CE->getOperand(1);
1295 // Print instruction
1296 switch (CE->getOpcode()) {
1297 case Instruction::Trunc:
1298 case Instruction::ZExt:
1299 case Instruction::SExt:
1300 case Instruction::FPTrunc:
1301 case Instruction::FPExt:
1302 case Instruction::UIToFP:
1303 case Instruction::SIToFP:
1304 case Instruction::FPToUI:
1305 case Instruction::FPToSI:
1306 case Instruction::PtrToInt:
1307 case Instruction::IntToPtr:
1308 case Instruction::BitCast:
1309 printCastInstruction(CE->getOpcode(),left,CE->getType());
1310 break;
1311 case Instruction::GetElementPtr:
1312 printGepInstruction(CE->getOperand(0),gep_type_begin(CE),gep_type_end(CE));
1313 break;
1314 case Instruction::ICmp:
1315 printICmpInstruction(CE->getPredicate(),left,right);
1316 break;
1317 case Instruction::FCmp:
1318 printFCmpInstruction(CE->getPredicate(),left,right);
1319 break;
1320 case Instruction::Select:
1321 printSelectInstruction(CE->getOperand(0),CE->getOperand(1),CE->getOperand(2));
1322 break;
1323 case Instruction::Add:
1324 printBinaryInstruction("add",left,right);
1325 break;
1326 case Instruction::Sub:
1327 printBinaryInstruction("sub",left,right);
1328 break;
1329 case Instruction::Mul:
1330 printBinaryInstruction("mul",left,right);
1331 break;
1332 case Instruction::UDiv:
1333 printBinaryInstruction("div.un",left,right);
1334 break;
1335 case Instruction::SDiv:
1336 case Instruction::FDiv:
1337 printBinaryInstruction("div",left,right);
1338 break;
1339 case Instruction::URem:
1340 printBinaryInstruction("rem.un",left,right);
1341 break;
1342 case Instruction::SRem:
1343 case Instruction::FRem:
1344 printBinaryInstruction("rem",left,right);
1345 break;
1346 case Instruction::And:
1347 printBinaryInstruction("and",left,right);
1348 break;
1349 case Instruction::Or:
1350 printBinaryInstruction("or",left,right);
1351 break;
1352 case Instruction::Xor:
1353 printBinaryInstruction("xor",left,right);
1354 break;
1355 case Instruction::Shl:
1356 printBinaryInstruction("shl",left,right);
1357 break;
1358 case Instruction::LShr:
1359 printBinaryInstruction("shr.un",left,right);
1360 break;
1361 case Instruction::AShr:
1362 printBinaryInstruction("shr",left,right);
1363 break;
1364 default:
1365 cerr << "Expression = " << *CE << "\n";
1366 assert(0 && "Invalid constant expression");
1367 }
1368}
1369
1370
1371void MSILWriter::printStaticInitializerList() {
1372 // List of global variables with uninitialized fields.
1373 for (std::map<const GlobalVariable*,std::vector<StaticInitializer> >::iterator
1374 VarI = StaticInitList.begin(), VarE = StaticInitList.end(); VarI!=VarE;
1375 ++VarI) {
1376 const std::vector<StaticInitializer>& InitList = VarI->second;
1377 if (InitList.empty()) continue;
1378 // For each uninitialized field.
1379 for (std::vector<StaticInitializer>::const_iterator I = InitList.begin(),
1380 E = InitList.end(); I!=E; ++I) {
1381 if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(I->constant)) {
Owen Andersoncb371882008-08-21 00:14:44 +00001382 // Out << "\n// Init " << getValueName(VarI->first) << ", offset " <<
1383 // utostr(I->offset) << ", type "<< *I->constant->getType() << "\n\n";
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001384 // Load variable address
1385 printValueLoad(VarI->first);
1386 // Add offset
1387 if (I->offset!=0) {
1388 printPtrLoad(I->offset);
1389 printSimpleInstruction("add");
1390 }
1391 // Load value
1392 printConstantExpr(CE);
1393 // Save result at offset
1394 std::string postfix = getTypePostfix(CE->getType(),true);
1395 if (*postfix.begin()=='u') *postfix.begin() = 'i';
1396 postfix = "stind."+postfix;
1397 printSimpleInstruction(postfix.c_str());
1398 } else {
1399 cerr << "Constant = " << *I->constant << '\n';
1400 assert(0 && "Invalid static initializer");
1401 }
1402 }
1403 }
1404}
1405
1406
1407void MSILWriter::printFunction(const Function& F) {
Devang Patel05988662008-09-25 21:00:45 +00001408 bool isSigned = F.paramHasAttr(0, Attribute::SExt);
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001409 Out << "\n.method static ";
Rafael Espindolabb46f522009-01-15 20:18:42 +00001410 Out << (F.hasLocalLinkage() ? "private " : "public ");
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001411 if (F.isVarArg()) Out << "vararg ";
1412 Out << getTypeName(F.getReturnType(),isSigned) <<
1413 getConvModopt(F.getCallingConv()) << getValueName(&F) << '\n';
1414 // Arguments
1415 Out << "\t(";
1416 unsigned ArgIdx = 1;
1417 for (Function::const_arg_iterator I = F.arg_begin(), E = F.arg_end(); I!=E;
1418 ++I, ++ArgIdx) {
Devang Patel05988662008-09-25 21:00:45 +00001419 isSigned = F.paramHasAttr(ArgIdx, Attribute::SExt);
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001420 if (I!=F.arg_begin()) Out << ", ";
1421 Out << getTypeName(I->getType(),isSigned) << getValueName(I);
1422 }
1423 Out << ") cil managed\n";
1424 // Body
1425 Out << "{\n";
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001426 printLocalVariables(F);
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001427 printFunctionBody(F);
1428 Out << "}\n";
1429}
1430
1431
1432void MSILWriter::printDeclarations(const TypeSymbolTable& ST) {
1433 std::string Name;
1434 std::set<const Type*> Printed;
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001435 for (std::set<const Type*>::const_iterator
1436 UI = UsedTypes->begin(), UE = UsedTypes->end(); UI!=UE; ++UI) {
1437 const Type* Ty = *UI;
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001438 if (isa<ArrayType>(Ty) || isa<VectorType>(Ty) || isa<StructType>(Ty))
1439 Name = getTypeName(Ty, false, true);
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001440 // Type with no need to declare.
1441 else continue;
1442 // Print not duplicated type
1443 if (Printed.insert(Ty).second) {
1444 Out << ".class value explicit ansi sealed '" << Name << "'";
Duncan Sandsceb4d1a2009-01-12 20:38:59 +00001445 Out << " { .pack " << 1 << " .size " << TD->getTypePaddedSize(Ty);
1446 Out << " }\n\n";
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001447 }
1448 }
1449}
1450
1451
1452unsigned int MSILWriter::getBitWidth(const Type* Ty) {
1453 unsigned int N = Ty->getPrimitiveSizeInBits();
1454 assert(N!=0 && "Invalid type in getBitWidth()");
1455 switch (N) {
1456 case 1:
1457 case 8:
1458 case 16:
1459 case 32:
1460 case 64:
1461 return N;
1462 default:
1463 cerr << "Bits = " << N << '\n';
1464 assert(0 && "Unsupported integer width");
1465 }
Chris Lattnerd27c9912008-03-30 18:22:13 +00001466 return 0; // Not reached
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001467}
1468
1469
1470void MSILWriter::printStaticConstant(const Constant* C, uint64_t& Offset) {
1471 uint64_t TySize = 0;
1472 const Type* Ty = C->getType();
1473 // Print zero initialized constant.
1474 if (isa<ConstantAggregateZero>(C) || C->isNullValue()) {
Duncan Sandsceb4d1a2009-01-12 20:38:59 +00001475 TySize = TD->getTypePaddedSize(C->getType());
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001476 Offset += TySize;
1477 Out << "int8 (0) [" << TySize << "]";
1478 return;
1479 }
1480 // Print constant initializer
1481 switch (Ty->getTypeID()) {
1482 case Type::IntegerTyID: {
Duncan Sandsceb4d1a2009-01-12 20:38:59 +00001483 TySize = TD->getTypePaddedSize(Ty);
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001484 const ConstantInt* Int = cast<ConstantInt>(C);
1485 Out << getPrimitiveTypeName(Ty,true) << "(" << Int->getSExtValue() << ")";
1486 break;
1487 }
1488 case Type::FloatTyID:
1489 case Type::DoubleTyID: {
Duncan Sandsceb4d1a2009-01-12 20:38:59 +00001490 TySize = TD->getTypePaddedSize(Ty);
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001491 const ConstantFP* FP = cast<ConstantFP>(C);
1492 if (Ty->getTypeID() == Type::FloatTyID)
Dale Johannesen43421b32007-09-06 18:13:44 +00001493 Out << "int32 (" <<
Dale Johannesen7111b022008-10-09 18:53:47 +00001494 (uint32_t)FP->getValueAPF().bitcastToAPInt().getZExtValue() << ')';
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001495 else
Dale Johannesen43421b32007-09-06 18:13:44 +00001496 Out << "int64 (" <<
Dale Johannesen7111b022008-10-09 18:53:47 +00001497 FP->getValueAPF().bitcastToAPInt().getZExtValue() << ')';
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001498 break;
1499 }
1500 case Type::ArrayTyID:
1501 case Type::VectorTyID:
1502 case Type::StructTyID:
1503 for (unsigned I = 0, E = C->getNumOperands(); I<E; I++) {
1504 if (I!=0) Out << ",\n";
1505 printStaticConstant(C->getOperand(I),Offset);
1506 }
1507 break;
1508 case Type::PointerTyID:
Duncan Sandsceb4d1a2009-01-12 20:38:59 +00001509 TySize = TD->getTypePaddedSize(C->getType());
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001510 // Initialize with global variable address
1511 if (const GlobalVariable *G = dyn_cast<GlobalVariable>(C)) {
1512 std::string name = getValueName(G);
1513 Out << "&(" << name.insert(name.length()-1,"$data") << ")";
1514 } else {
1515 // Dynamic initialization
1516 if (!isa<ConstantPointerNull>(C) && !C->isNullValue())
1517 InitListPtr->push_back(StaticInitializer(C,Offset));
1518 // Null pointer initialization
1519 if (TySize==4) Out << "int32 (0)";
1520 else if (TySize==8) Out << "int64 (0)";
1521 else assert(0 && "Invalid pointer size");
1522 }
1523 break;
1524 default:
1525 cerr << "TypeID = " << Ty->getTypeID() << '\n';
1526 assert(0 && "Invalid type in printStaticConstant()");
1527 }
1528 // Increase offset.
1529 Offset += TySize;
1530}
1531
1532
1533void MSILWriter::printStaticInitializer(const Constant* C,
1534 const std::string& Name) {
1535 switch (C->getType()->getTypeID()) {
1536 case Type::IntegerTyID:
1537 case Type::FloatTyID:
1538 case Type::DoubleTyID:
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001539 Out << getPrimitiveTypeName(C->getType(), false);
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001540 break;
1541 case Type::ArrayTyID:
1542 case Type::VectorTyID:
1543 case Type::StructTyID:
1544 case Type::PointerTyID:
1545 Out << getTypeName(C->getType());
1546 break;
1547 default:
1548 cerr << "Type = " << *C << "\n";
1549 assert(0 && "Invalid constant type");
1550 }
1551 // Print initializer
1552 std::string label = Name;
1553 label.insert(label.length()-1,"$data");
1554 Out << Name << " at " << label << '\n';
1555 Out << ".data " << label << " = {\n";
1556 uint64_t offset = 0;
1557 printStaticConstant(C,offset);
1558 Out << "\n}\n\n";
1559}
1560
1561
1562void MSILWriter::printVariableDefinition(const GlobalVariable* G) {
1563 const Constant* C = G->getInitializer();
1564 if (C->isNullValue() || isa<ConstantAggregateZero>(C) || isa<UndefValue>(C))
1565 InitListPtr = 0;
1566 else
1567 InitListPtr = &StaticInitList[G];
1568 printStaticInitializer(C,getValueName(G));
1569}
1570
1571
1572void MSILWriter::printGlobalVariables() {
1573 if (ModulePtr->global_empty()) return;
1574 Module::global_iterator I,E;
1575 for (I = ModulePtr->global_begin(), E = ModulePtr->global_end(); I!=E; ++I) {
1576 // Variable definition
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001577 Out << ".field static " << (I->isDeclaration() ? "public " :
1578 "private ");
1579 if (I->isDeclaration()) {
1580 Out << getTypeName(I->getType()) << getValueName(&*I) << "\n\n";
1581 } else
1582 printVariableDefinition(&*I);
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001583 }
1584}
1585
1586
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001587const char* MSILWriter::getLibraryName(const Function* F) {
1588 return getLibraryForSymbol(F->getName().c_str(), true, F->getCallingConv());
1589}
1590
1591
1592const char* MSILWriter::getLibraryName(const GlobalVariable* GV) {
1593 return getLibraryForSymbol(Mang->getValueName(GV).c_str(), false, 0);
1594}
1595
1596
1597const char* MSILWriter::getLibraryForSymbol(const char* Name, bool isFunction,
1598 unsigned CallingConv) {
1599 // TODO: Read *.def file with function and libraries definitions.
1600 return "MSVCRT.DLL";
1601}
1602
1603
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001604void MSILWriter::printExternals() {
1605 Module::const_iterator I,E;
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001606 // Functions.
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001607 for (I=ModulePtr->begin(),E=ModulePtr->end(); I!=E; ++I) {
1608 // Skip intrisics
Duncan Sandsa3355ff2007-12-03 20:06:50 +00001609 if (I->isIntrinsic()) continue;
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001610 if (I->isDeclaration()) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001611 const Function* F = I;
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001612 std::string Name = getConvModopt(F->getCallingConv())+getValueName(F);
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001613 std::string Sig =
1614 getCallSignature(cast<FunctionType>(F->getFunctionType()), NULL, Name);
1615 Out << ".method static hidebysig pinvokeimpl(\""
1616 << getLibraryName(F) << "\")\n\t" << Sig << " preservesig {}\n\n";
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001617 }
1618 }
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001619 // External variables and static initialization.
1620 Out <<
1621 ".method public hidebysig static pinvokeimpl(\"KERNEL32.DLL\" ansi winapi)"
1622 " native int LoadLibrary(string) preservesig {}\n"
1623 ".method public hidebysig static pinvokeimpl(\"KERNEL32.DLL\" ansi winapi)"
1624 " native int GetProcAddress(native int, string) preservesig {}\n";
1625 Out <<
1626 ".method private static void* $MSIL_Import(string lib,string sym)\n"
1627 " managed cil\n{\n"
1628 "\tldarg\tlib\n"
1629 "\tcall\tnative int LoadLibrary(string)\n"
1630 "\tldarg\tsym\n"
1631 "\tcall\tnative int GetProcAddress(native int,string)\n"
1632 "\tdup\n"
1633 "\tbrtrue\tL_01\n"
1634 "\tldstr\t\"Can no import variable\"\n"
1635 "\tnewobj\tinstance void [mscorlib]System.Exception::.ctor(string)\n"
1636 "\tthrow\n"
1637 "L_01:\n"
1638 "\tret\n"
1639 "}\n\n"
1640 ".method static private void $MSIL_Init() managed cil\n{\n";
1641 printStaticInitializerList();
1642 // Foreach global variable.
1643 for (Module::global_iterator I = ModulePtr->global_begin(),
1644 E = ModulePtr->global_end(); I!=E; ++I) {
1645 if (!I->isDeclaration() || !I->hasDLLImportLinkage()) continue;
1646 // Use "LoadLibrary"/"GetProcAddress" to recive variable address.
1647 std::string Label = "not_null$_"+utostr(getUniqID());
1648 std::string Tmp = getTypeName(I->getType())+getValueName(&*I);
1649 printSimpleInstruction("ldsflda",Tmp.c_str());
1650 Out << "\tldstr\t\"" << getLibraryName(&*I) << "\"\n";
1651 Out << "\tldstr\t\"" << Mang->getValueName(&*I) << "\"\n";
1652 printSimpleInstruction("call","void* $MSIL_Import(string,string)");
1653 printIndirectSave(I->getType());
1654 }
1655 printSimpleInstruction("ret");
1656 Out << "}\n\n";
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001657}
1658
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001659
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001660//===----------------------------------------------------------------------===//
Bill Wendling85db3a92008-02-26 10:57:23 +00001661// External Interface declaration
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001662//===----------------------------------------------------------------------===//
1663
Owen Andersoncb371882008-08-21 00:14:44 +00001664bool MSILTarget::addPassesToEmitWholeFile(PassManager &PM, raw_ostream &o,
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001665 CodeGenFileType FileType, bool Fast)
1666{
1667 if (FileType != TargetMachine::AssemblyFile) return true;
1668 MSILWriter* Writer = new MSILWriter(o);
Gordon Henriksence224772008-01-07 01:30:38 +00001669 PM.add(createGCLoweringPass());
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001670 PM.add(createLowerAllocationsPass(true));
1671 // FIXME: Handle switch trougth native IL instruction "switch"
1672 PM.add(createLowerSwitchPass());
1673 PM.add(createCFGSimplificationPass());
1674 PM.add(new MSILModule(Writer->UsedTypes,Writer->TD));
1675 PM.add(Writer);
Gordon Henriksen5eca0752008-08-17 18:44:35 +00001676 PM.add(createGCInfoDeleter());
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001677 return false;
1678}