1 //===-- llc.cpp - Implement the LLVM Compiler -----------------------------===//
3 // This is the llc compiler driver.
5 //===----------------------------------------------------------------------===//
7 #include "llvm/Bytecode/Reader.h"
8 #include "llvm/Optimizations/Normalize.h"
9 #include "llvm/Target/Sparc.h"
10 #include "llvm/Target/TargetMachine.h"
11 #include "llvm/Support/CommandLine.h"
12 #include "llvm/Module.h"
13 #include "llvm/Method.h"
17 cl::String InputFilename ("", "Input filename", cl::NoFlags, "-");
18 cl::String OutputFilename("o", "Output filename", cl::NoFlags, "");
19 cl::Flag Force ("f", "Overwrite output files", cl::NoFlags, false);
20 cl::Flag DumpAsm ("d", "Print assembly as compiled", cl::Hidden, false);
22 #include "llvm/Assembly/Writer.h" // For DumpAsm
24 //-------------------------- Internal Functions ------------------------------//
28 // TODO: Remove to external file.... When Chris gets back he'll do it
30 #include "llvm/DerivedTypes.h"
31 #include "llvm/iMemory.h"
32 #include "llvm/iOther.h"
33 #include "llvm/SymbolTable.h"
36 Method *MallocMeth = 0, *FreeMeth = 0;
38 // InsertMallocFreeDecls - Insert an external declaration for malloc and an
39 // external declaration for free for use by the ReplaceMallocFree function.
41 static void InsertMallocFreeDecls(Module *M) {
42 const MethodType *MallocType =
43 MethodType::get(PointerType::get(Type::UByteTy),
44 vector<const Type*>(1, Type::UIntTy), false);
46 SymbolTable *SymTab = M->getSymbolTableSure();
48 // Check for a definition of malloc
49 if (Value *V = SymTab->lookup(PointerType::get(MallocType), "malloc")) {
50 MallocMeth = cast<Method>(V); // Yup, got it
51 } else { // Nope, add one
52 M->getMethodList().push_back(MallocMeth = new Method(MallocType, "malloc"));
55 const MethodType *FreeType =
56 MethodType::get(Type::VoidTy,
57 vector<const Type*>(1, PointerType::get(Type::UByteTy)),
60 // Check for a definition of free
61 if (Value *V = SymTab->lookup(PointerType::get(FreeType), "free")) {
62 FreeMeth = cast<Method>(V); // Yup, got it
63 } else { // Nope, add one
64 M->getMethodList().push_back(FreeMeth = new Method(FreeType, "free"));
69 static void ReplaceMallocFree(Method *M, const TargetData &DataLayout) {
70 assert(MallocMeth && FreeMeth && M && "Must call InsertMallocFreeDecls!");
72 // Loop over all of the instructions, looking for malloc or free instructions
73 for (Method::iterator BBI = M->begin(), BBE = M->end(); BBI != BBE; ++BBI) {
74 BasicBlock *BB = *BBI;
75 for (unsigned i = 0; i < BB->size(); ++i) {
76 BasicBlock::InstListType &BBIL = BB->getInstList();
77 if (MallocInst *MI = dyn_cast<MallocInst>(*(BBIL.begin()+i))) {
78 BBIL.remove(BBIL.begin()+i); // remove the malloc instr...
80 const Type *AllocTy = cast<PointerType>(MI->getType())->getValueType();
82 // If the user is allocating an unsized array with a dynamic size arg,
83 // start by getting the size of one element.
85 if (const ArrayType *ATy = dyn_cast<ArrayType>(AllocTy))
86 if (ATy->isUnsized()) AllocTy = ATy->getElementType();
88 // Get the number of bytes to be allocated for one element of the
90 unsigned Size = DataLayout.getTypeSize(AllocTy);
92 // malloc(type) becomes sbyte *malloc(constint)
93 Value *MallocArg = ConstPoolUInt::get(Type::UIntTy, Size);
94 if (MI->getNumOperands() && Size == 1) {
95 MallocArg = MI->getOperand(0); // Operand * 1 = Operand
96 } else if (MI->getNumOperands()) {
97 // Multiply it by the array size if neccesary...
98 MallocArg = BinaryOperator::create(Instruction::Mul,MI->getOperand(0),
100 BBIL.insert(BBIL.begin()+i++, cast<Instruction>(MallocArg));
103 // Create the call to Malloc...
104 CallInst *MCall = new CallInst(MallocMeth,
105 vector<Value*>(1, MallocArg));
106 BBIL.insert(BBIL.begin()+i, MCall);
108 // Create a cast instruction to convert to the right type...
109 CastInst *MCast = new CastInst(MCall, MI->getType());
110 BBIL.insert(BBIL.begin()+i+1, MCast);
112 // Replace all uses of the old malloc inst with the cast inst
113 MI->replaceAllUsesWith(MCast);
114 delete MI; // Delete the malloc inst
115 } else if (FreeInst *FI = dyn_cast<FreeInst>(*(BBIL.begin()+i))) {
116 BBIL.remove(BB->getInstList().begin()+i);
118 // Cast the argument to free into a ubyte*...
119 CastInst *MCast = new CastInst(FI->getOperand(0),
120 PointerType::get(Type::UByteTy));
121 BBIL.insert(BBIL.begin()+i, MCast);
123 // Insert a call to the free function...
124 CallInst *FCall = new CallInst(FreeMeth,
125 vector<Value*>(1, MCast));
126 BBIL.insert(BBIL.begin()+i+1, FCall);
128 // Delete the old free instruction
136 // END TODO: Remove to external file....
138 static void NormalizeMethod(Method *M) {
139 NormalizePhiConstantArgs(M);
143 //===---------------------------------------------------------------------===//
146 // Entry point for the llc compiler.
147 //===---------------------------------------------------------------------===//
149 int main(int argc, char **argv) {
150 // Parse command line options...
151 cl::ParseCommandLineOptions(argc, argv, " llvm system compiler\n");
153 // Allocate a target... in the future this will be controllable on the
155 auto_ptr<TargetMachine> Target(allocateSparcTargetMachine());
157 // Load the module to be compiled...
158 auto_ptr<Module> M(ParseBytecodeFile(InputFilename));
160 cerr << "bytecode didn't read correctly.\n";
164 InsertMallocFreeDecls(M.get());
166 // Loop over all of the methods in the module, compiling them.
167 for (Module::const_iterator MI = M->begin(), ME = M->end(); MI != ME; ++MI) {
170 NormalizeMethod(Meth);
171 ReplaceMallocFree(Meth, Target->DataLayout);
174 cerr << "Method after xformations: \n" << Meth;
176 if (Target->compileMethod(Meth)) {
177 cerr << "Error compiling " << InputFilename << "!\n";
182 // Figure out where we are going to send the output...
184 if (OutputFilename != "") { // Specified an output filename?
185 Out = new ofstream(OutputFilename.c_str(),
186 (Force ? 0 : ios::noreplace)|ios::out);
188 if (InputFilename == "-") {
189 OutputFilename = "-";
192 string IFN = InputFilename;
193 int Len = IFN.length();
194 if (IFN[Len-3] == '.' && IFN[Len-2] == 'b' && IFN[Len-1] == 'c') {
195 OutputFilename = string(IFN.begin(), IFN.end()-3); // s/.bc/.s/
197 OutputFilename = IFN; // Append a .s to it
199 OutputFilename += ".s";
200 Out = new ofstream(OutputFilename.c_str(),
201 (Force ? 0 : ios::noreplace)|ios::out);
203 cerr << "Error opening " << OutputFilename << "!\n";
210 // Emit the output...
211 Target->emitAssembly(M.get(), *Out);
213 if (Out != &cout) delete Out;