00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "comma/ast/Decl.h"
00010 #include "comma/codegen/CodeGen.h"
00011 #include "comma/codegen/CodeGenCapsule.h"
00012 #include "comma/codegen/CodeGenTypes.h"
00013 #include "comma/codegen/CodeGenRoutine.h"
00014 #include "comma/codegen/CommaRT.h"
00015
00016 #include "llvm/Support/Casting.h"
00017
00018 #include <sstream>
00019
00020 using namespace comma;
00021
00022 using llvm::cast;
00023 using llvm::dyn_cast;
00024 using llvm::isa;
00025
00026 CodeGen::CodeGen(llvm::Module *M, const llvm::TargetData &data)
00027 : M(M),
00028 TD(data),
00029 CGTypes(new CodeGenTypes(*this)),
00030 CRT(new CommaRT(*this)) { }
00031
00032 CodeGen::~CodeGen()
00033 {
00034 delete CGTypes;
00035 delete CRT;
00036 }
00037
00038 CodeGenTypes &CodeGen::getTypeGenerator()
00039 {
00040 return *CGTypes;
00041 }
00042
00043 const CodeGenTypes &CodeGen::getTypeGenerator() const
00044 {
00045 return *CGTypes;
00046 }
00047
00048 void CodeGen::emitToplevelDecl(Decl *decl)
00049 {
00050 if (Domoid *domoid = dyn_cast<Domoid>(decl)) {
00051 CodeGenCapsule CGC(*this, domoid);
00052 llvm::GlobalVariable *info = CRT->registerCapsule(CGC);
00053 capsuleInfoTable[CGC.getLinkName()] = info;
00054 }
00055 else if (Sigoid *sigoid = dyn_cast<Sigoid>(decl))
00056 CRT->registerSignature(sigoid);
00057 }
00058
00059 bool CodeGen::insertGlobal(const std::string &linkName, llvm::GlobalValue *GV)
00060 {
00061 assert(GV && "Cannot insert null values into the global table!");
00062
00063 if (lookupGlobal(linkName))
00064 return false;
00065
00066 globalTable[linkName] = GV;
00067 return true;
00068 }
00069
00070 llvm::GlobalValue *CodeGen::lookupGlobal(const std::string &linkName) const
00071 {
00072 StringGlobalMap::const_iterator iter = globalTable.find(linkName);
00073
00074 if (iter != globalTable.end())
00075 return iter->second;
00076 return 0;
00077 }
00078
00079 llvm::GlobalValue *CodeGen::lookupCapsuleInfo(Domoid *domoid) const
00080 {
00081 std::string name = getLinkName(domoid);
00082 StringGlobalMap::const_iterator iter = capsuleInfoTable.find(name);
00083
00084 if (iter != capsuleInfoTable.end())
00085 return iter->second;
00086 else
00087 return 0;
00088 }
00089
00090
00091 llvm::Constant *CodeGen::emitStringLiteral(const std::string &str,
00092 bool isConstant,
00093 const std::string &name)
00094 {
00095 llvm::Constant *stringConstant = llvm::ConstantArray::get(str, true);
00096 return new llvm::GlobalVariable(stringConstant->getType(), isConstant,
00097 llvm::GlobalValue::InternalLinkage,
00098 stringConstant, name, M);
00099 }
00100
00101 std::string CodeGen::getLinkPrefix(const Decl *decl)
00102 {
00103 std::string prefix;
00104 const DeclRegion *region = decl->getDeclRegion();
00105 const char *component;
00106
00107 while (region) {
00108 if (isa<AddDecl>(region))
00109 region = region->getParent();
00110
00111 component = cast<Decl>(region)->getString();
00112 prefix.insert(0, "__");
00113 prefix.insert(0, component);
00114
00115 region = region->getParent();
00116 }
00117
00118 return prefix;
00119 }
00120
00121 std::string CodeGen::getLinkName(const SubroutineDecl *sr)
00122 {
00123 std::string name;
00124 int index;
00125
00126 name = getLinkPrefix(sr);
00127 name.append(getSubroutineName(sr));
00128
00129 index = getDeclIndex(sr, sr->getParent());
00130 assert(index >= 0 && "getDeclIndex failed!");
00131
00132 if (index) {
00133 std::ostringstream ss;
00134 ss << "__" << index;
00135 name += ss.str();
00136 }
00137
00138 return name;
00139 }
00140
00141 std::string CodeGen::getLinkName(const Domoid *domoid)
00142 {
00143 return domoid->getString();
00144 }
00145
00146 int CodeGen::getDeclIndex(const Decl *decl, const DeclRegion *region)
00147 {
00148 IdentifierInfo *idInfo = decl->getIdInfo();
00149 unsigned result = 0;
00150
00151 typedef DeclRegion::ConstDeclIter iterator;
00152
00153 for (iterator i = region->beginDecls(); i != region->endDecls(); ++i) {
00154 if (idInfo == (*i)->getIdInfo()) {
00155 if (decl == (*i))
00156 return result;
00157 else
00158 result++;
00159 }
00160 }
00161 return -1;
00162 }
00163
00164 std::string CodeGen::getSubroutineName(const SubroutineDecl *srd)
00165 {
00166 const char *name = srd->getIdInfo()->getString();
00167
00168 switch (strlen(name)) {
00169
00170 default:
00171 return name;
00172
00173 case 1:
00174 if (strncmp(name, "!", 1) == 0)
00175 return "0bang";
00176 else if (strncmp(name, "&", 1) == 0)
00177 return "0amper";
00178 else if (strncmp(name, "#", 1) == 0)
00179 return "0hash";
00180 else if (strncmp(name, "*", 1) == 0)
00181 return "0multiply";
00182 else if (strncmp(name, "+", 1) == 0)
00183 return "0plus";
00184 else if (strncmp(name, "-", 1) == 0)
00185 return "0minus";
00186 else if (strncmp(name, "<", 1) == 0)
00187 return "0less";
00188 else if (strncmp(name, "=", 1) == 0)
00189 return "0equal";
00190 else if (strncmp(name, ">", 1) == 0)
00191 return "0great";
00192 else if (strncmp(name, "@", 1) == 0)
00193 return "0at";
00194 else if (strncmp(name, "\\", 1) == 0)
00195 return "0bslash";
00196 else if (strncmp(name, "^", 1) == 0)
00197 return "0hat";
00198 else if (strncmp(name, "`", 1) == 0)
00199 return "0grave";
00200 else if (strncmp(name, "|", 1) == 0)
00201 return "0bar";
00202 else if (strncmp(name, "/", 1) == 0)
00203 return "0fslash";
00204 else if (strncmp(name, "~", 1) == 0)
00205 return "0tilde";
00206 else
00207 return name;
00208
00209 case 2:
00210 if (strncmp(name, "<=", 2) == 0)
00211 return "0leq";
00212 else if (strncmp(name, "<>", 2) == 0)
00213 return "0diamond";
00214 else if (strncmp(name, "<<", 2) == 0)
00215 return "0dless";
00216 else if (strncmp(name, "==", 2) == 0)
00217 return "0dequal";
00218 else if (strncmp(name, ">=", 2) == 0)
00219 return "0geq";
00220 else if (strncmp(name, ">>", 2) == 0)
00221 return "0dgreat";
00222 else if (strncmp(name, "||", 2) == 0)
00223 return "0dbar";
00224 else if (strncmp(name, "~=", 2) == 0)
00225 return "0nequal";
00226 else
00227 return name;
00228 }
00229 }
00230
00231 llvm::Constant *CodeGen::getNullPointer(const llvm::PointerType *Ty) const
00232 {
00233 return llvm::ConstantPointerNull::get(Ty);
00234 }
00235
00236 llvm::PointerType *CodeGen::getPointerType(const llvm::Type *Ty) const
00237 {
00238 return llvm::PointerType::getUnqual(Ty);
00239 }
00240
00241 llvm::GlobalVariable *CodeGen::makeExternGlobal(llvm::Constant *init,
00242 bool isConstant,
00243 const std::string &name)
00244
00245 {
00246 return new llvm::GlobalVariable(init->getType(), isConstant,
00247 llvm::GlobalValue::ExternalLinkage,
00248 init, name, M);
00249 }
00250
00251 llvm::GlobalVariable *CodeGen::makeInternGlobal(llvm::Constant *init,
00252 bool isConstant,
00253 const std::string &name)
00254
00255 {
00256 return new llvm::GlobalVariable(init->getType(), isConstant,
00257 llvm::GlobalValue::InternalLinkage,
00258 init, name, M);
00259 }
00260
00261 llvm::Function *CodeGen::makeFunction(const llvm::FunctionType *Ty,
00262 const std::string &name)
00263 {
00264 llvm::Function *fn =
00265 llvm::Function::Create(Ty, llvm::Function::ExternalLinkage, name, M);
00266
00267
00268
00269
00270 fn->setDoesNotThrow();
00271 return fn;
00272 }
00273
00274 llvm::Function *CodeGen::makeInternFunction(const llvm::FunctionType *Ty,
00275 const std::string &name)
00276 {
00277 llvm::Function *fn =
00278 llvm::Function::Create(Ty, llvm::Function::InternalLinkage, name, M);
00279
00280
00281
00282
00283 fn->setDoesNotThrow();
00284 return fn;
00285 }
00286
00287 llvm::Constant *CodeGen::getPointerCast(llvm::Constant *constant,
00288 const llvm::PointerType *Ty) const
00289 {
00290 return llvm::ConstantExpr::getPointerCast(constant, Ty);
00291 }
00292
00293 llvm::Constant *
00294 CodeGen::getConstantArray(const llvm::Type *elementType,
00295 std::vector<llvm::Constant*> &elems) const
00296 {
00297 llvm::ArrayType *arrayTy = llvm::ArrayType::get(elementType, elems.size());
00298 return llvm::ConstantArray::get(arrayTy, elems);
00299 }