blob: 35eec842a3c19115b722ee217aea1a508cced8e7 [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"
Reid Spencer5694b6e2007-04-09 06:17:21 +000019#include "llvm/ParameterAttributes.h"
Anton Korobeynikov099883f2007-03-21 21:38:25 +000020#include "llvm/TypeSymbolTable.h"
21#include "llvm/Analysis/ConstantsScanner.h"
22#include "llvm/Support/CallSite.h"
23#include "llvm/Support/InstVisitor.h"
Anton Korobeynikovf13090c2007-05-06 20:13:33 +000024#include "llvm/Support/MathExtras.h"
Anton Korobeynikov099883f2007-03-21 21:38:25 +000025#include "llvm/Transforms/Scalar.h"
26#include "llvm/ADT/StringExtras.h"
Gordon Henriksence224772008-01-07 01:30:38 +000027#include "llvm/CodeGen/Passes.h"
Anton Korobeynikov099883f2007-03-21 21:38:25 +000028
29namespace {
30 // TargetMachine for the MSIL
31 struct VISIBILITY_HIDDEN MSILTarget : public TargetMachine {
32 const TargetData DataLayout; // Calculates type size & alignment
33
34 MSILTarget(const Module &M, const std::string &FS)
35 : DataLayout(&M) {}
36
37 virtual bool WantsWholeFile() const { return true; }
Owen Andersoncb371882008-08-21 00:14:44 +000038 virtual bool addPassesToEmitWholeFile(PassManager &PM, raw_ostream &Out,
Anton Korobeynikov099883f2007-03-21 21:38:25 +000039 CodeGenFileType FileType, bool Fast);
40
41 // This class always works, but shouldn't be the default in most cases.
42 static unsigned getModuleMatchQuality(const Module &M) { return 1; }
43
44 virtual const TargetData *getTargetData() const { return &DataLayout; }
45 };
46}
47
48
Dan Gohman844731a2008-05-13 00:00:25 +000049static RegisterTarget<MSILTarget> X("msil", " MSIL backend");
Anton Korobeynikov099883f2007-03-21 21:38:25 +000050
51bool MSILModule::runOnModule(Module &M) {
52 ModulePtr = &M;
53 TD = &getAnalysis<TargetData>();
54 bool Changed = false;
55 // Find named types.
56 TypeSymbolTable& Table = M.getTypeSymbolTable();
57 std::set<const Type *> Types = getAnalysis<FindUsedTypes>().getTypes();
58 for (TypeSymbolTable::iterator I = Table.begin(), E = Table.end(); I!=E; ) {
59 if (!isa<StructType>(I->second) && !isa<OpaqueType>(I->second))
60 Table.remove(I++);
61 else {
62 std::set<const Type *>::iterator T = Types.find(I->second);
63 if (T==Types.end())
64 Table.remove(I++);
65 else {
66 Types.erase(T);
67 ++I;
68 }
69 }
70 }
71 // Find unnamed types.
72 unsigned RenameCounter = 0;
73 for (std::set<const Type *>::const_iterator I = Types.begin(),
74 E = Types.end(); I!=E; ++I)
75 if (const StructType *STy = dyn_cast<StructType>(*I)) {
76 while (ModulePtr->addTypeName("unnamed$"+utostr(RenameCounter), STy))
77 ++RenameCounter;
78 Changed = true;
79 }
80 // Pointer for FunctionPass.
81 UsedTypes = &getAnalysis<FindUsedTypes>().getTypes();
82 return Changed;
83}
84
Devang Patel19974732007-05-03 01:11:54 +000085char MSILModule::ID = 0;
86char MSILWriter::ID = 0;
Anton Korobeynikov099883f2007-03-21 21:38:25 +000087
88bool MSILWriter::runOnFunction(Function &F) {
89 if (F.isDeclaration()) return false;
90 LInfo = &getAnalysis<LoopInfo>();
91 printFunction(F);
92 return false;
93}
94
95
96bool MSILWriter::doInitialization(Module &M) {
97 ModulePtr = &M;
Anton Korobeynikovf13090c2007-05-06 20:13:33 +000098 Mang = new Mangler(M);
Anton Korobeynikov099883f2007-03-21 21:38:25 +000099 Out << ".assembly extern mscorlib {}\n";
100 Out << ".assembly MSIL {}\n\n";
101 Out << "// External\n";
102 printExternals();
103 Out << "// Declarations\n";
104 printDeclarations(M.getTypeSymbolTable());
105 Out << "// Definitions\n";
106 printGlobalVariables();
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000107 Out << "// Startup code\n";
108 printModuleStartup();
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000109 return false;
110}
111
112
113bool MSILWriter::doFinalization(Module &M) {
114 delete Mang;
115 return false;
116}
117
118
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000119void MSILWriter::printModuleStartup() {
120 Out <<
121 ".method static public int32 $MSIL_Startup() {\n"
122 "\t.entrypoint\n"
123 "\t.locals (native int i)\n"
124 "\t.locals (native int argc)\n"
125 "\t.locals (native int ptr)\n"
126 "\t.locals (void* argv)\n"
127 "\t.locals (string[] args)\n"
128 "\tcall\tstring[] [mscorlib]System.Environment::GetCommandLineArgs()\n"
129 "\tdup\n"
130 "\tstloc\targs\n"
131 "\tldlen\n"
132 "\tconv.i4\n"
133 "\tdup\n"
134 "\tstloc\targc\n";
135 printPtrLoad(TD->getPointerSize());
136 Out <<
137 "\tmul\n"
138 "\tlocalloc\n"
139 "\tstloc\targv\n"
140 "\tldc.i4.0\n"
141 "\tstloc\ti\n"
142 "L_01:\n"
143 "\tldloc\ti\n"
144 "\tldloc\targc\n"
145 "\tceq\n"
146 "\tbrtrue\tL_02\n"
147 "\tldloc\targs\n"
148 "\tldloc\ti\n"
149 "\tldelem.ref\n"
150 "\tcall\tnative int [mscorlib]System.Runtime.InteropServices.Marshal::"
151 "StringToHGlobalAnsi(string)\n"
152 "\tstloc\tptr\n"
153 "\tldloc\targv\n"
154 "\tldloc\ti\n";
155 printPtrLoad(TD->getPointerSize());
156 Out <<
157 "\tmul\n"
158 "\tadd\n"
159 "\tldloc\tptr\n"
160 "\tstind.i\n"
161 "\tldloc\ti\n"
162 "\tldc.i4.1\n"
163 "\tadd\n"
164 "\tstloc\ti\n"
165 "\tbr\tL_01\n"
166 "L_02:\n"
167 "\tcall void $MSIL_Init()\n";
168
169 // Call user 'main' function.
170 const Function* F = ModulePtr->getFunction("main");
171 if (!F || F->isDeclaration()) {
172 Out << "\tldc.i4.0\n\tret\n}\n";
173 return;
174 }
175 bool BadSig = true;;
176 std::string Args("");
177 Function::const_arg_iterator Arg1,Arg2;
178
179 switch (F->arg_size()) {
180 case 0:
181 BadSig = false;
182 break;
183 case 1:
184 Arg1 = F->arg_begin();
185 if (Arg1->getType()->isInteger()) {
186 Out << "\tldloc\targc\n";
187 Args = getTypeName(Arg1->getType());
188 BadSig = false;
189 }
190 break;
191 case 2:
192 Arg1 = Arg2 = F->arg_begin(); ++Arg2;
193 if (Arg1->getType()->isInteger() &&
194 Arg2->getType()->getTypeID() == Type::PointerTyID) {
195 Out << "\tldloc\targc\n\tldloc\targv\n";
196 Args = getTypeName(Arg1->getType())+","+getTypeName(Arg2->getType());
197 BadSig = false;
198 }
199 break;
200 default:
201 BadSig = true;
202 }
203
204 bool RetVoid = (F->getReturnType()->getTypeID() == Type::VoidTyID);
Anton Korobeynikov7c1c2612008-02-20 11:22:39 +0000205 if (BadSig || (!F->getReturnType()->isInteger() && !RetVoid)) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000206 Out << "\tldc.i4.0\n";
207 } else {
208 Out << "\tcall\t" << getTypeName(F->getReturnType()) <<
209 getConvModopt(F->getCallingConv()) << "main(" << Args << ")\n";
210 if (RetVoid)
211 Out << "\tldc.i4.0\n";
212 else
213 Out << "\tconv.i4\n";
214 }
215 Out << "\tret\n}\n";
216}
217
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000218bool MSILWriter::isZeroValue(const Value* V) {
219 if (const Constant *C = dyn_cast<Constant>(V))
220 return C->isNullValue();
221 return false;
222}
223
224
225std::string MSILWriter::getValueName(const Value* V) {
226 // Name into the quotes allow control and space characters.
227 return "'"+Mang->getValueName(V)+"'";
228}
229
230
231std::string MSILWriter::getLabelName(const std::string& Name) {
232 if (Name.find('.')!=std::string::npos) {
233 std::string Tmp(Name);
234 // Replace unaccepable characters in the label name.
235 for (std::string::iterator I = Tmp.begin(), E = Tmp.end(); I!=E; ++I)
236 if (*I=='.') *I = '@';
237 return Tmp;
238 }
239 return Name;
240}
241
242
243std::string MSILWriter::getLabelName(const Value* V) {
244 return getLabelName(Mang->getValueName(V));
245}
246
247
248std::string MSILWriter::getConvModopt(unsigned CallingConvID) {
249 switch (CallingConvID) {
250 case CallingConv::C:
251 case CallingConv::Cold:
252 case CallingConv::Fast:
253 return "modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl) ";
254 case CallingConv::X86_FastCall:
255 return "modopt([mscorlib]System.Runtime.CompilerServices.CallConvFastcall) ";
256 case CallingConv::X86_StdCall:
257 return "modopt([mscorlib]System.Runtime.CompilerServices.CallConvStdcall) ";
258 default:
259 cerr << "CallingConvID = " << CallingConvID << '\n';
260 assert(0 && "Unsupported calling convention");
261 }
Chris Lattnerd27c9912008-03-30 18:22:13 +0000262 return ""; // Not reached
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000263}
264
265
266std::string MSILWriter::getArrayTypeName(Type::TypeID TyID, const Type* Ty) {
267 std::string Tmp = "";
268 const Type* ElemTy = Ty;
269 assert(Ty->getTypeID()==TyID && "Invalid type passed");
270 // Walk trought array element types.
271 for (;;) {
272 // Multidimensional array.
273 if (ElemTy->getTypeID()==TyID) {
274 if (const ArrayType* ATy = dyn_cast<ArrayType>(ElemTy))
275 Tmp += utostr(ATy->getNumElements());
276 else if (const VectorType* VTy = dyn_cast<VectorType>(ElemTy))
277 Tmp += utostr(VTy->getNumElements());
278 ElemTy = cast<SequentialType>(ElemTy)->getElementType();
279 }
280 // Base element type found.
281 if (ElemTy->getTypeID()!=TyID) break;
282 Tmp += ",";
283 }
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000284 return getTypeName(ElemTy, false, true)+"["+Tmp+"]";
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000285}
286
287
288std::string MSILWriter::getPrimitiveTypeName(const Type* Ty, bool isSigned) {
289 unsigned NumBits = 0;
290 switch (Ty->getTypeID()) {
291 case Type::VoidTyID:
292 return "void ";
293 case Type::IntegerTyID:
294 NumBits = getBitWidth(Ty);
295 if(NumBits==1)
296 return "bool ";
297 if (!isSigned)
298 return "unsigned int"+utostr(NumBits)+" ";
299 return "int"+utostr(NumBits)+" ";
300 case Type::FloatTyID:
301 return "float32 ";
302 case Type::DoubleTyID:
303 return "float64 ";
304 default:
305 cerr << "Type = " << *Ty << '\n';
306 assert(0 && "Invalid primitive type");
307 }
Chris Lattnerd27c9912008-03-30 18:22:13 +0000308 return ""; // Not reached
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000309}
310
311
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000312std::string MSILWriter::getTypeName(const Type* Ty, bool isSigned,
313 bool isNested) {
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000314 if (Ty->isPrimitiveType() || Ty->isInteger())
315 return getPrimitiveTypeName(Ty,isSigned);
316 // FIXME: "OpaqueType" support
317 switch (Ty->getTypeID()) {
318 case Type::PointerTyID:
319 return "void* ";
320 case Type::StructTyID:
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000321 if (isNested)
322 return ModulePtr->getTypeName(Ty);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000323 return "valuetype '"+ModulePtr->getTypeName(Ty)+"' ";
324 case Type::ArrayTyID:
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000325 if (isNested)
326 return getArrayTypeName(Ty->getTypeID(),Ty);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000327 return "valuetype '"+getArrayTypeName(Ty->getTypeID(),Ty)+"' ";
328 case Type::VectorTyID:
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000329 if (isNested)
330 return getArrayTypeName(Ty->getTypeID(),Ty);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000331 return "valuetype '"+getArrayTypeName(Ty->getTypeID(),Ty)+"' ";
332 default:
333 cerr << "Type = " << *Ty << '\n';
334 assert(0 && "Invalid type in getTypeName()");
335 }
Chris Lattnerd27c9912008-03-30 18:22:13 +0000336 return ""; // Not reached
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000337}
338
339
340MSILWriter::ValueType MSILWriter::getValueLocation(const Value* V) {
341 // Function argument
342 if (isa<Argument>(V))
343 return ArgumentVT;
344 // Function
345 else if (const Function* F = dyn_cast<Function>(V))
346 return F->hasInternalLinkage() ? InternalVT : GlobalVT;
347 // Variable
348 else if (const GlobalVariable* G = dyn_cast<GlobalVariable>(V))
349 return G->hasInternalLinkage() ? InternalVT : GlobalVT;
350 // Constant
351 else if (isa<Constant>(V))
352 return isa<ConstantExpr>(V) ? ConstExprVT : ConstVT;
353 // Local variable
354 return LocalVT;
355}
356
357
358std::string MSILWriter::getTypePostfix(const Type* Ty, bool Expand,
359 bool isSigned) {
360 unsigned NumBits = 0;
361 switch (Ty->getTypeID()) {
362 // Integer constant, expanding for stack operations.
363 case Type::IntegerTyID:
364 NumBits = getBitWidth(Ty);
365 // Expand integer value to "int32" or "int64".
366 if (Expand) return (NumBits<=32 ? "i4" : "i8");
367 if (NumBits==1) return "i1";
368 return (isSigned ? "i" : "u")+utostr(NumBits/8);
369 // Float constant.
370 case Type::FloatTyID:
371 return "r4";
372 case Type::DoubleTyID:
373 return "r8";
374 case Type::PointerTyID:
Duncan Sandsca0ed742007-11-05 00:04:43 +0000375 return "i"+utostr(TD->getABITypeSize(Ty));
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000376 default:
377 cerr << "TypeID = " << Ty->getTypeID() << '\n';
378 assert(0 && "Invalid type in TypeToPostfix()");
379 }
Chris Lattnerd27c9912008-03-30 18:22:13 +0000380 return ""; // Not reached
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000381}
382
383
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000384void MSILWriter::printConvToPtr() {
385 switch (ModulePtr->getPointerSize()) {
386 case Module::Pointer32:
387 printSimpleInstruction("conv.u4");
388 break;
389 case Module::Pointer64:
390 printSimpleInstruction("conv.u8");
391 break;
392 default:
393 assert(0 && "Module use not supporting pointer size");
394 }
395}
396
397
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000398void MSILWriter::printPtrLoad(uint64_t N) {
399 switch (ModulePtr->getPointerSize()) {
400 case Module::Pointer32:
401 printSimpleInstruction("ldc.i4",utostr(N).c_str());
402 // FIXME: Need overflow test?
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000403 if (!isUInt32(N)) {
404 cerr << "Value = " << utostr(N) << '\n';
405 assert(0 && "32-bit pointer overflowed");
406 }
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000407 break;
408 case Module::Pointer64:
409 printSimpleInstruction("ldc.i8",utostr(N).c_str());
410 break;
411 default:
412 assert(0 && "Module use not supporting pointer size");
413 }
414}
415
416
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000417void MSILWriter::printValuePtrLoad(const Value* V) {
418 printValueLoad(V);
419 printConvToPtr();
420}
421
422
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000423void MSILWriter::printConstLoad(const Constant* C) {
424 if (const ConstantInt* CInt = dyn_cast<ConstantInt>(C)) {
425 // Integer constant
426 Out << "\tldc." << getTypePostfix(C->getType(),true) << '\t';
427 if (CInt->isMinValue(true))
428 Out << CInt->getSExtValue();
429 else
430 Out << CInt->getZExtValue();
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000431 } else if (const ConstantFP* FP = dyn_cast<ConstantFP>(C)) {
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000432 // Float constant
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000433 uint64_t X;
434 unsigned Size;
435 if (FP->getType()->getTypeID()==Type::FloatTyID) {
Dale Johannesen9d5f4562007-09-12 03:30:33 +0000436 X = (uint32_t)FP->getValueAPF().convertToAPInt().getZExtValue();
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000437 Size = 4;
438 } else {
Dale Johannesen9d5f4562007-09-12 03:30:33 +0000439 X = FP->getValueAPF().convertToAPInt().getZExtValue();
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000440 Size = 8;
441 }
442 Out << "\tldc.r" << Size << "\t( " << utohexstr(X) << ')';
443 } else if (isa<UndefValue>(C)) {
444 // Undefined constant value = NULL.
445 printPtrLoad(0);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000446 } else {
447 cerr << "Constant = " << *C << '\n';
448 assert(0 && "Invalid constant value");
449 }
450 Out << '\n';
451}
452
453
454void MSILWriter::printValueLoad(const Value* V) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000455 MSILWriter::ValueType Location = getValueLocation(V);
456 switch (Location) {
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000457 // Global variable or function address.
458 case GlobalVT:
459 case InternalVT:
460 if (const Function* F = dyn_cast<Function>(V)) {
461 std::string Name = getConvModopt(F->getCallingConv())+getValueName(F);
462 printSimpleInstruction("ldftn",
463 getCallSignature(F->getFunctionType(),NULL,Name).c_str());
464 } else {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000465 std::string Tmp;
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000466 const Type* ElemTy = cast<PointerType>(V->getType())->getElementType();
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000467 if (Location==GlobalVT && cast<GlobalVariable>(V)->hasDLLImportLinkage()) {
468 Tmp = "void* "+getValueName(V);
469 printSimpleInstruction("ldsfld",Tmp.c_str());
470 } else {
471 Tmp = getTypeName(ElemTy)+getValueName(V);
472 printSimpleInstruction("ldsflda",Tmp.c_str());
473 }
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000474 }
475 break;
476 // Function argument.
477 case ArgumentVT:
478 printSimpleInstruction("ldarg",getValueName(V).c_str());
479 break;
480 // Local function variable.
481 case LocalVT:
482 printSimpleInstruction("ldloc",getValueName(V).c_str());
483 break;
484 // Constant value.
485 case ConstVT:
486 if (isa<ConstantPointerNull>(V))
487 printPtrLoad(0);
488 else
489 printConstLoad(cast<Constant>(V));
490 break;
491 // Constant expression.
492 case ConstExprVT:
493 printConstantExpr(cast<ConstantExpr>(V));
494 break;
495 default:
496 cerr << "Value = " << *V << '\n';
497 assert(0 && "Invalid value location");
498 }
499}
500
501
502void MSILWriter::printValueSave(const Value* V) {
503 switch (getValueLocation(V)) {
504 case ArgumentVT:
505 printSimpleInstruction("starg",getValueName(V).c_str());
506 break;
507 case LocalVT:
508 printSimpleInstruction("stloc",getValueName(V).c_str());
509 break;
510 default:
511 cerr << "Value = " << *V << '\n';
512 assert(0 && "Invalid value location");
513 }
514}
515
516
517void MSILWriter::printBinaryInstruction(const char* Name, const Value* Left,
518 const Value* Right) {
519 printValueLoad(Left);
520 printValueLoad(Right);
521 Out << '\t' << Name << '\n';
522}
523
524
525void MSILWriter::printSimpleInstruction(const char* Inst, const char* Operand) {
526 if(Operand)
527 Out << '\t' << Inst << '\t' << Operand << '\n';
528 else
529 Out << '\t' << Inst << '\n';
530}
531
532
533void MSILWriter::printPHICopy(const BasicBlock* Src, const BasicBlock* Dst) {
534 for (BasicBlock::const_iterator I = Dst->begin(), E = Dst->end();
535 isa<PHINode>(I); ++I) {
536 const PHINode* Phi = cast<PHINode>(I);
537 const Value* Val = Phi->getIncomingValueForBlock(Src);
538 if (isa<UndefValue>(Val)) continue;
539 printValueLoad(Val);
540 printValueSave(Phi);
541 }
542}
543
544
545void MSILWriter::printBranchToBlock(const BasicBlock* CurrBB,
546 const BasicBlock* TrueBB,
547 const BasicBlock* FalseBB) {
548 if (TrueBB==FalseBB) {
549 // "TrueBB" and "FalseBB" destination equals
550 printPHICopy(CurrBB,TrueBB);
551 printSimpleInstruction("pop");
552 printSimpleInstruction("br",getLabelName(TrueBB).c_str());
553 } else if (FalseBB==NULL) {
554 // If "FalseBB" not used the jump have condition
555 printPHICopy(CurrBB,TrueBB);
556 printSimpleInstruction("brtrue",getLabelName(TrueBB).c_str());
557 } else if (TrueBB==NULL) {
558 // If "TrueBB" not used the jump is unconditional
559 printPHICopy(CurrBB,FalseBB);
560 printSimpleInstruction("br",getLabelName(FalseBB).c_str());
561 } else {
562 // Copy PHI instructions for each block
563 std::string TmpLabel;
564 // Print PHI instructions for "TrueBB"
565 if (isa<PHINode>(TrueBB->begin())) {
566 TmpLabel = getLabelName(TrueBB)+"$phi_"+utostr(getUniqID());
567 printSimpleInstruction("brtrue",TmpLabel.c_str());
568 } else {
569 printSimpleInstruction("brtrue",getLabelName(TrueBB).c_str());
570 }
571 // Print PHI instructions for "FalseBB"
572 if (isa<PHINode>(FalseBB->begin())) {
573 printPHICopy(CurrBB,FalseBB);
574 printSimpleInstruction("br",getLabelName(FalseBB).c_str());
575 } else {
576 printSimpleInstruction("br",getLabelName(FalseBB).c_str());
577 }
578 if (isa<PHINode>(TrueBB->begin())) {
579 // Handle "TrueBB" PHI Copy
580 Out << TmpLabel << ":\n";
581 printPHICopy(CurrBB,TrueBB);
582 printSimpleInstruction("br",getLabelName(TrueBB).c_str());
583 }
584 }
585}
586
587
588void MSILWriter::printBranchInstruction(const BranchInst* Inst) {
589 if (Inst->isUnconditional()) {
590 printBranchToBlock(Inst->getParent(),NULL,Inst->getSuccessor(0));
591 } else {
592 printValueLoad(Inst->getCondition());
593 printBranchToBlock(Inst->getParent(),Inst->getSuccessor(0),
594 Inst->getSuccessor(1));
595 }
596}
597
598
599void MSILWriter::printSelectInstruction(const Value* Cond, const Value* VTrue,
600 const Value* VFalse) {
601 std::string TmpLabel = std::string("select$true_")+utostr(getUniqID());
602 printValueLoad(VTrue);
603 printValueLoad(Cond);
604 printSimpleInstruction("brtrue",TmpLabel.c_str());
605 printSimpleInstruction("pop");
606 printValueLoad(VFalse);
607 Out << TmpLabel << ":\n";
608}
609
610
611void MSILWriter::printIndirectLoad(const Value* V) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000612 const Type* Ty = V->getType();
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000613 printValueLoad(V);
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000614 if (const PointerType* P = dyn_cast<PointerType>(Ty))
615 Ty = P->getElementType();
616 std::string Tmp = "ldind."+getTypePostfix(Ty, false);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000617 printSimpleInstruction(Tmp.c_str());
618}
619
620
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000621void MSILWriter::printIndirectSave(const Value* Ptr, const Value* Val) {
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000622 printValueLoad(Ptr);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000623 printValueLoad(Val);
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000624 printIndirectSave(Val->getType());
625}
626
627
628void MSILWriter::printIndirectSave(const Type* Ty) {
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000629 // Instruction need signed postfix for any type.
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000630 std::string postfix = getTypePostfix(Ty, false);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000631 if (*postfix.begin()=='u') *postfix.begin() = 'i';
632 postfix = "stind."+postfix;
633 printSimpleInstruction(postfix.c_str());
634}
635
636
637void MSILWriter::printCastInstruction(unsigned int Op, const Value* V,
638 const Type* Ty) {
639 std::string Tmp("");
640 printValueLoad(V);
641 switch (Op) {
642 // Signed
643 case Instruction::SExt:
644 case Instruction::SIToFP:
645 case Instruction::FPToSI:
646 Tmp = "conv."+getTypePostfix(Ty,false,true);
647 printSimpleInstruction(Tmp.c_str());
648 break;
649 // Unsigned
650 case Instruction::FPTrunc:
651 case Instruction::FPExt:
652 case Instruction::UIToFP:
653 case Instruction::Trunc:
654 case Instruction::ZExt:
655 case Instruction::FPToUI:
656 case Instruction::PtrToInt:
657 case Instruction::IntToPtr:
658 Tmp = "conv."+getTypePostfix(Ty,false);
659 printSimpleInstruction(Tmp.c_str());
660 break;
661 // Do nothing
662 case Instruction::BitCast:
663 // FIXME: meaning that ld*/st* instruction do not change data format.
664 break;
665 default:
666 cerr << "Opcode = " << Op << '\n';
667 assert(0 && "Invalid conversion instruction");
668 }
669}
670
671
672void MSILWriter::printGepInstruction(const Value* V, gep_type_iterator I,
673 gep_type_iterator E) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000674 unsigned Size;
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000675 // Load address
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000676 printValuePtrLoad(V);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000677 // Calculate element offset.
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000678 for (; I!=E; ++I){
679 Size = 0;
680 const Value* IndexValue = I.getOperand();
681 if (const StructType* StrucTy = dyn_cast<StructType>(*I)) {
682 uint64_t FieldIndex = cast<ConstantInt>(IndexValue)->getZExtValue();
683 // Offset is the sum of all previous structure fields.
684 for (uint64_t F = 0; F<FieldIndex; ++F)
Duncan Sandsca0ed742007-11-05 00:04:43 +0000685 Size += TD->getABITypeSize(StrucTy->getContainedType((unsigned)F));
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000686 printPtrLoad(Size);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000687 printSimpleInstruction("add");
688 continue;
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000689 } else if (const SequentialType* SeqTy = dyn_cast<SequentialType>(*I)) {
Duncan Sandsca0ed742007-11-05 00:04:43 +0000690 Size = TD->getABITypeSize(SeqTy->getElementType());
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000691 } else {
Duncan Sandsca0ed742007-11-05 00:04:43 +0000692 Size = TD->getABITypeSize(*I);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000693 }
694 // Add offset of current element to stack top.
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000695 if (!isZeroValue(IndexValue)) {
696 // Constant optimization.
697 if (const ConstantInt* C = dyn_cast<ConstantInt>(IndexValue)) {
698 if (C->getValue().isNegative()) {
699 printPtrLoad(C->getValue().abs().getZExtValue()*Size);
700 printSimpleInstruction("sub");
701 continue;
702 } else
703 printPtrLoad(C->getZExtValue()*Size);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000704 } else {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000705 printPtrLoad(Size);
706 printValuePtrLoad(IndexValue);
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000707 printSimpleInstruction("mul");
708 }
709 printSimpleInstruction("add");
710 }
711 }
712}
713
714
715std::string MSILWriter::getCallSignature(const FunctionType* Ty,
716 const Instruction* Inst,
717 std::string Name) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000718 std::string Tmp("");
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000719 if (Ty->isVarArg()) Tmp += "vararg ";
720 // Name and return type.
721 Tmp += getTypeName(Ty->getReturnType())+Name+"(";
722 // Function argument type list.
723 unsigned NumParams = Ty->getNumParams();
724 for (unsigned I = 0; I!=NumParams; ++I) {
725 if (I!=0) Tmp += ",";
726 Tmp += getTypeName(Ty->getParamType(I));
727 }
728 // CLR needs to know the exact amount of parameters received by vararg
729 // function, because caller cleans the stack.
730 if (Ty->isVarArg() && Inst) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000731 // Origin to function arguments in "CallInst" or "InvokeInst".
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000732 unsigned Org = isa<InvokeInst>(Inst) ? 3 : 1;
733 // Print variable argument types.
734 unsigned NumOperands = Inst->getNumOperands()-Org;
735 if (NumParams<NumOperands) {
736 if (NumParams!=0) Tmp += ", ";
737 Tmp += "... , ";
738 for (unsigned J = NumParams; J!=NumOperands; ++J) {
739 if (J!=NumParams) Tmp += ", ";
740 Tmp += getTypeName(Inst->getOperand(J+Org)->getType());
741 }
742 }
743 }
744 return Tmp+")";
745}
746
747
748void MSILWriter::printFunctionCall(const Value* FnVal,
749 const Instruction* Inst) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000750 // Get function calling convention.
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000751 std::string Name = "";
752 if (const CallInst* Call = dyn_cast<CallInst>(Inst))
753 Name = getConvModopt(Call->getCallingConv());
754 else if (const InvokeInst* Invoke = dyn_cast<InvokeInst>(Inst))
755 Name = getConvModopt(Invoke->getCallingConv());
756 else {
757 cerr << "Instruction = " << Inst->getName() << '\n';
758 assert(0 && "Need \"Invoke\" or \"Call\" instruction only");
759 }
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000760 if (const Function* F = dyn_cast<Function>(FnVal)) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000761 // Direct call.
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000762 Name += getValueName(F);
763 printSimpleInstruction("call",
764 getCallSignature(F->getFunctionType(),Inst,Name).c_str());
765 } else {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000766 // Indirect function call.
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000767 const PointerType* PTy = cast<PointerType>(FnVal->getType());
768 const FunctionType* FTy = cast<FunctionType>(PTy->getElementType());
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000769 // Load function address.
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000770 printValueLoad(FnVal);
771 printSimpleInstruction("calli",getCallSignature(FTy,Inst,Name).c_str());
772 }
773}
774
775
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000776void MSILWriter::printIntrinsicCall(const IntrinsicInst* Inst) {
777 std::string Name;
778 switch (Inst->getIntrinsicID()) {
779 case Intrinsic::vastart:
780 Name = getValueName(Inst->getOperand(1));
781 Name.insert(Name.length()-1,"$valist");
782 // Obtain the argument handle.
783 printSimpleInstruction("ldloca",Name.c_str());
784 printSimpleInstruction("arglist");
785 printSimpleInstruction("call",
786 "instance void [mscorlib]System.ArgIterator::.ctor"
787 "(valuetype [mscorlib]System.RuntimeArgumentHandle)");
788 // Save as pointer type "void*"
789 printValueLoad(Inst->getOperand(1));
790 printSimpleInstruction("ldloca",Name.c_str());
Christopher Lamb43ad6b32007-12-17 01:12:55 +0000791 printIndirectSave(PointerType::getUnqual(IntegerType::get(8)));
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000792 break;
793 case Intrinsic::vaend:
794 // Close argument list handle.
795 printIndirectLoad(Inst->getOperand(1));
796 printSimpleInstruction("call","instance void [mscorlib]System.ArgIterator::End()");
797 break;
798 case Intrinsic::vacopy:
799 // Copy "ArgIterator" valuetype.
800 printIndirectLoad(Inst->getOperand(1));
801 printIndirectLoad(Inst->getOperand(2));
802 printSimpleInstruction("cpobj","[mscorlib]System.ArgIterator");
803 break;
804 default:
805 cerr << "Intrinsic ID = " << Inst->getIntrinsicID() << '\n';
806 assert(0 && "Invalid intrinsic function");
807 }
808}
809
810
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000811void MSILWriter::printCallInstruction(const Instruction* Inst) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000812 if (isa<IntrinsicInst>(Inst)) {
813 // Handle intrinsic function.
814 printIntrinsicCall(cast<IntrinsicInst>(Inst));
815 } else {
816 // Load arguments to stack and call function.
817 for (int I = 1, E = Inst->getNumOperands(); I!=E; ++I)
818 printValueLoad(Inst->getOperand(I));
819 printFunctionCall(Inst->getOperand(0),Inst);
820 }
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000821}
822
823
824void MSILWriter::printICmpInstruction(unsigned Predicate, const Value* Left,
825 const Value* Right) {
826 switch (Predicate) {
827 case ICmpInst::ICMP_EQ:
828 printBinaryInstruction("ceq",Left,Right);
829 break;
830 case ICmpInst::ICMP_NE:
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000831 // Emulate = not neg (Op1 eq Op2)
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000832 printBinaryInstruction("ceq",Left,Right);
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000833 printSimpleInstruction("neg");
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000834 printSimpleInstruction("not");
835 break;
836 case ICmpInst::ICMP_ULE:
837 case ICmpInst::ICMP_SLE:
838 // Emulate = (Op1 eq Op2) or (Op1 lt Op2)
839 printBinaryInstruction("ceq",Left,Right);
840 if (Predicate==ICmpInst::ICMP_ULE)
841 printBinaryInstruction("clt.un",Left,Right);
842 else
843 printBinaryInstruction("clt",Left,Right);
844 printSimpleInstruction("or");
845 break;
846 case ICmpInst::ICMP_UGE:
847 case ICmpInst::ICMP_SGE:
848 // Emulate = (Op1 eq Op2) or (Op1 gt Op2)
849 printBinaryInstruction("ceq",Left,Right);
850 if (Predicate==ICmpInst::ICMP_UGE)
851 printBinaryInstruction("cgt.un",Left,Right);
852 else
853 printBinaryInstruction("cgt",Left,Right);
854 printSimpleInstruction("or");
855 break;
856 case ICmpInst::ICMP_ULT:
857 printBinaryInstruction("clt.un",Left,Right);
858 break;
859 case ICmpInst::ICMP_SLT:
860 printBinaryInstruction("clt",Left,Right);
861 break;
862 case ICmpInst::ICMP_UGT:
863 printBinaryInstruction("cgt.un",Left,Right);
864 case ICmpInst::ICMP_SGT:
865 printBinaryInstruction("cgt",Left,Right);
866 break;
867 default:
868 cerr << "Predicate = " << Predicate << '\n';
869 assert(0 && "Invalid icmp predicate");
870 }
871}
872
873
874void MSILWriter::printFCmpInstruction(unsigned Predicate, const Value* Left,
875 const Value* Right) {
876 // FIXME: Correct comparison
877 std::string NanFunc = "bool [mscorlib]System.Double::IsNaN(float64)";
878 switch (Predicate) {
879 case FCmpInst::FCMP_UGT:
880 // X > Y || llvm_fcmp_uno(X, Y)
881 printBinaryInstruction("cgt",Left,Right);
882 printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
883 printSimpleInstruction("or");
884 break;
885 case FCmpInst::FCMP_OGT:
886 // X > Y
887 printBinaryInstruction("cgt",Left,Right);
888 break;
889 case FCmpInst::FCMP_UGE:
890 // X >= Y || llvm_fcmp_uno(X, Y)
891 printBinaryInstruction("ceq",Left,Right);
892 printBinaryInstruction("cgt",Left,Right);
893 printSimpleInstruction("or");
894 printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
895 printSimpleInstruction("or");
896 break;
897 case FCmpInst::FCMP_OGE:
898 // X >= Y
899 printBinaryInstruction("ceq",Left,Right);
900 printBinaryInstruction("cgt",Left,Right);
901 printSimpleInstruction("or");
902 break;
903 case FCmpInst::FCMP_ULT:
904 // X < Y || llvm_fcmp_uno(X, Y)
905 printBinaryInstruction("clt",Left,Right);
906 printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
907 printSimpleInstruction("or");
908 break;
909 case FCmpInst::FCMP_OLT:
910 // X < Y
911 printBinaryInstruction("clt",Left,Right);
912 break;
913 case FCmpInst::FCMP_ULE:
914 // X <= Y || llvm_fcmp_uno(X, Y)
915 printBinaryInstruction("ceq",Left,Right);
916 printBinaryInstruction("clt",Left,Right);
917 printSimpleInstruction("or");
918 printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
919 printSimpleInstruction("or");
920 break;
921 case FCmpInst::FCMP_OLE:
922 // X <= Y
923 printBinaryInstruction("ceq",Left,Right);
924 printBinaryInstruction("clt",Left,Right);
925 printSimpleInstruction("or");
926 break;
927 case FCmpInst::FCMP_UEQ:
928 // X == Y || llvm_fcmp_uno(X, Y)
929 printBinaryInstruction("ceq",Left,Right);
930 printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
931 printSimpleInstruction("or");
932 break;
933 case FCmpInst::FCMP_OEQ:
934 // X == Y
935 printBinaryInstruction("ceq",Left,Right);
936 break;
937 case FCmpInst::FCMP_UNE:
938 // X != Y
939 printBinaryInstruction("ceq",Left,Right);
Anton Korobeynikovf13090c2007-05-06 20:13:33 +0000940 printSimpleInstruction("neg");
Anton Korobeynikov099883f2007-03-21 21:38:25 +0000941 printSimpleInstruction("not");
942 break;
943 case FCmpInst::FCMP_ONE:
944 // X != Y && llvm_fcmp_ord(X, Y)
945 printBinaryInstruction("ceq",Left,Right);
946 printSimpleInstruction("not");
947 break;
948 case FCmpInst::FCMP_ORD:
949 // return X == X && Y == Y
950 printBinaryInstruction("ceq",Left,Left);
951 printBinaryInstruction("ceq",Right,Right);
952 printSimpleInstruction("or");
953 break;
954 case FCmpInst::FCMP_UNO:
955 // X != X || Y != Y
956 printBinaryInstruction("ceq",Left,Left);
957 printSimpleInstruction("not");
958 printBinaryInstruction("ceq",Right,Right);
959 printSimpleInstruction("not");
960 printSimpleInstruction("or");
961 break;
962 default:
963 assert(0 && "Illegal FCmp predicate");
964 }
965}
966
967
968void MSILWriter::printInvokeInstruction(const InvokeInst* Inst) {
969 std::string Label = "leave$normal_"+utostr(getUniqID());
970 Out << ".try {\n";
971 // Load arguments
972 for (int I = 3, E = Inst->getNumOperands(); I!=E; ++I)
973 printValueLoad(Inst->getOperand(I));
974 // Print call instruction
975 printFunctionCall(Inst->getOperand(0),Inst);
976 // Save function result and leave "try" block
977 printValueSave(Inst);
978 printSimpleInstruction("leave",Label.c_str());
979 Out << "}\n";
980 Out << "catch [mscorlib]System.Exception {\n";
981 // Redirect to unwind block
982 printSimpleInstruction("pop");
983 printBranchToBlock(Inst->getParent(),NULL,Inst->getUnwindDest());
984 Out << "}\n" << Label << ":\n";
985 // Redirect to continue block
986 printBranchToBlock(Inst->getParent(),NULL,Inst->getNormalDest());
987}
988
989
990void MSILWriter::printSwitchInstruction(const SwitchInst* Inst) {
991 // FIXME: Emulate with IL "switch" instruction
992 // Emulate = if () else if () else if () else ...
993 for (unsigned int I = 1, E = Inst->getNumCases(); I!=E; ++I) {
994 printValueLoad(Inst->getCondition());
995 printValueLoad(Inst->getCaseValue(I));
996 printSimpleInstruction("ceq");
997 // Condition jump to successor block
998 printBranchToBlock(Inst->getParent(),Inst->getSuccessor(I),NULL);
999 }
1000 // Jump to default block
1001 printBranchToBlock(Inst->getParent(),NULL,Inst->getDefaultDest());
1002}
1003
1004
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001005void MSILWriter::printVAArgInstruction(const VAArgInst* Inst) {
1006 printIndirectLoad(Inst->getOperand(0));
1007 printSimpleInstruction("call",
1008 "instance typedref [mscorlib]System.ArgIterator::GetNextArg()");
1009 printSimpleInstruction("refanyval","void*");
Christopher Lamb43ad6b32007-12-17 01:12:55 +00001010 std::string Name =
1011 "ldind."+getTypePostfix(PointerType::getUnqual(IntegerType::get(8)),false);
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001012 printSimpleInstruction(Name.c_str());
1013}
1014
1015
1016void MSILWriter::printAllocaInstruction(const AllocaInst* Inst) {
Duncan Sandsca0ed742007-11-05 00:04:43 +00001017 uint64_t Size = TD->getABITypeSize(Inst->getAllocatedType());
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001018 // Constant optimization.
1019 if (const ConstantInt* CInt = dyn_cast<ConstantInt>(Inst->getOperand(0))) {
1020 printPtrLoad(CInt->getZExtValue()*Size);
1021 } else {
1022 printPtrLoad(Size);
1023 printValueLoad(Inst->getOperand(0));
1024 printSimpleInstruction("mul");
1025 }
1026 printSimpleInstruction("localloc");
1027}
1028
1029
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001030void MSILWriter::printInstruction(const Instruction* Inst) {
1031 const Value *Left = 0, *Right = 0;
1032 if (Inst->getNumOperands()>=1) Left = Inst->getOperand(0);
1033 if (Inst->getNumOperands()>=2) Right = Inst->getOperand(1);
1034 // Print instruction
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001035 // FIXME: "ShuffleVector","ExtractElement","InsertElement" support.
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001036 switch (Inst->getOpcode()) {
1037 // Terminator
1038 case Instruction::Ret:
1039 if (Inst->getNumOperands()) {
1040 printValueLoad(Left);
1041 printSimpleInstruction("ret");
1042 } else
1043 printSimpleInstruction("ret");
1044 break;
1045 case Instruction::Br:
1046 printBranchInstruction(cast<BranchInst>(Inst));
1047 break;
1048 // Binary
1049 case Instruction::Add:
1050 printBinaryInstruction("add",Left,Right);
1051 break;
1052 case Instruction::Sub:
1053 printBinaryInstruction("sub",Left,Right);
1054 break;
1055 case Instruction::Mul:
1056 printBinaryInstruction("mul",Left,Right);
1057 break;
1058 case Instruction::UDiv:
1059 printBinaryInstruction("div.un",Left,Right);
1060 break;
1061 case Instruction::SDiv:
1062 case Instruction::FDiv:
1063 printBinaryInstruction("div",Left,Right);
1064 break;
1065 case Instruction::URem:
1066 printBinaryInstruction("rem.un",Left,Right);
1067 break;
1068 case Instruction::SRem:
1069 case Instruction::FRem:
1070 printBinaryInstruction("rem",Left,Right);
1071 break;
1072 // Binary Condition
1073 case Instruction::ICmp:
1074 printICmpInstruction(cast<ICmpInst>(Inst)->getPredicate(),Left,Right);
1075 break;
1076 case Instruction::FCmp:
1077 printFCmpInstruction(cast<FCmpInst>(Inst)->getPredicate(),Left,Right);
1078 break;
1079 // Bitwise Binary
1080 case Instruction::And:
1081 printBinaryInstruction("and",Left,Right);
1082 break;
1083 case Instruction::Or:
1084 printBinaryInstruction("or",Left,Right);
1085 break;
1086 case Instruction::Xor:
1087 printBinaryInstruction("xor",Left,Right);
1088 break;
1089 case Instruction::Shl:
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001090 printValueLoad(Left);
1091 printValueLoad(Right);
1092 printSimpleInstruction("conv.i4");
1093 printSimpleInstruction("shl");
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001094 break;
1095 case Instruction::LShr:
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001096 printValueLoad(Left);
1097 printValueLoad(Right);
1098 printSimpleInstruction("conv.i4");
1099 printSimpleInstruction("shr.un");
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001100 break;
1101 case Instruction::AShr:
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001102 printValueLoad(Left);
1103 printValueLoad(Right);
1104 printSimpleInstruction("conv.i4");
1105 printSimpleInstruction("shr");
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001106 break;
1107 case Instruction::Select:
1108 printSelectInstruction(Inst->getOperand(0),Inst->getOperand(1),Inst->getOperand(2));
1109 break;
1110 case Instruction::Load:
1111 printIndirectLoad(Inst->getOperand(0));
1112 break;
1113 case Instruction::Store:
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001114 printIndirectSave(Inst->getOperand(1), Inst->getOperand(0));
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001115 break;
1116 case Instruction::Trunc:
1117 case Instruction::ZExt:
1118 case Instruction::SExt:
1119 case Instruction::FPTrunc:
1120 case Instruction::FPExt:
1121 case Instruction::UIToFP:
1122 case Instruction::SIToFP:
1123 case Instruction::FPToUI:
1124 case Instruction::FPToSI:
1125 case Instruction::PtrToInt:
1126 case Instruction::IntToPtr:
1127 case Instruction::BitCast:
1128 printCastInstruction(Inst->getOpcode(),Left,
1129 cast<CastInst>(Inst)->getDestTy());
1130 break;
1131 case Instruction::GetElementPtr:
1132 printGepInstruction(Inst->getOperand(0),gep_type_begin(Inst),
1133 gep_type_end(Inst));
1134 break;
1135 case Instruction::Call:
1136 printCallInstruction(cast<CallInst>(Inst));
1137 break;
1138 case Instruction::Invoke:
1139 printInvokeInstruction(cast<InvokeInst>(Inst));
1140 break;
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001141 case Instruction::Unwind:
1142 printSimpleInstruction("newobj",
1143 "instance void [mscorlib]System.Exception::.ctor()");
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001144 printSimpleInstruction("throw");
1145 break;
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001146 case Instruction::Switch:
1147 printSwitchInstruction(cast<SwitchInst>(Inst));
1148 break;
1149 case Instruction::Alloca:
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001150 printAllocaInstruction(cast<AllocaInst>(Inst));
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001151 break;
1152 case Instruction::Malloc:
1153 assert(0 && "LowerAllocationsPass used");
1154 break;
1155 case Instruction::Free:
1156 assert(0 && "LowerAllocationsPass used");
1157 break;
1158 case Instruction::Unreachable:
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001159 printSimpleInstruction("ldstr", "\"Unreachable instruction\"");
1160 printSimpleInstruction("newobj",
1161 "instance void [mscorlib]System.Exception::.ctor(string)");
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001162 printSimpleInstruction("throw");
1163 break;
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001164 case Instruction::VAArg:
1165 printVAArgInstruction(cast<VAArgInst>(Inst));
1166 break;
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001167 default:
1168 cerr << "Instruction = " << Inst->getName() << '\n';
1169 assert(0 && "Unsupported instruction");
1170 }
1171}
1172
1173
1174void MSILWriter::printLoop(const Loop* L) {
1175 Out << getLabelName(L->getHeader()->getName()) << ":\n";
1176 const std::vector<BasicBlock*>& blocks = L->getBlocks();
1177 for (unsigned I = 0, E = blocks.size(); I!=E; I++) {
1178 BasicBlock* BB = blocks[I];
1179 Loop* BBLoop = LInfo->getLoopFor(BB);
1180 if (BBLoop == L)
1181 printBasicBlock(BB);
1182 else if (BB==BBLoop->getHeader() && BBLoop->getParentLoop()==L)
1183 printLoop(BBLoop);
1184 }
1185 printSimpleInstruction("br",getLabelName(L->getHeader()->getName()).c_str());
1186}
1187
1188
1189void MSILWriter::printBasicBlock(const BasicBlock* BB) {
1190 Out << getLabelName(BB) << ":\n";
1191 for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I!=E; ++I) {
1192 const Instruction* Inst = I;
1193 // Comment llvm original instruction
Owen Andersoncb371882008-08-21 00:14:44 +00001194 // Out << "\n//" << *Inst << "\n";
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001195 // Do not handle PHI instruction in current block
1196 if (Inst->getOpcode()==Instruction::PHI) continue;
1197 // Print instruction
1198 printInstruction(Inst);
1199 // Save result
1200 if (Inst->getType()!=Type::VoidTy) {
1201 // Do not save value after invoke, it done in "try" block
1202 if (Inst->getOpcode()==Instruction::Invoke) continue;
1203 printValueSave(Inst);
1204 }
1205 }
1206}
1207
1208
1209void MSILWriter::printLocalVariables(const Function& F) {
1210 std::string Name;
1211 const Type* Ty = NULL;
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001212 std::set<const Value*> Printed;
1213 const Value* VaList = NULL;
1214 unsigned StackDepth = 8;
1215 // Find local variables
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001216 for (const_inst_iterator I = inst_begin(&F), E = inst_end(&F); I!=E; ++I) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001217 if (I->getOpcode()==Instruction::Call ||
1218 I->getOpcode()==Instruction::Invoke) {
1219 // Test stack depth.
1220 if (StackDepth<I->getNumOperands())
1221 StackDepth = I->getNumOperands();
1222 }
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001223 const AllocaInst* AI = dyn_cast<AllocaInst>(&*I);
1224 if (AI && !isa<GlobalVariable>(AI)) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001225 // Local variable allocation.
Christopher Lamb43ad6b32007-12-17 01:12:55 +00001226 Ty = PointerType::getUnqual(AI->getAllocatedType());
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001227 Name = getValueName(AI);
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001228 Out << "\t.locals (" << getTypeName(Ty) << Name << ")\n";
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001229 } else if (I->getType()!=Type::VoidTy) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001230 // Operation result.
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001231 Ty = I->getType();
1232 Name = getValueName(&*I);
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001233 Out << "\t.locals (" << getTypeName(Ty) << Name << ")\n";
1234 }
1235 // Test on 'va_list' variable
1236 bool isVaList = false;
1237 if (const VAArgInst* VaInst = dyn_cast<VAArgInst>(&*I)) {
1238 // "va_list" as "va_arg" instruction operand.
1239 isVaList = true;
1240 VaList = VaInst->getOperand(0);
1241 } else if (const IntrinsicInst* Inst = dyn_cast<IntrinsicInst>(&*I)) {
1242 // "va_list" as intrinsic function operand.
1243 switch (Inst->getIntrinsicID()) {
1244 case Intrinsic::vastart:
1245 case Intrinsic::vaend:
1246 case Intrinsic::vacopy:
1247 isVaList = true;
1248 VaList = Inst->getOperand(1);
1249 break;
1250 default:
1251 isVaList = false;
1252 }
1253 }
1254 // Print "va_list" variable.
1255 if (isVaList && Printed.insert(VaList).second) {
1256 Name = getValueName(VaList);
1257 Name.insert(Name.length()-1,"$valist");
1258 Out << "\t.locals (valuetype [mscorlib]System.ArgIterator "
1259 << Name << ")\n";
1260 }
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001261 }
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001262 printSimpleInstruction(".maxstack",utostr(StackDepth*2).c_str());
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001263}
1264
1265
1266void MSILWriter::printFunctionBody(const Function& F) {
1267 // Print body
1268 for (Function::const_iterator I = F.begin(), E = F.end(); I!=E; ++I) {
1269 if (Loop *L = LInfo->getLoopFor(I)) {
1270 if (L->getHeader()==I && L->getParentLoop()==0)
1271 printLoop(L);
1272 } else {
1273 printBasicBlock(I);
1274 }
1275 }
1276}
1277
1278
1279void MSILWriter::printConstantExpr(const ConstantExpr* CE) {
1280 const Value *left = 0, *right = 0;
1281 if (CE->getNumOperands()>=1) left = CE->getOperand(0);
1282 if (CE->getNumOperands()>=2) right = CE->getOperand(1);
1283 // Print instruction
1284 switch (CE->getOpcode()) {
1285 case Instruction::Trunc:
1286 case Instruction::ZExt:
1287 case Instruction::SExt:
1288 case Instruction::FPTrunc:
1289 case Instruction::FPExt:
1290 case Instruction::UIToFP:
1291 case Instruction::SIToFP:
1292 case Instruction::FPToUI:
1293 case Instruction::FPToSI:
1294 case Instruction::PtrToInt:
1295 case Instruction::IntToPtr:
1296 case Instruction::BitCast:
1297 printCastInstruction(CE->getOpcode(),left,CE->getType());
1298 break;
1299 case Instruction::GetElementPtr:
1300 printGepInstruction(CE->getOperand(0),gep_type_begin(CE),gep_type_end(CE));
1301 break;
1302 case Instruction::ICmp:
1303 printICmpInstruction(CE->getPredicate(),left,right);
1304 break;
1305 case Instruction::FCmp:
1306 printFCmpInstruction(CE->getPredicate(),left,right);
1307 break;
1308 case Instruction::Select:
1309 printSelectInstruction(CE->getOperand(0),CE->getOperand(1),CE->getOperand(2));
1310 break;
1311 case Instruction::Add:
1312 printBinaryInstruction("add",left,right);
1313 break;
1314 case Instruction::Sub:
1315 printBinaryInstruction("sub",left,right);
1316 break;
1317 case Instruction::Mul:
1318 printBinaryInstruction("mul",left,right);
1319 break;
1320 case Instruction::UDiv:
1321 printBinaryInstruction("div.un",left,right);
1322 break;
1323 case Instruction::SDiv:
1324 case Instruction::FDiv:
1325 printBinaryInstruction("div",left,right);
1326 break;
1327 case Instruction::URem:
1328 printBinaryInstruction("rem.un",left,right);
1329 break;
1330 case Instruction::SRem:
1331 case Instruction::FRem:
1332 printBinaryInstruction("rem",left,right);
1333 break;
1334 case Instruction::And:
1335 printBinaryInstruction("and",left,right);
1336 break;
1337 case Instruction::Or:
1338 printBinaryInstruction("or",left,right);
1339 break;
1340 case Instruction::Xor:
1341 printBinaryInstruction("xor",left,right);
1342 break;
1343 case Instruction::Shl:
1344 printBinaryInstruction("shl",left,right);
1345 break;
1346 case Instruction::LShr:
1347 printBinaryInstruction("shr.un",left,right);
1348 break;
1349 case Instruction::AShr:
1350 printBinaryInstruction("shr",left,right);
1351 break;
1352 default:
1353 cerr << "Expression = " << *CE << "\n";
1354 assert(0 && "Invalid constant expression");
1355 }
1356}
1357
1358
1359void MSILWriter::printStaticInitializerList() {
1360 // List of global variables with uninitialized fields.
1361 for (std::map<const GlobalVariable*,std::vector<StaticInitializer> >::iterator
1362 VarI = StaticInitList.begin(), VarE = StaticInitList.end(); VarI!=VarE;
1363 ++VarI) {
1364 const std::vector<StaticInitializer>& InitList = VarI->second;
1365 if (InitList.empty()) continue;
1366 // For each uninitialized field.
1367 for (std::vector<StaticInitializer>::const_iterator I = InitList.begin(),
1368 E = InitList.end(); I!=E; ++I) {
1369 if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(I->constant)) {
Owen Andersoncb371882008-08-21 00:14:44 +00001370 // Out << "\n// Init " << getValueName(VarI->first) << ", offset " <<
1371 // utostr(I->offset) << ", type "<< *I->constant->getType() << "\n\n";
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001372 // Load variable address
1373 printValueLoad(VarI->first);
1374 // Add offset
1375 if (I->offset!=0) {
1376 printPtrLoad(I->offset);
1377 printSimpleInstruction("add");
1378 }
1379 // Load value
1380 printConstantExpr(CE);
1381 // Save result at offset
1382 std::string postfix = getTypePostfix(CE->getType(),true);
1383 if (*postfix.begin()=='u') *postfix.begin() = 'i';
1384 postfix = "stind."+postfix;
1385 printSimpleInstruction(postfix.c_str());
1386 } else {
1387 cerr << "Constant = " << *I->constant << '\n';
1388 assert(0 && "Invalid static initializer");
1389 }
1390 }
1391 }
1392}
1393
1394
1395void MSILWriter::printFunction(const Function& F) {
Duncan Sandsafa3b6d2007-11-28 17:07:01 +00001396 bool isSigned = F.paramHasAttr(0, ParamAttr::SExt);
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001397 Out << "\n.method static ";
1398 Out << (F.hasInternalLinkage() ? "private " : "public ");
1399 if (F.isVarArg()) Out << "vararg ";
1400 Out << getTypeName(F.getReturnType(),isSigned) <<
1401 getConvModopt(F.getCallingConv()) << getValueName(&F) << '\n';
1402 // Arguments
1403 Out << "\t(";
1404 unsigned ArgIdx = 1;
1405 for (Function::const_arg_iterator I = F.arg_begin(), E = F.arg_end(); I!=E;
1406 ++I, ++ArgIdx) {
Duncan Sandsafa3b6d2007-11-28 17:07:01 +00001407 isSigned = F.paramHasAttr(ArgIdx, ParamAttr::SExt);
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001408 if (I!=F.arg_begin()) Out << ", ";
1409 Out << getTypeName(I->getType(),isSigned) << getValueName(I);
1410 }
1411 Out << ") cil managed\n";
1412 // Body
1413 Out << "{\n";
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001414 printLocalVariables(F);
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001415 printFunctionBody(F);
1416 Out << "}\n";
1417}
1418
1419
1420void MSILWriter::printDeclarations(const TypeSymbolTable& ST) {
1421 std::string Name;
1422 std::set<const Type*> Printed;
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001423 for (std::set<const Type*>::const_iterator
1424 UI = UsedTypes->begin(), UE = UsedTypes->end(); UI!=UE; ++UI) {
1425 const Type* Ty = *UI;
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001426 if (isa<ArrayType>(Ty) || isa<VectorType>(Ty) || isa<StructType>(Ty))
1427 Name = getTypeName(Ty, false, true);
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001428 // Type with no need to declare.
1429 else continue;
1430 // Print not duplicated type
1431 if (Printed.insert(Ty).second) {
1432 Out << ".class value explicit ansi sealed '" << Name << "'";
Duncan Sandsca0ed742007-11-05 00:04:43 +00001433 Out << " { .pack " << 1 << " .size " << TD->getABITypeSize(Ty)<< " }\n\n";
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001434 }
1435 }
1436}
1437
1438
1439unsigned int MSILWriter::getBitWidth(const Type* Ty) {
1440 unsigned int N = Ty->getPrimitiveSizeInBits();
1441 assert(N!=0 && "Invalid type in getBitWidth()");
1442 switch (N) {
1443 case 1:
1444 case 8:
1445 case 16:
1446 case 32:
1447 case 64:
1448 return N;
1449 default:
1450 cerr << "Bits = " << N << '\n';
1451 assert(0 && "Unsupported integer width");
1452 }
Chris Lattnerd27c9912008-03-30 18:22:13 +00001453 return 0; // Not reached
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001454}
1455
1456
1457void MSILWriter::printStaticConstant(const Constant* C, uint64_t& Offset) {
1458 uint64_t TySize = 0;
1459 const Type* Ty = C->getType();
1460 // Print zero initialized constant.
1461 if (isa<ConstantAggregateZero>(C) || C->isNullValue()) {
Duncan Sandsca0ed742007-11-05 00:04:43 +00001462 TySize = TD->getABITypeSize(C->getType());
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001463 Offset += TySize;
1464 Out << "int8 (0) [" << TySize << "]";
1465 return;
1466 }
1467 // Print constant initializer
1468 switch (Ty->getTypeID()) {
1469 case Type::IntegerTyID: {
Duncan Sandsca0ed742007-11-05 00:04:43 +00001470 TySize = TD->getABITypeSize(Ty);
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001471 const ConstantInt* Int = cast<ConstantInt>(C);
1472 Out << getPrimitiveTypeName(Ty,true) << "(" << Int->getSExtValue() << ")";
1473 break;
1474 }
1475 case Type::FloatTyID:
1476 case Type::DoubleTyID: {
Duncan Sandsca0ed742007-11-05 00:04:43 +00001477 TySize = TD->getABITypeSize(Ty);
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001478 const ConstantFP* FP = cast<ConstantFP>(C);
1479 if (Ty->getTypeID() == Type::FloatTyID)
Dale Johannesen43421b32007-09-06 18:13:44 +00001480 Out << "int32 (" <<
Dale Johannesen9d5f4562007-09-12 03:30:33 +00001481 (uint32_t)FP->getValueAPF().convertToAPInt().getZExtValue() << ')';
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001482 else
Dale Johannesen43421b32007-09-06 18:13:44 +00001483 Out << "int64 (" <<
Dale Johannesen9d5f4562007-09-12 03:30:33 +00001484 FP->getValueAPF().convertToAPInt().getZExtValue() << ')';
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001485 break;
1486 }
1487 case Type::ArrayTyID:
1488 case Type::VectorTyID:
1489 case Type::StructTyID:
1490 for (unsigned I = 0, E = C->getNumOperands(); I<E; I++) {
1491 if (I!=0) Out << ",\n";
1492 printStaticConstant(C->getOperand(I),Offset);
1493 }
1494 break;
1495 case Type::PointerTyID:
Duncan Sandsca0ed742007-11-05 00:04:43 +00001496 TySize = TD->getABITypeSize(C->getType());
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001497 // Initialize with global variable address
1498 if (const GlobalVariable *G = dyn_cast<GlobalVariable>(C)) {
1499 std::string name = getValueName(G);
1500 Out << "&(" << name.insert(name.length()-1,"$data") << ")";
1501 } else {
1502 // Dynamic initialization
1503 if (!isa<ConstantPointerNull>(C) && !C->isNullValue())
1504 InitListPtr->push_back(StaticInitializer(C,Offset));
1505 // Null pointer initialization
1506 if (TySize==4) Out << "int32 (0)";
1507 else if (TySize==8) Out << "int64 (0)";
1508 else assert(0 && "Invalid pointer size");
1509 }
1510 break;
1511 default:
1512 cerr << "TypeID = " << Ty->getTypeID() << '\n';
1513 assert(0 && "Invalid type in printStaticConstant()");
1514 }
1515 // Increase offset.
1516 Offset += TySize;
1517}
1518
1519
1520void MSILWriter::printStaticInitializer(const Constant* C,
1521 const std::string& Name) {
1522 switch (C->getType()->getTypeID()) {
1523 case Type::IntegerTyID:
1524 case Type::FloatTyID:
1525 case Type::DoubleTyID:
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001526 Out << getPrimitiveTypeName(C->getType(), false);
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001527 break;
1528 case Type::ArrayTyID:
1529 case Type::VectorTyID:
1530 case Type::StructTyID:
1531 case Type::PointerTyID:
1532 Out << getTypeName(C->getType());
1533 break;
1534 default:
1535 cerr << "Type = " << *C << "\n";
1536 assert(0 && "Invalid constant type");
1537 }
1538 // Print initializer
1539 std::string label = Name;
1540 label.insert(label.length()-1,"$data");
1541 Out << Name << " at " << label << '\n';
1542 Out << ".data " << label << " = {\n";
1543 uint64_t offset = 0;
1544 printStaticConstant(C,offset);
1545 Out << "\n}\n\n";
1546}
1547
1548
1549void MSILWriter::printVariableDefinition(const GlobalVariable* G) {
1550 const Constant* C = G->getInitializer();
1551 if (C->isNullValue() || isa<ConstantAggregateZero>(C) || isa<UndefValue>(C))
1552 InitListPtr = 0;
1553 else
1554 InitListPtr = &StaticInitList[G];
1555 printStaticInitializer(C,getValueName(G));
1556}
1557
1558
1559void MSILWriter::printGlobalVariables() {
1560 if (ModulePtr->global_empty()) return;
1561 Module::global_iterator I,E;
1562 for (I = ModulePtr->global_begin(), E = ModulePtr->global_end(); I!=E; ++I) {
1563 // Variable definition
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001564 Out << ".field static " << (I->isDeclaration() ? "public " :
1565 "private ");
1566 if (I->isDeclaration()) {
1567 Out << getTypeName(I->getType()) << getValueName(&*I) << "\n\n";
1568 } else
1569 printVariableDefinition(&*I);
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001570 }
1571}
1572
1573
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001574const char* MSILWriter::getLibraryName(const Function* F) {
1575 return getLibraryForSymbol(F->getName().c_str(), true, F->getCallingConv());
1576}
1577
1578
1579const char* MSILWriter::getLibraryName(const GlobalVariable* GV) {
1580 return getLibraryForSymbol(Mang->getValueName(GV).c_str(), false, 0);
1581}
1582
1583
1584const char* MSILWriter::getLibraryForSymbol(const char* Name, bool isFunction,
1585 unsigned CallingConv) {
1586 // TODO: Read *.def file with function and libraries definitions.
1587 return "MSVCRT.DLL";
1588}
1589
1590
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001591void MSILWriter::printExternals() {
1592 Module::const_iterator I,E;
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001593 // Functions.
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001594 for (I=ModulePtr->begin(),E=ModulePtr->end(); I!=E; ++I) {
1595 // Skip intrisics
Duncan Sandsa3355ff2007-12-03 20:06:50 +00001596 if (I->isIntrinsic()) continue;
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001597 if (I->isDeclaration()) {
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001598 const Function* F = I;
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001599 std::string Name = getConvModopt(F->getCallingConv())+getValueName(F);
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001600 std::string Sig =
1601 getCallSignature(cast<FunctionType>(F->getFunctionType()), NULL, Name);
1602 Out << ".method static hidebysig pinvokeimpl(\""
1603 << getLibraryName(F) << "\")\n\t" << Sig << " preservesig {}\n\n";
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001604 }
1605 }
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001606 // External variables and static initialization.
1607 Out <<
1608 ".method public hidebysig static pinvokeimpl(\"KERNEL32.DLL\" ansi winapi)"
1609 " native int LoadLibrary(string) preservesig {}\n"
1610 ".method public hidebysig static pinvokeimpl(\"KERNEL32.DLL\" ansi winapi)"
1611 " native int GetProcAddress(native int, string) preservesig {}\n";
1612 Out <<
1613 ".method private static void* $MSIL_Import(string lib,string sym)\n"
1614 " managed cil\n{\n"
1615 "\tldarg\tlib\n"
1616 "\tcall\tnative int LoadLibrary(string)\n"
1617 "\tldarg\tsym\n"
1618 "\tcall\tnative int GetProcAddress(native int,string)\n"
1619 "\tdup\n"
1620 "\tbrtrue\tL_01\n"
1621 "\tldstr\t\"Can no import variable\"\n"
1622 "\tnewobj\tinstance void [mscorlib]System.Exception::.ctor(string)\n"
1623 "\tthrow\n"
1624 "L_01:\n"
1625 "\tret\n"
1626 "}\n\n"
1627 ".method static private void $MSIL_Init() managed cil\n{\n";
1628 printStaticInitializerList();
1629 // Foreach global variable.
1630 for (Module::global_iterator I = ModulePtr->global_begin(),
1631 E = ModulePtr->global_end(); I!=E; ++I) {
1632 if (!I->isDeclaration() || !I->hasDLLImportLinkage()) continue;
1633 // Use "LoadLibrary"/"GetProcAddress" to recive variable address.
1634 std::string Label = "not_null$_"+utostr(getUniqID());
1635 std::string Tmp = getTypeName(I->getType())+getValueName(&*I);
1636 printSimpleInstruction("ldsflda",Tmp.c_str());
1637 Out << "\tldstr\t\"" << getLibraryName(&*I) << "\"\n";
1638 Out << "\tldstr\t\"" << Mang->getValueName(&*I) << "\"\n";
1639 printSimpleInstruction("call","void* $MSIL_Import(string,string)");
1640 printIndirectSave(I->getType());
1641 }
1642 printSimpleInstruction("ret");
1643 Out << "}\n\n";
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001644}
1645
Anton Korobeynikovf13090c2007-05-06 20:13:33 +00001646
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001647//===----------------------------------------------------------------------===//
Bill Wendling85db3a92008-02-26 10:57:23 +00001648// External Interface declaration
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001649//===----------------------------------------------------------------------===//
1650
Owen Andersoncb371882008-08-21 00:14:44 +00001651bool MSILTarget::addPassesToEmitWholeFile(PassManager &PM, raw_ostream &o,
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001652 CodeGenFileType FileType, bool Fast)
1653{
1654 if (FileType != TargetMachine::AssemblyFile) return true;
1655 MSILWriter* Writer = new MSILWriter(o);
Gordon Henriksence224772008-01-07 01:30:38 +00001656 PM.add(createGCLoweringPass());
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001657 PM.add(createLowerAllocationsPass(true));
1658 // FIXME: Handle switch trougth native IL instruction "switch"
1659 PM.add(createLowerSwitchPass());
1660 PM.add(createCFGSimplificationPass());
1661 PM.add(new MSILModule(Writer->UsedTypes,Writer->TD));
1662 PM.add(Writer);
Gordon Henriksen5eca0752008-08-17 18:44:35 +00001663 PM.add(createGCInfoDeleter());
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001664 return false;
1665}