1 //===-- MSILWriter.cpp - Library for converting LLVM code to MSIL ---------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This library converts LLVM code to MSIL code.
12 //===----------------------------------------------------------------------===//
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"
23 #include "llvm/Support/MathExtras.h"
24 #include "llvm/Transforms/Scalar.h"
25 #include "llvm/ADT/StringExtras.h"
26 #include "llvm/CodeGen/Passes.h"
29 // TargetMachine for the MSIL
30 struct VISIBILITY_HIDDEN MSILTarget
: public TargetMachine
{
31 const TargetData DataLayout
; // Calculates type size & alignment
33 MSILTarget(const Module
&M
, const std::string
&FS
)
36 virtual bool WantsWholeFile() const { return true; }
37 virtual bool addPassesToEmitWholeFile(PassManager
&PM
, raw_ostream
&Out
,
38 CodeGenFileType FileType
,
39 CodeGenOpt::Level OptLevel
);
41 // This class always works, but shouldn't be the default in most cases.
42 static unsigned getModuleMatchQuality(const Module
&M
) { return 1; }
44 virtual const TargetData
*getTargetData() const { return &DataLayout
; }
48 /// MSILTargetMachineModule - Note that this is used on hosts that
49 /// cannot link in a library unless there are references into the
50 /// library. In particular, it seems that it is not possible to get
51 /// things to work on Win32 without this. Though it is unused, do not
53 extern "C" int MSILTargetMachineModule
;
54 int MSILTargetMachineModule
= 0;
56 static RegisterTarget
<MSILTarget
> X("msil", "MSIL backend");
58 bool MSILModule::runOnModule(Module
&M
) {
60 TD
= &getAnalysis
<TargetData
>();
63 TypeSymbolTable
& Table
= M
.getTypeSymbolTable();
64 std::set
<const Type
*> Types
= getAnalysis
<FindUsedTypes
>().getTypes();
65 for (TypeSymbolTable::iterator I
= Table
.begin(), E
= Table
.end(); I
!=E
; ) {
66 if (!isa
<StructType
>(I
->second
) && !isa
<OpaqueType
>(I
->second
))
69 std::set
<const Type
*>::iterator T
= Types
.find(I
->second
);
78 // Find unnamed types.
79 unsigned RenameCounter
= 0;
80 for (std::set
<const Type
*>::const_iterator I
= Types
.begin(),
81 E
= Types
.end(); I
!=E
; ++I
)
82 if (const StructType
*STy
= dyn_cast
<StructType
>(*I
)) {
83 while (ModulePtr
->addTypeName("unnamed$"+utostr(RenameCounter
), STy
))
87 // Pointer for FunctionPass.
88 UsedTypes
= &getAnalysis
<FindUsedTypes
>().getTypes();
92 char MSILModule::ID
= 0;
93 char MSILWriter::ID
= 0;
95 bool MSILWriter::runOnFunction(Function
&F
) {
96 if (F
.isDeclaration()) return false;
98 // Do not codegen any 'available_externally' functions at all, they have
99 // definitions outside the translation unit.
100 if (F
.hasAvailableExternallyLinkage())
103 LInfo
= &getAnalysis
<LoopInfo
>();
109 bool MSILWriter::doInitialization(Module
&M
) {
111 Mang
= new Mangler(M
);
112 Out
<< ".assembly extern mscorlib {}\n";
113 Out
<< ".assembly MSIL {}\n\n";
114 Out
<< "// External\n";
116 Out
<< "// Declarations\n";
117 printDeclarations(M
.getTypeSymbolTable());
118 Out
<< "// Definitions\n";
119 printGlobalVariables();
120 Out
<< "// Startup code\n";
121 printModuleStartup();
126 bool MSILWriter::doFinalization(Module
&M
) {
132 void MSILWriter::printModuleStartup() {
134 ".method static public int32 $MSIL_Startup() {\n"
136 "\t.locals (native int i)\n"
137 "\t.locals (native int argc)\n"
138 "\t.locals (native int ptr)\n"
139 "\t.locals (void* argv)\n"
140 "\t.locals (string[] args)\n"
141 "\tcall\tstring[] [mscorlib]System.Environment::GetCommandLineArgs()\n"
148 printPtrLoad(TD
->getPointerSize());
163 "\tcall\tnative int [mscorlib]System.Runtime.InteropServices.Marshal::"
164 "StringToHGlobalAnsi(string)\n"
168 printPtrLoad(TD
->getPointerSize());
180 "\tcall void $MSIL_Init()\n";
182 // Call user 'main' function.
183 const Function
* F
= ModulePtr
->getFunction("main");
184 if (!F
|| F
->isDeclaration()) {
185 Out
<< "\tldc.i4.0\n\tret\n}\n";
189 std::string
Args("");
190 Function::const_arg_iterator Arg1
,Arg2
;
192 switch (F
->arg_size()) {
197 Arg1
= F
->arg_begin();
198 if (Arg1
->getType()->isInteger()) {
199 Out
<< "\tldloc\targc\n";
200 Args
= getTypeName(Arg1
->getType());
205 Arg1
= Arg2
= F
->arg_begin(); ++Arg2
;
206 if (Arg1
->getType()->isInteger() &&
207 Arg2
->getType()->getTypeID() == Type::PointerTyID
) {
208 Out
<< "\tldloc\targc\n\tldloc\targv\n";
209 Args
= getTypeName(Arg1
->getType())+","+getTypeName(Arg2
->getType());
217 bool RetVoid
= (F
->getReturnType()->getTypeID() == Type::VoidTyID
);
218 if (BadSig
|| (!F
->getReturnType()->isInteger() && !RetVoid
)) {
219 Out
<< "\tldc.i4.0\n";
221 Out
<< "\tcall\t" << getTypeName(F
->getReturnType()) <<
222 getConvModopt(F
->getCallingConv()) << "main(" << Args
<< ")\n";
224 Out
<< "\tldc.i4.0\n";
226 Out
<< "\tconv.i4\n";
231 bool MSILWriter::isZeroValue(const Value
* V
) {
232 if (const Constant
*C
= dyn_cast
<Constant
>(V
))
233 return C
->isNullValue();
238 std::string
MSILWriter::getValueName(const Value
* V
) {
239 // Name into the quotes allow control and space characters.
240 return "'"+Mang
->getValueName(V
)+"'";
244 std::string
MSILWriter::getLabelName(const std::string
& Name
) {
245 if (Name
.find('.')!=std::string::npos
) {
246 std::string
Tmp(Name
);
247 // Replace unaccepable characters in the label name.
248 for (std::string::iterator I
= Tmp
.begin(), E
= Tmp
.end(); I
!=E
; ++I
)
249 if (*I
=='.') *I
= '@';
256 std::string
MSILWriter::getLabelName(const Value
* V
) {
257 return getLabelName(Mang
->getValueName(V
));
261 std::string
MSILWriter::getConvModopt(unsigned CallingConvID
) {
262 switch (CallingConvID
) {
264 case CallingConv::Cold
:
265 case CallingConv::Fast
:
266 return "modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl) ";
267 case CallingConv::X86_FastCall
:
268 return "modopt([mscorlib]System.Runtime.CompilerServices.CallConvFastcall) ";
269 case CallingConv::X86_StdCall
:
270 return "modopt([mscorlib]System.Runtime.CompilerServices.CallConvStdcall) ";
272 cerr
<< "CallingConvID = " << CallingConvID
<< '\n';
273 assert(0 && "Unsupported calling convention");
275 return ""; // Not reached
279 std::string
MSILWriter::getArrayTypeName(Type::TypeID TyID
, const Type
* Ty
) {
280 std::string Tmp
= "";
281 const Type
* ElemTy
= Ty
;
282 assert(Ty
->getTypeID()==TyID
&& "Invalid type passed");
283 // Walk trought array element types.
285 // Multidimensional array.
286 if (ElemTy
->getTypeID()==TyID
) {
287 if (const ArrayType
* ATy
= dyn_cast
<ArrayType
>(ElemTy
))
288 Tmp
+= utostr(ATy
->getNumElements());
289 else if (const VectorType
* VTy
= dyn_cast
<VectorType
>(ElemTy
))
290 Tmp
+= utostr(VTy
->getNumElements());
291 ElemTy
= cast
<SequentialType
>(ElemTy
)->getElementType();
293 // Base element type found.
294 if (ElemTy
->getTypeID()!=TyID
) break;
297 return getTypeName(ElemTy
, false, true)+"["+Tmp
+"]";
301 std::string
MSILWriter::getPrimitiveTypeName(const Type
* Ty
, bool isSigned
) {
302 unsigned NumBits
= 0;
303 switch (Ty
->getTypeID()) {
306 case Type::IntegerTyID
:
307 NumBits
= getBitWidth(Ty
);
311 return "unsigned int"+utostr(NumBits
)+" ";
312 return "int"+utostr(NumBits
)+" ";
313 case Type::FloatTyID
:
315 case Type::DoubleTyID
:
318 cerr
<< "Type = " << *Ty
<< '\n';
319 assert(0 && "Invalid primitive type");
321 return ""; // Not reached
325 std::string
MSILWriter::getTypeName(const Type
* Ty
, bool isSigned
,
327 if (Ty
->isPrimitiveType() || Ty
->isInteger())
328 return getPrimitiveTypeName(Ty
,isSigned
);
329 // FIXME: "OpaqueType" support
330 switch (Ty
->getTypeID()) {
331 case Type::PointerTyID
:
333 case Type::StructTyID
:
335 return ModulePtr
->getTypeName(Ty
);
336 return "valuetype '"+ModulePtr
->getTypeName(Ty
)+"' ";
337 case Type::ArrayTyID
:
339 return getArrayTypeName(Ty
->getTypeID(),Ty
);
340 return "valuetype '"+getArrayTypeName(Ty
->getTypeID(),Ty
)+"' ";
341 case Type::VectorTyID
:
343 return getArrayTypeName(Ty
->getTypeID(),Ty
);
344 return "valuetype '"+getArrayTypeName(Ty
->getTypeID(),Ty
)+"' ";
346 cerr
<< "Type = " << *Ty
<< '\n';
347 assert(0 && "Invalid type in getTypeName()");
349 return ""; // Not reached
353 MSILWriter::ValueType
MSILWriter::getValueLocation(const Value
* V
) {
355 if (isa
<Argument
>(V
))
358 else if (const Function
* F
= dyn_cast
<Function
>(V
))
359 return F
->hasLocalLinkage() ? InternalVT
: GlobalVT
;
361 else if (const GlobalVariable
* G
= dyn_cast
<GlobalVariable
>(V
))
362 return G
->hasLocalLinkage() ? InternalVT
: GlobalVT
;
364 else if (isa
<Constant
>(V
))
365 return isa
<ConstantExpr
>(V
) ? ConstExprVT
: ConstVT
;
371 std::string
MSILWriter::getTypePostfix(const Type
* Ty
, bool Expand
,
373 unsigned NumBits
= 0;
374 switch (Ty
->getTypeID()) {
375 // Integer constant, expanding for stack operations.
376 case Type::IntegerTyID
:
377 NumBits
= getBitWidth(Ty
);
378 // Expand integer value to "int32" or "int64".
379 if (Expand
) return (NumBits
<=32 ? "i4" : "i8");
380 if (NumBits
==1) return "i1";
381 return (isSigned
? "i" : "u")+utostr(NumBits
/8);
383 case Type::FloatTyID
:
385 case Type::DoubleTyID
:
387 case Type::PointerTyID
:
388 return "i"+utostr(TD
->getTypeAllocSize(Ty
));
390 cerr
<< "TypeID = " << Ty
->getTypeID() << '\n';
391 assert(0 && "Invalid type in TypeToPostfix()");
393 return ""; // Not reached
397 void MSILWriter::printConvToPtr() {
398 switch (ModulePtr
->getPointerSize()) {
399 case Module::Pointer32
:
400 printSimpleInstruction("conv.u4");
402 case Module::Pointer64
:
403 printSimpleInstruction("conv.u8");
406 assert(0 && "Module use not supporting pointer size");
411 void MSILWriter::printPtrLoad(uint64_t N
) {
412 switch (ModulePtr
->getPointerSize()) {
413 case Module::Pointer32
:
414 printSimpleInstruction("ldc.i4",utostr(N
).c_str());
415 // FIXME: Need overflow test?
417 cerr
<< "Value = " << utostr(N
) << '\n';
418 assert(0 && "32-bit pointer overflowed");
421 case Module::Pointer64
:
422 printSimpleInstruction("ldc.i8",utostr(N
).c_str());
425 assert(0 && "Module use not supporting pointer size");
430 void MSILWriter::printValuePtrLoad(const Value
* V
) {
436 void MSILWriter::printConstLoad(const Constant
* C
) {
437 if (const ConstantInt
* CInt
= dyn_cast
<ConstantInt
>(C
)) {
439 Out
<< "\tldc." << getTypePostfix(C
->getType(),true) << '\t';
440 if (CInt
->isMinValue(true))
441 Out
<< CInt
->getSExtValue();
443 Out
<< CInt
->getZExtValue();
444 } else if (const ConstantFP
* FP
= dyn_cast
<ConstantFP
>(C
)) {
448 if (FP
->getType()->getTypeID()==Type::FloatTyID
) {
449 X
= (uint32_t)FP
->getValueAPF().bitcastToAPInt().getZExtValue();
452 X
= FP
->getValueAPF().bitcastToAPInt().getZExtValue();
455 Out
<< "\tldc.r" << Size
<< "\t( " << utohexstr(X
) << ')';
456 } else if (isa
<UndefValue
>(C
)) {
457 // Undefined constant value = NULL.
460 cerr
<< "Constant = " << *C
<< '\n';
461 assert(0 && "Invalid constant value");
467 void MSILWriter::printValueLoad(const Value
* V
) {
468 MSILWriter::ValueType Location
= getValueLocation(V
);
470 // Global variable or function address.
473 if (const Function
* F
= dyn_cast
<Function
>(V
)) {
474 std::string Name
= getConvModopt(F
->getCallingConv())+getValueName(F
);
475 printSimpleInstruction("ldftn",
476 getCallSignature(F
->getFunctionType(),NULL
,Name
).c_str());
479 const Type
* ElemTy
= cast
<PointerType
>(V
->getType())->getElementType();
480 if (Location
==GlobalVT
&& cast
<GlobalVariable
>(V
)->hasDLLImportLinkage()) {
481 Tmp
= "void* "+getValueName(V
);
482 printSimpleInstruction("ldsfld",Tmp
.c_str());
484 Tmp
= getTypeName(ElemTy
)+getValueName(V
);
485 printSimpleInstruction("ldsflda",Tmp
.c_str());
489 // Function argument.
491 printSimpleInstruction("ldarg",getValueName(V
).c_str());
493 // Local function variable.
495 printSimpleInstruction("ldloc",getValueName(V
).c_str());
499 if (isa
<ConstantPointerNull
>(V
))
502 printConstLoad(cast
<Constant
>(V
));
504 // Constant expression.
506 printConstantExpr(cast
<ConstantExpr
>(V
));
509 cerr
<< "Value = " << *V
<< '\n';
510 assert(0 && "Invalid value location");
515 void MSILWriter::printValueSave(const Value
* V
) {
516 switch (getValueLocation(V
)) {
518 printSimpleInstruction("starg",getValueName(V
).c_str());
521 printSimpleInstruction("stloc",getValueName(V
).c_str());
524 cerr
<< "Value = " << *V
<< '\n';
525 assert(0 && "Invalid value location");
530 void MSILWriter::printBinaryInstruction(const char* Name
, const Value
* Left
,
531 const Value
* Right
) {
532 printValueLoad(Left
);
533 printValueLoad(Right
);
534 Out
<< '\t' << Name
<< '\n';
538 void MSILWriter::printSimpleInstruction(const char* Inst
, const char* Operand
) {
540 Out
<< '\t' << Inst
<< '\t' << Operand
<< '\n';
542 Out
<< '\t' << Inst
<< '\n';
546 void MSILWriter::printPHICopy(const BasicBlock
* Src
, const BasicBlock
* Dst
) {
547 for (BasicBlock::const_iterator I
= Dst
->begin(), E
= Dst
->end();
548 isa
<PHINode
>(I
); ++I
) {
549 const PHINode
* Phi
= cast
<PHINode
>(I
);
550 const Value
* Val
= Phi
->getIncomingValueForBlock(Src
);
551 if (isa
<UndefValue
>(Val
)) continue;
558 void MSILWriter::printBranchToBlock(const BasicBlock
* CurrBB
,
559 const BasicBlock
* TrueBB
,
560 const BasicBlock
* FalseBB
) {
561 if (TrueBB
==FalseBB
) {
562 // "TrueBB" and "FalseBB" destination equals
563 printPHICopy(CurrBB
,TrueBB
);
564 printSimpleInstruction("pop");
565 printSimpleInstruction("br",getLabelName(TrueBB
).c_str());
566 } else if (FalseBB
==NULL
) {
567 // If "FalseBB" not used the jump have condition
568 printPHICopy(CurrBB
,TrueBB
);
569 printSimpleInstruction("brtrue",getLabelName(TrueBB
).c_str());
570 } else if (TrueBB
==NULL
) {
571 // If "TrueBB" not used the jump is unconditional
572 printPHICopy(CurrBB
,FalseBB
);
573 printSimpleInstruction("br",getLabelName(FalseBB
).c_str());
575 // Copy PHI instructions for each block
576 std::string TmpLabel
;
577 // Print PHI instructions for "TrueBB"
578 if (isa
<PHINode
>(TrueBB
->begin())) {
579 TmpLabel
= getLabelName(TrueBB
)+"$phi_"+utostr(getUniqID());
580 printSimpleInstruction("brtrue",TmpLabel
.c_str());
582 printSimpleInstruction("brtrue",getLabelName(TrueBB
).c_str());
584 // Print PHI instructions for "FalseBB"
585 if (isa
<PHINode
>(FalseBB
->begin())) {
586 printPHICopy(CurrBB
,FalseBB
);
587 printSimpleInstruction("br",getLabelName(FalseBB
).c_str());
589 printSimpleInstruction("br",getLabelName(FalseBB
).c_str());
591 if (isa
<PHINode
>(TrueBB
->begin())) {
592 // Handle "TrueBB" PHI Copy
593 Out
<< TmpLabel
<< ":\n";
594 printPHICopy(CurrBB
,TrueBB
);
595 printSimpleInstruction("br",getLabelName(TrueBB
).c_str());
601 void MSILWriter::printBranchInstruction(const BranchInst
* Inst
) {
602 if (Inst
->isUnconditional()) {
603 printBranchToBlock(Inst
->getParent(),NULL
,Inst
->getSuccessor(0));
605 printValueLoad(Inst
->getCondition());
606 printBranchToBlock(Inst
->getParent(),Inst
->getSuccessor(0),
607 Inst
->getSuccessor(1));
612 void MSILWriter::printSelectInstruction(const Value
* Cond
, const Value
* VTrue
,
613 const Value
* VFalse
) {
614 std::string TmpLabel
= std::string("select$true_")+utostr(getUniqID());
615 printValueLoad(VTrue
);
616 printValueLoad(Cond
);
617 printSimpleInstruction("brtrue",TmpLabel
.c_str());
618 printSimpleInstruction("pop");
619 printValueLoad(VFalse
);
620 Out
<< TmpLabel
<< ":\n";
624 void MSILWriter::printIndirectLoad(const Value
* V
) {
625 const Type
* Ty
= V
->getType();
627 if (const PointerType
* P
= dyn_cast
<PointerType
>(Ty
))
628 Ty
= P
->getElementType();
629 std::string Tmp
= "ldind."+getTypePostfix(Ty
, false);
630 printSimpleInstruction(Tmp
.c_str());
634 void MSILWriter::printIndirectSave(const Value
* Ptr
, const Value
* Val
) {
637 printIndirectSave(Val
->getType());
641 void MSILWriter::printIndirectSave(const Type
* Ty
) {
642 // Instruction need signed postfix for any type.
643 std::string postfix
= getTypePostfix(Ty
, false);
644 if (*postfix
.begin()=='u') *postfix
.begin() = 'i';
645 postfix
= "stind."+postfix
;
646 printSimpleInstruction(postfix
.c_str());
650 void MSILWriter::printCastInstruction(unsigned int Op
, const Value
* V
,
656 case Instruction::SExt
:
657 case Instruction::SIToFP
:
658 case Instruction::FPToSI
:
659 Tmp
= "conv."+getTypePostfix(Ty
,false,true);
660 printSimpleInstruction(Tmp
.c_str());
663 case Instruction::FPTrunc
:
664 case Instruction::FPExt
:
665 case Instruction::UIToFP
:
666 case Instruction::Trunc
:
667 case Instruction::ZExt
:
668 case Instruction::FPToUI
:
669 case Instruction::PtrToInt
:
670 case Instruction::IntToPtr
:
671 Tmp
= "conv."+getTypePostfix(Ty
,false);
672 printSimpleInstruction(Tmp
.c_str());
675 case Instruction::BitCast
:
676 // FIXME: meaning that ld*/st* instruction do not change data format.
679 cerr
<< "Opcode = " << Op
<< '\n';
680 assert(0 && "Invalid conversion instruction");
685 void MSILWriter::printGepInstruction(const Value
* V
, gep_type_iterator I
,
686 gep_type_iterator E
) {
689 printValuePtrLoad(V
);
690 // Calculate element offset.
693 const Value
* IndexValue
= I
.getOperand();
694 if (const StructType
* StrucTy
= dyn_cast
<StructType
>(*I
)) {
695 uint64_t FieldIndex
= cast
<ConstantInt
>(IndexValue
)->getZExtValue();
696 // Offset is the sum of all previous structure fields.
697 for (uint64_t F
= 0; F
<FieldIndex
; ++F
)
698 Size
+= TD
->getTypeAllocSize(StrucTy
->getContainedType((unsigned)F
));
700 printSimpleInstruction("add");
702 } else if (const SequentialType
* SeqTy
= dyn_cast
<SequentialType
>(*I
)) {
703 Size
= TD
->getTypeAllocSize(SeqTy
->getElementType());
705 Size
= TD
->getTypeAllocSize(*I
);
707 // Add offset of current element to stack top.
708 if (!isZeroValue(IndexValue
)) {
709 // Constant optimization.
710 if (const ConstantInt
* C
= dyn_cast
<ConstantInt
>(IndexValue
)) {
711 if (C
->getValue().isNegative()) {
712 printPtrLoad(C
->getValue().abs().getZExtValue()*Size
);
713 printSimpleInstruction("sub");
716 printPtrLoad(C
->getZExtValue()*Size
);
719 printValuePtrLoad(IndexValue
);
720 printSimpleInstruction("mul");
722 printSimpleInstruction("add");
728 std::string
MSILWriter::getCallSignature(const FunctionType
* Ty
,
729 const Instruction
* Inst
,
732 if (Ty
->isVarArg()) Tmp
+= "vararg ";
733 // Name and return type.
734 Tmp
+= getTypeName(Ty
->getReturnType())+Name
+"(";
735 // Function argument type list.
736 unsigned NumParams
= Ty
->getNumParams();
737 for (unsigned I
= 0; I
!=NumParams
; ++I
) {
738 if (I
!=0) Tmp
+= ",";
739 Tmp
+= getTypeName(Ty
->getParamType(I
));
741 // CLR needs to know the exact amount of parameters received by vararg
742 // function, because caller cleans the stack.
743 if (Ty
->isVarArg() && Inst
) {
744 // Origin to function arguments in "CallInst" or "InvokeInst".
745 unsigned Org
= isa
<InvokeInst
>(Inst
) ? 3 : 1;
746 // Print variable argument types.
747 unsigned NumOperands
= Inst
->getNumOperands()-Org
;
748 if (NumParams
<NumOperands
) {
749 if (NumParams
!=0) Tmp
+= ", ";
751 for (unsigned J
= NumParams
; J
!=NumOperands
; ++J
) {
752 if (J
!=NumParams
) Tmp
+= ", ";
753 Tmp
+= getTypeName(Inst
->getOperand(J
+Org
)->getType());
761 void MSILWriter::printFunctionCall(const Value
* FnVal
,
762 const Instruction
* Inst
) {
763 // Get function calling convention.
764 std::string Name
= "";
765 if (const CallInst
* Call
= dyn_cast
<CallInst
>(Inst
))
766 Name
= getConvModopt(Call
->getCallingConv());
767 else if (const InvokeInst
* Invoke
= dyn_cast
<InvokeInst
>(Inst
))
768 Name
= getConvModopt(Invoke
->getCallingConv());
770 cerr
<< "Instruction = " << Inst
->getName() << '\n';
771 assert(0 && "Need \"Invoke\" or \"Call\" instruction only");
773 if (const Function
* F
= dyn_cast
<Function
>(FnVal
)) {
775 Name
+= getValueName(F
);
776 printSimpleInstruction("call",
777 getCallSignature(F
->getFunctionType(),Inst
,Name
).c_str());
779 // Indirect function call.
780 const PointerType
* PTy
= cast
<PointerType
>(FnVal
->getType());
781 const FunctionType
* FTy
= cast
<FunctionType
>(PTy
->getElementType());
782 // Load function address.
783 printValueLoad(FnVal
);
784 printSimpleInstruction("calli",getCallSignature(FTy
,Inst
,Name
).c_str());
789 void MSILWriter::printIntrinsicCall(const IntrinsicInst
* Inst
) {
791 switch (Inst
->getIntrinsicID()) {
792 case Intrinsic::vastart
:
793 Name
= getValueName(Inst
->getOperand(1));
794 Name
.insert(Name
.length()-1,"$valist");
795 // Obtain the argument handle.
796 printSimpleInstruction("ldloca",Name
.c_str());
797 printSimpleInstruction("arglist");
798 printSimpleInstruction("call",
799 "instance void [mscorlib]System.ArgIterator::.ctor"
800 "(valuetype [mscorlib]System.RuntimeArgumentHandle)");
801 // Save as pointer type "void*"
802 printValueLoad(Inst
->getOperand(1));
803 printSimpleInstruction("ldloca",Name
.c_str());
804 printIndirectSave(PointerType::getUnqual(IntegerType::get(8)));
806 case Intrinsic::vaend
:
807 // Close argument list handle.
808 printIndirectLoad(Inst
->getOperand(1));
809 printSimpleInstruction("call","instance void [mscorlib]System.ArgIterator::End()");
811 case Intrinsic::vacopy
:
812 // Copy "ArgIterator" valuetype.
813 printIndirectLoad(Inst
->getOperand(1));
814 printIndirectLoad(Inst
->getOperand(2));
815 printSimpleInstruction("cpobj","[mscorlib]System.ArgIterator");
818 cerr
<< "Intrinsic ID = " << Inst
->getIntrinsicID() << '\n';
819 assert(0 && "Invalid intrinsic function");
824 void MSILWriter::printCallInstruction(const Instruction
* Inst
) {
825 if (isa
<IntrinsicInst
>(Inst
)) {
826 // Handle intrinsic function.
827 printIntrinsicCall(cast
<IntrinsicInst
>(Inst
));
829 // Load arguments to stack and call function.
830 for (int I
= 1, E
= Inst
->getNumOperands(); I
!=E
; ++I
)
831 printValueLoad(Inst
->getOperand(I
));
832 printFunctionCall(Inst
->getOperand(0),Inst
);
837 void MSILWriter::printICmpInstruction(unsigned Predicate
, const Value
* Left
,
838 const Value
* Right
) {
840 case ICmpInst::ICMP_EQ
:
841 printBinaryInstruction("ceq",Left
,Right
);
843 case ICmpInst::ICMP_NE
:
844 // Emulate = not neg (Op1 eq Op2)
845 printBinaryInstruction("ceq",Left
,Right
);
846 printSimpleInstruction("neg");
847 printSimpleInstruction("not");
849 case ICmpInst::ICMP_ULE
:
850 case ICmpInst::ICMP_SLE
:
851 // Emulate = (Op1 eq Op2) or (Op1 lt Op2)
852 printBinaryInstruction("ceq",Left
,Right
);
853 if (Predicate
==ICmpInst::ICMP_ULE
)
854 printBinaryInstruction("clt.un",Left
,Right
);
856 printBinaryInstruction("clt",Left
,Right
);
857 printSimpleInstruction("or");
859 case ICmpInst::ICMP_UGE
:
860 case ICmpInst::ICMP_SGE
:
861 // Emulate = (Op1 eq Op2) or (Op1 gt Op2)
862 printBinaryInstruction("ceq",Left
,Right
);
863 if (Predicate
==ICmpInst::ICMP_UGE
)
864 printBinaryInstruction("cgt.un",Left
,Right
);
866 printBinaryInstruction("cgt",Left
,Right
);
867 printSimpleInstruction("or");
869 case ICmpInst::ICMP_ULT
:
870 printBinaryInstruction("clt.un",Left
,Right
);
872 case ICmpInst::ICMP_SLT
:
873 printBinaryInstruction("clt",Left
,Right
);
875 case ICmpInst::ICMP_UGT
:
876 printBinaryInstruction("cgt.un",Left
,Right
);
877 case ICmpInst::ICMP_SGT
:
878 printBinaryInstruction("cgt",Left
,Right
);
881 cerr
<< "Predicate = " << Predicate
<< '\n';
882 assert(0 && "Invalid icmp predicate");
887 void MSILWriter::printFCmpInstruction(unsigned Predicate
, const Value
* Left
,
888 const Value
* Right
) {
889 // FIXME: Correct comparison
890 std::string NanFunc
= "bool [mscorlib]System.Double::IsNaN(float64)";
892 case FCmpInst::FCMP_UGT
:
893 // X > Y || llvm_fcmp_uno(X, Y)
894 printBinaryInstruction("cgt",Left
,Right
);
895 printFCmpInstruction(FCmpInst::FCMP_UNO
,Left
,Right
);
896 printSimpleInstruction("or");
898 case FCmpInst::FCMP_OGT
:
900 printBinaryInstruction("cgt",Left
,Right
);
902 case FCmpInst::FCMP_UGE
:
903 // X >= Y || llvm_fcmp_uno(X, Y)
904 printBinaryInstruction("ceq",Left
,Right
);
905 printBinaryInstruction("cgt",Left
,Right
);
906 printSimpleInstruction("or");
907 printFCmpInstruction(FCmpInst::FCMP_UNO
,Left
,Right
);
908 printSimpleInstruction("or");
910 case FCmpInst::FCMP_OGE
:
912 printBinaryInstruction("ceq",Left
,Right
);
913 printBinaryInstruction("cgt",Left
,Right
);
914 printSimpleInstruction("or");
916 case FCmpInst::FCMP_ULT
:
917 // X < Y || llvm_fcmp_uno(X, Y)
918 printBinaryInstruction("clt",Left
,Right
);
919 printFCmpInstruction(FCmpInst::FCMP_UNO
,Left
,Right
);
920 printSimpleInstruction("or");
922 case FCmpInst::FCMP_OLT
:
924 printBinaryInstruction("clt",Left
,Right
);
926 case FCmpInst::FCMP_ULE
:
927 // X <= Y || llvm_fcmp_uno(X, Y)
928 printBinaryInstruction("ceq",Left
,Right
);
929 printBinaryInstruction("clt",Left
,Right
);
930 printSimpleInstruction("or");
931 printFCmpInstruction(FCmpInst::FCMP_UNO
,Left
,Right
);
932 printSimpleInstruction("or");
934 case FCmpInst::FCMP_OLE
:
936 printBinaryInstruction("ceq",Left
,Right
);
937 printBinaryInstruction("clt",Left
,Right
);
938 printSimpleInstruction("or");
940 case FCmpInst::FCMP_UEQ
:
941 // X == Y || llvm_fcmp_uno(X, Y)
942 printBinaryInstruction("ceq",Left
,Right
);
943 printFCmpInstruction(FCmpInst::FCMP_UNO
,Left
,Right
);
944 printSimpleInstruction("or");
946 case FCmpInst::FCMP_OEQ
:
948 printBinaryInstruction("ceq",Left
,Right
);
950 case FCmpInst::FCMP_UNE
:
952 printBinaryInstruction("ceq",Left
,Right
);
953 printSimpleInstruction("neg");
954 printSimpleInstruction("not");
956 case FCmpInst::FCMP_ONE
:
957 // X != Y && llvm_fcmp_ord(X, Y)
958 printBinaryInstruction("ceq",Left
,Right
);
959 printSimpleInstruction("not");
961 case FCmpInst::FCMP_ORD
:
962 // return X == X && Y == Y
963 printBinaryInstruction("ceq",Left
,Left
);
964 printBinaryInstruction("ceq",Right
,Right
);
965 printSimpleInstruction("or");
967 case FCmpInst::FCMP_UNO
:
969 printBinaryInstruction("ceq",Left
,Left
);
970 printSimpleInstruction("not");
971 printBinaryInstruction("ceq",Right
,Right
);
972 printSimpleInstruction("not");
973 printSimpleInstruction("or");
976 assert(0 && "Illegal FCmp predicate");
981 void MSILWriter::printInvokeInstruction(const InvokeInst
* Inst
) {
982 std::string Label
= "leave$normal_"+utostr(getUniqID());
985 for (int I
= 3, E
= Inst
->getNumOperands(); I
!=E
; ++I
)
986 printValueLoad(Inst
->getOperand(I
));
987 // Print call instruction
988 printFunctionCall(Inst
->getOperand(0),Inst
);
989 // Save function result and leave "try" block
990 printValueSave(Inst
);
991 printSimpleInstruction("leave",Label
.c_str());
993 Out
<< "catch [mscorlib]System.Exception {\n";
994 // Redirect to unwind block
995 printSimpleInstruction("pop");
996 printBranchToBlock(Inst
->getParent(),NULL
,Inst
->getUnwindDest());
997 Out
<< "}\n" << Label
<< ":\n";
998 // Redirect to continue block
999 printBranchToBlock(Inst
->getParent(),NULL
,Inst
->getNormalDest());
1003 void MSILWriter::printSwitchInstruction(const SwitchInst
* Inst
) {
1004 // FIXME: Emulate with IL "switch" instruction
1005 // Emulate = if () else if () else if () else ...
1006 for (unsigned int I
= 1, E
= Inst
->getNumCases(); I
!=E
; ++I
) {
1007 printValueLoad(Inst
->getCondition());
1008 printValueLoad(Inst
->getCaseValue(I
));
1009 printSimpleInstruction("ceq");
1010 // Condition jump to successor block
1011 printBranchToBlock(Inst
->getParent(),Inst
->getSuccessor(I
),NULL
);
1013 // Jump to default block
1014 printBranchToBlock(Inst
->getParent(),NULL
,Inst
->getDefaultDest());
1018 void MSILWriter::printVAArgInstruction(const VAArgInst
* Inst
) {
1019 printIndirectLoad(Inst
->getOperand(0));
1020 printSimpleInstruction("call",
1021 "instance typedref [mscorlib]System.ArgIterator::GetNextArg()");
1022 printSimpleInstruction("refanyval","void*");
1024 "ldind."+getTypePostfix(PointerType::getUnqual(IntegerType::get(8)),false);
1025 printSimpleInstruction(Name
.c_str());
1029 void MSILWriter::printAllocaInstruction(const AllocaInst
* Inst
) {
1030 uint64_t Size
= TD
->getTypeAllocSize(Inst
->getAllocatedType());
1031 // Constant optimization.
1032 if (const ConstantInt
* CInt
= dyn_cast
<ConstantInt
>(Inst
->getOperand(0))) {
1033 printPtrLoad(CInt
->getZExtValue()*Size
);
1036 printValueLoad(Inst
->getOperand(0));
1037 printSimpleInstruction("mul");
1039 printSimpleInstruction("localloc");
1043 void MSILWriter::printInstruction(const Instruction
* Inst
) {
1044 const Value
*Left
= 0, *Right
= 0;
1045 if (Inst
->getNumOperands()>=1) Left
= Inst
->getOperand(0);
1046 if (Inst
->getNumOperands()>=2) Right
= Inst
->getOperand(1);
1047 // Print instruction
1048 // FIXME: "ShuffleVector","ExtractElement","InsertElement" support.
1049 switch (Inst
->getOpcode()) {
1051 case Instruction::Ret
:
1052 if (Inst
->getNumOperands()) {
1053 printValueLoad(Left
);
1054 printSimpleInstruction("ret");
1056 printSimpleInstruction("ret");
1058 case Instruction::Br
:
1059 printBranchInstruction(cast
<BranchInst
>(Inst
));
1062 case Instruction::Add
:
1063 printBinaryInstruction("add",Left
,Right
);
1065 case Instruction::Sub
:
1066 printBinaryInstruction("sub",Left
,Right
);
1068 case Instruction::Mul
:
1069 printBinaryInstruction("mul",Left
,Right
);
1071 case Instruction::UDiv
:
1072 printBinaryInstruction("div.un",Left
,Right
);
1074 case Instruction::SDiv
:
1075 case Instruction::FDiv
:
1076 printBinaryInstruction("div",Left
,Right
);
1078 case Instruction::URem
:
1079 printBinaryInstruction("rem.un",Left
,Right
);
1081 case Instruction::SRem
:
1082 case Instruction::FRem
:
1083 printBinaryInstruction("rem",Left
,Right
);
1086 case Instruction::ICmp
:
1087 printICmpInstruction(cast
<ICmpInst
>(Inst
)->getPredicate(),Left
,Right
);
1089 case Instruction::FCmp
:
1090 printFCmpInstruction(cast
<FCmpInst
>(Inst
)->getPredicate(),Left
,Right
);
1093 case Instruction::And
:
1094 printBinaryInstruction("and",Left
,Right
);
1096 case Instruction::Or
:
1097 printBinaryInstruction("or",Left
,Right
);
1099 case Instruction::Xor
:
1100 printBinaryInstruction("xor",Left
,Right
);
1102 case Instruction::Shl
:
1103 printValueLoad(Left
);
1104 printValueLoad(Right
);
1105 printSimpleInstruction("conv.i4");
1106 printSimpleInstruction("shl");
1108 case Instruction::LShr
:
1109 printValueLoad(Left
);
1110 printValueLoad(Right
);
1111 printSimpleInstruction("conv.i4");
1112 printSimpleInstruction("shr.un");
1114 case Instruction::AShr
:
1115 printValueLoad(Left
);
1116 printValueLoad(Right
);
1117 printSimpleInstruction("conv.i4");
1118 printSimpleInstruction("shr");
1120 case Instruction::Select
:
1121 printSelectInstruction(Inst
->getOperand(0),Inst
->getOperand(1),Inst
->getOperand(2));
1123 case Instruction::Load
:
1124 printIndirectLoad(Inst
->getOperand(0));
1126 case Instruction::Store
:
1127 printIndirectSave(Inst
->getOperand(1), Inst
->getOperand(0));
1129 case Instruction::Trunc
:
1130 case Instruction::ZExt
:
1131 case Instruction::SExt
:
1132 case Instruction::FPTrunc
:
1133 case Instruction::FPExt
:
1134 case Instruction::UIToFP
:
1135 case Instruction::SIToFP
:
1136 case Instruction::FPToUI
:
1137 case Instruction::FPToSI
:
1138 case Instruction::PtrToInt
:
1139 case Instruction::IntToPtr
:
1140 case Instruction::BitCast
:
1141 printCastInstruction(Inst
->getOpcode(),Left
,
1142 cast
<CastInst
>(Inst
)->getDestTy());
1144 case Instruction::GetElementPtr
:
1145 printGepInstruction(Inst
->getOperand(0),gep_type_begin(Inst
),
1146 gep_type_end(Inst
));
1148 case Instruction::Call
:
1149 printCallInstruction(cast
<CallInst
>(Inst
));
1151 case Instruction::Invoke
:
1152 printInvokeInstruction(cast
<InvokeInst
>(Inst
));
1154 case Instruction::Unwind
:
1155 printSimpleInstruction("newobj",
1156 "instance void [mscorlib]System.Exception::.ctor()");
1157 printSimpleInstruction("throw");
1159 case Instruction::Switch
:
1160 printSwitchInstruction(cast
<SwitchInst
>(Inst
));
1162 case Instruction::Alloca
:
1163 printAllocaInstruction(cast
<AllocaInst
>(Inst
));
1165 case Instruction::Malloc
:
1166 assert(0 && "LowerAllocationsPass used");
1168 case Instruction::Free
:
1169 assert(0 && "LowerAllocationsPass used");
1171 case Instruction::Unreachable
:
1172 printSimpleInstruction("ldstr", "\"Unreachable instruction\"");
1173 printSimpleInstruction("newobj",
1174 "instance void [mscorlib]System.Exception::.ctor(string)");
1175 printSimpleInstruction("throw");
1177 case Instruction::VAArg
:
1178 printVAArgInstruction(cast
<VAArgInst
>(Inst
));
1181 cerr
<< "Instruction = " << Inst
->getName() << '\n';
1182 assert(0 && "Unsupported instruction");
1187 void MSILWriter::printLoop(const Loop
* L
) {
1188 Out
<< getLabelName(L
->getHeader()->getName()) << ":\n";
1189 const std::vector
<BasicBlock
*>& blocks
= L
->getBlocks();
1190 for (unsigned I
= 0, E
= blocks
.size(); I
!=E
; I
++) {
1191 BasicBlock
* BB
= blocks
[I
];
1192 Loop
* BBLoop
= LInfo
->getLoopFor(BB
);
1194 printBasicBlock(BB
);
1195 else if (BB
==BBLoop
->getHeader() && BBLoop
->getParentLoop()==L
)
1198 printSimpleInstruction("br",getLabelName(L
->getHeader()->getName()).c_str());
1202 void MSILWriter::printBasicBlock(const BasicBlock
* BB
) {
1203 Out
<< getLabelName(BB
) << ":\n";
1204 for (BasicBlock::const_iterator I
= BB
->begin(), E
= BB
->end(); I
!=E
; ++I
) {
1205 const Instruction
* Inst
= I
;
1206 // Comment llvm original instruction
1207 // Out << "\n//" << *Inst << "\n";
1208 // Do not handle PHI instruction in current block
1209 if (Inst
->getOpcode()==Instruction::PHI
) continue;
1210 // Print instruction
1211 printInstruction(Inst
);
1213 if (Inst
->getType()!=Type::VoidTy
) {
1214 // Do not save value after invoke, it done in "try" block
1215 if (Inst
->getOpcode()==Instruction::Invoke
) continue;
1216 printValueSave(Inst
);
1222 void MSILWriter::printLocalVariables(const Function
& F
) {
1224 const Type
* Ty
= NULL
;
1225 std::set
<const Value
*> Printed
;
1226 const Value
* VaList
= NULL
;
1227 unsigned StackDepth
= 8;
1228 // Find local variables
1229 for (const_inst_iterator I
= inst_begin(&F
), E
= inst_end(&F
); I
!=E
; ++I
) {
1230 if (I
->getOpcode()==Instruction::Call
||
1231 I
->getOpcode()==Instruction::Invoke
) {
1232 // Test stack depth.
1233 if (StackDepth
<I
->getNumOperands())
1234 StackDepth
= I
->getNumOperands();
1236 const AllocaInst
* AI
= dyn_cast
<AllocaInst
>(&*I
);
1237 if (AI
&& !isa
<GlobalVariable
>(AI
)) {
1238 // Local variable allocation.
1239 Ty
= PointerType::getUnqual(AI
->getAllocatedType());
1240 Name
= getValueName(AI
);
1241 Out
<< "\t.locals (" << getTypeName(Ty
) << Name
<< ")\n";
1242 } else if (I
->getType()!=Type::VoidTy
) {
1243 // Operation result.
1245 Name
= getValueName(&*I
);
1246 Out
<< "\t.locals (" << getTypeName(Ty
) << Name
<< ")\n";
1248 // Test on 'va_list' variable
1249 bool isVaList
= false;
1250 if (const VAArgInst
* VaInst
= dyn_cast
<VAArgInst
>(&*I
)) {
1251 // "va_list" as "va_arg" instruction operand.
1253 VaList
= VaInst
->getOperand(0);
1254 } else if (const IntrinsicInst
* Inst
= dyn_cast
<IntrinsicInst
>(&*I
)) {
1255 // "va_list" as intrinsic function operand.
1256 switch (Inst
->getIntrinsicID()) {
1257 case Intrinsic::vastart
:
1258 case Intrinsic::vaend
:
1259 case Intrinsic::vacopy
:
1261 VaList
= Inst
->getOperand(1);
1267 // Print "va_list" variable.
1268 if (isVaList
&& Printed
.insert(VaList
).second
) {
1269 Name
= getValueName(VaList
);
1270 Name
.insert(Name
.length()-1,"$valist");
1271 Out
<< "\t.locals (valuetype [mscorlib]System.ArgIterator "
1275 printSimpleInstruction(".maxstack",utostr(StackDepth
*2).c_str());
1279 void MSILWriter::printFunctionBody(const Function
& F
) {
1281 for (Function::const_iterator I
= F
.begin(), E
= F
.end(); I
!=E
; ++I
) {
1282 if (Loop
*L
= LInfo
->getLoopFor(I
)) {
1283 if (L
->getHeader()==I
&& L
->getParentLoop()==0)
1292 void MSILWriter::printConstantExpr(const ConstantExpr
* CE
) {
1293 const Value
*left
= 0, *right
= 0;
1294 if (CE
->getNumOperands()>=1) left
= CE
->getOperand(0);
1295 if (CE
->getNumOperands()>=2) right
= CE
->getOperand(1);
1296 // Print instruction
1297 switch (CE
->getOpcode()) {
1298 case Instruction::Trunc
:
1299 case Instruction::ZExt
:
1300 case Instruction::SExt
:
1301 case Instruction::FPTrunc
:
1302 case Instruction::FPExt
:
1303 case Instruction::UIToFP
:
1304 case Instruction::SIToFP
:
1305 case Instruction::FPToUI
:
1306 case Instruction::FPToSI
:
1307 case Instruction::PtrToInt
:
1308 case Instruction::IntToPtr
:
1309 case Instruction::BitCast
:
1310 printCastInstruction(CE
->getOpcode(),left
,CE
->getType());
1312 case Instruction::GetElementPtr
:
1313 printGepInstruction(CE
->getOperand(0),gep_type_begin(CE
),gep_type_end(CE
));
1315 case Instruction::ICmp
:
1316 printICmpInstruction(CE
->getPredicate(),left
,right
);
1318 case Instruction::FCmp
:
1319 printFCmpInstruction(CE
->getPredicate(),left
,right
);
1321 case Instruction::Select
:
1322 printSelectInstruction(CE
->getOperand(0),CE
->getOperand(1),CE
->getOperand(2));
1324 case Instruction::Add
:
1325 printBinaryInstruction("add",left
,right
);
1327 case Instruction::Sub
:
1328 printBinaryInstruction("sub",left
,right
);
1330 case Instruction::Mul
:
1331 printBinaryInstruction("mul",left
,right
);
1333 case Instruction::UDiv
:
1334 printBinaryInstruction("div.un",left
,right
);
1336 case Instruction::SDiv
:
1337 case Instruction::FDiv
:
1338 printBinaryInstruction("div",left
,right
);
1340 case Instruction::URem
:
1341 printBinaryInstruction("rem.un",left
,right
);
1343 case Instruction::SRem
:
1344 case Instruction::FRem
:
1345 printBinaryInstruction("rem",left
,right
);
1347 case Instruction::And
:
1348 printBinaryInstruction("and",left
,right
);
1350 case Instruction::Or
:
1351 printBinaryInstruction("or",left
,right
);
1353 case Instruction::Xor
:
1354 printBinaryInstruction("xor",left
,right
);
1356 case Instruction::Shl
:
1357 printBinaryInstruction("shl",left
,right
);
1359 case Instruction::LShr
:
1360 printBinaryInstruction("shr.un",left
,right
);
1362 case Instruction::AShr
:
1363 printBinaryInstruction("shr",left
,right
);
1366 cerr
<< "Expression = " << *CE
<< "\n";
1367 assert(0 && "Invalid constant expression");
1372 void MSILWriter::printStaticInitializerList() {
1373 // List of global variables with uninitialized fields.
1374 for (std::map
<const GlobalVariable
*,std::vector
<StaticInitializer
> >::iterator
1375 VarI
= StaticInitList
.begin(), VarE
= StaticInitList
.end(); VarI
!=VarE
;
1377 const std::vector
<StaticInitializer
>& InitList
= VarI
->second
;
1378 if (InitList
.empty()) continue;
1379 // For each uninitialized field.
1380 for (std::vector
<StaticInitializer
>::const_iterator I
= InitList
.begin(),
1381 E
= InitList
.end(); I
!=E
; ++I
) {
1382 if (const ConstantExpr
*CE
= dyn_cast
<ConstantExpr
>(I
->constant
)) {
1383 // Out << "\n// Init " << getValueName(VarI->first) << ", offset " <<
1384 // utostr(I->offset) << ", type "<< *I->constant->getType() << "\n\n";
1385 // Load variable address
1386 printValueLoad(VarI
->first
);
1389 printPtrLoad(I
->offset
);
1390 printSimpleInstruction("add");
1393 printConstantExpr(CE
);
1394 // Save result at offset
1395 std::string postfix
= getTypePostfix(CE
->getType(),true);
1396 if (*postfix
.begin()=='u') *postfix
.begin() = 'i';
1397 postfix
= "stind."+postfix
;
1398 printSimpleInstruction(postfix
.c_str());
1400 cerr
<< "Constant = " << *I
->constant
<< '\n';
1401 assert(0 && "Invalid static initializer");
1408 void MSILWriter::printFunction(const Function
& F
) {
1409 bool isSigned
= F
.paramHasAttr(0, Attribute::SExt
);
1410 Out
<< "\n.method static ";
1411 Out
<< (F
.hasLocalLinkage() ? "private " : "public ");
1412 if (F
.isVarArg()) Out
<< "vararg ";
1413 Out
<< getTypeName(F
.getReturnType(),isSigned
) <<
1414 getConvModopt(F
.getCallingConv()) << getValueName(&F
) << '\n';
1417 unsigned ArgIdx
= 1;
1418 for (Function::const_arg_iterator I
= F
.arg_begin(), E
= F
.arg_end(); I
!=E
;
1420 isSigned
= F
.paramHasAttr(ArgIdx
, Attribute::SExt
);
1421 if (I
!=F
.arg_begin()) Out
<< ", ";
1422 Out
<< getTypeName(I
->getType(),isSigned
) << getValueName(I
);
1424 Out
<< ") cil managed\n";
1427 printLocalVariables(F
);
1428 printFunctionBody(F
);
1433 void MSILWriter::printDeclarations(const TypeSymbolTable
& ST
) {
1435 std::set
<const Type
*> Printed
;
1436 for (std::set
<const Type
*>::const_iterator
1437 UI
= UsedTypes
->begin(), UE
= UsedTypes
->end(); UI
!=UE
; ++UI
) {
1438 const Type
* Ty
= *UI
;
1439 if (isa
<ArrayType
>(Ty
) || isa
<VectorType
>(Ty
) || isa
<StructType
>(Ty
))
1440 Name
= getTypeName(Ty
, false, true);
1441 // Type with no need to declare.
1443 // Print not duplicated type
1444 if (Printed
.insert(Ty
).second
) {
1445 Out
<< ".class value explicit ansi sealed '" << Name
<< "'";
1446 Out
<< " { .pack " << 1 << " .size " << TD
->getTypeAllocSize(Ty
);
1453 unsigned int MSILWriter::getBitWidth(const Type
* Ty
) {
1454 unsigned int N
= Ty
->getPrimitiveSizeInBits();
1455 assert(N
!=0 && "Invalid type in getBitWidth()");
1464 cerr
<< "Bits = " << N
<< '\n';
1465 assert(0 && "Unsupported integer width");
1467 return 0; // Not reached
1471 void MSILWriter::printStaticConstant(const Constant
* C
, uint64_t& Offset
) {
1472 uint64_t TySize
= 0;
1473 const Type
* Ty
= C
->getType();
1474 // Print zero initialized constant.
1475 if (isa
<ConstantAggregateZero
>(C
) || C
->isNullValue()) {
1476 TySize
= TD
->getTypeAllocSize(C
->getType());
1478 Out
<< "int8 (0) [" << TySize
<< "]";
1481 // Print constant initializer
1482 switch (Ty
->getTypeID()) {
1483 case Type::IntegerTyID
: {
1484 TySize
= TD
->getTypeAllocSize(Ty
);
1485 const ConstantInt
* Int
= cast
<ConstantInt
>(C
);
1486 Out
<< getPrimitiveTypeName(Ty
,true) << "(" << Int
->getSExtValue() << ")";
1489 case Type::FloatTyID
:
1490 case Type::DoubleTyID
: {
1491 TySize
= TD
->getTypeAllocSize(Ty
);
1492 const ConstantFP
* FP
= cast
<ConstantFP
>(C
);
1493 if (Ty
->getTypeID() == Type::FloatTyID
)
1495 (uint32_t)FP
->getValueAPF().bitcastToAPInt().getZExtValue() << ')';
1498 FP
->getValueAPF().bitcastToAPInt().getZExtValue() << ')';
1501 case Type::ArrayTyID
:
1502 case Type::VectorTyID
:
1503 case Type::StructTyID
:
1504 for (unsigned I
= 0, E
= C
->getNumOperands(); I
<E
; I
++) {
1505 if (I
!=0) Out
<< ",\n";
1506 printStaticConstant(C
->getOperand(I
),Offset
);
1509 case Type::PointerTyID
:
1510 TySize
= TD
->getTypeAllocSize(C
->getType());
1511 // Initialize with global variable address
1512 if (const GlobalVariable
*G
= dyn_cast
<GlobalVariable
>(C
)) {
1513 std::string name
= getValueName(G
);
1514 Out
<< "&(" << name
.insert(name
.length()-1,"$data") << ")";
1516 // Dynamic initialization
1517 if (!isa
<ConstantPointerNull
>(C
) && !C
->isNullValue())
1518 InitListPtr
->push_back(StaticInitializer(C
,Offset
));
1519 // Null pointer initialization
1520 if (TySize
==4) Out
<< "int32 (0)";
1521 else if (TySize
==8) Out
<< "int64 (0)";
1522 else assert(0 && "Invalid pointer size");
1526 cerr
<< "TypeID = " << Ty
->getTypeID() << '\n';
1527 assert(0 && "Invalid type in printStaticConstant()");
1534 void MSILWriter::printStaticInitializer(const Constant
* C
,
1535 const std::string
& Name
) {
1536 switch (C
->getType()->getTypeID()) {
1537 case Type::IntegerTyID
:
1538 case Type::FloatTyID
:
1539 case Type::DoubleTyID
:
1540 Out
<< getPrimitiveTypeName(C
->getType(), false);
1542 case Type::ArrayTyID
:
1543 case Type::VectorTyID
:
1544 case Type::StructTyID
:
1545 case Type::PointerTyID
:
1546 Out
<< getTypeName(C
->getType());
1549 cerr
<< "Type = " << *C
<< "\n";
1550 assert(0 && "Invalid constant type");
1552 // Print initializer
1553 std::string label
= Name
;
1554 label
.insert(label
.length()-1,"$data");
1555 Out
<< Name
<< " at " << label
<< '\n';
1556 Out
<< ".data " << label
<< " = {\n";
1557 uint64_t offset
= 0;
1558 printStaticConstant(C
,offset
);
1563 void MSILWriter::printVariableDefinition(const GlobalVariable
* G
) {
1564 const Constant
* C
= G
->getInitializer();
1565 if (C
->isNullValue() || isa
<ConstantAggregateZero
>(C
) || isa
<UndefValue
>(C
))
1568 InitListPtr
= &StaticInitList
[G
];
1569 printStaticInitializer(C
,getValueName(G
));
1573 void MSILWriter::printGlobalVariables() {
1574 if (ModulePtr
->global_empty()) return;
1575 Module::global_iterator I
,E
;
1576 for (I
= ModulePtr
->global_begin(), E
= ModulePtr
->global_end(); I
!=E
; ++I
) {
1577 // Variable definition
1578 Out
<< ".field static " << (I
->isDeclaration() ? "public " :
1580 if (I
->isDeclaration()) {
1581 Out
<< getTypeName(I
->getType()) << getValueName(&*I
) << "\n\n";
1583 printVariableDefinition(&*I
);
1588 const char* MSILWriter::getLibraryName(const Function
* F
) {
1589 return getLibraryForSymbol(F
->getName().c_str(), true, F
->getCallingConv());
1593 const char* MSILWriter::getLibraryName(const GlobalVariable
* GV
) {
1594 return getLibraryForSymbol(Mang
->getValueName(GV
).c_str(), false, 0);
1598 const char* MSILWriter::getLibraryForSymbol(const char* Name
, bool isFunction
,
1599 unsigned CallingConv
) {
1600 // TODO: Read *.def file with function and libraries definitions.
1601 return "MSVCRT.DLL";
1605 void MSILWriter::printExternals() {
1606 Module::const_iterator I
,E
;
1608 for (I
=ModulePtr
->begin(),E
=ModulePtr
->end(); I
!=E
; ++I
) {
1610 if (I
->isIntrinsic()) continue;
1611 if (I
->isDeclaration()) {
1612 const Function
* F
= I
;
1613 std::string Name
= getConvModopt(F
->getCallingConv())+getValueName(F
);
1615 getCallSignature(cast
<FunctionType
>(F
->getFunctionType()), NULL
, Name
);
1616 Out
<< ".method static hidebysig pinvokeimpl(\""
1617 << getLibraryName(F
) << "\")\n\t" << Sig
<< " preservesig {}\n\n";
1620 // External variables and static initialization.
1622 ".method public hidebysig static pinvokeimpl(\"KERNEL32.DLL\" ansi winapi)"
1623 " native int LoadLibrary(string) preservesig {}\n"
1624 ".method public hidebysig static pinvokeimpl(\"KERNEL32.DLL\" ansi winapi)"
1625 " native int GetProcAddress(native int, string) preservesig {}\n";
1627 ".method private static void* $MSIL_Import(string lib,string sym)\n"
1630 "\tcall\tnative int LoadLibrary(string)\n"
1632 "\tcall\tnative int GetProcAddress(native int,string)\n"
1635 "\tldstr\t\"Can no import variable\"\n"
1636 "\tnewobj\tinstance void [mscorlib]System.Exception::.ctor(string)\n"
1641 ".method static private void $MSIL_Init() managed cil\n{\n";
1642 printStaticInitializerList();
1643 // Foreach global variable.
1644 for (Module::global_iterator I
= ModulePtr
->global_begin(),
1645 E
= ModulePtr
->global_end(); I
!=E
; ++I
) {
1646 if (!I
->isDeclaration() || !I
->hasDLLImportLinkage()) continue;
1647 // Use "LoadLibrary"/"GetProcAddress" to recive variable address.
1648 std::string Label
= "not_null$_"+utostr(getUniqID());
1649 std::string Tmp
= getTypeName(I
->getType())+getValueName(&*I
);
1650 printSimpleInstruction("ldsflda",Tmp
.c_str());
1651 Out
<< "\tldstr\t\"" << getLibraryName(&*I
) << "\"\n";
1652 Out
<< "\tldstr\t\"" << Mang
->getValueName(&*I
) << "\"\n";
1653 printSimpleInstruction("call","void* $MSIL_Import(string,string)");
1654 printIndirectSave(I
->getType());
1656 printSimpleInstruction("ret");
1661 //===----------------------------------------------------------------------===//
1662 // External Interface declaration
1663 //===----------------------------------------------------------------------===//
1665 bool MSILTarget::addPassesToEmitWholeFile(PassManager
&PM
, raw_ostream
&o
,
1666 CodeGenFileType FileType
,
1667 CodeGenOpt::Level OptLevel
)
1669 if (FileType
!= TargetMachine::AssemblyFile
) return true;
1670 MSILWriter
* Writer
= new MSILWriter(o
);
1671 PM
.add(createGCLoweringPass());
1672 PM
.add(createLowerAllocationsPass(true));
1673 // FIXME: Handle switch trougth native IL instruction "switch"
1674 PM
.add(createLowerSwitchPass());
1675 PM
.add(createCFGSimplificationPass());
1676 PM
.add(new MSILModule(Writer
->UsedTypes
,Writer
->TD
));
1678 PM
.add(createGCInfoDeleter());