Fix PR1101 and Analysis/ScalarEvolution/trip-count.ll
[oota-llvm.git] / lib / Archive / Archive.cpp
1 //===-- Archive.cpp - Generic LLVM archive functions ------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by Reid Spencer and is distributed under the
6 // University of Illinois Open Source License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file contains the implementation of the Archive and ArchiveMember
11 // classes that is common to both reading and writing archives..
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "ArchiveInternals.h"
16 #include "llvm/ModuleProvider.h"
17 #include "llvm/System/Process.h"
18
19 using namespace llvm;
20
21 // getMemberSize - compute the actual physical size of the file member as seen
22 // on disk. This isn't the size of member's payload. Use getSize() for that.
23 unsigned
24 ArchiveMember::getMemberSize() const {
25   // Basically its the file size plus the header size
26   unsigned result =  info.fileSize + sizeof(ArchiveMemberHeader);
27
28   // If it has a long filename, include the name length
29   if (hasLongFilename())
30     result += path.toString().length() + 1;
31
32   // If its now odd lengthed, include the padding byte
33   if (result % 2 != 0 )
34     result++;
35
36   return result;
37 }
38
39 // This default constructor is only use by the ilist when it creates its
40 // sentry node. We give it specific static values to make it stand out a bit.
41 ArchiveMember::ArchiveMember()
42   : next(0), prev(0), parent(0), path("--invalid--"), flags(0), data(0)
43 {
44   info.user = sys::Process::GetCurrentUserId();
45   info.group = sys::Process::GetCurrentGroupId();
46   info.mode = 0777;
47   info.fileSize = 0;
48   info.modTime = sys::TimeValue::now();
49 }
50
51 // This is the constructor that the Archive class uses when it is building or
52 // reading an archive. It just defaults a few things and ensures the parent is
53 // set for the iplist. The Archive class fills in the ArchiveMember's data.
54 // This is required because correctly setting the data may depend on other
55 // things in the Archive.
56 ArchiveMember::ArchiveMember(Archive* PAR)
57   : next(0), prev(0), parent(PAR), path(), flags(0), data(0)
58 {
59 }
60
61 // This method allows an ArchiveMember to be replaced with the data for a
62 // different file, presumably as an update to the member. It also makes sure
63 // the flags are reset correctly.
64 bool ArchiveMember::replaceWith(const sys::Path& newFile, std::string* ErrMsg) {
65   if (!newFile.exists()) {
66     if (ErrMsg) 
67       *ErrMsg = "Can not replace an archive member with a non-existent file";
68     return true;
69   }
70
71   data = 0;
72   path = newFile;
73
74   // SVR4 symbol tables have an empty name
75   if (path.toString() == ARFILE_SVR4_SYMTAB_NAME)
76     flags |= SVR4SymbolTableFlag;
77   else
78     flags &= ~SVR4SymbolTableFlag;
79
80   // BSD4.4 symbol tables have a special name
81   if (path.toString() == ARFILE_BSD4_SYMTAB_NAME)
82     flags |= BSD4SymbolTableFlag;
83   else
84     flags &= ~BSD4SymbolTableFlag;
85
86   // LLVM symbol tables have a very specific name
87   if (path.toString() == ARFILE_LLVM_SYMTAB_NAME)
88     flags |= LLVMSymbolTableFlag;
89   else
90     flags &= ~LLVMSymbolTableFlag;
91
92   // String table name
93   if (path.toString() == ARFILE_STRTAB_NAME)
94     flags |= StringTableFlag;
95   else
96     flags &= ~StringTableFlag;
97
98   // If it has a slash then it has a path
99   bool hasSlash = path.toString().find('/') != std::string::npos;
100   if (hasSlash)
101     flags |= HasPathFlag;
102   else
103     flags &= ~HasPathFlag;
104
105   // If it has a slash or its over 15 chars then its a long filename format
106   if (hasSlash || path.toString().length() > 15)
107     flags |= HasLongFilenameFlag;
108   else
109     flags &= ~HasLongFilenameFlag;
110
111   // Get the signature and status info
112   const char* signature = (const char*) data;
113   std::string magic;
114   if (!signature) {
115     path.getMagicNumber(magic,4);
116     signature = magic.c_str();
117     std::string err;
118     if (path.getFileStatus(info, ErrMsg))
119       return true;
120   }
121
122   // Determine what kind of file it is
123   switch (sys::IdentifyFileType(signature,4)) {
124     case sys::BytecodeFileType:
125       flags |= BytecodeFlag;
126       break;
127     case sys::CompressedBytecodeFileType:
128       flags |= CompressedBytecodeFlag;
129       flags &= ~CompressedFlag;
130       break;
131     default:
132       flags &= ~(BytecodeFlag|CompressedBytecodeFlag);
133       break;
134   }
135   return false;
136 }
137
138 // Archive constructor - this is the only constructor that gets used for the
139 // Archive class. Everything else (default,copy) is deprecated. This just
140 // initializes and maps the file into memory, if requested.
141 Archive::Archive(const sys::Path& filename)
142   : archPath(filename), members(), mapfile(0), base(0), symTab(), strtab(),
143     symTabSize(0), firstFileOffset(0), modules(), foreignST(0)
144 {
145 }
146
147 bool
148 Archive::mapToMemory(std::string* ErrMsg)
149 {
150   mapfile = new sys::MappedFile();
151   if (mapfile->open(archPath, sys::MappedFile::READ_ACCESS, ErrMsg))
152     return true;
153   if (!(base = (char*) mapfile->map(ErrMsg)))
154     return true;
155   return false;
156 }
157
158 void Archive::cleanUpMemory() {
159   // Shutdown the file mapping
160   if (mapfile) {
161     mapfile->close();
162     delete mapfile;
163     
164     mapfile = 0;
165     base = 0;
166   }
167   
168   // Forget the entire symbol table
169   symTab.clear();
170   symTabSize = 0;
171   
172   firstFileOffset = 0;
173   
174   // Free the foreign symbol table member
175   if (foreignST) {
176     delete foreignST;
177     foreignST = 0;
178   }
179   
180   // Delete any ModuleProviders and ArchiveMember's we've allocated as a result
181   // of symbol table searches.
182   for (ModuleMap::iterator I=modules.begin(), E=modules.end(); I != E; ++I ) {
183     delete I->second.first;
184     delete I->second.second;
185   }
186 }
187
188 // Archive destructor - just clean up memory
189 Archive::~Archive() {
190   cleanUpMemory();
191 }
192