From lattner at cs.uiuc.edu Tue Apr 15 11:08:07 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Apr 15 11:08:07 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Assembler/2003-04-15-ConstantInitAssertion.llx Message-ID: <200304151607.LAA12783@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Assembler: 2003-04-15-ConstantInitAssertion.llx added (r1.1) --- Log message: New testcase that triggered assertion failure. --- Diffs of the changes: Index: llvm/test/Regression/Assembler/2003-04-15-ConstantInitAssertion.llx diff -c /dev/null llvm/test/Regression/Assembler/2003-04-15-ConstantInitAssertion.llx:1.1 *** /dev/null Tue Apr 15 11:07:16 2003 --- llvm/test/Regression/Assembler/2003-04-15-ConstantInitAssertion.llx Tue Apr 15 11:07:05 2003 *************** *** 0 **** --- 1,4 ---- + ; RUN: (as < %s 2>&1) | grep Expected + ; Test the case of a misformed constant initializer + ; This should cause an assembler error, not an assertion failure! + %X = constant {int} { float 1.0 } From lattner at cs.uiuc.edu Tue Apr 15 11:10:03 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Apr 15 11:10:03 2003 Subject: [llvm-commits] CVS: llvm/lib/AsmParser/llvmAsmParser.y Message-ID: <200304151609.LAA12839@apoc.cs.uiuc.edu> Changes in directory llvm/lib/AsmParser: llvmAsmParser.y updated: 1.102 -> 1.103 --- Log message: Fix bug: Assember2003-04-15-ConstantInitAssertion.llx --- Diffs of the changes: Index: llvm/lib/AsmParser/llvmAsmParser.y diff -u llvm/lib/AsmParser/llvmAsmParser.y:1.102 llvm/lib/AsmParser/llvmAsmParser.y:1.103 --- llvm/lib/AsmParser/llvmAsmParser.y:1.102 Mon Mar 3 17:28:55 2003 +++ llvm/lib/AsmParser/llvmAsmParser.y Tue Apr 15 11:09:31 2003 @@ -919,8 +919,15 @@ if (STy == 0) ThrowException("Cannot make struct constant with type: '" + (*$1)->getDescription() + "'!"); - // FIXME: TODO: Check to see that the constants are compatible with the type - // initializer! + + // Check to ensure that constants are compatible with the type initializer! + for (unsigned i = 0, e = $3->size(); i != e; ++i) + if ((*$3)[i]->getType() != STy->getElementTypes()[i]) + ThrowException("Expected type '" + + STy->getElementTypes()[i]->getDescription() + + "' for element #" + utostr(i) + + " of structure initializer!"); + $$ = ConstantStruct::get(STy, *$3); delete $1; delete $3; } From jstanley at cs.uiuc.edu Tue Apr 15 16:24:01 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Tue Apr 15 16:24:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/Inst/InstManip.cpp InstManip.h Phases.cpp Message-ID: <200304152126.QAA27960@cypher.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/Inst: InstManip.cpp updated: 1.6 -> 1.7 InstManip.h updated: 1.6 -> 1.7 Phases.cpp updated: 1.10 -> 1.11 --- Log message: Load candidate heuristic is implemented, phase 4 being invoked with register contents being passed as a parameter. --- Diffs of the changes: Index: llvm/lib/Reoptimizer/Inst/InstManip.cpp diff -u llvm/lib/Reoptimizer/Inst/InstManip.cpp:1.6 llvm/lib/Reoptimizer/Inst/InstManip.cpp:1.7 --- llvm/lib/Reoptimizer/Inst/InstManip.cpp:1.6 Fri Apr 11 18:57:07 2003 +++ llvm/lib/Reoptimizer/Inst/InstManip.cpp Tue Apr 15 16:26:19 2003 @@ -17,6 +17,31 @@ using std::cerr; using std::endl; +std::ostream& operator<<(std::ostream& ostr, + const InstCandidate& cand) +{ + cand.print(ostr); + return ostr; +} + +void InstCandidate::print(std::ostream& ostr) const +{ + ostr << "InstCandidate {" << endl; + ostr << " type = " + << (m_type == DIRECT ? "DIRECT" : "STACK XFER") + << endl; + ostr << " Instruction dump (address, inst):" << endl; + + for(std::vector >::const_iterator i = + m_insts.begin(), e = m_insts.end(); i != e; ++i) { + ostr << std::hex << " (" << i->first << ", " << std::flush; + sparc_print(i->second); + fflush(stdout); + ostr << ")" << endl; + } + ostr << "}"; +} + void InstManip::printRange(unsigned* start, unsigned* end) const { // Dumps contents (and corresponding disassembly) of memory range given by range @@ -93,9 +118,28 @@ "Unexpected number of instructions in code sequence for 64-bit value -> %destReg"); } +void InstManip::generateAddressCopy(unsigned loadInst, + std::vector& snippet, + TargetRegister reg) const +{ + unsigned destReg = (reg == REG_0) ? R_O0 : R_O1; + unsigned rs1 = RD_FLD(loadInst, INSTR_RS1); + + if(RD_FLD(loadInst, INSTR_I)) { + // Case 1: load is immediate-valued --> reg, imm value add instruction needed + unsigned imm = RD_FLD(loadInst, INSTR_SIMM13); + snippet.push_back(MK_ADD_R_I(destReg, rs1, imm)); + } + else { + // Case 2: load is register-valued --> reg, reg add instruction needed + unsigned rs2 = RD_FLD(loadInst, INSTR_RS2); + snippet.push_back(MK_ADD_R_R(destReg, rs1, rs2)); + } +} + void InstManip::generateCall(uint64_t dest, uint64_t slotBase, - std::vector& snippet) + std::vector& snippet) const { unsigned initSize = snippet.size(); @@ -110,10 +154,22 @@ "Unexpected number of instructions in code sequence for call"); } +void InstManip::generateRestore(std::vector& snippet) const +{ + // restore %o0, 0, %o0 + snippet.push_back(MK_RESTORE(R_O0, R_O0, 0)); +} + +void InstManip::generateSave(std::vector& snippet) const +{ + // save %o0, 0, %o0 + snippet.push_back(MK_SAVE(R_O0, R_O0, 0)); +} + void InstManip::generateBranchAlways(uint64_t dest, uint64_t slotBase, std::vector& snippet, - bool annul) + bool annul) const { unsigned initSize = snippet.size(); @@ -133,25 +189,31 @@ std::vector& candidates) { for(uint64_t currAddr = start; currAddr <= end; currAddr += getInstWidth()) { - unsigned inst = m_pVM->readInstrFrmVm(currAddr); - - cout << "findCandidates processing instruction:\t"; - printInst(m_pVM->readInstrFrmVm(currAddr)); - cout << endl; - InstCandidate cand; if(isCandidateLoad(currAddr, end, cand)) - cerr << "It's a candidate load!" << endl; + candidates.push_back(cand); } } static inline bool isLoadHalfWord(unsigned inst) { - // Returns true if inst is an lduh instruction + // Returns true if inst is an LDUH instruction return RD_FLD(inst, INSTR_OP) == OP_3 && RD_FLD(inst, INSTR_OP3) == OP3_LDUH; } +static inline bool isLoadByte(unsigned inst) +{ + // Returns true if inst is a LDUB instruction + return RD_FLD(inst, INSTR_OP) == OP_3 && + RD_FLD(inst, INSTR_OP3) == OP3_LDUB; +} + +static inline bool isFPRelative(unsigned inst) +{ + return RD_FLD(inst, INSTR_RS1) == R_BP && RD_FLD(inst, INSTR_I) == 1; +} + static inline bool isSTH(unsigned inst) { return RD_FLD(inst, INSTR_OP) == OP_3 && @@ -168,7 +230,7 @@ { // Assumes that inst is a load instruction, and returns the register ID of its // destination operand. - + return RD_FLD(inst, INSTR_RD); } @@ -176,16 +238,80 @@ { // Assumes that inst is a stb/sth instruction, and returns the register ID of its // source operand (by source, we don't mean rs1 or rs2, but rather rd, which specifies - // the register which contains the value being stored) + // the register which contains the value being stored); return RD_FLD(inst, INSTR_RD); } +static inline unsigned getFPOffset(unsigned inst) +{ + assert(isFPRelative(inst) && "Expect instruction to be FP-relative"); + return RD_FLD(inst, INSTR_SIMM13); +} + +bool InstManip::determineSchema(InstCandidate& cand, + uint64_t end, + std::pair& load, + std::pair& store) +{ + // inst1 contains the load instruction (the actual candidate). inst2 contains the + // corresponding store instruction, which is either STB or STH. If STB, take actions + // for schema 1, and if STH, schema 2. + + if(isSTB(store.second)) { + // Schema 1: "direct" pattern + cand.setType(InstCandidate::DIRECT); + cand.push_back(load); + cand.push_back(store); + return true; + } + else { + assert(isSTH(store.second) && "Instruction must be STH"); + + // We have potentially discovered an instance of schema 2, but must search + // more to determine if this is the case. + // + // KIS heuristic concession: The STH given by storeInst *must* be storing to the stack + // in an fp-relative manner; if not, we deny the originating load's candidacy. + + if(isFPRelative(store.second)) { + // Search forward until a LDUB from same stack location (+1) as the STH wrote to + // is encountered. The +1 in specified in the FP offset we're searching for is + // due to the fact that we stored a half-word but are loading a byte. + + if(uint64_t stkLoadAddr = findNextStackLoad(store.first, end, getFPOffset(store.second) + 1)) { + // Last schema-2 search: find the STB instruction that stores from the + // LDUB's destination register. + + unsigned ldubInst = m_pVM->readInstrFrmVm(stkLoadAddr); + uint64_t stbAddr = findNextStore(stkLoadAddr, end, getLoadDest(ldubInst)); + unsigned stbInst; + + if(stbAddr && isSTB((stbInst = m_pVM->readInstrFrmVm(stbAddr)))) { + + // All of the criteria have been met for Schema 2, the "stack transfer" + // pattern. + + cand.setType(InstCandidate::STACK_XFER); + cand.push_back(load); + cand.push_back(store); + cand.push_back(stkLoadAddr, ldubInst); + cand.push_back(stbAddr, stbInst); + return true; + } + } + } + } + + return false; +} + bool InstManip::isCandidateLoad(uint64_t addr, uint64_t end, InstCandidate& cand) { // {{{ Description of heuristic + // A candidate load is the first instruction in a sequence (with an arbitrary number // of instructions in between elements of this sequence) that is a "signature" for the // particular load of a volatile variable which needs to be replaced with a call to an @@ -214,6 +340,7 @@ // The current heurstic catches both of these patterns (designated "direct" and "stack // transfer" respectively), and will be extended as insufficiencies in the heuristic // are revealed. + // }}} // Address of potential candidate load is given by 'addr', maximum search address is @@ -223,34 +350,44 @@ if(isLoadHalfWord(inst)) { // Search forward until a sth/stb from inst's target register is encountered - uint64_t storeAddr = findNextStore(addr, end, getLoadDest(inst)); - if(!storeAddr) - return false; // No store? Can't be a candidate load. - - // If STB, ... If STH, ... + if(uint64_t storeAddr = findNextStore(addr, end, getLoadDest(inst))) { - unsigned storeInst = m_pVM->readInstrFrmVm(storeAddr); - if(isSTH(storeInst)) { - cerr << "Discovered sth: " << endl; - } - else { - // STB instruction - cerr << "Discovered stb: " << endl; + // If STB, take actions for schema 1, otherwise check for schema 2 conditions. + + unsigned storeInst = m_pVM->readInstrFrmVm(storeAddr); + std::pair inst1(addr, inst); + std::pair inst2(storeAddr, storeInst); + + return determineSchema(cand, end, inst1, inst2); } - - printInst(storeInst); - - return true; } return false; } +uint64_t InstManip::findNextStackLoad(uint64_t addr, + uint64_t end, + unsigned fpOffset) +{ + // Sweep the range of addresses starting at addr, up to end, looking for a load byte + // that is loading from [%fp + fpOffset]. Return the first such instance, or 0 is such + // an instance cannot be found. + + for(uint64_t currAddr = addr; currAddr <= end; currAddr += getInstWidth()) { + unsigned inst = m_pVM->readInstrFrmVm(currAddr); + + if(isLoadByte(inst) && isFPRelative(inst) && getFPOffset(inst) == fpOffset) + return currAddr; + } + + return 0; +} + uint64_t InstManip::findNextStore(uint64_t addr, uint64_t end, unsigned srcReg) { - // Sweep the range of addresses starting at addr (up to end) looking for stb or sth + // Sweep the range of addresses starting at addr, up to end, looking for stb or sth // instructions that are storing _from_ 'fromReg'. Return the first such instance, or // 0 if such an instance cannot be found. Index: llvm/lib/Reoptimizer/Inst/InstManip.h diff -u llvm/lib/Reoptimizer/Inst/InstManip.h:1.6 llvm/lib/Reoptimizer/Inst/InstManip.h:1.7 --- llvm/lib/Reoptimizer/Inst/InstManip.h:1.6 Fri Apr 11 18:57:07 2003 +++ llvm/lib/Reoptimizer/Inst/InstManip.h Tue Apr 15 16:26:19 2003 @@ -38,7 +38,7 @@ bool isDirect() const { return m_type == DIRECT; } bool isStackXfer() const { return m_type == STACK_XFER; } - const std::vector >& getInsts() const + std::vector >& getInsts() { return m_insts; } @@ -48,6 +48,18 @@ m_insts.push_back(std::make_pair(addr, inst)); } + void push_back(std::pair& inst) + { + m_insts.push_back(inst); + } + + const std::pair& front() const + { + return m_insts.front(); + } + + void print(std::ostream& ostr) const; + protected: CandType m_type; @@ -55,6 +67,8 @@ std::vector > m_insts; }; +std::ostream& operator<<(std::ostream& ostr, const InstCandidate& cand); + class InstManip { public: @@ -75,18 +89,25 @@ uint64_t skipFunctionHdr(uint64_t addr) const; + void generateAddressCopy(unsigned loadInst, + std::vector& snippet, + TargetRegister reg = REG_0) const; + void generateLoad(uint64_t value, std::vector& snippet, TargetRegister reg = REG_0) const; void generateCall(uint64_t dest, uint64_t slotBase, - std::vector& snippet); + std::vector& snippet) const; + void generateRestore(std::vector& snippet) const; + void generateSave(std::vector& snippet) const; + void generateBranchAlways(uint64_t dest, uint64_t slotBase, std::vector& snippet, - bool annul = true); + bool annul = true) const; void findCandidates(uint64_t start, uint64_t end, @@ -99,11 +120,15 @@ // These are functions so when InstManip is superclassed, they'd become virtual, etc. // In the short term we could use class constants, but this is more clear. - unsigned getNOP() const { return 0x01000000; } - unsigned getGenLoadSize() const { return 6; } - unsigned getGenCallSize() const { return 2; } - unsigned getGenBranchAlwaysSize() const { return 2; } - unsigned getInstWidth() const { return 4; } + unsigned getNOP() const { return NOP_INST; } + unsigned getGenLoadSize() const { return 6; } + unsigned getGenCallSize() const { return 2; } + unsigned getGenBranchAlwaysSize() const { return 2; } + unsigned getGenSaveSize() const { return 1; } + unsigned getGenRestoreSize() const { return 1; } + unsigned getInstWidth() const { return 4; } + + inline unsigned getAddressCopySize(unsigned loadInst) const; private: InstManip() {} @@ -112,9 +137,18 @@ uint64_t end, InstCandidate& cand); + bool determineSchema(InstCandidate& cand, + uint64_t end, + std::pair& load, + std::pair& store); + uint64_t findNextStore(uint64_t addr, uint64_t end, unsigned srcReg); + + uint64_t findNextStackLoad(uint64_t addr, + uint64_t end, + unsigned fpOffset); // Branch-always (annul bit high) instruction base (i.e. address not filled in yet) static const unsigned BRANCH_ALWAYS_BASE = 0x30480000; @@ -163,5 +197,17 @@ { return ::isBranchInstr(inst); } + +unsigned InstManip::getAddressCopySize(unsigned loadInst) const +{ + // Determine the number of instructions required to load the address value used by the + // load instruction into some register. + + // Case 1: load is immediate-valued --> add-immediate instruction needed, size is 1 inst + // Case 2: load is register-valued --> add-registers instruction needed, size is 1 inst + + return 1; +} + #endif // _INCLUDED_INSTMANIP_H Index: llvm/lib/Reoptimizer/Inst/Phases.cpp diff -u llvm/lib/Reoptimizer/Inst/Phases.cpp:1.10 llvm/lib/Reoptimizer/Inst/Phases.cpp:1.11 --- llvm/lib/Reoptimizer/Inst/Phases.cpp:1.10 Fri Apr 11 18:57:07 2003 +++ llvm/lib/Reoptimizer/Inst/Phases.cpp Tue Apr 15 16:26:19 2003 @@ -12,15 +12,21 @@ // // 2. For each function F (only in text segment preferably), write code to call phase 3. // -// 2a. Replace the first instruction in F with a branch to a new slot in the -// dummy function. +// 2a. Replace the first (replacable) instruction in F with a branch to a new +// slot (annulling bit should specify *not* to execute the branch delay slot) in +// the dummy function. +// +// 2b. In the new slot, write the contents of the phase 2 slot: +// +------------------------------+ +// | load parameter for phase 3 | +// | call to phase 3 | +// | nop | +// | branch back to orig code | +// | nop | +// +------------------------------+ +// where the parameter to phase 3 is a pointer the heap-allocated Phase3Info +// instance. // -// 2b. At the new slot write the call to phase 3, passing it a pointer to an -// info structure which contains the original (replaced) instruction, the -// address range of the function, etc. -// -// 2c. At the end of the new slot write the direct branch back to the original -// code. // // PHASE 3: // @@ -32,8 +38,19 @@ // 2. Analyze the function and determine the load-volatile candidates. // // 3. For each load-volatile candidate, -// -// 3a. +// 3a. Obtain a new slot in the dummy function. +// 3b. Replace the load candidate with branch to slot. +// 3c. In the new slot, write the contents of the phase 3 slot: +// +---------------------------------------+ +// | save registers | +// | copy load-src addr to param1 register | +// | load p4 struct ptr to param2 register | +// | call to phase 4 | +// | nop | +// | restore registers | +// | branch back to orig code | +// | nop | +// +---------------------------------------+ // // 4. Deallocate the slot that originated this invocation. // @@ -66,11 +83,13 @@ unsigned origInst, uint64_t replaceAddr, uint64_t slotDescriptor, + unsigned slotSize, TraceCache* pTraceCache): m_addrRange(addressRange), m_origInst(origInst), m_replaceAddr(replaceAddr), m_slotDescriptor(slotDescriptor), + m_slotSize(slotSize), m_pTraceCache(pTraceCache) { } @@ -89,7 +108,8 @@ uint64_t getEndAddr() const { return m_addrRange.second; } uint64_t getOrigInst() const { return m_origInst; } uint64_t getReplaceAddr() const { return m_replaceAddr; } - uint64_t getSlot() const { return m_slotDescriptor; } + uint64_t getSlot() const { return m_slotDescriptor; } + uint64_t getSlotSize() const { return m_slotSize; } TraceCache* getTraceCache() { return m_pTraceCache; } private: @@ -99,10 +119,40 @@ unsigned m_origInst; // Instruction replaced by phase 2 uint64_t m_replaceAddr; // Address at which to restore original inst uint64_t m_slotDescriptor; // Slot created by phase 2 + unsigned m_slotSize; // Size of slot created by phase 2 TraceCache* m_pTraceCache; // TraceCache instance used by phase 2 }; +class Phase4Info +{ + public: + Phase4Info(const InstCandidate& candidate, + uint64_t slotDescriptor, + uint64_t slotSize, + TraceCache* pTraceCache): + m_candidate(candidate), + m_slotDescriptor(slotDescriptor), + m_slotSize(slotSize), + m_pTraceCache(pTraceCache) + { + } + + const InstCandidate& getCandidate() const { return m_candidate; } + uint64_t getSlot() const { return m_slotDescriptor; } + uint64_t getSlotSize() const { return m_slotSize; } + TraceCache* getTraceCache() { return m_pTraceCache; } + + private: + Phase4Info() {} + + InstCandidate m_candidate; // Candidate responsible for this instance's creation + uint64_t m_slotDescriptor; // Slot created by phase 3 + unsigned m_slotSize; // Size of slot created by phase 3 + TraceCache* m_pTraceCache; // TraceCache instance used by phases 2 and 3 +}; + void phase3(Phase3Info* p3info); +void phase4(uint64_t tag, Phase4Info* p4info); // Phase2 is the class that is responsible for effecting the core of the phase 2 // transformation; the global function phase2() is simply an C-linkage interface. @@ -130,16 +180,19 @@ { public: Phase3(Phase3Info* p3info); + ~Phase3(); + void transform(); private: Phase3(): m_instManip(0) {} - uint64_t m_startAddr; - uint64_t m_endAddr; + void processCandidates(vector& candidates); + inline unsigned getSlotSize(InstCandidate&) const; + + Phase3Info* m_pPhase3Info; TraceCache* m_pTraceCache; InstManip m_instManip; - uint64_t m_slotDescriptor; }; @@ -197,21 +250,6 @@ void Phase2::transformFunction(AddressRange& range) { - //////////////// - // 1. Replace the first (replacable) instruction in F with a branch to a new slot - // (annulling bit should specify *not* to execute the branch delay slot) in the dummy - // function. - // - // 2. In the slot, write: - // - // - The code to load the pointer to the heap-allocated Phase3Info instance. - // - // - The call to phase 3 - // - // - The branch back to the location of the replaced instruction (phase 3 will - // replace the instruction at runtime). - // - // Obtain address of first replacable instruction in function and obtain a new slot from // the TraceCache memory manager (i.e., a new slot in the dummy function). @@ -230,7 +268,8 @@ // register, which will be used as a parameter to the phase3 call, b) the call to // phase 3 itself, and c) the direct branch back to the original code. - Phase3Info* p3info = new Phase3Info(range, origInst, repInstAddr, slotBase, m_pTraceCache); + Phase3Info* p3info = new Phase3Info(range, origInst, repInstAddr, + slotBase, getSlotSize(), m_pTraceCache); vector snippet; m_instManip.generateLoad((uint64_t) p3info, snippet); @@ -244,14 +283,8 @@ unsigned Phase2::getSlotSize() const { - // A slot used by phase 2 looks like: - // +------------------------------+ - // | load parameter for phase 3 | - // | call to phase 3 | - // | nop | - // | branch back to orig code | - // | nop | - // +------------------------------+ + // The following sum corresponds to the sizes consumed by the various regions of the + // phase 2 slot. See picture of phase 2 contents for details. return m_instManip.getGenLoadSize() + m_instManip.getGenCallSize() + @@ -263,10 +296,27 @@ void phase3(Phase3Info* p3info) { Phase3 p3(p3info); - p3info = 0; - p3.transform(); +} + +Phase3::Phase3(Phase3Info* p3info): + m_pPhase3Info(p3info), + m_pTraceCache(p3info->getTraceCache()), + m_instManip(p3info->getTraceCache()->getVM()) +{ + cerr << "================ Begin Phase 3 [" << std::hex + << m_pPhase3Info->getStartAddr() << ", " << m_pPhase3Info->getEndAddr() + << "] ================\n"; + + // 1. Replace the original (replaced) instruction at the proper location in the + // original code (thus effectively removing the branch to the slot created by phase 2 + // as well). + + m_pTraceCache->getVM()->writeInstToVM(p3info->getReplaceAddr(), p3info->getOrigInst()); +} +Phase3::~Phase3() +{ // Deallocate the originating slot (i.e. the slot that invoked us). // // NB: Yes, we are, in fact, deallocating a memory segment (i.e., the slot obtained by @@ -275,36 +325,107 @@ // write to it. However, it does indeed pose a problem for multi-threaded codes. A // modification to the general mechanism itself is required to achieve thread-safety. - // (TODO) + cerr << "About to deallocate phase2-created slot" << endl; + + uint64_t slotBase = m_pPhase3Info->getSlot(); + unsigned slotSize = m_pPhase3Info->getSlotSize(); + m_pTraceCache->getMemMgr()->freeTraceMemory(slotBase, slotSize); + + // Deallocate the parameter structure + delete m_pPhase3Info; } -Phase3::Phase3(Phase3Info* p3info): - m_instManip(p3info->getTraceCache()->getVM()) +void Phase3::processCandidates(vector& candidates) { - assert(p3info && "phase3 requires valid Phase3Info ptr"); + // For each load candidate, obtain a new slot and write the phase 3 slot region + // contents into it. See diagram in comments at top of file for more info. - m_startAddr = p3info->getStartAddr(); - m_endAddr = p3info->getEndAddr(); - m_pTraceCache = p3info->getTraceCache(); - m_slotDescriptor = p3info->getSlot(); - - cerr << "================ Begin Phase 3 [" << std::hex - << m_startAddr << ", " << m_endAddr - << "] ================\n"; + for(vector::iterator i = candidates.begin(), e = candidates.end(); i != e; ++i) { + cerr << "Transforming " << *i << endl; - // Restore the replaced instruction to its original location (thus effectively - // removing the branch to the slot created by phase 2 as well) - m_pTraceCache->getVM()->writeInstToVM(p3info->getReplaceAddr(), p3info->getOrigInst()); + uint64_t slotBase = m_pTraceCache->getMemMgr()->getMemory(getSlotSize(*i)); + assert(slotBase && "Unable to obtain memory from MemoryManger instance"); + + // Replace load candidate instruction with a branch to start of slot. + VirtualMem* vm = m_pTraceCache->getVM(); + uint64_t loadAddr = i->front().first; + vm->writeInstToVM(loadAddr, m_instManip.getBranchAlways(slotBase, loadAddr)); + + // Generate a) code to save the registers, b) instruction(s) to store the load + // source address into a phase4 parameter register, c) the load of (the + // pointer-to) the heap-allocated Phase4Info structure into a phase4 parameter + // register, and d) code to call phase 3, restore regs, and branch back to + // original code. + + Phase4Info* p4info = new Phase4Info(*i, slotBase, getSlotSize(*i), m_pTraceCache); + + vector snippet; + m_instManip.generateSave(snippet); + m_instManip.generateAddressCopy(i->front().second, snippet); + m_instManip.generateLoad((uint64_t) p4info, snippet, InstManip::REG_1); + m_instManip.generateCall((uint64_t) &phase4, slotBase, snippet); + m_instManip.generateRestore(snippet); + m_instManip.generateBranchAlways(i->front().first, slotBase, snippet); + + // Dump snippet instructions: + + cerr << "phase4 slot instructions:" << endl; + + for(vector::iterator j = snippet.begin(), k = snippet.end(); j != k; ++j) { + m_instManip.printInst(*j); + cerr << endl; + } - // Deallocate the parameter structure - delete p3info; + // Copy the snippet code into the slot + assert(snippet.size() == getSlotSize(*i) && "Snippet size does not match slot size"); + copySnippetToSlot(snippet, slotBase, vm, &m_instManip); + + // just one candidate for now + break; + } +} + +unsigned Phase3::getSlotSize(InstCandidate& cand) const +{ + // The following sum corresponds to the sizes consumed by the various regions of the + // phase 3 slot. See picture of phase 3 contents for details. + + return m_instManip.getGenSaveSize() + + m_instManip.getAddressCopySize(cand.front().second) + + m_instManip.getGenLoadSize() + + m_instManip.getGenCallSize() + + m_instManip.getGenRestoreSize() + + m_instManip.getGenBranchAlwaysSize(); } void Phase3::transform() { - // Gather up the instruction candidates within the function we to transform. + // 2. Analyze the function and determine the load-volatile candidates... vector candidates; - m_instManip.findCandidates(m_startAddr, m_endAddr, candidates); + m_instManip.findCandidates(m_pPhase3Info->getStartAddr(), + m_pPhase3Info->getEndAddr(), + candidates); + // ...and process them + processCandidates(candidates); cerr << "============================== End Phase 3 ==============================\n"; +} + +//////////////// Phase4 implementation //////////////// + +void phase4(uint64_t tag, Phase4Info* p4info) +{ + cerr << "phase4 invoked!" << endl; + + cerr << "tag is " << std::hex << tag << endl; + + cerr << "inst candidate inside info structure is: " << endl; + cerr << p4info->getCandidate() << endl; + + // (TEMP) For now, restore the candidate load to its original position for debugging + // purposes. + + p4info->getTraceCache()->getVM()->writeInstToVM(p4info->getCandidate().front().first, + p4info->getCandidate().front().second); + delete p4info; } From jstanley at cs.uiuc.edu Tue Apr 15 16:30:02 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Tue Apr 15 16:30:02 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/BinInterface/sparc9.cpp sparcdis.cpp Message-ID: <200304152132.QAA27999@cypher.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/BinInterface: sparc9.cpp updated: 1.4 -> 1.5 sparcdis.cpp updated: 1.8 -> 1.9 --- Log message: Changed print routines, renamed registers properly, etc. --- Diffs of the changes: Index: llvm/lib/Reoptimizer/BinInterface/sparc9.cpp diff -u llvm/lib/Reoptimizer/BinInterface/sparc9.cpp:1.4 llvm/lib/Reoptimizer/BinInterface/sparc9.cpp:1.5 --- llvm/lib/Reoptimizer/BinInterface/sparc9.cpp:1.4 Thu Apr 10 18:12:35 2003 +++ llvm/lib/Reoptimizer/BinInterface/sparc9.cpp Tue Apr 15 16:32:13 2003 @@ -29,9 +29,9 @@ "RGEZ"}; -char * reg_names[32] = { "G0", "G1", "G2", "G3", "G4", "G5", "G6", "G7", - "O0", "O1", "O2", "O3", "O4", "O5", "O6(SP)", "O7", - "L0", "L1", "L2", "L3", "L4", "L5", "L6", "L7", - "I0", "I1", "I2", "I3", "I4", "I5", "I6(FP)", "I7"}; +char * reg_names[32] = { "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", + "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7", + "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", + "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7"}; Index: llvm/lib/Reoptimizer/BinInterface/sparcdis.cpp diff -u llvm/lib/Reoptimizer/BinInterface/sparcdis.cpp:1.8 llvm/lib/Reoptimizer/BinInterface/sparcdis.cpp:1.9 --- llvm/lib/Reoptimizer/BinInterface/sparcdis.cpp:1.8 Thu Apr 10 18:12:35 2003 +++ llvm/lib/Reoptimizer/BinInterface/sparcdis.cpp Tue Apr 15 16:32:13 2003 @@ -11,6 +11,9 @@ // labels instead of registers. And we wish to // ommit RD from the view when we are not explicitly // reading from it) +// +// * 14 Apr 2003: (jstanley) Parameterized print functions by ostream instance, +// fixed typos, corrected operand ordering issue. // // Todo: // * On the instructions that don't read from RD @@ -31,7 +34,7 @@ if (labelrs1) printf("l%d", labelrs1); else - printf("%s", reg_names[RD_FLD(instr, INSTR_RS1)]); + printf("%%%s", reg_names[RD_FLD(instr, INSTR_RS1)]); } void sparc_printop_rs2(unsigned instr, int labelrs2) @@ -39,7 +42,7 @@ if (labelrs2) printf("l%d", labelrs2); else - printf("%s", reg_names[RD_FLD(instr, INSTR_RS2)]); + printf("%%%s", reg_names[RD_FLD(instr, INSTR_RS2)]); } void sparc_printop_rrd(unsigned instr, int labelrrd) @@ -47,7 +50,7 @@ if (labelrrd) printf("l%d", labelrrd); else - printf("%s", reg_names[RD_FLD(instr, INSTR_RD)]); + printf("%%%s", reg_names[RD_FLD(instr, INSTR_RD)]); } void sparc_printbr(unsigned instr, bool labels, int labelrs1, int labelrs2, int labelrd, int labelccf) @@ -58,10 +61,10 @@ else if (RD_FLD(instr, INSTR_OP2)==OP2_SETHI) { if (RD_FLD(instr, INSTR_RD) == 0) - printf("NOP"); + printf("nop"); else { - printf("SETHI %%hi(%08X), ", RD_FLD(instr, INSTR_IMM22) << 10); + printf("sethi %%hi(%08X), ", RD_FLD(instr, INSTR_IMM22) << 10); sparc_printop_rrd(instr, labelrd); } } @@ -102,19 +105,20 @@ if (RD_FLD(instr, INSTR_I)==0) { printf("%s ", basename); - if (!labels) - printf("%s, ", reg_names[RD_FLD(instr, INSTR_RD)]); sparc_printop_rs1(instr, labelrs1); printf(" ,"); sparc_printop_rs2(instr, labelrs2); + printf(" ,"); + if (!labels) + printf("%%%s", reg_names[RD_FLD(instr, INSTR_RD)]); } else { printf("%s ", basename); - if (!labels) - printf("%s, ", reg_names[RD_FLD(instr, INSTR_RD)]); sparc_printop_rs1(instr, labelrs1); - printf(" , %d", SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13))); + printf(" , %d, ", SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13))); + if (!labels) + printf("%%%s", reg_names[RD_FLD(instr, INSTR_RD)]); } } @@ -127,12 +131,14 @@ if (RD_FLD(instr, INSTR_I)==0) { printf("%s%d ", (RD_FLD(instr, INSTR_X)==0 ? 32 : 64)); - if (!labels) - printf("%s, ", reg_names[RD_FLD(instr, INSTR_RD)]); sparc_printop_rs1(instr, labelrs1); printf(", "); sparc_printop_rs2(instr, labelrs2); + printf(", "); + + if (!labels) + printf("%%%s", reg_names[RD_FLD(instr, INSTR_RD)]); } else { @@ -144,7 +150,7 @@ ? RD_FLD(instr, INSTR_SHCNT32) : RD_FLD(instr, INSTR_SHCNT64))); if (!labels) - printf("%s", reg_names[RD_FLD(instr, INSTR_RD)]); + printf("%%%s", reg_names[RD_FLD(instr, INSTR_RD)]); } } @@ -250,153 +256,154 @@ printf("mov%s(%s) ", icond_names[RD_FLD(instr, INSTR_COND_L)], cc_names[(RD_FLD(instr, INSTR_CC2) << 2) | (RD_FLD(instr, INSTR_MOV_CC1) << 1) | RD_FLD(instr, INSTR_MOV_CC0)]); - if (!labels) - printf("%s, ", reg_names[RD_FLD(instr, INSTR_RD)]); - if (RD_FLD(instr, INSTR_I)==0) // RS2 sparc_printop_rs2(instr, labelrs2); else printf("%d", SIGN_EXTEND(RD_FLD(instr, INSTR_SIMM11), 11)); + printf(", "); + + if (!labels) + printf("%%%s", reg_names[RD_FLD(instr, INSTR_RD)]); return; } case OP3_ADD: - sparc_printalu("ADD", instr, labels, + sparc_printalu("add", instr, labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_ADDcc: - sparc_printalu("ADDcc", instr, labels, + sparc_printalu("addcc", instr, labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_ADDC: - sparc_printalu("ADDC", instr, labels, + sparc_printalu("addc", instr, labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_ADDCcc: - sparc_printalu("ADDCcc", instr, labels, + sparc_printalu("addccc", instr, labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_AND: - sparc_printalu("AND", instr, labels, + sparc_printalu("and", instr, labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_ANDcc: - sparc_printalu("ANDcc", instr, labels, + sparc_printalu("andcc", instr, labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_OR: - sparc_printalu("OR", instr, labels, + sparc_printalu("or", instr, labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_ORcc: - sparc_printalu("ORcc", instr, labels, + sparc_printalu("orcc", instr, labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_XOR: - sparc_printalu("XOR", instr, labels, + sparc_printalu("xor", instr, labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_XORcc: - sparc_printalu("XORcc", instr, labels, + sparc_printalu("xorcc", instr, labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_SUB: - sparc_printalu("SUB", instr, labels, + sparc_printalu("sub", instr, labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_SUBcc: - sparc_printalu("SUBcc", instr, labels, + sparc_printalu("subcc", instr, labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_ANDN: - sparc_printalu("ANDN", instr, labels, + sparc_printalu("andn", instr, labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_ANDNcc: - sparc_printalu("ANDNcc", instr, labels, + sparc_printalu("andncc", instr, labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_ORN: - sparc_printalu("ORN", instr, labels, + sparc_printalu("orn", instr, labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_ORNcc: - sparc_printalu("ORNcc", instr, labels, + sparc_printalu("orncc", instr, labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_XNOR: - sparc_printalu("XNOR", instr, labels, + sparc_printalu("xnor", instr, labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_XNORcc: - sparc_printalu("XNORcc", instr, labels, + sparc_printalu("xnorcc", instr, labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_SUBC: - sparc_printalu("SUBC", instr, labels, + sparc_printalu("subc", instr, labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_SUBCcc: - sparc_printalu("SUBCcc", instr, labels, + sparc_printalu("subccc", instr, labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_MULX: - sparc_printalu("MULX", instr, labels, + sparc_printalu("mulx", instr, labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_SDIVX: - sparc_printalu("SDIVX", instr, labels, + sparc_printalu("sdivx", instr, labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_UDIVX: - sparc_printalu("UDIVX", instr, labels, + sparc_printalu("udivx", instr, labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_SLL: - sparc_printshf("SLL",instr, labels, + sparc_printshf("sll",instr, labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_SRL: - sparc_printshf("SRL",instr, labels, + sparc_printshf("srl",instr, labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_SRA: - sparc_printshf("SRA",instr, labels, + sparc_printshf("sra",instr, labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_DONERETRY: { if (RD_FLD(instr, INSTR_FCN)==FCN_DONE) - printf("DONE"); + printf("done"); else if (RD_FLD(instr, INSTR_FCN)==FCN_RETRY) - printf("RETRY"); + printf("retry"); return; } @@ -404,9 +411,9 @@ { unsigned fop_n =RD_FLD(instr, INSTR_OPF) &~ OPF_MASK_ON; if (fop_n==OPF_FCMPn) - printf("FCMP"); + printf("fcmp"); else if (fop_n==OPF_FCMPEn) - printf("FCMPE"); + printf("fcmpe"); return; } @@ -441,7 +448,7 @@ return; case OP3_POPC: - printf("POPC ????"); + printf("popc ????"); return; case OP3_RETURN: @@ -510,26 +517,26 @@ { if (RD_FLD(instr, INSTR_I)==0) { - printf("%s ", basename); - if (!labels) - { - sparc_printop_rrd(instr, labelrd); - printf(", "); - } + printf("%s [", basename); + sparc_printop_rs1(instr, labelrs1); - printf("+"); + printf(" + "); sparc_printop_rs2(instr, labelrs2); + printf("], "); + + if (!labels) + sparc_printop_rrd(instr, labelrd); } else { - printf("%s ", basename); + printf("%s [", basename); + + sparc_printop_rs1(instr, labelrs1); + printf(" + %d", SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13))); + printf("], "); + if (!labels) - { sparc_printop_rrd(instr, labelrd); - printf(", "); - } - sparc_printop_rs1(instr, labelrs1); - printf("+%d", SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13))); } } @@ -540,19 +547,20 @@ { printf("%s ", basename); sparc_printop_rrd(instr, labelrd); - printf(", "); + printf(", ["); sparc_printop_rs1(instr, labelrs1); - printf("+"); + printf(" + "); sparc_printop_rs2(instr, labelrs2); - + printf("]"); } else { printf("%s ", basename); sparc_printop_rrd(instr, labelrd); - printf(", "); + printf(", ["); sparc_printop_rs1(instr, labelrs1); - printf("+%d", SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13))); + printf(" + %d", SIGN_EXTEND13(RD_FLD(instr, INSTR_SIMM13))); + printf("]"); } } void sparc_print3(unsigned instr, bool labels, int labelrs1, int labelrs2, @@ -569,62 +577,62 @@ { //OP=OP_3 RD, Rs1 {I=0->RS2, I=1->SIMM13} case OP3_LDSTUB: - sparc_printload("LDSTUB", instr,labels, + sparc_printload("ldstub", instr,labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_STB: - sparc_printstore("STB", instr,labels, + sparc_printstore("stb", instr,labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_STH: - sparc_printstore("STH", instr,labels, + sparc_printstore("sth", instr,labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_STW: - sparc_printstore("STW", instr,labels, + sparc_printstore("stw", instr,labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_STX: - sparc_printstore("STX", instr,labels, + sparc_printstore("stx", instr,labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_LDSB: - sparc_printload("LDSB", instr,labels, + sparc_printload("ldsb", instr,labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_LDSH: - sparc_printload("LDSH", instr,labels, + sparc_printload("ldsh", instr,labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_LDSW: - sparc_printload("LDSW", instr,labels, + sparc_printload("ldsw", instr,labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_LDUB: - sparc_printload("LDUB", instr,labels, + sparc_printload("ldub", instr,labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_LDUH: - sparc_printload("LDUH", instr,labels, + sparc_printload("lduh", instr,labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_LDUW: - sparc_printload("LDUW", instr,labels, + sparc_printload("lduw", instr,labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_LDX: - sparc_printload("LDX", instr,labels, + sparc_printload("ldx", instr,labels, labelrs1, labelrs2, labelrd, labelccf); return; @@ -632,14 +640,14 @@ if (RD_FLD(instr, INSTR_I)==0) { if (!labels) - printf("CASA [r%d] %%%d, r%d, r%d", + printf("casa [r%d] %%%d, r%d, r%d", RD_FLD(instr, INSTR_RS1), RD_FLD(instr, INSTR_IMMASI), RD_FLD(instr, INSTR_RS2), RD_FLD(instr, INSTR_RD)); else - printf("CASA [l%d] %%%d, l%d, l%d", + printf("casa [l%d] %%%d, l%d, l%d", labelrs1, RD_FLD(instr, INSTR_IMMASI), labelrs2, @@ -648,42 +656,42 @@ else { if (!labels) - printf("CASA [r%d] , r%d, r%d", + printf("casa [r%d] , r%d, r%d", RD_FLD(instr, INSTR_RS1), RD_FLD(instr, INSTR_RS2), RD_FLD(instr, INSTR_RD)); else - printf("CASA [l%d] , l%d, l%d", labelrs1, labelrs2, labelrd); + printf("casa [l%d] , l%d, l%d", labelrs1, labelrs2, labelrd); } - sparc_printalu("CASA", instr,labels, + sparc_printalu("casa", instr,labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_CASXA: - sparc_printalu("CASXA", instr,labels, + sparc_printalu("casxa", instr,labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_STFA: - sparc_printalu("STFA",instr,labels, + sparc_printalu("stfa",instr,labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_STDFA: - sparc_printalu("STDFA",instr,labels, + sparc_printalu("stdfa",instr,labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_STQFA: - sparc_printalu("STQFA",instr,labels, + sparc_printalu("stqfa",instr,labels, labelrs1, labelrs2, labelrd, labelccf); return; case OP3_PREFETCH: - printf("PREFETCH ??? "); + printf("prefetch ??? "); return; case OP3_PREFETCHA: - printf("PREFETCHA ??? "); + printf("prefetcha ??? "); return; } @@ -691,8 +699,6 @@ assert(0); } - - void sparc_print_pseudo(unsigned instr, int labelrs1, int labelrs2, int labelrd, int labelccf) { if (RD_FLD(instr,INSTR_OP)==OP_CALL) @@ -708,7 +714,7 @@ void sparc_print(unsigned instr) { if (RD_FLD(instr,INSTR_OP)==OP_CALL) - printf("CALL disp:+%08X", instr & 0x3FFFFFFF); + printf("call disp:+%08X", instr & 0x3FFFFFFF); else if (RD_FLD(instr,INSTR_OP)==OP_BRANCH) sparc_printbr(instr,false,0, 0, 0, 0); else if (RD_FLD(instr,INSTR_OP)==OP_2) @@ -716,6 +722,3 @@ else if (RD_FLD(instr,INSTR_OP)==OP_3) sparc_print3(instr,false,0, 0, 0, 0 ); } - - - From jstanley at cs.uiuc.edu Tue Apr 15 16:31:01 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Tue Apr 15 16:31:01 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Reoptimizer/BinInterface/sparc9.h sparcdis.h Message-ID: <200304152133.QAA28012@cypher.cs.uiuc.edu> Changes in directory llvm/include/llvm/Reoptimizer/BinInterface: sparc9.h updated: 1.11 -> 1.12 sparcdis.h updated: 1.5 -> 1.6 --- Log message: Changed print routines, renamed registers properly, etc. Added more instruction-creation macros. --- Diffs of the changes: Index: llvm/include/llvm/Reoptimizer/BinInterface/sparc9.h diff -u llvm/include/llvm/Reoptimizer/BinInterface/sparc9.h:1.11 llvm/include/llvm/Reoptimizer/BinInterface/sparc9.h:1.12 --- llvm/include/llvm/Reoptimizer/BinInterface/sparc9.h:1.11 Thu Apr 10 15:32:49 2003 +++ llvm/include/llvm/Reoptimizer/BinInterface/sparc9.h Tue Apr 15 16:32:53 2003 @@ -395,6 +395,15 @@ MK_FLD(INSTR_I, 1) | \ MK_FLD(INSTR_OP3, OP3_ADD)) +// Add a register to a register +#define MK_ADD_R_R(dreg, sreg1, sreg2) \ + (MK_FLD(INSTR_OP, OP_2) | \ + MK_FLD(INSTR_RD, dreg) | \ + MK_FLD(INSTR_OP3, OP3_ADD) | \ + MK_FLD(INSTR_RS1, sreg1) | \ + MK_FLD(INSTR_I, 0) | \ + MK_FLD(INSTR_RS2, sreg2)) + // Construct immediate-valued logical operation #define MK_LOGIC_IMM(op3, dreg, sreg, imm) \ @@ -425,7 +434,7 @@ // Construct S{LL,RL,RA}X shift instruction. -#define MK_SHIFTX(op3, dreg, sreg, shcnt) \ +#define MK_SHIFTX(op3, dreg, sreg, shcnt) \ (MK_FLD(INSTR_OP, OP_2) | \ MK_FLD(INSTR_RD, dreg) | \ MK_FLD(INSTR_OP3, op3) | \ @@ -433,3 +442,21 @@ MK_FLD(INSTR_I, 1) | \ MK_FLD(INSTR_X, 1) | \ MK_FLD(INSTR_SHCNT64, shcnt)) + +// Construct save instruction + +#define MK_SAVE(dreg, sreg, imm) \ + (MK_FLD(INSTR_OP, OP_2) | \ + MK_FLD(INSTR_RD, dreg) | \ + MK_FLD(INSTR_OP3, OP3_SAVE) | \ + MK_FLD(INSTR_RS1, sreg) | \ + MK_FLD(INSTR_I, 1) | \ + MK_FLD(INSTR_SIMM13, imm)) + +#define MK_RESTORE(dreg, sreg, imm) \ + (MK_FLD(INSTR_OP, OP_2) | \ + MK_FLD(INSTR_RD, dreg) | \ + MK_FLD(INSTR_OP3, OP3_RESTORE) | \ + MK_FLD(INSTR_RS1, sreg) | \ + MK_FLD(INSTR_I, 1) | \ + MK_FLD(INSTR_SIMM13, imm)) Index: llvm/include/llvm/Reoptimizer/BinInterface/sparcdis.h diff -u llvm/include/llvm/Reoptimizer/BinInterface/sparcdis.h:1.5 llvm/include/llvm/Reoptimizer/BinInterface/sparcdis.h:1.6 --- llvm/include/llvm/Reoptimizer/BinInterface/sparcdis.h:1.5 Sun Dec 15 05:07:46 2002 +++ llvm/include/llvm/Reoptimizer/BinInterface/sparcdis.h Tue Apr 15 16:32:53 2003 @@ -1,36 +1,35 @@ -//***************************************************************************** -// SPARC Instruction Disassembler -// -// Disassembler API Header -// -// * Initial implementation -// * Added support for MOVcc (somehow I missed it?!) -// * Added support for pseudo-disassembly -// ( In the print routine for bin-interface we want -// to be able to print the internal SSA form with -// labels instead of registers. And we wish to -// ommit RD from the view when we are not explicitly -// reading from it) -// -// Todo: -// * On the instructions that don't read from RD -// do not print the label field (we get l-1 when we print) -// -// 2002 Cameron Buschardt -//***************************************************************************** - -#ifndef __SPARCDIS__ -#define __SPARCDIS__ -// Conventional Disassembly. Prints instruction (no newline) -void sparc_print(unsigned instr); - -// Pseudo disasm -// uses the integers in labelrs1, labelrs2, labelrd, and labelccf as -// gen labels for the parameter sources -// instead of printing rxx for rs1, it will print l__labelrs1__ -void sparc_print_pseudo(unsigned instr, int labelrs1, int labelrs2, int labelrd, int labelccf); - - -#endif - - +//***************************************************************************** +// SPARC Instruction Disassembler +// +// Disassembler API Header +// +// * Initial implementation +// * Added support for MOVcc (somehow I missed it?!) +// * Added support for pseudo-disassembly +// ( In the print routine for bin-interface we want +// to be able to print the internal SSA form with +// labels instead of registers. And we wish to +// ommit RD from the view when we are not explicitly +// reading from it) +// +// Todo: +// * On the instructions that don't read from RD +// do not print the label field (we get l-1 when we print) +// +// 2002 Cameron Buschardt +//***************************************************************************** + +#ifndef __SPARCDIS__ +#define __SPARCDIS__ + + +// Conventional Disassembly. Prints instruction (no newline) +void sparc_print(unsigned instr); + +// Pseudo disasm +// uses the integers in labelrs1, labelrs2, labelrd, and labelccf as +// gen labels for the parameter sources +// instead of printing rxx for rs1, it will print l__labelrs1__ +void sparc_print_pseudo(unsigned instr, int labelrs1, int labelrs2, int labelrd, int labelccf); + +#endif From jstanley at cs.uiuc.edu Tue Apr 15 16:52:01 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Tue Apr 15 16:52:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/BinInterface/sparcdis.cpp Message-ID: <200304152154.QAA28080@cypher.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/BinInterface: sparcdis.cpp updated: 1.9 -> 1.10 --- Log message: Removed fallacious revision history from file. --- Diffs of the changes: Index: llvm/lib/Reoptimizer/BinInterface/sparcdis.cpp diff -u llvm/lib/Reoptimizer/BinInterface/sparcdis.cpp:1.9 llvm/lib/Reoptimizer/BinInterface/sparcdis.cpp:1.10 --- llvm/lib/Reoptimizer/BinInterface/sparcdis.cpp:1.9 Tue Apr 15 16:32:13 2003 +++ llvm/lib/Reoptimizer/BinInterface/sparcdis.cpp Tue Apr 15 16:54:37 2003 @@ -12,9 +12,6 @@ // ommit RD from the view when we are not explicitly // reading from it) // -// * 14 Apr 2003: (jstanley) Parameterized print functions by ostream instance, -// fixed typos, corrected operand ordering issue. -// // Todo: // * On the instructions that don't read from RD // do not print the label field (we get l-1 when we print) From lattner at cs.uiuc.edu Wed Apr 16 12:35:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Apr 16 12:35:01 2003 Subject: [llvm-commits] CVS: llvm/tools/gccas/gccas.cpp Message-ID: <200304161734.MAA20281@apoc.cs.uiuc.edu> Changes in directory llvm/tools/gccas: gccas.cpp updated: 1.54 -> 1.55 --- Log message: Namespacify command line options --- Diffs of the changes: Index: llvm/tools/gccas/gccas.cpp diff -u llvm/tools/gccas/gccas.cpp:1.54 llvm/tools/gccas/gccas.cpp:1.55 --- llvm/tools/gccas/gccas.cpp:1.54 Sun Nov 3 06:41:50 2002 +++ llvm/tools/gccas/gccas.cpp Wed Apr 16 12:34:29 2003 @@ -23,23 +23,26 @@ #include using std::cerr; -// FIXME: This should eventually be parameterized... -static TargetData TD("opt target"); +namespace { + // FIXME: This should eventually be parameterized... + TargetData TD("gccas target"); -static cl::opt -InputFilename(cl::Positional, cl::desc(""), cl::Required); + cl::opt + InputFilename(cl::Positional, cl::desc(""),cl::Required); -static cl::opt -OutputFilename("o", cl::desc("Override output filename"), - cl::value_desc("filename")); + cl::opt + OutputFilename("o", cl::desc("Override output filename"), + cl::value_desc("filename")); -static cl::opt -RunNPasses("stopAfterNPasses", - cl::desc("Only run the first N passes of gccas"), cl::Hidden, - cl::value_desc("# passes")); + cl::opt + RunNPasses("stopAfterNPasses", + cl::desc("Only run the first N passes of gccas"), cl::Hidden, + cl::value_desc("# passes")); -static cl::opt -Verify("verify", cl::desc("Verify each pass result")); + cl::opt + Verify("verify", cl::desc("Verify each pass result")); + +} static inline void addPass(PassManager &PM, Pass *P) { From lattner at cs.uiuc.edu Wed Apr 16 12:42:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Apr 16 12:42:01 2003 Subject: [llvm-commits] CVS: llvm/tools/gccas/gccas.cpp Message-ID: <200304161741.MAA20393@apoc.cs.uiuc.edu> Changes in directory llvm/tools/gccas: gccas.cpp updated: 1.55 -> 1.56 --- Log message: * Get rid of using declaration * Add two compatibility options to work better with new GCC frontend --- Diffs of the changes: Index: llvm/tools/gccas/gccas.cpp diff -u llvm/tools/gccas/gccas.cpp:1.55 llvm/tools/gccas/gccas.cpp:1.56 --- llvm/tools/gccas/gccas.cpp:1.55 Wed Apr 16 12:34:29 2003 +++ llvm/tools/gccas/gccas.cpp Wed Apr 16 12:41:08 2003 @@ -21,7 +21,6 @@ #include "Support/Signals.h" #include #include -using std::cerr; namespace { // FIXME: This should eventually be parameterized... @@ -42,6 +41,12 @@ cl::opt Verify("verify", cl::desc("Verify each pass result")); + + cl::opt // Be compatible with what GCC expects + QOption("Q", cl::desc("Compatibility option (ignored)"), + cl::Hidden, cl::Prefix); + cl::opt + PrintVersion("V", cl::desc("Print GCCAS version number"), cl::Hidden); } @@ -103,12 +108,12 @@ // Parse the file now... M.reset(ParseAssemblyFile(InputFilename)); } catch (const ParseException &E) { - cerr << argv[0] << ": " << E.getMessage() << "\n"; + std::cerr << argv[0] << ": " << E.getMessage() << "\n"; return 1; } if (M.get() == 0) { - cerr << argv[0] << ": assembly didn't read correctly.\n"; + std::cerr << argv[0] << ": assembly didn't read correctly.\n"; return 1; } @@ -125,12 +130,15 @@ std::ofstream Out(OutputFilename.c_str(), std::ios::out); if (!Out.good()) { - cerr << argv[0] << ": error opening " << OutputFilename << "!\n"; + std::cerr << argv[0] << ": error opening " << OutputFilename << "!\n"; return 1; } // Make sure that the Out file gets unlink'd from the disk if we get a SIGINT RemoveFileOnSignal(OutputFilename); + + if (PrintVersion) + std::cerr << "LLVM GCCAS version xx\n"; /* For GNU compatibility */ // In addition to just parsing the input from GCC, we also want to spiff it up // a little bit. Do this now. From lattner at cs.uiuc.edu Wed Apr 16 12:50:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Apr 16 12:50:01 2003 Subject: [llvm-commits] CVS: llvm/tools/gccas/gccas.cpp Message-ID: <200304161749.MAA20464@apoc.cs.uiuc.edu> Changes in directory llvm/tools/gccas: gccas.cpp updated: 1.56 -> 1.57 --- Log message: Improve compatibility with system AS further by allowing input from stdin --- Diffs of the changes: Index: llvm/tools/gccas/gccas.cpp diff -u llvm/tools/gccas/gccas.cpp:1.56 llvm/tools/gccas/gccas.cpp:1.57 --- llvm/tools/gccas/gccas.cpp:1.56 Wed Apr 16 12:41:08 2003 +++ llvm/tools/gccas/gccas.cpp Wed Apr 16 12:49:18 2003 @@ -27,7 +27,7 @@ TargetData TD("gccas target"); cl::opt - InputFilename(cl::Positional, cl::desc(""),cl::Required); + InputFilename(cl::Positional,cl::desc(""),cl::init("-")); cl::opt OutputFilename("o", cl::desc("Override output filename"), @@ -116,29 +116,41 @@ std::cerr << argv[0] << ": assembly didn't read correctly.\n"; return 1; } - + + std::ostream *Out = 0; if (OutputFilename == "") { // Didn't specify an output filename? - std::string IFN = InputFilename; - int Len = IFN.length(); - if (IFN[Len-2] == '.' && IFN[Len-1] == 's') { // Source ends in .s? - OutputFilename = std::string(IFN.begin(), IFN.end()-2); + if (InputFilename == "-") { + OutputFilename = "-"; } else { - OutputFilename = IFN; // Append a .o to it + std::string IFN = InputFilename; + int Len = IFN.length(); + if (IFN[Len-2] == '.' && IFN[Len-1] == 's') { // Source ends in .s? + OutputFilename = std::string(IFN.begin(), IFN.end()-2); + } else { + OutputFilename = IFN; // Append a .o to it + } + OutputFilename += ".o"; } - OutputFilename += ".o"; } - std::ofstream Out(OutputFilename.c_str(), std::ios::out); - if (!Out.good()) { + if (OutputFilename == "-") + Out = &std::cout; + else { + Out = new std::ofstream(OutputFilename.c_str(), std::ios::out); + + // Make sure that the Out file gets unlink'd from the disk if we get a + // signal + RemoveFileOnSignal(OutputFilename); + } + + + if (!Out->good()) { std::cerr << argv[0] << ": error opening " << OutputFilename << "!\n"; return 1; } - // Make sure that the Out file gets unlink'd from the disk if we get a SIGINT - RemoveFileOnSignal(OutputFilename); - - if (PrintVersion) - std::cerr << "LLVM GCCAS version xx\n"; /* For GNU compatibility */ + if (PrintVersion) /* For GNU compatibility */ + std::cerr << "LLVM GCCAS version xx\n" << std::flush; // In addition to just parsing the input from GCC, we also want to spiff it up // a little bit. Do this now. @@ -151,9 +163,11 @@ AddConfiguredTransformationPasses(Passes); // Write bytecode to file... - Passes.add(new WriteBytecodePass(&Out)); + Passes.add(new WriteBytecodePass(Out)); // Run our queue of passes all at once now, efficiently. Passes.run(*M.get()); + + if (Out != &std::cout) delete Out; return 0; } From lattner at cs.uiuc.edu Wed Apr 16 13:15:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Apr 16 13:15:01 2003 Subject: [llvm-commits] CVS: llvm/lib/AsmParser/llvmAsmParser.y Message-ID: <200304161814.NAA21485@apoc.cs.uiuc.edu> Changes in directory llvm/lib/AsmParser: llvmAsmParser.y updated: 1.103 -> 1.104 --- Log message: Don't allow declaring an external internal variable --- Diffs of the changes: Index: llvm/lib/AsmParser/llvmAsmParser.y diff -u llvm/lib/AsmParser/llvmAsmParser.y:1.103 llvm/lib/AsmParser/llvmAsmParser.y:1.104 --- llvm/lib/AsmParser/llvmAsmParser.y:1.103 Tue Apr 15 11:09:31 2003 +++ llvm/lib/AsmParser/llvmAsmParser.y Wed Apr 16 13:13:57 2003 @@ -522,6 +522,8 @@ EGV->setInitializer(GV->getInitializer()); if (GV->isConstant()) EGV->setConstant(true); + if (GV->hasInternalLinkage()) + EGV->setInternalLinkage(true); delete GV; // Destroy the duplicate! return true; // They are equivalent! @@ -1154,10 +1156,10 @@ } } } - | ConstPool OptAssign OptInternal EXTERNAL GlobalType Types { - const Type *Ty = *$6; + | ConstPool OptAssign EXTERNAL GlobalType Types { + const Type *Ty = *$5; // Global declarations appear in Constant Pool - GlobalVariable *GV = new GlobalVariable(Ty, $5, $3); + GlobalVariable *GV = new GlobalVariable(Ty, $4, false); if (!setValueName(GV, $2)) { // If not redefining... CurModule.CurrentModule->getGlobalList().push_back(GV); int Slot = InsertValue(GV, CurModule.Values); @@ -1170,7 +1172,7 @@ (char*)GV->getName().c_str())); } } - delete $6; + delete $5; } | /* empty: end of list */ { }; @@ -1216,23 +1218,23 @@ FuncName : VAR_ID | STRINGCONSTANT; -FunctionHeaderH : OptInternal TypesV FuncName '(' ArgList ')' { - UnEscapeLexed($3); - string FunctionName($3); +FunctionHeaderH : TypesV FuncName '(' ArgList ')' { + UnEscapeLexed($2); + string FunctionName($2); vector ParamTypeList; - if ($5) { // If there are arguments... - for (vector >::iterator I = $5->begin(); - I != $5->end(); ++I) + if ($4) { // If there are arguments... + for (vector >::iterator I = $4->begin(); + I != $4->end(); ++I) ParamTypeList.push_back(I->first->get()); } bool isVarArg = ParamTypeList.size() && ParamTypeList.back() == Type::VoidTy; if (isVarArg) ParamTypeList.pop_back(); - const FunctionType *FT = FunctionType::get(*$2, ParamTypeList, isVarArg); + const FunctionType *FT = FunctionType::get(*$1, ParamTypeList, isVarArg); const PointerType *PFT = PointerType::get(FT); - delete $2; + delete $1; Function *Fn = 0; // Is the function already in symtab? @@ -1242,11 +1244,6 @@ if (!CurMeth.isDeclare && !Fn->isExternal()) ThrowException("Redefinition of function '" + FunctionName + "'!"); - // Make sure that we keep track of the internal marker, even if there was - // a previous "declare". - if ($1) - Fn->setInternalLinkage(true); - // If we found a preexisting function prototype, remove it from the // module, so that we don't get spurious conflicts with global & local // variables. @@ -1258,25 +1255,25 @@ AI->setName(""); } else { // Not already defined? - Fn = new Function(FT, $1, FunctionName); + Fn = new Function(FT, false, FunctionName); InsertValue(Fn, CurModule.Values); - CurModule.DeclareNewGlobalValue(Fn, ValID::create($3)); + CurModule.DeclareNewGlobalValue(Fn, ValID::create($2)); } - free($3); // Free strdup'd memory! + free($2); // Free strdup'd memory! CurMeth.FunctionStart(Fn); // Add all of the arguments we parsed to the function... - if ($5) { // Is null if empty... + if ($4) { // Is null if empty... if (isVarArg) { // Nuke the last entry - assert($5->back().first->get() == Type::VoidTy && $5->back().second == 0&& + assert($4->back().first->get() == Type::VoidTy && $4->back().second == 0&& "Not a varargs marker!"); - delete $5->back().first; - $5->pop_back(); // Delete the last entry + delete $4->back().first; + $4->pop_back(); // Delete the last entry } Function::aiterator ArgIt = Fn->abegin(); - for (vector >::iterator I = $5->begin(); - I != $5->end(); ++I, ++ArgIt) { + for (vector >::iterator I = $4->begin(); + I != $4->end(); ++I, ++ArgIt) { delete I->first; // Delete the typeholder... if (setValueName(ArgIt, I->second)) // Insert arg into symtab... @@ -1285,14 +1282,19 @@ InsertValue(ArgIt); } - delete $5; // We're now done with the argument list + delete $4; // We're now done with the argument list } }; BEGIN : BEGINTOK | '{'; // Allow BEGIN or '{' to start a function -FunctionHeader : FunctionHeaderH BEGIN { +FunctionHeader : OptInternal FunctionHeaderH BEGIN { $$ = CurMeth.CurrentFunction; + + // Make sure that we keep track of the internal marker, even if there was + // a previous "declare". + if ($1) + $$->setInternalLinkage(true); // Resolve circular types before we parse the body of the function. ResolveTypes(CurMeth.LateResolveTypes); From lattner at cs.uiuc.edu Wed Apr 16 15:22:28 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Apr 16 15:22:28 2003 Subject: [llvm-commits] CVS: llvm/lib/VMCore/AsmWriter.cpp Message-ID: <200304162020.PAA27450@apoc.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: AsmWriter.cpp updated: 1.81 -> 1.82 --- Log message: Improve the efficiency and cleanup writing a bit --- Diffs of the changes: Index: llvm/lib/VMCore/AsmWriter.cpp diff -u llvm/lib/VMCore/AsmWriter.cpp:1.81 llvm/lib/VMCore/AsmWriter.cpp:1.82 --- llvm/lib/VMCore/AsmWriter.cpp:1.81 Thu Mar 6 17:23:32 2003 +++ llvm/lib/VMCore/AsmWriter.cpp Wed Apr 16 15:20:02 2003 @@ -804,20 +804,22 @@ bool PrintAllTypes = false; const Type *TheType = Operand->getType(); - for (unsigned i = 1, E = I.getNumOperands(); i != E; ++i) { - Operand = I.getOperand(i); - if (Operand->getType() != TheType) { - PrintAllTypes = true; // We have differing types! Print them all! - break; + // Shift Left & Right print both types even for Ubyte LHS + if (isa(I)) { + PrintAllTypes = true; + } else { + for (unsigned i = 1, E = I.getNumOperands(); i != E; ++i) { + Operand = I.getOperand(i); + if (Operand->getType() != TheType) { + PrintAllTypes = true; // We have differing types! Print them all! + break; + } } } - - // Shift Left & Right print both types even for Ubyte LHS - if (isa(I)) PrintAllTypes = true; - + if (!PrintAllTypes) { Out << " "; - printType(I.getOperand(0)->getType()); + printType(TheType); } for (unsigned i = 0, E = I.getNumOperands(); i != E; ++i) { From lattner at cs.uiuc.edu Wed Apr 16 15:24:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Apr 16 15:24:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/Makefile Message-ID: <200304162023.PAA27503@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms: Makefile updated: 1.20 -> 1.21 --- Log message: Add PRE directory --- Diffs of the changes: Index: llvm/test/Regression/Transforms/Makefile diff -u llvm/test/Regression/Transforms/Makefile:1.20 llvm/test/Regression/Transforms/Makefile:1.21 --- llvm/test/Regression/Transforms/Makefile:1.20 Mon Feb 3 15:31:53 2003 +++ llvm/test/Regression/Transforms/Makefile Wed Apr 16 15:23:42 2003 @@ -16,6 +16,7 @@ LICM \ Mem2Reg \ PiNodeInserter \ + PRE \ LoopPreheaders \ ProfilePaths \ Reassociate \ From lattner at cs.uiuc.edu Wed Apr 16 15:27:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Apr 16 15:27:01 2003 Subject: [llvm-commits] CVS: llvm/utils/vim/llvm.vim Message-ID: <200304162026.PAA27516@apoc.cs.uiuc.edu> Changes in directory llvm/utils/vim: llvm.vim updated: 1.1 -> 1.2 --- Log message: Add new linkage keywords. Spell uninitialized correctly --- Diffs of the changes: Index: llvm/utils/vim/llvm.vim diff -u llvm/utils/vim/llvm.vim:1.1 llvm/utils/vim/llvm.vim:1.2 --- llvm/utils/vim/llvm.vim:1.1 Mon Oct 7 17:54:48 2002 +++ llvm/utils/vim/llvm.vim Wed Apr 16 15:25:57 2003 @@ -26,7 +26,8 @@ syn keyword llvmStatement begin end true false syn keyword llvmStatement declare global constant const -syn keyword llvmStatement internal unititialized external implementation +syn keyword llvmStatement internal uninitialized external implementation +syn keyword llvmStatement linkonce appending syn keyword llvmStatement null to except not "syn match llvmFunction /%[a-zA-Z\$._\-][a-zA-Z\$._\-0-9]*/ From lattner at cs.uiuc.edu Wed Apr 16 15:27:03 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Apr 16 15:27:03 2003 Subject: [llvm-commits] CVS: llvm/utils/emacs/llvm-mode.el Message-ID: <200304162026.PAA27527@apoc.cs.uiuc.edu> Changes in directory llvm/utils/emacs: llvm-mode.el updated: 1.1 -> 1.2 --- Log message: Add missing keyword, add new linkage keywords --- Diffs of the changes: Index: llvm/utils/emacs/llvm-mode.el diff -u llvm/utils/emacs/llvm-mode.el:1.1 llvm/utils/emacs/llvm-mode.el:1.2 --- llvm/utils/emacs/llvm-mode.el:1.1 Tue Oct 8 19:30:20 2002 +++ llvm/utils/emacs/llvm-mode.el Wed Apr 16 15:26:11 2003 @@ -28,7 +28,7 @@ ;; Hex constants '("0x[0-9A-Fa-f]+" . font-lock-preprocessor-face) ;; Keywords - '("begin\\|end\\|true\\|false\\|declare\\|global\\|constant\\|const\\|internal\\|implementation\\|\\.\\.\\.\\|null\\|to\\|except\\|not" . font-lock-keyword-face) + '("begin\\|end\\|true\\|false\\|declare\\|global\\|constant\\|const\\|internal\\|linkonce\\|appending\\|uninitialized\\|implementation\\|\\.\\.\\.\\|null\\|to\\|except\\|not" . font-lock-keyword-face) ;; Types '("void\\|bool\\|sbyte\\|ubyte\\|u?short\\|u?int\\|u?long\\|float\\|double\\|type\\|label\\|opaque" . font-lock-type-face) ;; Arithmetic and Logical Operators From lattner at cs.uiuc.edu Wed Apr 16 15:29:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Apr 16 15:29:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/ExtractFunction.cpp Internalize.cpp MutateStructTypes.cpp Parallelize.cpp PoolAllocate.cpp Message-ID: <200304162028.PAA27585@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: ExtractFunction.cpp updated: 1.1 -> 1.2 Internalize.cpp updated: 1.12 -> 1.13 MutateStructTypes.cpp updated: 1.34 -> 1.35 Parallelize.cpp updated: 1.1 -> 1.2 PoolAllocate.cpp updated: 1.4 -> 1.5 --- Log message: Add new linkage types to support a real frontend --- Diffs of the changes: Index: llvm/lib/Transforms/IPO/ExtractFunction.cpp diff -u llvm/lib/Transforms/IPO/ExtractFunction.cpp:1.1 llvm/lib/Transforms/IPO/ExtractFunction.cpp:1.2 --- llvm/lib/Transforms/IPO/ExtractFunction.cpp:1.1 Tue Nov 19 12:42:55 2002 +++ llvm/lib/Transforms/IPO/ExtractFunction.cpp Wed Apr 16 15:28:39 2003 @@ -16,13 +16,13 @@ } // Make sure our result is globally accessable... - Named->setInternalLinkage(false); + Named->setLinkage(GlobalValue::ExternalLinkage); // Mark all global variables internal for (Module::giterator I = M.gbegin(), E = M.gend(); I != E; ++I) if (!I->isExternal()) { I->setInitializer(0); // Make all variables external - I->setInternalLinkage(false); // Make sure it's not internal + I->setLinkage(GlobalValue::ExternalLinkage); } // All of the functions may be used by global variables or the named @@ -35,7 +35,9 @@ for (Module::iterator I = M.begin(); ; ++I) { if (&*I != Named) { - Function *New = new Function(I->getFunctionType(),false,I->getName()); + Function *New = new Function(I->getFunctionType(), + GlobalValue::ExternalLinkage, + I->getName()); I->setName(""); // Remove Old name // If it's not the named function, delete the body of the function Index: llvm/lib/Transforms/IPO/Internalize.cpp diff -u llvm/lib/Transforms/IPO/Internalize.cpp:1.12 llvm/lib/Transforms/IPO/Internalize.cpp:1.13 --- llvm/lib/Transforms/IPO/Internalize.cpp:1.12 Fri Nov 8 14:34:21 2002 +++ llvm/lib/Transforms/IPO/Internalize.cpp Wed Apr 16 15:28:39 2003 @@ -29,7 +29,7 @@ if (&*I != MainFunc && // Leave the main function external !I->isExternal() && // Function must be defined here !I->hasInternalLinkage()) { // Can't already have internal linkage - I->setInternalLinkage(true); + I->setLinkage(GlobalValue::InternalLinkage); Changed = true; ++NumFunctions; DEBUG(std::cerr << "Internalizing func " << I->getName() << "\n"); @@ -38,7 +38,7 @@ // Mark all global variables with initializers as internal as well... for (Module::giterator I = M.gbegin(), E = M.gend(); I != E; ++I) if (!I->isExternal() && I->hasExternalLinkage()) { - I->setInternalLinkage(true); + I->setLinkage(GlobalValue::InternalLinkage); Changed = true; ++NumGlobals; DEBUG(std::cerr << "Internalizing gvar " << I->getName() << "\n"); Index: llvm/lib/Transforms/IPO/MutateStructTypes.cpp diff -u llvm/lib/Transforms/IPO/MutateStructTypes.cpp:1.34 llvm/lib/Transforms/IPO/MutateStructTypes.cpp:1.35 --- llvm/lib/Transforms/IPO/MutateStructTypes.cpp:1.34 Wed Nov 20 13:32:43 2002 +++ llvm/lib/Transforms/IPO/MutateStructTypes.cpp Wed Apr 16 15:28:39 2003 @@ -250,8 +250,7 @@ cast(ConvertType(I->getFunctionType())); // Create a new function to put stuff into... - Function *NewMeth = new Function(NewMTy, I->hasInternalLinkage(), - I->getName()); + Function *NewMeth = new Function(NewMTy, I->getLinkage(), I->getName()); if (I->hasName()) I->setName("OLD."+I->getName()); Index: llvm/lib/Transforms/IPO/Parallelize.cpp diff -u llvm/lib/Transforms/IPO/Parallelize.cpp:1.1 llvm/lib/Transforms/IPO/Parallelize.cpp:1.2 --- llvm/lib/Transforms/IPO/Parallelize.cpp:1.1 Mon Dec 9 18:43:34 2002 +++ llvm/lib/Transforms/IPO/Parallelize.cpp Wed Apr 16 15:28:39 2003 @@ -137,7 +137,8 @@ DummySyncFunc = new Function(FunctionType::get( Type::VoidTy, std::vector(), /*isVararg*/ false), - /*isInternal*/ false, DummySyncFuncName, &M); + GlobalValue::ExternalLinkage, DummySyncFuncName, + &M); } void Cilkifier::TransformFunc(Function* F, Index: llvm/lib/Transforms/IPO/PoolAllocate.cpp diff -u llvm/lib/Transforms/IPO/PoolAllocate.cpp:1.4 llvm/lib/Transforms/IPO/PoolAllocate.cpp:1.5 --- llvm/lib/Transforms/IPO/PoolAllocate.cpp:1.4 Thu Feb 6 16:03:46 2003 +++ llvm/lib/Transforms/IPO/PoolAllocate.cpp Wed Apr 16 15:28:39 2003 @@ -161,7 +161,8 @@ FunctionType *FuncTy = FunctionType::get(OldFuncTy->getReturnType(), ArgTys, OldFuncTy->isVarArg()); // Create the new function... - Function *New = new Function(FuncTy, true, F.getName(), F.getParent()); + Function *New = new Function(FuncTy, GlobalValue::InternalLinkage, + F.getName(), F.getParent()); // Set the rest of the new arguments names to be PDa and add entries to the // pool descriptors map From lattner at cs.uiuc.edu Wed Apr 16 15:29:03 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Apr 16 15:29:03 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Instrumentation/EmitFunctions.cpp TraceValues.cpp Message-ID: <200304162028.PAA27595@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Instrumentation: EmitFunctions.cpp updated: 1.5 -> 1.6 TraceValues.cpp updated: 1.54 -> 1.55 --- Log message: Add new linkage types to support a real frontend --- Diffs of the changes: Index: llvm/lib/Transforms/Instrumentation/EmitFunctions.cpp diff -u llvm/lib/Transforms/Instrumentation/EmitFunctions.cpp:1.5 llvm/lib/Transforms/Instrumentation/EmitFunctions.cpp:1.6 --- llvm/lib/Transforms/Instrumentation/EmitFunctions.cpp:1.5 Tue Jan 14 16:39:29 2003 +++ llvm/lib/Transforms/Instrumentation/EmitFunctions.cpp Wed Apr 16 15:28:40 2003 @@ -33,7 +33,8 @@ StructType *sttype = StructType::get(vType); ConstantStruct *cstruct = ConstantStruct::get(sttype, vConsts); - GlobalVariable *gb = new GlobalVariable(cstruct->getType(), true, false, + GlobalVariable *gb = new GlobalVariable(cstruct->getType(), true, + GlobalValue::ExternalLinkage, cstruct, "llvmFunctionTable"); M.getGlobalList().push_back(gb); return true; // Always modifies program Index: llvm/lib/Transforms/Instrumentation/TraceValues.cpp diff -u llvm/lib/Transforms/Instrumentation/TraceValues.cpp:1.54 llvm/lib/Transforms/Instrumentation/TraceValues.cpp:1.55 --- llvm/lib/Transforms/Instrumentation/TraceValues.cpp:1.54 Sat Apr 12 22:50:14 2003 +++ llvm/lib/Transforms/Instrumentation/TraceValues.cpp Wed Apr 16 15:28:40 2003 @@ -154,7 +154,8 @@ // Create the global variable and record it in the module // The GV will be renamed to a unique name if needed. - GlobalVariable *GV = new GlobalVariable(Init->getType(), true, true, Init, + GlobalVariable *GV = new GlobalVariable(Init->getType(), true, + GlobalValue::InternalLinkage, Init, "trstr"); M->getGlobalList().push_back(GV); return GV; From lattner at cs.uiuc.edu Wed Apr 16 15:29:04 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Apr 16 15:29:04 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Instrumentation/ProfilePaths/ProfilePaths.cpp Message-ID: <200304162028.PAA27602@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Instrumentation/ProfilePaths: ProfilePaths.cpp updated: 1.25 -> 1.26 --- Log message: Add new linkage types to support a real frontend --- Diffs of the changes: Index: llvm/lib/Transforms/Instrumentation/ProfilePaths/ProfilePaths.cpp diff -u llvm/lib/Transforms/Instrumentation/ProfilePaths/ProfilePaths.cpp:1.25 llvm/lib/Transforms/Instrumentation/ProfilePaths/ProfilePaths.cpp:1.26 --- llvm/lib/Transforms/Instrumentation/ProfilePaths/ProfilePaths.cpp:1.25 Fri Feb 14 14:37:42 2003 +++ llvm/lib/Transforms/Instrumentation/ProfilePaths/ProfilePaths.cpp Wed Apr 16 15:28:42 2003 @@ -183,14 +183,19 @@ for(int xi=0; xigetGlobalList().push_back(threshold); insertedThreshold = true; From lattner at cs.uiuc.edu Wed Apr 16 15:29:05 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Apr 16 15:29:05 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Utils/CloneFunction.cpp CloneModule.cpp Linker.cpp Message-ID: <200304162028.PAA27615@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Utils: CloneFunction.cpp updated: 1.14 -> 1.15 CloneModule.cpp updated: 1.1 -> 1.2 Linker.cpp updated: 1.37 -> 1.38 --- Log message: Add new linkage types to support a real frontend --- Diffs of the changes: Index: llvm/lib/Transforms/Utils/CloneFunction.cpp diff -u llvm/lib/Transforms/Utils/CloneFunction.cpp:1.14 llvm/lib/Transforms/Utils/CloneFunction.cpp:1.15 --- llvm/lib/Transforms/Utils/CloneFunction.cpp:1.14 Wed Nov 20 14:47:41 2002 +++ llvm/lib/Transforms/Utils/CloneFunction.cpp Wed Apr 16 15:28:43 2003 @@ -110,7 +110,7 @@ ArgTypes, F->getFunctionType()->isVarArg()); // Create the new function... - Function *NewF = new Function(FTy, F->hasInternalLinkage(), F->getName()); + Function *NewF = new Function(FTy, F->getLinkage(), F->getName()); // Loop over the arguments, copying the names of the mapped arguments over... Function::aiterator DestI = NewF->abegin(); Index: llvm/lib/Transforms/Utils/CloneModule.cpp diff -u llvm/lib/Transforms/Utils/CloneModule.cpp:1.1 llvm/lib/Transforms/Utils/CloneModule.cpp:1.2 --- llvm/lib/Transforms/Utils/CloneModule.cpp:1.1 Wed Nov 20 14:47:41 2002 +++ llvm/lib/Transforms/Utils/CloneModule.cpp Wed Apr 16 15:28:43 2003 @@ -29,13 +29,14 @@ // don't worry about attributes or initializers, they will come later. // for (Module::const_giterator I = M->gbegin(), E = M->gend(); I != E; ++I) - ValueMap[I] = new GlobalVariable(I->getType()->getElementType(), - false, false, 0, I->getName(), New); + ValueMap[I] = new GlobalVariable(I->getType()->getElementType(), false, + GlobalValue::ExternalLinkage, 0, + I->getName(), New); // Loop over the functions in the module, making external functions as before for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) ValueMap[I]=new Function(cast(I->getType()->getElementType()), - false, I->getName(), New); + GlobalValue::ExternalLinkage, I->getName(), New); // Now that all of the things that global variable initializer can refer to // have been created, loop through and copy the global variable referrers @@ -46,8 +47,7 @@ if (I->hasInitializer()) GV->setInitializer(cast(MapValue(I->getInitializer(), ValueMap))); - if (I->hasInternalLinkage()) - GV->setInternalLinkage(true); + GV->setLinkage(I->getLinkage()); } // Similarly, copy over function bodies now... @@ -65,8 +65,7 @@ CloneFunctionInto(F, I, ValueMap, Returns); } - if (I->hasInternalLinkage()) - F->setInternalLinkage(true); + F->setLinkage(I->getLinkage()); } return New; Index: llvm/lib/Transforms/Utils/Linker.cpp diff -u llvm/lib/Transforms/Utils/Linker.cpp:1.37 llvm/lib/Transforms/Utils/Linker.cpp:1.38 --- llvm/lib/Transforms/Utils/Linker.cpp:1.37 Thu Jan 30 14:53:43 2003 +++ llvm/lib/Transforms/Utils/Linker.cpp Wed Apr 16 15:28:43 2003 @@ -189,42 +189,48 @@ // for (Module::const_giterator I = Src->gbegin(), E = Src->gend(); I != E; ++I){ const GlobalVariable *SGV = I; - Value *V; - - // If the global variable has a name, and that name is already in use in the - // Dest module, make sure that the name is a compatible global variable... - // - if (SGV->hasExternalLinkage() && SGV->hasName() && - (V = ST->lookup(SGV->getType(), SGV->getName())) && - cast(V)->hasExternalLinkage()) { - // The same named thing is a global variable, because the only two things + GlobalVariable *DGV = 0; + if (SGV->hasName()) { + // A same named thing is a global variable, because the only two things // that may be in a module level symbol table are Global Vars and // Functions, and they both have distinct, nonoverlapping, possible types. // - GlobalVariable *DGV = cast(V); + DGV = cast_or_null(ST->lookup(SGV->getType(), + SGV->getName())); + } - // Check to see if the two GV's have the same Const'ness... - if (SGV->isConstant() != DGV->isConstant()) - return Error(Err, "Global Variable Collision on '" + - SGV->getType()->getDescription() + "':%" + SGV->getName() + - " - Global variables differ in const'ness"); + assert(SGV->hasInitializer() || SGV->hasExternalLinkage() && + "Global must either be external or have an initializer!"); - // Okay, everything is cool, remember the mapping... - ValueMap.insert(std::make_pair(SGV, DGV)); - } else { + if (!DGV || DGV->hasInternalLinkage() || SGV->hasInternalLinkage()) { // No linking to be performed, simply create an identical version of the // symbol over in the dest module... the initializer will be filled in // later by LinkGlobalInits... // - GlobalVariable *DGV = - new GlobalVariable(SGV->getType()->getElementType(), SGV->isConstant(), - SGV->hasInternalLinkage(), 0, SGV->getName()); - - // Add the new global to the dest module - Dest->getGlobalList().push_back(DGV); + DGV = new GlobalVariable(SGV->getType()->getElementType(), + SGV->isConstant(), SGV->getLinkage(), /*init*/0, + SGV->getName(), Dest); // Make sure to remember this mapping... ValueMap.insert(std::make_pair(SGV, DGV)); + } else if (SGV->getLinkage() != DGV->getLinkage()) { + return Error(Err, "Global variables named '" + SGV->getName() + + "' have different linkage specifiers!"); + } else if (SGV->hasExternalLinkage() || SGV->hasLinkOnceLinkage() || + SGV->hasAppendingLinkage()) { + // If the global variable has a name, and that name is already in use in + // the Dest module, make sure that the name is a compatible global + // variable... + // + // Check to see if the two GV's have the same Const'ness... + if (SGV->isConstant() != DGV->isConstant()) + return Error(Err, "Global Variable Collision on '" + + SGV->getType()->getDescription() + "':%" + SGV->getName() + + " - Global variables differ in const'ness"); + // Okay, everything is cool, remember the mapping... + ValueMap.insert(std::make_pair(SGV, DGV)); + } else { + assert(0 && "Unknown linkage!"); } } return false; @@ -245,19 +251,28 @@ if (SGV->hasInitializer()) { // Only process initialized GV's // Figure out what the initializer looks like in the dest module... - Constant *DInit = + Constant *SInit = cast(RemapOperand(SGV->getInitializer(), ValueMap, 0)); GlobalVariable *DGV = cast(ValueMap[SGV]); - if (DGV->hasInitializer() && SGV->hasExternalLinkage() && - DGV->hasExternalLinkage()) { - if (DGV->getInitializer() != DInit) - return Error(Err, "Global Variable Collision on '" + - SGV->getType()->getDescription() + "':%" +SGV->getName()+ - " - Global variables have different initializers"); + if (DGV->hasInitializer()) { + assert(SGV->getLinkage() == DGV->getLinkage()); + if (SGV->hasExternalLinkage()) { + if (DGV->getInitializer() != SInit) + return Error(Err, "Global Variable Collision on '" + + SGV->getType()->getDescription() +"':%"+SGV->getName()+ + " - Global variables have different initializers"); + } else if (DGV->hasLinkOnceLinkage()) { + // Nothing is required, mapped values will take the new global + // automatically. + } else if (DGV->hasAppendingLinkage()) { + assert(0 && "Appending linkage unimplemented!"); + } else { + assert(0 && "Unknown linkage!"); + } } else { // Copy the initializer over now... - DGV->setInitializer(DInit); + DGV->setInitializer(SInit); } } } @@ -278,39 +293,42 @@ // for (Module::const_iterator I = Src->begin(), E = Src->end(); I != E; ++I) { const Function *SF = I; // SrcFunction - Value *V; - - // If the function has a name, and that name is already in use in the Dest - // module, make sure that the name is a compatible function... - // - if (SF->hasExternalLinkage() && SF->hasName() && - (V = ST->lookup(SF->getType(), SF->getName())) && - cast(V)->hasExternalLinkage()) { + Function *DF = 0; + if (SF->hasName()) // The same named thing is a Function, because the only two things // that may be in a module level symbol table are Global Vars and // Functions, and they both have distinct, nonoverlapping, possible types. // - Function *DF = cast(V); // DestFunction + DF = cast_or_null(ST->lookup(SF->getType(), SF->getName())); + if (!DF || SF->hasInternalLinkage() || DF->hasInternalLinkage()) { + // Function does not already exist, simply insert an external function + // signature identical to SF into the dest module... + Function *DF = new Function(SF->getFunctionType(), SF->getLinkage(), + SF->getName(), Dest); + + // ... and remember this mapping... + ValueMap.insert(std::make_pair(SF, DF)); + } else if (SF->getLinkage() != DF->getLinkage()) { + return Error(Err, "Functions named '" + SF->getName() + + "' have different linkage specifiers!"); + } else if (SF->getLinkage() == GlobalValue::AppendingLinkage) { + return Error(Err, "Functions named '" + SF->getName() + + "' have appending linkage!"); + } else if (SF->getLinkage() == GlobalValue::ExternalLinkage) { + // If the function has a name, and that name is already in use in the Dest + // module, make sure that the name is a compatible function... + // // Check to make sure the function is not defined in both modules... if (!SF->isExternal() && !DF->isExternal()) return Error(Err, "Function '" + SF->getFunctionType()->getDescription() + "':\"" + SF->getName() + "\" - Function is already defined!"); - + // Otherwise, just remember this mapping... ValueMap.insert(std::make_pair(SF, DF)); - } else { - // Function does not already exist, simply insert an external function - // signature identical to SF into the dest module... - Function *DF = new Function(SF->getFunctionType(), - SF->hasInternalLinkage(), - SF->getName()); - - // Add the function signature to the dest module... - Dest->getFunctionList().push_back(DF); - - // ... and remember this mapping... + } else if (SF->getLinkage() == GlobalValue::LinkOnceLinkage) { + // Completely ignore the source function. ValueMap.insert(std::make_pair(SF, DF)); } } @@ -391,6 +409,7 @@ // DF not external SF external? if (!DF->isExternal()) { + if (DF->hasLinkOnceLinkage()) continue; // No relinkage for link-once! if (Err) *Err = "Function '" + (SF->hasName() ? SF->getName() :std::string("")) + "' body multiply defined!"; From lattner at cs.uiuc.edu Wed Apr 16 15:29:06 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Apr 16 15:29:06 2003 Subject: [llvm-commits] CVS: llvm/lib/VMCore/AsmWriter.cpp Function.cpp Module.cpp Message-ID: <200304162028.PAA27626@apoc.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: AsmWriter.cpp updated: 1.82 -> 1.83 Function.cpp updated: 1.36 -> 1.37 Module.cpp updated: 1.33 -> 1.34 --- Log message: Add new linkage types to support a real frontend --- Diffs of the changes: Index: llvm/lib/VMCore/AsmWriter.cpp diff -u llvm/lib/VMCore/AsmWriter.cpp:1.82 llvm/lib/VMCore/AsmWriter.cpp:1.83 --- llvm/lib/VMCore/AsmWriter.cpp:1.82 Wed Apr 16 15:20:02 2003 +++ llvm/lib/VMCore/AsmWriter.cpp Wed Apr 16 15:28:45 2003 @@ -535,8 +535,15 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) { if (GV->hasName()) Out << "%" << GV->getName() << " = "; - if (GV->hasInternalLinkage()) Out << "internal "; - if (!GV->hasInitializer()) Out << "external "; + if (!GV->hasInitializer()) + Out << "external "; + else + switch (GV->getLinkage()) { + case GlobalValue::InternalLinkage: Out << "internal "; break; + case GlobalValue::LinkOnceLinkage: Out << "linkonce "; break; + case GlobalValue::AppendingLinkage: Out << "appending "; break; + case GlobalValue::ExternalLinkage: break; + } Out << (GV->isConstant() ? "constant " : "global "); printType(GV->getType()->getElementType()); @@ -594,8 +601,18 @@ // void AssemblyWriter::printFunction(const Function *F) { // Print out the return type and name... - Out << "\n" << (F->isExternal() ? "declare " : "") - << (F->hasInternalLinkage() ? "internal " : ""); + Out << "\n"; + + if (F->isExternal()) + Out << "declare "; + else + switch (F->getLinkage()) { + case GlobalValue::InternalLinkage: Out << "internal "; break; + case GlobalValue::LinkOnceLinkage: Out << "linkonce "; break; + case GlobalValue::AppendingLinkage: Out << "appending "; break; + case GlobalValue::ExternalLinkage: break; + } + printType(F->getReturnType()) << " %" << F->getName() << "("; Table.incorporateFunction(F); Index: llvm/lib/VMCore/Function.cpp diff -u llvm/lib/VMCore/Function.cpp:1.36 llvm/lib/VMCore/Function.cpp:1.37 --- llvm/lib/VMCore/Function.cpp:1.36 Wed Nov 20 12:33:41 2002 +++ llvm/lib/VMCore/Function.cpp Wed Apr 16 15:28:45 2003 @@ -77,9 +77,9 @@ // Function Implementation //===----------------------------------------------------------------------===// -Function::Function(const FunctionType *Ty, bool isInternal, +Function::Function(const FunctionType *Ty, LinkageTypes Linkage, const std::string &name, Module *ParentModule) - : GlobalValue(PointerType::get(Ty), Value::FunctionVal, isInternal, name) { + : GlobalValue(PointerType::get(Ty), Value::FunctionVal, Linkage, name) { BasicBlocks.setItemParent(this); BasicBlocks.setParent(this); ArgumentList.setItemParent(this); @@ -154,10 +154,10 @@ // GlobalVariable Implementation //===----------------------------------------------------------------------===// -GlobalVariable::GlobalVariable(const Type *Ty, bool constant, bool isIntern, +GlobalVariable::GlobalVariable(const Type *Ty, bool constant, LinkageTypes Link, Constant *Initializer, const std::string &Name, Module *ParentModule) - : GlobalValue(PointerType::get(Ty), Value::GlobalVariableVal, isIntern, Name), + : GlobalValue(PointerType::get(Ty), Value::GlobalVariableVal, Link, Name), isConstantGlobal(constant) { if (Initializer) Operands.push_back(Use((Value*)Initializer, this)); Index: llvm/lib/VMCore/Module.cpp diff -u llvm/lib/VMCore/Module.cpp:1.33 llvm/lib/VMCore/Module.cpp:1.34 --- llvm/lib/VMCore/Module.cpp:1.33 Wed Nov 20 12:33:41 2002 +++ llvm/lib/VMCore/Module.cpp Wed Apr 16 15:28:45 2003 @@ -17,13 +17,14 @@ Function *ilist_traits::createNode() { FunctionType *FTy = FunctionType::get(Type::VoidTy, std::vector(), false); - Function *Ret = new Function(FTy, false); + Function *Ret = new Function(FTy, GlobalValue::ExternalLinkage); // This should not be garbage monitored. LeakDetector::removeGarbageObject(Ret); return Ret; } GlobalVariable *ilist_traits::createNode() { - GlobalVariable *Ret = new GlobalVariable(Type::IntTy, false, false); + GlobalVariable *Ret = new GlobalVariable(Type::IntTy, false, + GlobalValue::ExternalLinkage); // This should not be garbage monitored. LeakDetector::removeGarbageObject(Ret); return Ret; @@ -87,7 +88,7 @@ if (Value *V = SymTab.lookup(PointerType::get(Ty), Name)) { return cast(V); // Yup, got it } else { // Nope, add one - Function *New = new Function(Ty, false, Name); + Function *New = new Function(Ty, GlobalVariable::ExternalLinkage, Name); FunctionList.push_back(New); return New; // Return the new prototype... } From lattner at cs.uiuc.edu Wed Apr 16 15:30:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Apr 16 15:30:00 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Function.h GlobalValue.h GlobalVariable.h Message-ID: <200304162029.PAA27636@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm: Function.h updated: 1.40 -> 1.41 GlobalValue.h updated: 1.8 -> 1.9 GlobalVariable.h updated: 1.18 -> 1.19 --- Log message: Add new linkage types to support a real frontend --- Diffs of the changes: Index: llvm/include/llvm/Function.h diff -u llvm/include/llvm/Function.h:1.40 llvm/include/llvm/Function.h:1.41 --- llvm/include/llvm/Function.h:1.40 Wed Nov 20 12:31:31 2002 +++ llvm/include/llvm/Function.h Wed Apr 16 15:28:30 2003 @@ -71,8 +71,8 @@ /// function is automatically inserted into the end of the function list for /// the module. /// - Function(const FunctionType *Ty, bool isInternal, const std::string &N = "", - Module *M = 0); + Function(const FunctionType *Ty, LinkageTypes Linkage, + const std::string &N = "", Module *M = 0); ~Function(); // Specialize setName to handle symbol table majik... Index: llvm/include/llvm/GlobalValue.h diff -u llvm/include/llvm/GlobalValue.h:1.8 llvm/include/llvm/GlobalValue.h:1.9 --- llvm/include/llvm/GlobalValue.h:1.8 Wed Oct 9 18:11:33 2002 +++ llvm/include/llvm/GlobalValue.h Wed Apr 16 15:28:30 2003 @@ -16,12 +16,19 @@ class GlobalValue : public User { GlobalValue(const GlobalValue &); // do not implement +public: + enum LinkageTypes { + ExternalLinkage, // Externally visible function + LinkOnceLinkage, // Keep one copy of named function when linking (inline) + AppendingLinkage, // Special purpose, only applies to global arrays + InternalLinkage // Rename collisions when linking (static functions) + }; protected: - GlobalValue(const Type *Ty, ValueTy vty, bool hasInternalLinkage, + GlobalValue(const Type *Ty, ValueTy vty, LinkageTypes linkage, const std::string &name = "") - : User(Ty, vty, name), HasInternalLinkage(hasInternalLinkage), Parent(0) {} + : User(Ty, vty, name), Linkage(linkage), Parent(0) {} - bool HasInternalLinkage; // Is this value accessable externally? + LinkageTypes Linkage; // The linkage of this global Module *Parent; public: ~GlobalValue() {} @@ -31,10 +38,12 @@ return (const PointerType*)User::getType(); } - /// Internal Linkage - True if the global value is inaccessible to - bool hasInternalLinkage() const { return HasInternalLinkage; } - bool hasExternalLinkage() const { return !HasInternalLinkage; } - void setInternalLinkage(bool HIL) { HasInternalLinkage = HIL; } + bool hasExternalLinkage() const { return Linkage == ExternalLinkage; } + bool hasLinkOnceLinkage() const { return Linkage == LinkOnceLinkage; } + bool hasAppendingLinkage() const { return Linkage == AppendingLinkage; } + bool hasInternalLinkage() const { return Linkage == InternalLinkage; } + void setLinkage(LinkageTypes LT) { Linkage = LT; } + LinkageTypes getLinkage() const { return Linkage; } /// isExternal - Return true if the primary definition of this global value is /// outside of the current translation unit... Index: llvm/include/llvm/GlobalVariable.h diff -u llvm/include/llvm/GlobalVariable.h:1.18 llvm/include/llvm/GlobalVariable.h:1.19 --- llvm/include/llvm/GlobalVariable.h:1.18 Sun Feb 2 10:40:40 2003 +++ llvm/include/llvm/GlobalVariable.h Wed Apr 16 15:28:30 2003 @@ -35,7 +35,7 @@ /// GlobalVariable ctor - If a parent module is specified, the global is /// automatically inserted into the end of the specified modules global list. /// - GlobalVariable(const Type *Ty, bool isConstant, bool isInternal, + GlobalVariable(const Type *Ty, bool isConstant, LinkageTypes Linkage, Constant *Initializer = 0, const std::string &Name = "", Module *Parent = 0); From lattner at cs.uiuc.edu Wed Apr 16 15:30:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Apr 16 15:30:02 2003 Subject: [llvm-commits] CVS: llvm/lib/AsmParser/Lexer.l ParserInternals.h llvmAsmParser.y Message-ID: <200304162029.PAA27645@apoc.cs.uiuc.edu> Changes in directory llvm/lib/AsmParser: Lexer.l updated: 1.29 -> 1.30 ParserInternals.h updated: 1.28 -> 1.29 llvmAsmParser.y updated: 1.104 -> 1.105 --- Log message: Add new linkage types to support a real frontend --- Diffs of the changes: Index: llvm/lib/AsmParser/Lexer.l diff -u llvm/lib/AsmParser/Lexer.l:1.29 llvm/lib/AsmParser/Lexer.l:1.30 --- llvm/lib/AsmParser/Lexer.l:1.29 Sun Oct 6 17:45:08 2002 +++ llvm/lib/AsmParser/Lexer.l Wed Apr 16 15:28:31 2003 @@ -155,6 +155,8 @@ constant { return CONSTANT; } const { return CONST; } internal { return INTERNAL; } +linkonce { return LINKONCE; } +appending { return APPENDING; } uninitialized { return EXTERNAL; } /* Deprecated, turn into external */ external { return EXTERNAL; } implementation { return IMPLEMENTATION; } Index: llvm/lib/AsmParser/ParserInternals.h diff -u llvm/lib/AsmParser/ParserInternals.h:1.28 llvm/lib/AsmParser/ParserInternals.h:1.29 --- llvm/lib/AsmParser/ParserInternals.h:1.28 Fri Sep 13 17:25:00 2002 +++ llvm/lib/AsmParser/ParserInternals.h Wed Apr 16 15:28:31 2003 @@ -177,7 +177,7 @@ struct MethPlaceHolderHelper : public Function { MethPlaceHolderHelper(const Type *Ty) - : Function(cast(Ty), true) {} + : Function(cast(Ty), InternalLinkage) {} }; typedef PlaceholderValue ValuePlaceHolder; Index: llvm/lib/AsmParser/llvmAsmParser.y diff -u llvm/lib/AsmParser/llvmAsmParser.y:1.104 llvm/lib/AsmParser/llvmAsmParser.y:1.105 --- llvm/lib/AsmParser/llvmAsmParser.y:1.104 Wed Apr 16 13:13:57 2003 +++ llvm/lib/AsmParser/llvmAsmParser.y Wed Apr 16 15:28:31 2003 @@ -522,8 +522,7 @@ EGV->setInitializer(GV->getInitializer()); if (GV->isConstant()) EGV->setConstant(true); - if (GV->hasInternalLinkage()) - EGV->setInternalLinkage(true); + EGV->setLinkage(GV->getLinkage()); delete GV; // Destroy the duplicate! return true; // They are equivalent! @@ -624,6 +623,7 @@ std::vector > *JumpTable; std::vector *ConstVector; + GlobalValue::LinkageTypes Linkage; int64_t SInt64Val; uint64_t UInt64Val; int SIntVal; @@ -654,7 +654,8 @@ %type IndexList // For GEP derived indices %type TypeListI ArgTypeListI %type JumpTable -%type GlobalType OptInternal // GLOBAL or CONSTANT? Intern? +%type GlobalType // GLOBAL or CONSTANT? +%type OptLinkage // ValueRef - Unresolved reference to a definition or BB %type ValueRef ConstValueRef SymbolicValueRef @@ -684,7 +685,8 @@ %token IMPLEMENTATION TRUE FALSE BEGINTOK ENDTOK DECLARE GLOBAL CONSTANT -%token TO EXCEPT DOTDOTDOT NULL_TOK CONST INTERNAL OPAQUE NOT EXTERNAL +%token TO EXCEPT DOTDOTDOT NULL_TOK CONST INTERNAL LINKONCE APPENDING +%token OPAQUE NOT EXTERNAL // Basic Block Terminating Operators %token RET BR SWITCH @@ -748,7 +750,10 @@ $$ = 0; }; -OptInternal : INTERNAL { $$ = true; } | /*empty*/ { $$ = false; }; +OptLinkage : INTERNAL { $$ = GlobalValue::InternalLinkage; } | + LINKONCE { $$ = GlobalValue::LinkOnceLinkage; } | + APPENDING { $$ = GlobalValue::AppendingLinkage; } | + /*empty*/ { $$ = GlobalValue::ExternalLinkage; }; //===----------------------------------------------------------------------===// // Types includes all predefined types... except void, because it can only be @@ -982,7 +987,8 @@ // Create a placeholder for the global variable reference... GlobalVariable *GV = new GlobalVariable(PT->getElementType(), - false, true); + false, + GlobalValue::ExternalLinkage); // Keep track of the fact that we have a forward ref to recycle it CurModule.GlobalRefs.insert(make_pair(make_pair(PT, $2), GV)); @@ -1136,7 +1142,7 @@ } | ConstPool FunctionProto { // Function prototypes can be in const pool } - | ConstPool OptAssign OptInternal GlobalType ConstVal { + | ConstPool OptAssign OptLinkage GlobalType ConstVal { const Type *Ty = $5->getType(); // Global declarations appear in Constant Pool Constant *Initializer = $5; @@ -1159,7 +1165,7 @@ | ConstPool OptAssign EXTERNAL GlobalType Types { const Type *Ty = *$5; // Global declarations appear in Constant Pool - GlobalVariable *GV = new GlobalVariable(Ty, $4, false); + GlobalVariable *GV = new GlobalVariable(Ty,$4,GlobalValue::ExternalLinkage); if (!setValueName(GV, $2)) { // If not redefining... CurModule.CurrentModule->getGlobalList().push_back(GV); int Slot = InsertValue(GV, CurModule.Values); @@ -1255,7 +1261,7 @@ AI->setName(""); } else { // Not already defined? - Fn = new Function(FT, false, FunctionName); + Fn = new Function(FT, GlobalValue::ExternalLinkage, FunctionName); InsertValue(Fn, CurModule.Values); CurModule.DeclareNewGlobalValue(Fn, ValID::create($2)); } @@ -1288,13 +1294,12 @@ BEGIN : BEGINTOK | '{'; // Allow BEGIN or '{' to start a function -FunctionHeader : OptInternal FunctionHeaderH BEGIN { +FunctionHeader : OptLinkage FunctionHeaderH BEGIN { $$ = CurMeth.CurrentFunction; - // Make sure that we keep track of the internal marker, even if there was - // a previous "declare". - if ($1) - $$->setInternalLinkage(true); + // Make sure that we keep track of the linkage type even if there was a + // previous "declare". + $$->setLinkage($1); // Resolve circular types before we parse the body of the function. ResolveTypes(CurMeth.LateResolveTypes); From lattner at cs.uiuc.edu Wed Apr 16 15:30:03 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Apr 16 15:30:03 2003 Subject: [llvm-commits] CVS: llvm/lib/Bytecode/Reader/ReadConst.cpp Reader.cpp Message-ID: <200304162029.PAA27652@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Bytecode/Reader: ReadConst.cpp updated: 1.43 -> 1.44 Reader.cpp updated: 1.48 -> 1.49 --- Log message: Add new linkage types to support a real frontend --- Diffs of the changes: Index: llvm/lib/Bytecode/Reader/ReadConst.cpp diff -u llvm/lib/Bytecode/Reader/ReadConst.cpp:1.43 llvm/lib/Bytecode/Reader/ReadConst.cpp:1.44 --- llvm/lib/Bytecode/Reader/ReadConst.cpp:1.43 Wed Mar 19 14:54:26 2003 +++ llvm/lib/Bytecode/Reader/ReadConst.cpp Wed Apr 16 15:28:32 2003 @@ -352,7 +352,8 @@ // Create a placeholder for the global variable reference... GlobalVariable *GVar = - new GlobalVariable(PT->getElementType(), false, true); + new GlobalVariable(PT->getElementType(), false, + GlobalValue::InternalLinkage); // Keep track of the fact that we have a forward ref to recycle it GlobalRefs.insert(std::make_pair(std::make_pair(PT, Slot), GVar)); Index: llvm/lib/Bytecode/Reader/Reader.cpp diff -u llvm/lib/Bytecode/Reader/Reader.cpp:1.48 llvm/lib/Bytecode/Reader/Reader.cpp:1.49 --- llvm/lib/Bytecode/Reader/Reader.cpp:1.48 Wed Mar 19 14:54:26 2003 +++ llvm/lib/Bytecode/Reader/Reader.cpp Wed Apr 16 15:28:32 2003 @@ -307,7 +307,8 @@ Function *F = FunctionSignatureList.back().first; unsigned FunctionSlot = FunctionSignatureList.back().second; FunctionSignatureList.pop_back(); - F->setInternalLinkage(isInternal != 0); + F->setLinkage(isInternal ? GlobalValue::InternalLinkage : + GlobalValue::ExternalLinkage); const FunctionType::ParamTypes &Params =F->getFunctionType()->getParamTypes(); Function::aiterator AI = F->abegin(); @@ -399,8 +400,13 @@ const Type *ElTy = cast(Ty)->getElementType(); + + GlobalValue::LinkageTypes Linkage = + (VarType & 4) ? GlobalValue::InternalLinkage : + GlobalValue::ExternalLinkage; + // Create the global variable... - GlobalVariable *GV = new GlobalVariable(ElTy, VarType & 1, VarType & 4, + GlobalVariable *GV = new GlobalVariable(ElTy, VarType & 1, Linkage, 0, "", TheModule); int DestSlot = insertValue(GV, ModuleValues); if (DestSlot == -1) return true; @@ -435,7 +441,8 @@ // this placeholder is replaced. // Insert the placeholder... - Function *Func = new Function(cast(Ty), false, "", TheModule); + Function *Func = new Function(cast(Ty), + GlobalValue::InternalLinkage, "", TheModule); int DestSlot = insertValue(Func, ModuleValues); if (DestSlot == -1) return true; ResolveReferencesToValue(Func, (unsigned)DestSlot); From lattner at cs.uiuc.edu Wed Apr 16 15:30:05 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Apr 16 15:30:05 2003 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/PreOpts/PreSelection.cpp Message-ID: <200304162029.PAA27657@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/PreOpts: PreSelection.cpp updated: 1.7 -> 1.8 --- Log message: Add new linkage types to support a real frontend --- Diffs of the changes: Index: llvm/lib/CodeGen/PreOpts/PreSelection.cpp diff -u llvm/lib/CodeGen/PreOpts/PreSelection.cpp:1.7 llvm/lib/CodeGen/PreOpts/PreSelection.cpp:1.8 --- llvm/lib/CodeGen/PreOpts/PreSelection.cpp:1.7 Tue Jan 14 15:58:48 2003 +++ llvm/lib/CodeGen/PreOpts/PreSelection.cpp Wed Apr 16 15:28:33 2003 @@ -87,7 +87,8 @@ GV = PI->second; // put in map else { - GV = new GlobalVariable(CV->getType(), true,true,CV); //put in map + GV = new GlobalVariable(CV->getType(), true, //put in map + GlobalValue::InternalLinkage, CV); myModule->getGlobalList().push_back(GV); // GV owned by module now } } From lattner at cs.uiuc.edu Wed Apr 16 15:31:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Apr 16 15:31:01 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Instruction.h Message-ID: <200304162030.PAA27675@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm: Instruction.h updated: 1.38 -> 1.39 --- Log message: Revert modulo scheduling change that should be part of the modulo-sched pass itself, not part of the Instruction class. --- Diffs of the changes: Index: llvm/include/llvm/Instruction.h diff -u llvm/include/llvm/Instruction.h:1.38 llvm/include/llvm/Instruction.h:1.39 --- llvm/include/llvm/Instruction.h:1.38 Sun Apr 6 18:58:44 2003 +++ llvm/include/llvm/Instruction.h Wed Apr 16 15:30:02 2003 @@ -23,8 +23,6 @@ friend class SymbolTableListTraits >; void setParent(BasicBlock *P); -private: - Instruction* cln; //the newest cloned instruction protected: unsigned iType; // InstructionType: The opcode of the instruction @@ -44,9 +42,7 @@ /// * The instruction has no name /// virtual Instruction *clone() const = 0; - Instruction * getClone(){return cln;} - void setClone(Instruction* _cln){cln=_cln;} - void clearClone(){cln=NULL;} + // Accessor methods... // inline const BasicBlock *getParent() const { return Parent; } From lattner at cs.uiuc.edu Wed Apr 16 15:43:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Apr 16 15:43:01 2003 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Verifier.cpp Message-ID: <200304162042.PAA28103@apoc.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: Verifier.cpp updated: 1.44 -> 1.45 --- Log message: Add code to verify correctly linkages --- Diffs of the changes: Index: llvm/lib/VMCore/Verifier.cpp diff -u llvm/lib/VMCore/Verifier.cpp:1.44 llvm/lib/VMCore/Verifier.cpp:1.45 --- llvm/lib/VMCore/Verifier.cpp:1.44 Tue Jan 14 16:19:44 2003 +++ llvm/lib/VMCore/Verifier.cpp Wed Apr 16 15:42:40 2003 @@ -94,8 +94,7 @@ bool doFinalization(Module &M) { // Scan through, checking all of the external function's linkage now... for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) - if (I->isExternal() && I->hasInternalLinkage()) - CheckFailed("Function Declaration has Internal Linkage!", I); + visitGlobalValue(*I); for (Module::giterator I = M.gbegin(), E = M.gend(); I != E; ++I) if (I->isExternal() && I->hasInternalLinkage()) @@ -122,8 +121,10 @@ } } + // Verification methods... void verifySymbolTable(SymbolTable &ST); + void visitGlobalValue(GlobalValue &GV); void visitFunction(Function &F); void visitBasicBlock(BasicBlock &BB); void visitPHINode(PHINode &PN); @@ -170,6 +171,19 @@ #define Assert4(C, M, V1, V2, V3, V4) \ do { if (!(C)) { CheckFailed(M, V1, V2, V3, V4); return; } } while (0) + +void Verifier::visitGlobalValue(GlobalValue &GV) { + Assert1(!GV.isExternal() || GV.hasExternalLinkage(), + "Global value has Internal Linkage!", &GV); + Assert1(!GV.hasAppendingLinkage() || isa(GV), + "Only global variables can have appending linkage!", &GV); + + if (GV.hasAppendingLinkage()) { + GlobalVariable &GVar = cast(GV); + Assert1(isa(GVar.getType()->getElementType()), + "Only global arrays can have appending linkage!", &GV); + } +} // verifySymbolTable - Verify that a function or module symbol table is ok // From lattner at cs.uiuc.edu Wed Apr 16 15:52:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Apr 16 15:52:01 2003 Subject: [llvm-commits] CVS: llvm/tools/dis/dis.cpp Message-ID: <200304162051.PAA28259@apoc.cs.uiuc.edu> Changes in directory llvm/tools/dis: dis.cpp updated: 1.28 -> 1.29 --- Log message: Give verbose error messages if bytecode file cannot be parsed --- Diffs of the changes: Index: llvm/tools/dis/dis.cpp diff -u llvm/tools/dis/dis.cpp:1.28 llvm/tools/dis/dis.cpp:1.29 --- llvm/tools/dis/dis.cpp:1.28 Mon Sep 23 19:09:48 2002 +++ llvm/tools/dis/dis.cpp Wed Apr 16 15:51:35 2003 @@ -48,10 +48,15 @@ int main(int argc, char **argv) { cl::ParseCommandLineOptions(argc, argv, " llvm .bc -> .ll disassembler\n"); std::ostream *Out = &std::cout; // Default to printing to stdout... + std::string ErrorMessage; - std::auto_ptr M(ParseBytecodeFile(InputFilename)); + std::auto_ptr M(ParseBytecodeFile(InputFilename, &ErrorMessage)); if (M.get() == 0) { - cerr << argv[0] << ": bytecode didn't read correctly.\n"; + cerr << argv[0] << ": "; + if (ErrorMessage.size()) + cerr << ErrorMessage << "\n"; + else + cerr << "bytecode didn't read correctly.\n"; return 1; } From lattner at cs.uiuc.edu Wed Apr 16 15:52:03 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Apr 16 15:52:03 2003 Subject: [llvm-commits] CVS: llvm/tools/opt/opt.cpp Message-ID: <200304162051.PAA28266@apoc.cs.uiuc.edu> Changes in directory llvm/tools/opt: opt.cpp updated: 1.77 -> 1.78 --- Log message: Give verbose error messages if bytecode file cannot be parsed --- Diffs of the changes: Index: llvm/tools/opt/opt.cpp diff -u llvm/tools/opt/opt.cpp:1.77 llvm/tools/opt/opt.cpp:1.78 --- llvm/tools/opt/opt.cpp:1.77 Wed Feb 26 14:00:41 2003 +++ llvm/tools/opt/opt.cpp Wed Apr 16 15:51:36 2003 @@ -76,11 +76,16 @@ std::auto_ptr target; TargetMachine* TM = NULL; + std::string ErrorMessage; // Load the input module... - std::auto_ptr M(ParseBytecodeFile(InputFilename)); + std::auto_ptr M(ParseBytecodeFile(InputFilename, &ErrorMessage)); if (M.get() == 0) { - cerr << argv[0] << ": bytecode didn't read correctly.\n"; + cerr << argv[0] << ": "; + if (ErrorMessage.size()) + cerr << ErrorMessage << "\n"; + else + cerr << "bytecode didn't read correctly.\n"; return 1; } From lattner at cs.uiuc.edu Wed Apr 16 16:17:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Apr 16 16:17:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Bytecode/Reader/Reader.cpp ReaderInternals.h Message-ID: <200304162116.QAA28536@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Bytecode/Reader: Reader.cpp updated: 1.49 -> 1.50 ReaderInternals.h updated: 1.33 -> 1.34 --- Log message: Add support to the bytecode reader/writer for the new linkage types --- Diffs of the changes: Index: llvm/lib/Bytecode/Reader/Reader.cpp diff -u llvm/lib/Bytecode/Reader/Reader.cpp:1.49 llvm/lib/Bytecode/Reader/Reader.cpp:1.50 --- llvm/lib/Bytecode/Reader/Reader.cpp:1.49 Wed Apr 16 15:28:32 2003 +++ llvm/lib/Bytecode/Reader/Reader.cpp Wed Apr 16 16:16:03 2003 @@ -301,14 +301,24 @@ return true; // Unexpected function! } - unsigned isInternal; - if (read_vbr(Buf, EndBuf, isInternal)) return true; + GlobalValue::LinkageTypes Linkage = GlobalValue::ExternalLinkage; + + if (!hasInternalMarkerOnly) { + unsigned LinkageType; + if (read_vbr(Buf, EndBuf, LinkageType)) return true; + if (LinkageType & 0x3) return true; + Linkage = (GlobalValue::LinkageTypes)LinkageType; + } else { + // We used to only support two linkage models: internal and external + unsigned isInternal; + if (read_vbr(Buf, EndBuf, isInternal)) return true; + if (isInternal) Linkage = GlobalValue::InternalLinkage; + } Function *F = FunctionSignatureList.back().first; unsigned FunctionSlot = FunctionSignatureList.back().second; FunctionSignatureList.pop_back(); - F->setLinkage(isInternal ? GlobalValue::InternalLinkage : - GlobalValue::ExternalLinkage); + F->setLinkage(Linkage); const FunctionType::ParamTypes &Params =F->getFunctionType()->getParamTypes(); Function::aiterator AI = F->abegin(); @@ -390,9 +400,23 @@ unsigned VarType; if (read_vbr(Buf, End, VarType)) return true; while (VarType != Type::VoidTyID) { // List is terminated by Void - // VarType Fields: bit0 = isConstant, bit1 = hasInitializer, - // bit2 = isInternal, bit3+ = slot# - const Type *Ty = getType(VarType >> 3); + unsigned SlotNo; + GlobalValue::LinkageTypes Linkage; + + if (!hasInternalMarkerOnly) { + // VarType Fields: bit0 = isConstant, bit1 = hasInitializer, + // bit2,3 = Linkage, bit4+ = slot# + SlotNo = VarType >> 4; + Linkage = (GlobalValue::LinkageTypes)((VarType >> 2) & 3); + } else { + // VarType Fields: bit0 = isConstant, bit1 = hasInitializer, + // bit2 = isInternal, bit3+ = slot# + SlotNo = VarType >> 3; + Linkage = (VarType & 4) ? GlobalValue::InternalLinkage : + GlobalValue::ExternalLinkage; + } + + const Type *Ty = getType(SlotNo); if (!Ty || !isa(Ty)) { Error = "Global not pointer type! Ty = " + Ty->getDescription(); return true; @@ -400,11 +424,6 @@ const Type *ElTy = cast(Ty)->getElementType(); - - GlobalValue::LinkageTypes Linkage = - (VarType & 4) ? GlobalValue::InternalLinkage : - GlobalValue::ExternalLinkage; - // Create the global variable... GlobalVariable *GV = new GlobalVariable(ElTy, VarType & 1, Linkage, 0, "", TheModule); @@ -477,7 +496,11 @@ isBigEndian = Version & 1; hasLongPointers = Version & 2; RevisionNum = Version >> 4; + + // Default values for the current bytecode version HasImplicitZeroInitializer = true; + hasInternalMarkerOnly = false; + FirstDerivedTyID = 14; switch (RevisionNum) { case 0: // Initial revision @@ -486,13 +509,17 @@ // encoding zero initializers for arrays compactly. // if (Version != 14) return true; // Unknown revision 0 flags? - FirstDerivedTyID = 14; HasImplicitZeroInitializer = false; isBigEndian = hasLongPointers = true; + hasInternalMarkerOnly = true; break; case 1: // Version #1 has two bit fields: isBigEndian and hasLongPointers - FirstDerivedTyID = 14; + hasInternalMarkerOnly = true; + break; + case 2: + // Version #2 added information about all 4 linkage types instead of just + // having internal and external. break; default: Error = "Unknown bytecode version number!"; Index: llvm/lib/Bytecode/Reader/ReaderInternals.h diff -u llvm/lib/Bytecode/Reader/ReaderInternals.h:1.33 llvm/lib/Bytecode/Reader/ReaderInternals.h:1.34 --- llvm/lib/Bytecode/Reader/ReaderInternals.h:1.33 Wed Mar 19 14:54:26 2003 +++ llvm/lib/Bytecode/Reader/ReaderInternals.h Wed Apr 16 16:16:03 2003 @@ -85,6 +85,7 @@ unsigned char FirstDerivedTyID; // First variable index to use for type bool HasImplicitZeroInitializer; // Is entry 0 of every slot implicity zeros? bool isBigEndian, hasLongPointers;// Information about the target compiled for + bool hasInternalMarkerOnly; // Only types of linkage are intern/external typedef std::vector ValueTable; ValueTable Values, LateResolveValues; From lattner at cs.uiuc.edu Wed Apr 16 16:17:04 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Apr 16 16:17:04 2003 Subject: [llvm-commits] CVS: llvm/lib/Bytecode/Writer/Writer.cpp Message-ID: <200304162116.QAA28543@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Bytecode/Writer: Writer.cpp updated: 1.31 -> 1.32 --- Log message: Add support to the bytecode reader/writer for the new linkage types --- Diffs of the changes: Index: llvm/lib/Bytecode/Writer/Writer.cpp diff -u llvm/lib/Bytecode/Writer/Writer.cpp:1.31 llvm/lib/Bytecode/Writer/Writer.cpp:1.32 --- llvm/lib/Bytecode/Writer/Writer.cpp:1.31 Wed Mar 19 14:56:46 2003 +++ llvm/lib/Bytecode/Writer/Writer.cpp Wed Apr 16 16:16:05 2003 @@ -46,8 +46,8 @@ bool isBigEndian = true; bool hasLongPointers = true; - // Output the version identifier... we are currently on bytecode version #1 - unsigned Version = (1 << 4) | isBigEndian | (hasLongPointers << 1); + // Output the version identifier... we are currently on bytecode version #2 + unsigned Version = (2 << 4) | isBigEndian | (hasLongPointers << 1); output_vbr(Version, Out); align32(Out); @@ -154,9 +154,9 @@ int Slot = Table.getValSlot(I->getType()); assert(Slot != -1 && "Module global vars is broken!"); - // Fields: bit0 = isConstant, bit1 = hasInitializer, bit2=InternalLinkage, - // bit3+ = Slot # for type - unsigned oSlot = ((unsigned)Slot << 3) | (I->hasInternalLinkage() << 2) | + // Fields: bit0 = isConstant, bit1 = hasInitializer, bit2,3=Linkage, + // bit4+ = Slot # for type + unsigned oSlot = ((unsigned)Slot << 4) | ((unsigned)I->getLinkage() << 2) | (I->hasInitializer() << 1) | I->isConstant(); output_vbr(oSlot, Out); @@ -183,7 +183,7 @@ void BytecodeWriter::outputFunction(const Function *F) { BytecodeBlock FunctionBlock(BytecodeFormat::Function, Out); - output_vbr((unsigned)F->hasInternalLinkage(), Out); + output_vbr((unsigned)F->getLinkage(), Out); // Only output the constant pool and other goodies if needed... if (!F->isExternal()) { From lattner at cs.uiuc.edu Wed Apr 16 16:22:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Apr 16 16:22:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Linker/LinkOnce.ll Message-ID: <200304162121.QAA28781@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Linker: LinkOnce.ll added (r1.1) --- Log message: Add tests for linker and linkonce globals --- Diffs of the changes: Index: llvm/test/Regression/Linker/LinkOnce.ll diff -c /dev/null llvm/test/Regression/Linker/LinkOnce.ll:1.1 *** /dev/null Wed Apr 16 16:21:45 2003 --- llvm/test/Regression/Linker/LinkOnce.ll Wed Apr 16 16:21:35 2003 *************** *** 0 **** --- 1,8 ---- + ; This fails because the linker renames the non-opaque type not the opaque + ; one... + + ; RUN: echo "%X = linkonce global int 8" | as > Output/%s.2.bc + ; RUN: as < %s > Output/%s.1.bc + ; RUN: link Output/%s.[12].bc | dis + + %X = linkonce global int 7 From lattner at cs.uiuc.edu Wed Apr 16 16:44:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Apr 16 16:44:01 2003 Subject: [llvm-commits] CVS: llvm/tools/gccld/gccld.cpp Message-ID: <200304162143.QAA30495@apoc.cs.uiuc.edu> Changes in directory llvm/tools/gccld: gccld.cpp updated: 1.22 -> 1.23 --- Log message: Allow the user to disable the internalize pass --- Diffs of the changes: Index: llvm/tools/gccld/gccld.cpp diff -u llvm/tools/gccld/gccld.cpp:1.22 llvm/tools/gccld/gccld.cpp:1.23 --- llvm/tools/gccld/gccld.cpp:1.22 Sat Dec 14 15:28:32 2002 +++ llvm/tools/gccld/gccld.cpp Wed Apr 16 16:43:22 2003 @@ -52,6 +52,10 @@ static cl::opt Strip("s", cl::desc("Strip symbol info from executable")); +static cl::opt +NoInternalize("disable-internalize", + cl::desc("Do not mark all symbols as internal")); + // FileExists - Return true if the specified string is an openable file... static inline bool FileExists(const std::string &FN) { @@ -153,10 +157,13 @@ // Passes.add(createFunctionResolvingPass()); - // Now that composite has been compiled, scan through the module, looking for - // a main function. If main is defined, mark all other functions internal. - // - Passes.add(createInternalizePass()); + if (!NoInternalize) { + // Now that composite has been compiled, scan through the module, looking + // for a main function. If main is defined, mark all other functions + // internal. + // + Passes.add(createInternalizePass()); + } // Now that we have optimized the program, discard unreachable functions... // From lattner at cs.uiuc.edu Wed Apr 16 17:41:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Apr 16 17:41:01 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Constants.h Message-ID: <200304162240.RAA00339@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm: Constants.h updated: 1.20 -> 1.21 --- Log message: Change the interface to constant expressions to allow automatic folding --- Diffs of the changes: Index: llvm/include/llvm/Constants.h diff -u llvm/include/llvm/Constants.h:1.20 llvm/include/llvm/Constants.h:1.21 --- llvm/include/llvm/Constants.h:1.20 Mon Mar 10 16:39:01 2003 +++ llvm/include/llvm/Constants.h Wed Apr 16 17:40:43 2003 @@ -476,17 +476,19 @@ ~ConstantExpr() {} public: - // Static methods to construct a ConstantExpr of different kinds. + // Static methods to construct a ConstantExpr of different kinds. Note that + // these methods can return a constant of an arbitrary type, because they will + // attempt to fold the constant expression into something simple if they can. /// Cast constant expr - static ConstantExpr *getCast(Constant *C, const Type *Ty); + static Constant *getCast(Constant *C, const Type *Ty); /// Binary constant expr - Use with binary operators... - static ConstantExpr *get(unsigned Opcode, Constant *C1, Constant *C2); + static Constant *get(unsigned Opcode, Constant *C1, Constant *C2); /// Getelementptr form... - static ConstantExpr *getGetElementPtr(Constant *C, - const std::vector &IdxList); + static Constant *getGetElementPtr(Constant *C, + const std::vector &IdxList); /// isNullValue - Return true if this is the value that would be returned by /// getNullValue. From lattner at cs.uiuc.edu Wed Apr 16 17:41:03 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Apr 16 17:41:03 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/FunctionResolution.cpp Message-ID: <200304162240.RAA00346@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: FunctionResolution.cpp updated: 1.23 -> 1.24 --- Log message: Change the interface to constant expressions to allow automatic folding --- Diffs of the changes: Index: llvm/lib/Transforms/IPO/FunctionResolution.cpp diff -u llvm/lib/Transforms/IPO/FunctionResolution.cpp:1.23 llvm/lib/Transforms/IPO/FunctionResolution.cpp:1.24 --- llvm/lib/Transforms/IPO/FunctionResolution.cpp:1.23 Mon Mar 3 13:57:46 2003 +++ llvm/lib/Transforms/IPO/FunctionResolution.cpp Wed Apr 16 17:40:47 2003 @@ -207,7 +207,7 @@ std::vector Args; Args.push_back(Constant::getNullValue(Type::LongTy)); Args.push_back(Constant::getNullValue(Type::LongTy)); - ConstantExpr *Replacement = + Constant *Replacement = ConstantExpr::getGetElementPtr(ConstantPointerRef::get(Concrete), Args); for (unsigned i = 0; i != Globals.size(); ++i) From lattner at cs.uiuc.edu Wed Apr 16 17:41:05 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Apr 16 17:41:05 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200304162240.RAA00353@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: InstructionCombining.cpp updated: 1.78 -> 1.79 --- Log message: Change the interface to constant expressions to allow automatic folding --- Diffs of the changes: Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.78 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.79 --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.78 Mon Mar 10 18:12:48 2003 +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Wed Apr 16 17:40:49 2003 @@ -1011,7 +1011,7 @@ Indices.push_back(cast(*I)); if (I == E) { // If they are all constants... - ConstantExpr *CE = + Constant *CE = ConstantExpr::getGetElementPtr(ConstantPointerRef::get(GV), Indices); // Replace all uses of the GEP with the new constexpr... From lattner at cs.uiuc.edu Wed Apr 16 17:42:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Apr 16 17:42:01 2003 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Constants.cpp Message-ID: <200304162241.RAA00360@apoc.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: Constants.cpp updated: 1.34 -> 1.35 --- Log message: Change the interface to constant expressions to allow automatic folding --- Diffs of the changes: Index: llvm/lib/VMCore/Constants.cpp diff -u llvm/lib/VMCore/Constants.cpp:1.34 llvm/lib/VMCore/Constants.cpp:1.35 --- llvm/lib/VMCore/Constants.cpp:1.34 Mon Mar 10 16:39:02 2003 +++ llvm/lib/VMCore/Constants.cpp Wed Apr 16 17:40:51 2003 @@ -418,7 +418,7 @@ void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *To) { assert(isa(To) && "Cannot make Constant refer to non-constant!"); - ConstantExpr *Replacement = 0; + Constant *Replacement = 0; if (getOpcode() == Instruction::GetElementPtr) { std::vector Indices; Constant *Pointer = cast(getOperand(0)); @@ -635,8 +635,7 @@ typedef pair > ExprMapKeyType; static ValueMap ExprConstants; -ConstantExpr *ConstantExpr::getCast(Constant *C, const Type *Ty) { - +Constant *ConstantExpr::getCast(Constant *C, const Type *Ty) { // Look up the constant in the table first to ensure uniqueness vector argVec(1, C); const ExprMapKeyType &Key = make_pair(Instruction::Cast, argVec); @@ -649,7 +648,7 @@ return Result; } -ConstantExpr *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2) { +Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2) { // Look up the constant in the table first to ensure uniqueness vector argVec(1, C1); argVec.push_back(C2); const ExprMapKeyType &Key = make_pair(Opcode, argVec); @@ -670,8 +669,8 @@ return Result; } -ConstantExpr *ConstantExpr::getGetElementPtr(Constant *C, - const std::vector &IdxList) { +Constant *ConstantExpr::getGetElementPtr(Constant *C, + const std::vector &IdxList){ const Type *Ty = C->getType(); // Look up the constant in the table first to ensure uniqueness From lattner at cs.uiuc.edu Wed Apr 16 17:47:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Apr 16 17:47:00 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/IndVarsSimplify/2003-04-16-ExprAnalysis.ll Message-ID: <200304162246.RAA00616@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/IndVarsSimplify: 2003-04-16-ExprAnalysis.ll added (r1.1) --- Log message: New testcase --- Diffs of the changes: Index: llvm/test/Regression/Transforms/IndVarsSimplify/2003-04-16-ExprAnalysis.ll diff -c /dev/null llvm/test/Regression/Transforms/IndVarsSimplify/2003-04-16-ExprAnalysis.ll:1.1 *** /dev/null Wed Apr 16 17:46:26 2003 --- llvm/test/Regression/Transforms/IndVarsSimplify/2003-04-16-ExprAnalysis.ll Wed Apr 16 17:46:16 2003 *************** *** 0 **** --- 1,14 ---- + ; This is a test case for the expression analysis code, not really indvars. + ; It was assuming any constant of int type was a ConstantInteger. + ; + ; RUN: as < %s | opt -indvars + + %X = global int 7 + + void %test(int %A) { + br label %Loop + Loop: + %IV = phi int [%A, %0], [%IVNext, %Loop] + %IVNext = add int %IV, cast (int* %X to int) + br label %Loop + } From lattner at cs.uiuc.edu Wed Apr 16 17:51:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Apr 16 17:51:00 2003 Subject: [llvm-commits] CVS: llvm/lib/Analysis/Expressions.cpp Message-ID: <200304162250.RAA00761@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Analysis: Expressions.cpp updated: 1.29 -> 1.30 --- Log message: Fix bug: IndVarSimplify/2003-04-16-ExprAnalysis.ll --- Diffs of the changes: Index: llvm/lib/Analysis/Expressions.cpp diff -u llvm/lib/Analysis/Expressions.cpp:1.29 llvm/lib/Analysis/Expressions.cpp:1.30 --- llvm/lib/Analysis/Expressions.cpp:1.29 Mon Sep 2 20:05:48 2002 +++ llvm/lib/Analysis/Expressions.cpp Wed Apr 16 17:50:19 2003 @@ -244,11 +244,9 @@ case Value::ArgumentVal: // nothing known, return variable itself return Expr; case Value::ConstantVal: // Constant value, just return constant - Constant *CPV = cast(Expr); - if (CPV->getType()->isInteger()) { // It's an integral constant! - ConstantInt *CPI = cast(Expr); + if (ConstantInt *CPI = dyn_cast(cast(Expr))) + // It's an integral constant! return ExprType(CPI->isNullValue() ? 0 : CPI); - } return Expr; } From lattner at cs.uiuc.edu Wed Apr 16 17:57:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Apr 16 17:57:00 2003 Subject: [llvm-commits] CVS: llvm/tools/opt/Makefile Message-ID: <200304162256.RAA00831@apoc.cs.uiuc.edu> Changes in directory llvm/tools/opt: Makefile updated: 1.38 -> 1.39 --- Log message: Remove codegen libraries to speed up linking opt --- Diffs of the changes: Index: llvm/tools/opt/Makefile diff -u llvm/tools/opt/Makefile:1.38 llvm/tools/opt/Makefile:1.39 --- llvm/tools/opt/Makefile:1.38 Wed Dec 11 23:29:32 2002 +++ llvm/tools/opt/Makefile Wed Apr 16 17:55:55 2003 @@ -1,9 +1,8 @@ LEVEL = ../.. TOOLNAME = opt -USEDLIBS = bcreader bcwriter instrument profpaths \ - sparc mapping regalloc.a sched select codegen preopts \ - postopts.a livevar scalaropts \ +USEDLIBS = bcreader bcwriter \ + instrument profpaths scalaropts \ ipo ipa.a datastructure transforms target.a analysis \ transformutils vmcore support From lattner at cs.uiuc.edu Wed Apr 16 18:03:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Apr 16 18:03:01 2003 Subject: [llvm-commits] CVS: llvm/tools/opt/opt.cpp Message-ID: <200304162302.SAA00917@apoc.cs.uiuc.edu> Changes in directory llvm/tools/opt: opt.cpp updated: 1.78 -> 1.79 --- Log message: Don't support codegen passes in opt --- Diffs of the changes: Index: llvm/tools/opt/opt.cpp diff -u llvm/tools/opt/opt.cpp:1.78 llvm/tools/opt/opt.cpp:1.79 --- llvm/tools/opt/opt.cpp:1.78 Wed Apr 16 15:51:36 2003 +++ llvm/tools/opt/opt.cpp Wed Apr 16 18:02:16 2003 @@ -125,8 +125,10 @@ else if (Opt->getDataCtor()) Passes.add(Opt->getDataCtor()(TD)); // Provide dummy target data... else if (Opt->getTargetCtor()) { +#if 0 if (target.get() == NULL) target.reset(allocateSparcTargetMachine()); // FIXME: target option +#endif assert(target.get() && "Could not allocate target machine!"); Passes.add(Opt->getTargetCtor()(*target.get())); } else From lattner at cs.uiuc.edu Thu Apr 17 14:22:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Apr 17 14:22:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Assembler/ConstantExprFoldCast.llx Message-ID: <200304171921.OAA06172@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Assembler: ConstantExprFoldCast.llx added (r1.1) --- Log message: Test case to make sure that constexprs are automatically folded --- Diffs of the changes: Index: llvm/test/Regression/Assembler/ConstantExprFoldCast.llx diff -c /dev/null llvm/test/Regression/Assembler/ConstantExprFoldCast.llx:1.1 *** /dev/null Thu Apr 17 14:21:33 2003 --- llvm/test/Regression/Assembler/ConstantExprFoldCast.llx Thu Apr 17 14:21:22 2003 *************** *** 0 **** --- 1,17 ---- + ; This test checks to make sure that constant exprs fold in some simple situations + + ; RUN: if as < %s | dis | grep cast + ; RUN: then exit 1 + ; RUN: else exit 0 + ; RUN: fi + + %A = global int* cast (sbyte* null to int*) ; Cast null -> fold + %B = global int** cast (int** %A to int**) ; Cast to same type -> fold + %C = global int cast (long 42 to int) ; Integral casts + %D = global int* cast(float* cast (int* %C to float*) to int*) ; cast of cast ptr->ptr + %E = global int cast(float* cast (sbyte 5 to float*) to int) ; int -> ptr -> int + + ; Test folding of binary instrs + %F = global int* cast(int add (int 5, int -5) to int*) + %G = global int* cast(int sub (int 5, int 5) to int*) + From lattner at cs.uiuc.edu Thu Apr 17 14:23:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Apr 17 14:23:01 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/ConstantHandling.h Message-ID: <200304171922.OAA06241@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm: ConstantHandling.h updated: 1.23 -> 1.24 --- Log message: Don't force a ConstantPointer to be returned --- Diffs of the changes: Index: llvm/include/llvm/ConstantHandling.h diff -u llvm/include/llvm/ConstantHandling.h:1.23 llvm/include/llvm/ConstantHandling.h:1.24 --- llvm/include/llvm/ConstantHandling.h:1.23 Mon Sep 2 20:04:11 2002 +++ llvm/include/llvm/ConstantHandling.h Thu Apr 17 14:22:47 2003 @@ -41,14 +41,12 @@ // Implement == and != directly... //===----------------------------------------------------------------------===// -inline ConstantBool *operator==(const Constant &V1, - const Constant &V2) { +inline ConstantBool *operator==(const Constant &V1, const Constant &V2) { assert(V1.getType() == V2.getType() && "Constant types must be identical!"); return ConstantBool::get(&V1 == &V2); } -inline ConstantBool *operator!=(const Constant &V1, - const Constant &V2) { +inline ConstantBool *operator!=(const Constant &V1, const Constant &V2) { return ConstantBool::get(&V1 != &V2); } @@ -89,8 +87,8 @@ virtual ConstantUInt *castToULong (const Constant *V) const = 0; virtual ConstantFP *castToFloat (const Constant *V) const = 0; virtual ConstantFP *castToDouble(const Constant *V) const = 0; - virtual ConstantPointer *castToPointer(const Constant *V, - const PointerType *Ty) const = 0; + virtual Constant *castToPointer(const Constant *V, + const PointerType *Ty) const = 0; inline Constant *castTo(const Constant *V, const Type *Ty) const { switch (Ty->getPrimitiveID()) { @@ -117,7 +115,7 @@ static inline ConstRules *get(const Constant &V) { return (ConstRules*)V.getType()->getOrCreateAnnotation(AID); } -private : +private: static Annotation *find(AnnotationID AID, const Annotable *Ty, void *); ConstRules(const ConstRules &); // Do not implement @@ -220,5 +218,6 @@ const Constant *V2); Constant *ConstantFoldShiftInstruction(unsigned Opcode, const Constant *V1, const Constant *V2); - +Constant *ConstantFoldGetElementPtr(const Constant *C, + const std::vector &IdxList); #endif From lattner at cs.uiuc.edu Thu Apr 17 14:25:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Apr 17 14:25:01 2003 Subject: [llvm-commits] CVS: llvm/lib/VMCore/ConstantHandling.cpp Message-ID: <200304171924.OAA06278@apoc.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: ConstantHandling.cpp updated: 1.24 -> 1.25 --- Log message: Allow constant folding of GEP instructions, even if we don't do a whole lot yet. Fold ConstExpr casts better castToPointer shouldn't be forced to return a constantpointer --- Diffs of the changes: Index: llvm/lib/VMCore/ConstantHandling.cpp diff -u llvm/lib/VMCore/ConstantHandling.cpp:1.24 llvm/lib/VMCore/ConstantHandling.cpp:1.25 --- llvm/lib/VMCore/ConstantHandling.cpp:1.24 Tue Sep 3 15:09:49 2002 +++ llvm/lib/VMCore/ConstantHandling.cpp Thu Apr 17 14:24:18 2003 @@ -6,6 +6,7 @@ #include "llvm/ConstantHandling.h" #include "llvm/iPHINode.h" +#include "llvm/DerivedTypes.h" #include AnnotationID ConstRules::AID(AnnotationManager::getID("opt::ConstRules", @@ -64,12 +65,48 @@ case Instruction::SetGT: return *Op0 > *Op1; case Instruction::Shl: return *Op0 << *Op1; case Instruction::Shr: return *Op0 >> *Op1; + case Instruction::GetElementPtr: { + std::vector IdxList; + IdxList.reserve(I->getNumOperands()-1); + if (Op1) IdxList.push_back(Op1); + for (unsigned i = 2, e = I->getNumOperands(); i != e; ++i) + if (Constant *C = dyn_cast(I->getOperand(i))) + IdxList.push_back(C); + else + return 0; // Non-constant operand + return ConstantFoldGetElementPtr(Op0, IdxList); + } default: return 0; } } +static unsigned getSize(const Type *Ty) { + unsigned S = Ty->getPrimitiveSize(); + return S ? S : 8; // Treat pointers at 8 bytes +} + Constant *ConstantFoldCastInstruction(const Constant *V, const Type *DestTy) { + if (V->getType() == DestTy) return (Constant*)V; + + if (const ConstantExpr *CE = dyn_cast(V)) + if (CE->getOpcode() == Instruction::Cast) { + Constant *Op = (Constant*)cast(CE->getOperand(0)); + // Try to not produce a cast of a cast, which is almost always redundant. + if (!Op->getType()->isFloatingPoint() && + !CE->getType()->isFloatingPoint() && + !DestTy->getType()->isFloatingPoint()) { + unsigned S1 = getSize(Op->getType()), S2 = getSize(CE->getType()); + unsigned S3 = getSize(DestTy); + if (Op->getType() == DestTy && S3 >= S2) + return Op; + if (S1 >= S2 && S2 >= S3) + return ConstantExpr::getCast(Op, DestTy); + if (S1 <= S2 && S2 >= S3 && S1 <= S3) + return ConstantExpr::getCast(Op, DestTy); + } + } + return ConstRules::get(*V)->castTo(V, DestTy); } @@ -104,6 +141,18 @@ } } +Constant *ConstantFoldGetElementPtr(const Constant *C, + const std::vector &IdxList) { + if (IdxList.size() == 0 || + (IdxList.size() == 1 && IdxList[0]->isNullValue())) + return const_cast(C); + + // If C is null and all idx's are null, return null of the right type. + + // FIXME: Implement folding of GEP constant exprs the same as instcombine does + return 0; +} + //===----------------------------------------------------------------------===// // TemplateRules Class @@ -194,8 +243,8 @@ virtual ConstantFP *castToDouble(const Constant *V) const { return SubClassName::CastToDouble((const ArgType*)V); } - virtual ConstantPointer *castToPointer(const Constant *V, - const PointerType *Ty) const { + virtual Constant *castToPointer(const Constant *V, + const PointerType *Ty) const { return SubClassName::CastToPointer((const ArgType*)V, Ty); } @@ -229,8 +278,8 @@ static ConstantUInt *CastToULong (const Constant *V) { return 0; } static ConstantFP *CastToFloat (const Constant *V) { return 0; } static ConstantFP *CastToDouble(const Constant *V) { return 0; } - static ConstantPointer *CastToPointer(const Constant *, - const PointerType *) {return 0;} + static Constant *CastToPointer(const Constant *, + const PointerType *) {return 0;} }; @@ -324,8 +373,8 @@ return 0; // Can't const prop other types of pointers } - static ConstantPointer *CastToPointer(const ConstantPointer *V, - const PointerType *PTy) { + static Constant *CastToPointer(const ConstantPointer *V, + const PointerType *PTy) { if (V->getType() == PTy) return const_cast(V); // Allow cast %PTy %ptr to %PTy if (V->isNullValue()) @@ -372,8 +421,8 @@ return ConstantBool::get(R); } - static ConstantPointer *CastToPointer(const ConstantClass *V, - const PointerType *PTy) { + static Constant *CastToPointer(const ConstantClass *V, + const PointerType *PTy) { if (V->isNullValue()) // Is it a FP or Integral null value? return ConstantPointerNull::get(PTy); return 0; // Can't const prop other types of pointers @@ -462,7 +511,6 @@ return ConstantClass::get(*Ty, Result); } }; - //===----------------------------------------------------------------------===// // DirectRules Subclasses From lattner at cs.uiuc.edu Thu Apr 17 14:25:03 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Apr 17 14:25:03 2003 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Constants.cpp Message-ID: <200304171924.OAA06316@apoc.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: Constants.cpp updated: 1.35 -> 1.36 --- Log message: Don't build constantexprs that could be folded --- Diffs of the changes: Index: llvm/lib/VMCore/Constants.cpp diff -u llvm/lib/VMCore/Constants.cpp:1.35 llvm/lib/VMCore/Constants.cpp:1.36 --- llvm/lib/VMCore/Constants.cpp:1.35 Wed Apr 16 17:40:51 2003 +++ llvm/lib/VMCore/Constants.cpp Thu Apr 17 14:24:48 2003 @@ -5,6 +5,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Constants.h" +#include "llvm/ConstantHandling.h" #include "llvm/DerivedTypes.h" #include "llvm/iMemory.h" #include "llvm/SymbolTable.h" @@ -636,6 +637,9 @@ static ValueMap ExprConstants; Constant *ConstantExpr::getCast(Constant *C, const Type *Ty) { + if (Constant *FC = ConstantFoldCastInstruction(C, Ty)) + return FC; // Fold a few common cases... + // Look up the constant in the table first to ensure uniqueness vector argVec(1, C); const ExprMapKeyType &Key = make_pair(Instruction::Cast, argVec); @@ -649,6 +653,10 @@ } Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2) { + + if (Constant *FC = ConstantFoldBinaryInstruction(Opcode, C1, C2)) + return FC; // Fold a few common cases... + // Look up the constant in the table first to ensure uniqueness vector argVec(1, C1); argVec.push_back(C2); const ExprMapKeyType &Key = make_pair(Opcode, argVec); @@ -671,6 +679,8 @@ Constant *ConstantExpr::getGetElementPtr(Constant *C, const std::vector &IdxList){ + if (Constant *FC = ConstantFoldGetElementPtr(C, IdxList)) + return FC; // Fold a few common cases... const Type *Ty = C->getType(); // Look up the constant in the table first to ensure uniqueness From lattner at cs.uiuc.edu Thu Apr 17 17:18:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Apr 17 17:18:01 2003 Subject: [llvm-commits] CVS: llvm/lib/AsmParser/Lexer.l Message-ID: <200304172217.RAA11448@apoc.cs.uiuc.edu> Changes in directory llvm/lib/AsmParser: Lexer.l updated: 1.30 -> 1.31 --- Log message: Allow hexadecimal integer constants to be used --- Diffs of the changes: Index: llvm/lib/AsmParser/Lexer.l diff -u llvm/lib/AsmParser/Lexer.l:1.30 llvm/lib/AsmParser/Lexer.l:1.31 --- llvm/lib/AsmParser/Lexer.l:1.30 Wed Apr 16 15:28:31 2003 +++ llvm/lib/AsmParser/Lexer.l Thu Apr 17 17:17:32 2003 @@ -48,10 +48,7 @@ return Result; } -// HexToFP - Convert the ascii string in hexidecimal format to the floating -// point representation of it. -// -static double HexToFP(const char *Buffer) { +static uint64_t HexIntToVal(const char *Buffer) { uint64_t Result = 0; for (; *Buffer; ++Buffer) { uint64_t OldRes = Result; @@ -67,6 +64,15 @@ if (Result < OldRes) // Uh, oh, overflow detected!!! ThrowException("constant bigger than 64 bits detected!"); } + return Result; +} + + +// HexToFP - Convert the ascii string in hexidecimal format to the floating +// point representation of it. +// +static double HexToFP(const char *Buffer) { + uint64_t Result = HexIntToVal(Buffer); assert(sizeof(double) == sizeof(Result) && "Data sizes incompatible on this target!"); @@ -142,6 +148,11 @@ * hexadecimal number for when exponential notation is not precise enough. */ HexFPConstant 0x[0-9A-Fa-f]+ + +/* HexIntConstant - Hexadecimal constant generated by the CFE to avoid forcing + * it to deal with 64 bit numbers. + */ +HexIntConstant [us]0x[0-9A-Fa-f]+ %% {Comment} { /* Ignore comments for now */ } @@ -249,7 +260,10 @@ llvmAsmlval.SInt64Val = -Val; return ESINT64VAL; } - +{HexIntConstant} { + llvmAsmlval.UInt64Val = HexIntToVal(yytext+3); + return yytext[0] == 's' ? ESINT64VAL : EUINT64VAL; + } {EPInteger} { llvmAsmlval.UIntVal = atoull(yytext+1); return UINTVAL; } {ENInteger} { From lattner at cs.uiuc.edu Thu Apr 17 17:20:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Apr 17 17:20:01 2003 Subject: [llvm-commits] CVS: llvm/test/Feature/constexpr.ll Message-ID: <200304172219.RAA11483@apoc.cs.uiuc.edu> Changes in directory llvm/test/Feature: constexpr.ll updated: 1.6 -> 1.7 --- Log message: Add a simple test for hex constant integers --- Diffs of the changes: Index: llvm/test/Feature/constexpr.ll diff -u llvm/test/Feature/constexpr.ll:1.6 llvm/test/Feature/constexpr.ll:1.7 --- llvm/test/Feature/constexpr.ll:1.6 Tue Mar 18 16:53:19 2003 +++ llvm/test/Feature/constexpr.ll Thu Apr 17 17:19:23 2003 @@ -6,6 +6,9 @@ ;; Test constant cast expressions ;;------------------------------- +global ulong u0x00001 ; hexadecimal unsigned integer constants +global long s0x0012312 ; hexadecimal signed integer constants + %t2 = global int* %t1 ;; Forward reference without cast %t3 = global uint* cast (int* %t1 to uint*) ;; Forward reference with cast %t1 = global int 4 ;; int* %0 From lattner at cs.uiuc.edu Thu Apr 17 22:50:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Apr 17 22:50:01 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Transforms/Utils/Cloning.h Message-ID: <200304180349.WAA13199@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/Transforms/Utils: Cloning.h updated: 1.4 -> 1.5 --- Log message: Add prototype for new CloneBasicBlock function --- Diffs of the changes: Index: llvm/include/llvm/Transforms/Utils/Cloning.h diff -u llvm/include/llvm/Transforms/Utils/Cloning.h:1.4 llvm/include/llvm/Transforms/Utils/Cloning.h:1.5 --- llvm/include/llvm/Transforms/Utils/Cloning.h:1.4 Wed Nov 20 14:22:58 2002 +++ llvm/include/llvm/Transforms/Utils/Cloning.h Thu Apr 17 22:49:22 2003 @@ -8,8 +8,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TRANSFORMS_UTIlS_CLONING_H -#define LLVM_TRANSFORMS_UTIlS_CLONING_H +#ifndef LLVM_TRANSFORMS_UTILS_CLONING_H +#define LLVM_TRANSFORMS_UTILS_CLONING_H #include #include @@ -23,6 +23,32 @@ /// CloneModule - Return an exact copy of the specified module /// Module *CloneModule(const Module *M); + +/// CloneBasicBlock - Return a copy of the specified basic block, but without +/// embedding the block into a particular function. The block returned is an +/// exact copy of the specified basic block, without any remapping having been +/// performed. Because of this, this is only suitable for applications where +/// the basic block will be inserted into the same function that it was cloned +/// from (loop unrolling would use this, for example). +/// +/// Also, note that this function makes a direct copy of the basic block, and +/// can thus produce illegal LLVM code. In particular, it will copy any PHI +/// nodes from the original block, even though there are no predecessors for the +/// newly cloned block (thus, phi nodes will have to be updated). Also, this +/// block will branch to the old successors of the original block: these +/// successors will have to have any PHI nodes updated to account for the new +/// incoming edges. +/// +/// The correlation between instructions in the source and result basic blocks +/// is recorded in the ValueMap map. +/// +/// If you have a particular suffix you'd like to use to add to any cloned +/// names, specify it as the optional second parameter. +/// +BasicBlock *CloneBasicBlock(const BasicBlock *BB, + std::map &ValueMap, + const char *NameSuffix = ""); + /// CloneFunction - Return a copy of the specified function, but without /// embedding the function into another module. Also, any references specified From lattner at cs.uiuc.edu Thu Apr 17 22:51:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Apr 17 22:51:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Utils/CloneFunction.cpp Message-ID: <200304180350.WAA13248@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Utils: CloneFunction.cpp updated: 1.15 -> 1.16 --- Log message: Refactor CloneFunction to expose the new CloneBasicBlock function --- Diffs of the changes: Index: llvm/lib/Transforms/Utils/CloneFunction.cpp diff -u llvm/lib/Transforms/Utils/CloneFunction.cpp:1.15 llvm/lib/Transforms/Utils/CloneFunction.cpp:1.16 --- llvm/lib/Transforms/Utils/CloneFunction.cpp:1.15 Wed Apr 16 15:28:43 2003 +++ llvm/lib/Transforms/Utils/CloneFunction.cpp Thu Apr 17 22:50:09 2003 @@ -31,6 +31,25 @@ } } +// CloneBasicBlock - See comments in Cloning.h +BasicBlock *CloneBasicBlock(const BasicBlock *BB, + std::map &ValueMap, + const char *NameSuffix) { + BasicBlock *NewBB = new BasicBlock(""); + if (BB->hasName()) NewBB->setName(BB->getName()+NameSuffix); + + // Loop over all instructions copying them over... + for (BasicBlock::const_iterator II = BB->begin(), IE = BB->end(); + II != IE; ++II) { + Instruction *NewInst = II->clone(); + if (II->hasName()) + NewInst->setName(II->getName()+NameSuffix); + NewBB->getInstList().push_back(NewInst); + ValueMap[II] = NewInst; // Add instruction map to value. + } + return NewBB; +} + // Clone OldFunc into NewFunc, transforming the old arguments into references to // ArgMap values. // @@ -54,20 +73,10 @@ BI != BE; ++BI) { const BasicBlock &BB = *BI; - // Create a new basic block to copy instructions into! - BasicBlock *CBB = new BasicBlock("", NewFunc); - if (BB.hasName()) CBB->setName(BB.getName()+NameSuffix); + // Create a new basic block and copy instructions into it! + BasicBlock *CBB = CloneBasicBlock(&BB, ValueMap, NameSuffix); + NewFunc->getBasicBlockList().push_back(CBB); ValueMap[&BB] = CBB; // Add basic block mapping. - - // Loop over all instructions copying them over... - for (BasicBlock::const_iterator II = BB.begin(), IE = BB.end(); - II != IE; ++II) { - Instruction *NewInst = II->clone(); - if (II->hasName()) - NewInst->setName(II->getName()+NameSuffix); // Name is not cloned... - CBB->getInstList().push_back(NewInst); - ValueMap[II] = NewInst; // Add instruction map to value. - } if (ReturnInst *RI = dyn_cast(CBB->getTerminator())) Returns.push_back(RI); From lattner at cs.uiuc.edu Thu Apr 17 22:51:03 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Apr 17 22:51:03 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Utils/ValueMapper.cpp Message-ID: <200304180350.WAA13254@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Utils: ValueMapper.cpp updated: 1.3 -> 1.4 --- Log message: New const_cast instead of c style cast --- Diffs of the changes: Index: llvm/lib/Transforms/Utils/ValueMapper.cpp diff -u llvm/lib/Transforms/Utils/ValueMapper.cpp:1.3 llvm/lib/Transforms/Utils/ValueMapper.cpp:1.4 --- llvm/lib/Transforms/Utils/ValueMapper.cpp:1.3 Sun Jan 12 18:52:25 2003 +++ llvm/lib/Transforms/Utils/ValueMapper.cpp Thu Apr 17 22:49:49 2003 @@ -13,7 +13,7 @@ Value *&VMSlot = VM[V]; if (VMSlot) return VMSlot; // Does it exist in the map yet? - if (Constant *C = (Constant*)dyn_cast(V)) { + if (Constant *C = const_cast(dyn_cast(V))) { if (isa(C) || isa(C) || isa(C)) return VMSlot = C; // Primitive constants map directly From lattner at cs.uiuc.edu Thu Apr 17 23:13:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Apr 17 23:13:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Bytecode/Reader/Reader.cpp Message-ID: <200304180412.XAA15971@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Bytecode/Reader: Reader.cpp updated: 1.50 -> 1.51 --- Log message: Fix a big bad bug I checked in yesterday :( --- Diffs of the changes: Index: llvm/lib/Bytecode/Reader/Reader.cpp diff -u llvm/lib/Bytecode/Reader/Reader.cpp:1.50 llvm/lib/Bytecode/Reader/Reader.cpp:1.51 --- llvm/lib/Bytecode/Reader/Reader.cpp:1.50 Wed Apr 16 16:16:03 2003 +++ llvm/lib/Bytecode/Reader/Reader.cpp Thu Apr 17 23:11:56 2003 @@ -306,7 +306,7 @@ if (!hasInternalMarkerOnly) { unsigned LinkageType; if (read_vbr(Buf, EndBuf, LinkageType)) return true; - if (LinkageType & 0x3) return true; + if (LinkageType & ~0x3) return true; Linkage = (GlobalValue::LinkageTypes)LinkageType; } else { // We used to only support two linkage models: internal and external From lattner at cs.uiuc.edu Thu Apr 17 23:35:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Apr 17 23:35:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/ConstantMerge.cpp Message-ID: <200304180434.XAA17301@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: ConstantMerge.cpp updated: 1.18 -> 1.19 --- Log message: Global constants CAN be external --- Diffs of the changes: Index: llvm/lib/Transforms/IPO/ConstantMerge.cpp diff -u llvm/lib/Transforms/IPO/ConstantMerge.cpp:1.18 llvm/lib/Transforms/IPO/ConstantMerge.cpp:1.19 --- llvm/lib/Transforms/IPO/ConstantMerge.cpp:1.18 Wed Oct 9 18:16:04 2002 +++ llvm/lib/Transforms/IPO/ConstantMerge.cpp Thu Apr 17 23:34:29 2003 @@ -1,4 +1,4 @@ -//===- ConstantMerge.cpp - Merge duplicate global constants -----------------=// +//===- ConstantMerge.cpp - Merge duplicate global constants ---------------===// // // This file defines the interface to a pass that merges duplicate global // constants together into a single constant that is shared. This is useful @@ -36,8 +36,8 @@ bool MadeChanges = false; for (Module::giterator GV = M.gbegin(), E = M.gend(); GV != E; ++GV) - if (GV->isConstant()) { // Only process constants - assert(GV->hasInitializer() && "Globals constants must have inits!"); + // Only process constants with initializers + if (GV->isConstant() && GV->hasInitializer()) { Constant *Init = GV->getInitializer(); // Check to see if the initializer is already known... From jstanley at cs.uiuc.edu Fri Apr 18 12:26:01 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Fri Apr 18 12:26:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/Inst/InstManip.h Phases.cpp design.txt Message-ID: <200304181729.MAA07782@cypher.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/Inst: InstManip.h updated: 1.7 -> 1.8 Phases.cpp updated: 1.11 -> 1.12 design.txt updated: 1.8 -> 1.9 --- Log message: Reading GBT contents correctly. Preliminary load-tag matching now working. --- Diffs of the changes: Index: llvm/lib/Reoptimizer/Inst/InstManip.h diff -u llvm/lib/Reoptimizer/Inst/InstManip.h:1.7 llvm/lib/Reoptimizer/Inst/InstManip.h:1.8 --- llvm/lib/Reoptimizer/Inst/InstManip.h:1.7 Tue Apr 15 16:26:19 2003 +++ llvm/lib/Reoptimizer/Inst/InstManip.h Fri Apr 18 12:29:00 2003 @@ -5,7 +5,7 @@ // purpose: InstManip is a wrapper class around any BinInterface macros/mechanisms, as // well as the TraceCache "instruction utilities", all which are (currently) // SparcV9-specific. This class exists both for conceptual clarity and to facilitate -// the hiding of Sparc-specific code from the Phase2/3 actions (and thus making it +// the hiding of Sparc-specific code from the Phase 2-4 actions (and thus making it // easier to use the transformations on other platforms in the future; we should be // able to change which instruction manipulator object is instantiated, after making // the appropriate superclass, etc). Index: llvm/lib/Reoptimizer/Inst/Phases.cpp diff -u llvm/lib/Reoptimizer/Inst/Phases.cpp:1.11 llvm/lib/Reoptimizer/Inst/Phases.cpp:1.12 --- llvm/lib/Reoptimizer/Inst/Phases.cpp:1.11 Tue Apr 15 16:26:19 2003 +++ llvm/lib/Reoptimizer/Inst/Phases.cpp Fri Apr 18 12:29:00 2003 @@ -74,6 +74,17 @@ using std::cerr; using std::endl; +// Description of GBT contents emitted by phase 1. The extern reference to the GBT will be +// resolved at link-time, and will point to the GBT itself. The size of the GBT is +// obtained in the same manner. + +extern unsigned ppGBTSize; +extern struct PrimInfo { + unsigned gbtType; + unsigned short* loadVar; + unsigned gbtStartIdx; +} ppGBT[]; + typedef std::pair AddressRange; class Phase3Info @@ -223,7 +234,7 @@ AddressRange range; while(elfReader.GetNextFunction(funcName, range)) { - if(funcName == "l16_fibs") { + if(funcName == "fibs") { //cerr << "Printing information about function " << funcName << endl; //m_instManip.printRange(range.first, range.second); @@ -325,8 +336,6 @@ // write to it. However, it does indeed pose a problem for multi-threaded codes. A // modification to the general mechanism itself is required to achieve thread-safety. - cerr << "About to deallocate phase2-created slot" << endl; - uint64_t slotBase = m_pPhase3Info->getSlot(); unsigned slotSize = m_pPhase3Info->getSlotSize(); m_pTraceCache->getMemMgr()->freeTraceMemory(slotBase, slotSize); @@ -428,4 +437,18 @@ p4info->getTraceCache()->getVM()->writeInstToVM(p4info->getCandidate().front().first, p4info->getCandidate().front().second); delete p4info; + + cerr << "ppGBT is: " << ppGBT << endl; + cerr << "ppGBTSize is: " << ppGBTSize << endl; + + for(int i = 0; i < ppGBTSize; ++i) { + cerr << "ppGBT[" << i << "]: " << ppGBT[i].gbtType << ", " + << ppGBT[i].loadVar << ", " << ppGBT[i].gbtStartIdx << endl; + } + + // tmp + if(tag == (uint64_t)(ppGBT[0].loadVar)) { + cerr << "TAG MATCHES, BOYYYYYYYYYYY!" << endl; + } + // tmp } Index: llvm/lib/Reoptimizer/Inst/design.txt diff -u llvm/lib/Reoptimizer/Inst/design.txt:1.8 llvm/lib/Reoptimizer/Inst/design.txt:1.9 --- llvm/lib/Reoptimizer/Inst/design.txt:1.8 Thu Apr 10 17:34:16 2003 +++ llvm/lib/Reoptimizer/Inst/design.txt Fri Apr 18 12:29:00 2003 @@ -920,6 +920,37 @@ Approach B: Other phases use heap-managed dynamic memory; no dummy function needed. + GBT construction: + + In the KIS prototype implementation, the GBT will be an array of structs. Each + struct will contain: + + - The type of metric (i.e. COUNTER, POINT, REGION) + + - The pointer to the global volatile whose load represents an instrumentation + site. + + - Other information, such as what function to call, etc. + + The complicated thing that must be handled here is how to relate interval metrics + to each other in a pairwise manner. Consider the following scenario: Phase 4 is + triggered for a particular start interval site, and the GBT is consulted to + determine that the candidate is indeed a load-volatile. A new slot is written + containing the call to the instrumentation code, etc, together with an alloca for + the temporary, etc. So far, so good. Now...we must pass the address of this + alloca'd temporary to the function invoked at the end-interval site. However, when + we encounter the end-interval site, all we do is look up in the GBT and determine + that we have a valid load-volatile site. What we need is two distinct types to + describe the struct contents: INTERVAL_START, and INTERVAL_END: + + If INTERVAL_START, we have a link to the alloca'd temporary, and that is stored + when the start-interval site is processed. If INTERVAL_END, we have a link back to + the corresponding INTERVAL_START record, which contains the link to the alloca'd + temporary. Since the intervals are pairwise-processed in Phase 1 (although this + needs to be made more robust, etc, it is clear that the pairwise matching ought to + be done at the sigfun/parser level as opposed to at the machine code level), the + structure records can indeed be constructed in this manner. + In phase 2: On program startup ("phase 2" function called from main()): From lattner at cs.uiuc.edu Fri Apr 18 14:23:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Apr 18 14:23:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/Mem2Reg/2003-04-18-DeadBlockProblem.ll Message-ID: <200304181922.OAA10727@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/Mem2Reg: 2003-04-18-DeadBlockProblem.ll added (r1.1) --- Log message: New testcase --- Diffs of the changes: Index: llvm/test/Regression/Transforms/Mem2Reg/2003-04-18-DeadBlockProblem.ll diff -c /dev/null llvm/test/Regression/Transforms/Mem2Reg/2003-04-18-DeadBlockProblem.ll:1.1 *** /dev/null Fri Apr 18 14:22:50 2003 --- llvm/test/Regression/Transforms/Mem2Reg/2003-04-18-DeadBlockProblem.ll Fri Apr 18 14:22:39 2003 *************** *** 0 **** --- 1,17 ---- + ; This testcases makes sure that mem2reg can handle unreachable blocks. + ; RUN: as < %s | opt -mem2reg + + int %test() { + %X = alloca int + + store int 6, int* %X + br label %Loop + Loop: + store int 5, int* %X + br label %EndOfLoop + Unreachable: + br label %EndOfLoop + + EndOfLoop: + br label %Loop + } From lattner at cs.uiuc.edu Fri Apr 18 14:26:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Apr 18 14:26:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp Message-ID: <200304181925.OAA10797@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Utils: PromoteMemoryToRegister.cpp updated: 1.37 -> 1.38 --- Log message: Fix bug: Mem2reg/2003-04-18-DeadBlockProblem.ll --- Diffs of the changes: Index: llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp diff -u llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp:1.37 llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp:1.38 --- llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp:1.37 Thu Apr 10 14:41:13 2003 +++ llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp Fri Apr 18 14:25:22 2003 @@ -24,6 +24,7 @@ #include "llvm/Function.h" #include "llvm/Constant.h" #include "llvm/Type.h" +#include "llvm/Support/CFG.h" #include "Support/StringExtras.h" /// isAllocaPromotable - Return true if this alloca is legal for promotion. @@ -187,11 +188,20 @@ if (BBPNs[AllocaNo]) return false; // Create a PhiNode using the dereferenced type... and add the phi-node to the - // BasicBlock + // BasicBlock. PHINode *PN = new PHINode(Allocas[AllocaNo]->getAllocatedType(), Allocas[AllocaNo]->getName() + "." + utostr(VersionNumbers[AllocaNo]++), BB->begin()); + + // Add null incoming values for all predecessors. This ensures that if one of + // the predecessors is not found in the depth-first traversal of the CFG (ie, + // because it is an unreachable predecessor), that all PHI nodes will have the + // correct number of entries for their predecessors. + Value *NullVal = Constant::getNullValue(PN->getType()); + for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB); PI != PE; ++PI) + PN->addIncoming(NullVal, *PI); + BBPNs[AllocaNo] = PN; PhiNodes[AllocaNo].push_back(BB); return true; @@ -205,9 +215,12 @@ std::vector &BBPNs = NewPhiNodes[BB]; for (unsigned k = 0; k != BBPNs.size(); ++k) if (PHINode *PN = BBPNs[k]) { - // at this point we can assume that the array has phi nodes.. let's add - // the incoming data - PN->addIncoming(IncomingVals[k], Pred); + int BBI = PN->getBasicBlockIndex(Pred); + assert(BBI >= 0 && "Predecessor not in basic block yet!"); + + // At this point we can assume that the array has phi nodes.. let's update + // the incoming data. + PN->setIncomingValue(BBI, IncomingVals[k]); // also note that the active variable IS designated by the phi node IncomingVals[k] = PN; From lattner at cs.uiuc.edu Fri Apr 18 18:02:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Apr 18 18:02:01 2003 Subject: [llvm-commits] CVS: llvm/tools/gccld/gccld.cpp Message-ID: <200304182301.SAA15246@apoc.cs.uiuc.edu> Changes in directory llvm/tools/gccld: gccld.cpp updated: 1.23 -> 1.24 --- Log message: Use anonymous namespace instead of "static" Kill using decl --- Diffs of the changes: Index: llvm/tools/gccld/gccld.cpp diff -u llvm/tools/gccld/gccld.cpp:1.23 llvm/tools/gccld/gccld.cpp:1.24 --- llvm/tools/gccld/gccld.cpp:1.23 Wed Apr 16 16:43:22 2003 +++ llvm/tools/gccld/gccld.cpp Fri Apr 18 18:01:25 2003 @@ -28,34 +28,34 @@ #include #include // For FileExists #include -using std::cerr; - -static cl::list -InputFilenames(cl::Positional, cl::desc(""), - cl::OneOrMore); - -static cl::opt -OutputFilename("o", cl::desc("Override output filename"), cl::init("a.out"), - cl::value_desc("filename")); - -static cl::opt -Verbose("v", cl::desc("Print information about actions taken")); - -static cl::list -LibPaths("L", cl::desc("Specify a library search path"), cl::Prefix, - cl::value_desc("directory")); - -static cl::list -Libraries("l", cl::desc("Specify libraries to link to"), cl::Prefix, - cl::value_desc("library prefix")); - -static cl::opt -Strip("s", cl::desc("Strip symbol info from executable")); - -static cl::opt -NoInternalize("disable-internalize", - cl::desc("Do not mark all symbols as internal")); +namespace { + cl::list + InputFilenames(cl::Positional, cl::desc(""), + cl::OneOrMore); + + cl::opt + OutputFilename("o", cl::desc("Override output filename"), cl::init("a.out"), + cl::value_desc("filename")); + + cl::opt + Verbose("v", cl::desc("Print information about actions taken")); + + cl::list + LibPaths("L", cl::desc("Specify a library search path"), cl::Prefix, + cl::value_desc("directory")); + + cl::list + Libraries("l", cl::desc("Specify libraries to link to"), cl::Prefix, + cl::value_desc("library prefix")); + + cl::opt + Strip("s", cl::desc("Strip symbol info from executable")); + + cl::opt + NoInternalize("disable-internalize", + cl::desc("Do not mark all symbols as internal")); +} // FileExists - Return true if the specified string is an openable file... static inline bool FileExists(const std::string &FN) { @@ -74,15 +74,15 @@ bool FoundAFile = false; while (1) { - if (Verbose) cerr << "Loading '" << Filename << "'\n"; + if (Verbose) std::cerr << "Loading '" << Filename << "'\n"; if (FileExists(Filename)) FoundAFile = true; Module *Result = ParseBytecodeFile(Filename, &ErrorMessage); if (Result) return std::auto_ptr(Result); // Load successful! if (Verbose) { - cerr << "Error opening bytecode file: '" << Filename << "'"; - if (ErrorMessage.size()) cerr << ": " << ErrorMessage; - cerr << "\n"; + std::cerr << "Error opening bytecode file: '" << Filename << "'"; + if (ErrorMessage.size()) std::cerr << ": " << ErrorMessage; + std::cerr << "\n"; } if (NextLibPathIdx == LibPaths.size()) break; @@ -90,10 +90,10 @@ } if (FoundAFile) - cerr << "Bytecode file '" << FN << "' corrupt! " - << "Use 'gccld -v ...' for more info.\n"; + std::cerr << "Bytecode file '" << FN << "' corrupt! " + << "Use 'gccld -v ...' for more info.\n"; else - cerr << "Could not locate bytecode file: '" << FN << "'\n"; + std::cerr << "Could not locate bytecode file: '" << FN << "'\n"; return std::auto_ptr(); } @@ -124,11 +124,11 @@ std::auto_ptr M(LoadFile(InputFilenames[i])); if (M.get() == 0) return 1; - if (Verbose) cerr << "Linking in '" << InputFilenames[i] << "'\n"; + if (Verbose) std::cerr << "Linking in '" << InputFilenames[i] << "'\n"; if (LinkModules(Composite.get(), M.get(), &ErrorMessage)) { - cerr << argv[0] << ": error linking in '" << InputFilenames[i] << "': " - << ErrorMessage << "\n"; + std::cerr << argv[0] << ": error linking in '" << InputFilenames[i] + << "': " << ErrorMessage << "\n"; return 1; } } @@ -172,8 +172,8 @@ // Add the pass that writes bytecode to the output file... std::ofstream Out((OutputFilename+".bc").c_str()); if (!Out.good()) { - cerr << argv[0] << ": error opening '" << OutputFilename - << ".bc' for writing!\n"; + std::cerr << argv[0] << ": error opening '" << OutputFilename + << ".bc' for writing!\n"; return 1; } Passes.add(new WriteBytecodePass(&Out)); // Write bytecode to file... @@ -188,8 +188,8 @@ // Output the script to start the program... std::ofstream Out2(OutputFilename.c_str()); if (!Out2.good()) { - cerr << argv[0] << ": error opening '" << OutputFilename - << "' for writing!\n"; + std::cerr << argv[0] << ": error opening '" << OutputFilename + << "' for writing!\n"; return 1; } Out2 << "#!/bin/sh\nlli -q -abort-on-exception $0.bc $*\n"; From lattner at cs.uiuc.edu Fri Apr 18 18:39:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Apr 18 18:39:00 2003 Subject: [llvm-commits] CVS: llvm/tools/gccas/gccas.cpp Message-ID: <200304182338.SAA19239@apoc.cs.uiuc.edu> Changes in directory llvm/tools/gccas: gccas.cpp updated: 1.57 -> 1.58 --- Log message: Eliminate some compatibility stuff no longer needed :P --- Diffs of the changes: Index: llvm/tools/gccas/gccas.cpp diff -u llvm/tools/gccas/gccas.cpp:1.57 llvm/tools/gccas/gccas.cpp:1.58 --- llvm/tools/gccas/gccas.cpp:1.57 Wed Apr 16 12:49:18 2003 +++ llvm/tools/gccas/gccas.cpp Fri Apr 18 18:38:09 2003 @@ -40,13 +40,6 @@ cl::opt Verify("verify", cl::desc("Verify each pass result")); - - - cl::opt // Be compatible with what GCC expects - QOption("Q", cl::desc("Compatibility option (ignored)"), - cl::Hidden, cl::Prefix); - cl::opt - PrintVersion("V", cl::desc("Print GCCAS version number"), cl::Hidden); } @@ -148,9 +141,6 @@ std::cerr << argv[0] << ": error opening " << OutputFilename << "!\n"; return 1; } - - if (PrintVersion) /* For GNU compatibility */ - std::cerr << "LLVM GCCAS version xx\n" << std::flush; // In addition to just parsing the input from GCC, we also want to spiff it up // a little bit. Do this now. From lattner at cs.uiuc.edu Fri Apr 18 18:39:03 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Apr 18 18:39:03 2003 Subject: [llvm-commits] CVS: llvm/tools/gccld/gccld.cpp Message-ID: <200304182338.SAA19263@apoc.cs.uiuc.edu> Changes in directory llvm/tools/gccld: gccld.cpp updated: 1.24 -> 1.25 --- Log message: Add crufty compatibility stuff for ld --- Diffs of the changes: Index: llvm/tools/gccld/gccld.cpp diff -u llvm/tools/gccld/gccld.cpp:1.24 llvm/tools/gccld/gccld.cpp:1.25 --- llvm/tools/gccld/gccld.cpp:1.24 Fri Apr 18 18:01:25 2003 +++ llvm/tools/gccld/gccld.cpp Fri Apr 18 18:38:22 2003 @@ -55,6 +55,14 @@ cl::opt NoInternalize("disable-internalize", cl::desc("Do not mark all symbols as internal")); + + // Compatibility options that are ignored, but support by LD + cl::opt + CO3("soname", cl::Hidden, cl::desc("Compatibility option: ignored")); + cl::opt + CO4("version-script", cl::Hidden, cl::desc("Compatibility option: ignored")); + cl::opt + CO5("eh-frame-hdr", cl::Hidden, cl::desc("Compatibility option: ignored")); } // FileExists - Return true if the specified string is an openable file... From lattner at cs.uiuc.edu Fri Apr 18 18:47:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Apr 18 18:47:00 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/FunctionResolve/2003-04-18-ForwardDeclGlobal.ll Message-ID: <200304182346.SAA19534@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/FunctionResolve: 2003-04-18-ForwardDeclGlobal.ll added (r1.1) --- Log message: Test case for forward declared global array with no size --- Diffs of the changes: Index: llvm/test/Regression/Transforms/FunctionResolve/2003-04-18-ForwardDeclGlobal.ll diff -c /dev/null llvm/test/Regression/Transforms/FunctionResolve/2003-04-18-ForwardDeclGlobal.ll:1.1 *** /dev/null Fri Apr 18 18:46:54 2003 --- llvm/test/Regression/Transforms/FunctionResolve/2003-04-18-ForwardDeclGlobal.ll Fri Apr 18 18:46:44 2003 *************** *** 0 **** --- 1,13 ---- + ; RUN: if as < %s | opt -funcresolve -disable-output 2>&1 | grep WARNING + ; RUN: then exit 1 + ; RUN: else exit 0 + ; RUN: fi + %__popcount_tab = external constant [0 x ubyte] + %__popcount_tab = constant [4 x ubyte] c"\00\01\01\02" + + void %test() { + getelementptr [0 x ubyte]* %__popcount_tab, long 0, long 2 + getelementptr [4 x ubyte]* %__popcount_tab, long 0, long 2 + ret void + } + From lattner at cs.uiuc.edu Fri Apr 18 19:16:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Apr 18 19:16:00 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/FunctionResolve/2003-04-18-ForwardDeclGlobal.ll Message-ID: <200304190015.TAA19901@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/FunctionResolve: 2003-04-18-ForwardDeclGlobal.ll updated: 1.1 -> 1.2 --- Log message: Add testcase for constantexpr gep --- Diffs of the changes: Index: llvm/test/Regression/Transforms/FunctionResolve/2003-04-18-ForwardDeclGlobal.ll diff -u llvm/test/Regression/Transforms/FunctionResolve/2003-04-18-ForwardDeclGlobal.ll:1.1 llvm/test/Regression/Transforms/FunctionResolve/2003-04-18-ForwardDeclGlobal.ll:1.2 --- llvm/test/Regression/Transforms/FunctionResolve/2003-04-18-ForwardDeclGlobal.ll:1.1 Fri Apr 18 18:46:44 2003 +++ llvm/test/Regression/Transforms/FunctionResolve/2003-04-18-ForwardDeclGlobal.ll Fri Apr 18 19:15:00 2003 @@ -5,9 +5,12 @@ %__popcount_tab = external constant [0 x ubyte] %__popcount_tab = constant [4 x ubyte] c"\00\01\01\02" +declare void %foo(ubyte *) + void %test() { getelementptr [0 x ubyte]* %__popcount_tab, long 0, long 2 getelementptr [4 x ubyte]* %__popcount_tab, long 0, long 2 + call void %foo(ubyte * getelementptr ([0 x ubyte]* %__popcount_tab, long 0, long 2)) ret void } From lattner at cs.uiuc.edu Fri Apr 18 19:16:03 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Apr 18 19:16:03 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/FunctionResolution.cpp Message-ID: <200304190015.TAA19910@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: FunctionResolution.cpp updated: 1.24 -> 1.25 --- Log message: Implement: FunctionResolve/2003-04-18-ForwardDeclGlobal.ll --- Diffs of the changes: Index: llvm/lib/Transforms/IPO/FunctionResolution.cpp diff -u llvm/lib/Transforms/IPO/FunctionResolution.cpp:1.24 llvm/lib/Transforms/IPO/FunctionResolution.cpp:1.25 --- llvm/lib/Transforms/IPO/FunctionResolution.cpp:1.24 Wed Apr 16 17:40:47 2003 +++ llvm/lib/Transforms/IPO/FunctionResolution.cpp Fri Apr 18 19:15:27 2003 @@ -201,30 +201,23 @@ "Concrete version should be an array type!"); // Get the type of the things that may be resolved to us... - const Type *AETy = - cast(Concrete->getType()->getElementType())->getElementType(); + const ArrayType *CATy =cast(Concrete->getType()->getElementType()); + const Type *AETy = CATy->getElementType(); + + Constant *CCPR = ConstantPointerRef::get(Concrete); - std::vector Args; - Args.push_back(Constant::getNullValue(Type::LongTy)); - Args.push_back(Constant::getNullValue(Type::LongTy)); - Constant *Replacement = - ConstantExpr::getGetElementPtr(ConstantPointerRef::get(Concrete), Args); - for (unsigned i = 0; i != Globals.size(); ++i) if (Globals[i] != Concrete) { GlobalVariable *Old = cast(Globals[i]); - if (Old->getType()->getElementType() != AETy) { + const ArrayType *OATy = cast(Old->getType()->getElementType()); + if (OATy->getElementType() != AETy || OATy->getNumElements() != 0) { std::cerr << "WARNING: Two global variables exist with the same name " << "that cannot be resolved!\n"; return false; } - // In this case, Old is a pointer to T, Concrete is a pointer to array of - // T. Because of this, replace all uses of Old with a constantexpr - // getelementptr that returns the address of the first element of the - // array. - // - Old->replaceAllUsesWith(Replacement); + Old->replaceAllUsesWith(ConstantExpr::getCast(CCPR, Old->getType())); + // Since there are no uses of Old anymore, remove it from the module. M.getGlobalList().erase(Old); @@ -239,7 +232,6 @@ assert(!Globals.empty() && "Globals list shouldn't be empty here!"); bool isFunction = isa(Globals[0]); // Is this group all functions? - bool Changed = false; GlobalValue *Concrete = 0; // The most concrete implementation to resolve to assert((isFunction ^ isa(Globals[0])) && @@ -271,32 +263,36 @@ } else { Concrete = F; } - ++i; } else { // For global variables, we have to merge C definitions int A[][4] with - // int[6][4] + // int[6][4]. A[][4] is represented as A[0][4] by the CFE. GlobalVariable *GV = cast(Globals[i]); - if (Concrete == 0) { - if (isa(GV->getType()->getElementType())) - Concrete = GV; - } else { // Must have different types... one is an array of the other? - const ArrayType *AT = - dyn_cast(GV->getType()->getElementType()); - - // If GV is an array of Concrete, then GV is the array. - if (AT && AT->getElementType() == Concrete->getType()->getElementType()) - Concrete = GV; - else { - // Concrete must be an array type, check to see if the element type of - // concrete is already GV. - AT = cast(Concrete->getType()->getElementType()); - if (AT->getElementType() != GV->getType()->getElementType()) - Concrete = 0; // Don't know how to handle it! + if (!isa(GV->getType()->getElementType())) { + Concrete = 0; + break; // Non array's cannot be compatible with other types. + } else if (Concrete == 0) { + Concrete = GV; + } else { + // Must have different types... allow merging A[0][4] w/ A[6][4] if + // A[0][4] is external. + const ArrayType *NAT = cast(GV->getType()->getElementType()); + const ArrayType *CAT = + cast(Concrete->getType()->getElementType()); + + if (NAT->getElementType() != CAT->getElementType()) { + Concrete = 0; // Non-compatible types + break; + } else if (NAT->getNumElements() == 0 && GV->isExternal()) { + // Concrete remains the same + } else if (CAT->getNumElements() == 0 && Concrete->isExternal()) { + Concrete = GV; // Concrete becomes GV + } else { + Concrete = 0; // Cannot merge these types... + break; } } - - ++i; } + ++i; } if (Globals.size() > 1) { // Found a multiply defined global... @@ -305,23 +301,23 @@ // uses to use it instead. // if (!Concrete) { - std::cerr << "WARNING: Found function types that are not compatible:\n"; + std::cerr << "WARNING: Found global types that are not compatible:\n"; for (unsigned i = 0; i < Globals.size(); ++i) { std::cerr << "\t" << Globals[i]->getType()->getDescription() << " %" << Globals[i]->getName() << "\n"; } std::cerr << " No linkage of globals named '" << Globals[0]->getName() << "' performed!\n"; - return Changed; + return false; } if (isFunction) - return Changed | ResolveFunctions(M, Globals, cast(Concrete)); + return ResolveFunctions(M, Globals, cast(Concrete)); else - return Changed | ResolveGlobalVariables(M, Globals, - cast(Concrete)); + return ResolveGlobalVariables(M, Globals, + cast(Concrete)); } - return Changed; + return false; } bool FunctionResolvingPass::run(Module &M) { From lattner at cs.uiuc.edu Fri Apr 18 19:18:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Apr 18 19:18:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/FunctionResolve/2002-08-19-ResolveGlobalVars.ll 2002-08-19-ResolveGlobalVarsEasier.ll Message-ID: <200304190017.TAA19968@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/FunctionResolve: 2002-08-19-ResolveGlobalVars.ll updated: 1.3 -> 1.4 2002-08-19-ResolveGlobalVarsEasier.ll updated: 1.1 -> 1.2 --- Log message: Update testcases to match what is currently output by the CFE --- Diffs of the changes: Index: llvm/test/Regression/Transforms/FunctionResolve/2002-08-19-ResolveGlobalVars.ll diff -u llvm/test/Regression/Transforms/FunctionResolve/2002-08-19-ResolveGlobalVars.ll:1.3 llvm/test/Regression/Transforms/FunctionResolve/2002-08-19-ResolveGlobalVars.ll:1.4 --- llvm/test/Regression/Transforms/FunctionResolve/2002-08-19-ResolveGlobalVars.ll:1.3 Wed Oct 9 15:55:32 2002 +++ llvm/test/Regression/Transforms/FunctionResolve/2002-08-19-ResolveGlobalVars.ll Fri Apr 18 19:17:11 2003 @@ -12,15 +12,15 @@ ; RUN: fi ; -%X = external global int +%X = external global [0 x int] %X = global [4 x int] [ int 1, int 2, int 3, int 4 ] implementation ; Functions: int %foo(int %x) { bb1: ;[#uses=0] - store int 5, int* getelementptr (int* %X, long 2) - %F = getelementptr int* %X, long 2 + store int 5, int* getelementptr ([0 x int]* %X, long 0, long 2) + %F = getelementptr [0 x int]* %X, long 0, long 2 %val = load int* %F ret int %val } Index: llvm/test/Regression/Transforms/FunctionResolve/2002-08-19-ResolveGlobalVarsEasier.ll diff -u llvm/test/Regression/Transforms/FunctionResolve/2002-08-19-ResolveGlobalVarsEasier.ll:1.1 llvm/test/Regression/Transforms/FunctionResolve/2002-08-19-ResolveGlobalVarsEasier.ll:1.2 --- llvm/test/Regression/Transforms/FunctionResolve/2002-08-19-ResolveGlobalVarsEasier.ll:1.1 Wed Oct 9 15:37:13 2002 +++ llvm/test/Regression/Transforms/FunctionResolve/2002-08-19-ResolveGlobalVarsEasier.ll Fri Apr 18 19:17:11 2003 @@ -7,16 +7,16 @@ ; RUN: fi ; -%X = external global int +%X = external global [0 x int] %X = global [4 x int] [ int 1, int 2, int 3, int 4 ] implementation ; Functions: int %foo(int %x) { bb1: ;[#uses=0] - %G = getelementptr int* %X, long 1 + %G = getelementptr [0 x int]* %X, long 0, long 1 store int 5, int* %G - %F = getelementptr int* %X, long 2 + %F = getelementptr [0 x int]* %X, long 0, long 2 %val = load int* %F ret int %val } From lattner at cs.uiuc.edu Fri Apr 18 19:51:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Apr 18 19:51:01 2003 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Verifier.cpp Message-ID: <200304190050.TAA28513@apoc.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: Verifier.cpp updated: 1.45 -> 1.46 --- Log message: Remove arbitrary limitation --- Diffs of the changes: Index: llvm/lib/VMCore/Verifier.cpp diff -u llvm/lib/VMCore/Verifier.cpp:1.45 llvm/lib/VMCore/Verifier.cpp:1.46 --- llvm/lib/VMCore/Verifier.cpp:1.45 Wed Apr 16 15:42:40 2003 +++ llvm/lib/VMCore/Verifier.cpp Fri Apr 18 19:50:37 2003 @@ -210,7 +210,6 @@ const FunctionType *FT = F.getFunctionType(); unsigned NumArgs = F.getArgumentList().size(); - Assert2(!FT->isVarArg(), "Cannot define varargs functions in LLVM!", &F, FT); Assert2(FT->getNumParams() == NumArgs, "# formal arguments must match # of arguments for function type!", &F, FT); From lattner at cs.uiuc.edu Sat Apr 19 16:46:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sat Apr 19 16:46:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Bytecode/Reader/ReadArchive.cpp Message-ID: <200304192145.QAA09661@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Bytecode/Reader: ReadArchive.cpp added (r1.1) --- Log message: Initial support for reading standard .a files --- Diffs of the changes: Index: llvm/lib/Bytecode/Reader/ReadArchive.cpp diff -c /dev/null llvm/lib/Bytecode/Reader/ReadArchive.cpp:1.1 *** /dev/null Sat Apr 19 16:45:44 2003 --- llvm/lib/Bytecode/Reader/ReadArchive.cpp Sat Apr 19 16:45:34 2003 *************** *** 0 **** --- 1,166 ---- + //===- ReadArchive.cpp - Code to read LLVM bytecode from .a files ---------===// + // + // This file implements the ReadArchiveFile interface, which allows a linker to + // read all of the LLVM bytecode files contained in a .a file. This file + // understands the standard system .a file format. This can only handle the .a + // variant prevelant on linux systems so far, but may be extended. See + // information in this source file for more information: + // http://sources.redhat.com/cgi-bin/cvsweb.cgi/src/bfd/archive.c?cvsroot=src + // + //===----------------------------------------------------------------------===// + + #include "llvm/Bytecode/Reader.h" + #include "llvm/Module.h" + #include + #include + #include + + namespace { + struct ar_hdr { + char name[16]; + char date[12]; + char uid[6]; + char gid[6]; + char mode[8]; + char size[10]; + char fmag[2]; // Always equal to '`\n' + }; + + enum ObjectType { + UserObject, // A user .o/.bc file + Unknown, // Unknown file, just ignore it + SVR4LongFilename, // a "//" section used for long file names + }; + } + + + // getObjectType - Determine the type of object that this header represents. + // This is capable of parsing the variety of special sections used for various + // purposes. + static enum ObjectType getObjectType(ar_hdr *H, unsigned Size) { + // Check for sections with special names... + if (!memcmp(H->name, "// ", 16)) + return SVR4LongFilename; + + // Check to see if it looks like an llvm object file... + if (Size >= 4 && !memcmp(H+1, "llvm", 4)) + return UserObject; + + return Unknown; + } + + + static inline bool Error(std::string *ErrorStr, const char *Message) { + if (ErrorStr) *ErrorStr = Message; + return true; + } + + static bool ParseLongFilenameSection(unsigned char *Buffer, unsigned Size, + std::vector &LongFilenames, + std::string *S) { + if (!LongFilenames.empty()) + return Error(S, "archive file contains multiple long filename entries"); + + while (Size) { + // Long filename entries are newline delimited to keep the archive readable. + unsigned char *Ptr = (unsigned char*)memchr(Buffer, '\n', Size); + if (Ptr == 0) + return Error(S, "archive long filename entry doesn't end with newline!"); + assert(*Ptr == '\n'); + + if (Ptr == Buffer) break; // Last entry contains just a newline. + + unsigned char *End = Ptr; + if (End[-1] == '/') --End; // Remove trailing / from name + + LongFilenames.push_back(std::string(Buffer, End)); + Size -= Ptr-Buffer+1; + Buffer = Ptr+1; + } + + return false; + } + + + static bool ReadArchiveBuffer(unsigned char *Buffer, unsigned Length, + std::vector &Objects, + std::string *ErrorStr) { + if (Length < 8 || memcmp(Buffer, "!\n", 8)) + return Error(ErrorStr, "signature incorrect for an archive file!"); + Buffer += 8; Length -= 8; // Skip the magic string. + + std::vector LongFilenames; + + while (Length >= sizeof(ar_hdr)) { + ar_hdr *Hdr = (ar_hdr*)Buffer; + unsigned Size = atoi(Hdr->size); + if (Size+sizeof(ar_hdr) > Length) + return Error(ErrorStr, "invalid record length in archive file!"); + + switch (getObjectType(Hdr, Size)) { + case SVR4LongFilename: + // If this is a long filename section, read all of the file names into the + // LongFilenames vector. + // + if (ParseLongFilenameSection(Buffer+sizeof(ar_hdr), Size, + LongFilenames, ErrorStr)) + return true; + break; + case UserObject: { + Module *M = ParseBytecodeBuffer(Buffer+sizeof(ar_hdr), Size, ErrorStr); + if (!M) return true; + Objects.push_back(M); + break; + } + case Unknown: + std::cerr << "ReadArchiveBuffer: WARNING: Skipping unknown file: "; + std::cerr << std::string(Hdr->name, Hdr->name+sizeof(Hdr->name+1)) <<"\n"; + break; // Just ignore unknown files. + } + + // Round Size up to an even number... + Size = (Size+1)/2*2; + Buffer += sizeof(ar_hdr)+Size; // Move to the next entry + Length -= sizeof(ar_hdr)+Size; + } + + return Length != 0; + } + + + // ReadArchiveFile - Read bytecode files from the specfied .a file, returning + // true on error, or false on success. This does not support reading files from + // standard input. + // + bool ReadArchiveFile(const std::string &Filename, std::vector &Objects, + std::string *ErrorStr) { + int FD = open(Filename.c_str(), O_RDONLY); + if (FD == -1) + return Error(ErrorStr, "Error opening file!"); + + // Stat the file to get its length... + struct stat StatBuf; + if (fstat(FD, &StatBuf) == -1 || StatBuf.st_size == 0) + return Error(ErrorStr, "Error stat'ing file!"); + + // mmap in the file all at once... + int Length = StatBuf.st_size; + unsigned char *Buffer = (unsigned char*)mmap(0, Length, PROT_READ, + MAP_PRIVATE, FD, 0); + if (Buffer == (unsigned char*)MAP_FAILED) + return Error(ErrorStr, "Error mmapping file!"); + + // Parse the archive files we mmap'ped in + bool Result = ReadArchiveBuffer(Buffer, Length, Objects, ErrorStr); + + // Unmmap the archive... + munmap((char*)Buffer, Length); + + if (Result) // Free any loaded objects + while (!Objects.empty()) { + delete Objects.back(); + Objects.pop_back(); + } + + return Result; + } From lattner at cs.uiuc.edu Sat Apr 19 16:46:05 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sat Apr 19 16:46:05 2003 Subject: [llvm-commits] CVS: llvm/lib/Bytecode/Reader/Reader.cpp Message-ID: <200304192145.QAA09670@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Bytecode/Reader: Reader.cpp updated: 1.51 -> 1.52 --- Log message: Add support for reading unaligned bytecode buffers --- Diffs of the changes: Index: llvm/lib/Bytecode/Reader/Reader.cpp diff -u llvm/lib/Bytecode/Reader/Reader.cpp:1.51 llvm/lib/Bytecode/Reader/Reader.cpp:1.52 --- llvm/lib/Bytecode/Reader/Reader.cpp:1.51 Thu Apr 17 23:11:56 2003 +++ llvm/lib/Bytecode/Reader/Reader.cpp Sat Apr 19 16:45:17 2003 @@ -639,8 +639,19 @@ Module *ParseBytecodeBuffer(const unsigned char *Buffer, unsigned Length, std::string *ErrorStr) { BytecodeParser Parser; + unsigned char *PtrToDelete = 0; + if ((intptr_t)Buffer & 3) { // If the buffer is not 4 byte aligned... + // Allocate a new buffer to hold the bytecode... + PtrToDelete = new unsigned char[Length+4]; + unsigned Offset = 4-((intptr_t)PtrToDelete & 3); // Make sure it's aligned + memcpy(PtrToDelete+Offset, Buffer, Length); // Copy it over + Buffer = PtrToDelete+Offset; + } + Module *R = Parser.ParseBytecode(Buffer, Buffer+Length); if (ErrorStr) *ErrorStr = Parser.getError(); + + delete [] PtrToDelete; // Delete alignment buffer if neccesary return R; } From lattner at cs.uiuc.edu Sat Apr 19 16:47:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sat Apr 19 16:47:00 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Bytecode/Reader.h Message-ID: <200304192146.QAA09677@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/Bytecode: Reader.h updated: 1.8 -> 1.9 --- Log message: Add prototype to read .a files --- Diffs of the changes: Index: llvm/include/llvm/Bytecode/Reader.h diff -u llvm/include/llvm/Bytecode/Reader.h:1.8 llvm/include/llvm/Bytecode/Reader.h:1.9 --- llvm/include/llvm/Bytecode/Reader.h:1.8 Thu Mar 6 10:50:21 2003 +++ llvm/include/llvm/Bytecode/Reader.h Sat Apr 19 16:45:52 2003 @@ -13,6 +13,7 @@ #define LLVM_BYTECODE_READER_H #include +#include class Module; @@ -22,5 +23,11 @@ std::string *ErrorStr = 0); Module *ParseBytecodeBuffer(const unsigned char *Buffer, unsigned BufferSize, std::string *ErrorStr = 0); + +// ReadArchiveFile - Read bytecode files from the specfied .a file, returning +// true on error, or false on success. +// +bool ReadArchiveFile(const std::string &Filename, std::vector &Objects, + std::string *ErrorStr = 0); #endif From lattner at cs.uiuc.edu Sat Apr 19 17:45:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sat Apr 19 17:45:01 2003 Subject: [llvm-commits] CVS: llvm/tools/gccld/gccld.cpp Message-ID: <200304192244.RAA11191@apoc.cs.uiuc.edu> Changes in directory llvm/tools/gccld: gccld.cpp updated: 1.25 -> 1.26 --- Log message: Add first support for linking in .a files correctly and minimally, like a real linker does --- Diffs of the changes: Index: llvm/tools/gccld/gccld.cpp diff -u llvm/tools/gccld/gccld.cpp:1.25 llvm/tools/gccld/gccld.cpp:1.26 --- llvm/tools/gccld/gccld.cpp:1.25 Fri Apr 18 18:38:22 2003 +++ llvm/tools/gccld/gccld.cpp Sat Apr 19 17:44:38 2003 @@ -1,8 +1,7 @@ -//===----------------------------------------------------------------------===// -// LLVM 'GCCLD' UTILITY +//===- gccld.cpp - LLVM 'ld' compatible linker ----------------------------===// // // This utility is intended to be compatible with GCC, and follows standard -// system ld conventions. As such, the default output file is ./a.out. +// system 'ld' conventions. As such, the default output file is ./a.out. // Additionally, this program outputs a shell script that is used to invoke LLI // to execute the program. In this manner, the generated executable (a.out for // example), is directly executable, whereas the bytecode file actually lives in @@ -25,6 +24,7 @@ #include "Support/Signals.h" #include #include +#include #include #include // For FileExists #include @@ -56,6 +56,10 @@ NoInternalize("disable-internalize", cl::desc("Do not mark all symbols as internal")); + cl::opt + LinkAsLibrary("link-as-library", cl::desc("Link the .bc files together as a" + " library, not an executable")); + // Compatibility options that are ignored, but support by LD cl::opt CO3("soname", cl::Hidden, cl::desc("Compatibility option: ignored")); @@ -71,74 +75,241 @@ return stat(FN.c_str(), &StatBuf) != -1; } -// LoadFile - Read the specified bytecode file in and return it. This routine -// searches the link path for the specified file to try to find it... -// -static inline std::auto_ptr LoadFile(const std::string &FN) { - std::string Filename = FN; + +// LoadObject - Read the specified "object file", which should not search the +// library path to find it. +static inline std::auto_ptr LoadObject(const std::string &FN, + std::string &OutErrorMessage) { + if (Verbose) std::cerr << "Loading '" << FN << "'\n"; + if (!FileExists(FN)) { + OutErrorMessage = "could not find input file '" + FN + "'!"; + return std::auto_ptr(); + } + std::string ErrorMessage; + Module *Result = ParseBytecodeFile(FN, &ErrorMessage); + if (Result) return std::auto_ptr(Result); - unsigned NextLibPathIdx = 0; - bool FoundAFile = false; + OutErrorMessage = "Bytecode file '" + FN + "' corrupt!"; + if (ErrorMessage.size()) OutErrorMessage += ": " + ErrorMessage; + return std::auto_ptr(); +} - while (1) { - if (Verbose) std::cerr << "Loading '" << Filename << "'\n"; - if (FileExists(Filename)) FoundAFile = true; - Module *Result = ParseBytecodeFile(Filename, &ErrorMessage); - if (Result) return std::auto_ptr(Result); // Load successful! + +static Module *LoadSingleLibraryObject(const std::string &Filename) { + std::string ErrorMessage; + std::auto_ptr M = LoadObject(Filename, ErrorMessage); + if (M.get() == 0 && Verbose) { + std::cerr << "Error loading '" + Filename + "'"; + if (!ErrorMessage.empty()) std::cerr << ": " << ErrorMessage; + std::cerr << "\n"; + } + + return M.release(); +} + + +// LoadLibraryFromDirectory - This looks for a .a, .so, or .bc file in a +// particular directory. It returns true if no library is found, otherwise it +// puts the loaded modules into the Objects list, and sets isArchive to true if +// a .a file was loaded. +// +static inline bool LoadLibraryFromDirectory(const std::string &LibName, + const std::string &Directory, + std::vector &Objects, + bool &isArchive) { + if (FileExists(Directory + "lib" + LibName + ".a")) { + std::string ErrorMessage; + if (Verbose) std::cerr << "Loading '" << Directory << LibName << ".a'\n"; + if (!ReadArchiveFile(Directory + "lib" + LibName + ".a", Objects, + &ErrorMessage)) { // Read the archive file + isArchive = true; + return false; // Success! + } if (Verbose) { - std::cerr << "Error opening bytecode file: '" << Filename << "'"; - if (ErrorMessage.size()) std::cerr << ": " << ErrorMessage; + std::cerr << "Error loading archive '" + Directory + "lib"+LibName+".a'"; + if (!ErrorMessage.empty()) std::cerr << ": " << ErrorMessage; std::cerr << "\n"; } - - if (NextLibPathIdx == LibPaths.size()) break; - Filename = LibPaths[NextLibPathIdx++] + "/" + FN; } - if (FoundAFile) - std::cerr << "Bytecode file '" << FN << "' corrupt! " - << "Use 'gccld -v ...' for more info.\n"; - else - std::cerr << "Could not locate bytecode file: '" << FN << "'\n"; - return std::auto_ptr(); + if (FileExists(Directory + "lib" + LibName + ".so")) + if (Module *M = LoadSingleLibraryObject(Directory + "lib" + LibName+".so")){ + isArchive = false; + Objects.push_back(M); + return false; + } + + if (FileExists(Directory + "lib" + LibName + ".bc")) + if (Module *M = LoadSingleLibraryObject(Directory + "lib" + LibName+".bc")){ + isArchive = false; + Objects.push_back(M); + return false; + } + return true; } +// LoadLibrary - This searches for a .a, .so, or .bc file which provides the +// LLVM bytecode for the library. It returns true if no library is found, +// otherwise it puts the loaded modules into the Objects list, and sets +// isArchive to true if a .a file was loaded. +// +static inline bool LoadLibrary(const std::string &LibName, + std::vector &Objects, bool &isArchive, + std::string &ErrorMessage) { + std::string Directory; + unsigned NextLibPathIdx = 0; -int main(int argc, char **argv) { - cl::ParseCommandLineOptions(argc, argv, " llvm linker for GCC\n"); + while (1) { + // Try loading from the current directory... + if (Verbose) std::cerr << " Looking in directory '" << Directory << "'\n"; + if (!LoadLibraryFromDirectory(LibName, Directory, Objects, isArchive)) + return false; - unsigned BaseArg = 0; - std::string ErrorMessage; + if (NextLibPathIdx == LibPaths.size()) break; + Directory = LibPaths[NextLibPathIdx++]+"/"; + } - if (!Libraries.empty()) { - // Sort libraries list... - std::sort(Libraries.begin(), Libraries.end()); + ErrorMessage = "error linking library '-l" + LibName+ "': library not found!"; + return true; +} - // Remove duplicate libraries entries... - Libraries.erase(unique(Libraries.begin(), Libraries.end()), - Libraries.end()); +static void GetAllDefinedSymbols(Module *M, + std::set &DefinedSymbols) { + for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) + if (I->hasName() && !I->isExternal() && !I->hasInternalLinkage()) + DefinedSymbols.insert(I->getName()); + for (Module::giterator I = M->gbegin(), E = M->gend(); I != E; ++I) + if (I->hasName() && !I->isExternal() && !I->hasInternalLinkage()) + DefinedSymbols.insert(I->getName()); +} - // Add all of the libraries to the end of the link line... - for (unsigned i = 0; i < Libraries.size(); ++i) - InputFilenames.push_back("lib" + Libraries[i] + ".bc"); +// GetAllUndefinedSymbols - This calculates the set of undefined symbols that +// still exist in an LLVM module. This is a bit tricky because there may be two +// symbols with the same name, but different LLVM types that will be resolved to +// each other, but aren't currently (thus we need to treat it as resolved). +// +static void GetAllUndefinedSymbols(Module *M, + std::set &UndefinedSymbols) { + std::set DefinedSymbols; + UndefinedSymbols.clear(); // Start out empty + + for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) + if (I->hasName()) { + if (I->isExternal()) + UndefinedSymbols.insert(I->getName()); + else if (!I->hasInternalLinkage()) + DefinedSymbols.insert(I->getName()); + } + for (Module::giterator I = M->gbegin(), E = M->gend(); I != E; ++I) + if (I->hasName()) { + if (I->isExternal()) + UndefinedSymbols.insert(I->getName()); + else if (!I->hasInternalLinkage()) + DefinedSymbols.insert(I->getName()); + } + + // Prune out any defined symbols from the undefined symbols set... + for (std::set::iterator I = UndefinedSymbols.begin(); + I != UndefinedSymbols.end(); ) + if (DefinedSymbols.count(*I)) + UndefinedSymbols.erase(I++); // This symbol really is defined! + else + ++I; // Keep this symbol in the undefined symbols list +} + + +static bool LinkLibrary(Module *M, const std::string &LibName, + std::string &ErrorMessage) { + std::vector Objects; + bool isArchive; + if (LoadLibrary(LibName, Objects, isArchive, ErrorMessage)) return true; + + // Figure out which symbols are defined by all of the modules in the .a file + std::vector > DefinedSymbols; + DefinedSymbols.resize(Objects.size()); + for (unsigned i = 0; i != Objects.size(); ++i) + GetAllDefinedSymbols(Objects[i], DefinedSymbols[i]); + + std::set UndefinedSymbols; + GetAllUndefinedSymbols(M, UndefinedSymbols); + + bool Linked = true; + while (Linked) { // While we are linking in object files, loop. + Linked = false; + + for (unsigned i = 0; i != Objects.size(); ++i) { + // Consider whether we need to link in this module... we only need to + // link it in if it defines some symbol which is so far undefined. + // + const std::set &DefSymbols = DefinedSymbols[i]; + + bool ObjectRequired = false; + for (std::set::iterator I = UndefinedSymbols.begin(), + E = UndefinedSymbols.end(); I != E; ++I) + if (DefSymbols.count(*I)) { + if (Verbose) + std::cerr << " Found object providing symbol '" << *I << "'...\n"; + ObjectRequired = true; + break; + } + + // We DO need to link this object into the program... + if (ObjectRequired) { + if (LinkModules(M, Objects[i], &ErrorMessage)) + return true; // Couldn't link in the right object file... + + // Since we have linked in this object, delete it from the list of + // objects to consider in this archive file. + std::swap(Objects[i], Objects.back()); + std::swap(DefinedSymbols[i], DefinedSymbols.back()); + Objects.pop_back(); + DefinedSymbols.pop_back(); + --i; // Do not skip an entry + + // The undefined symbols set should have shrunk. + GetAllUndefinedSymbols(M, UndefinedSymbols); + Linked = true; // We have linked something in! + } + } } + + return false; +} + +static int PrintAndReturn(const char *progname, const std::string &Message, + const std::string &Extra = "") { + std::cerr << progname << Extra << ": " << Message << "\n"; + return 1; +} - std::auto_ptr Composite(LoadFile(InputFilenames[BaseArg])); - if (Composite.get() == 0) return 1; - for (unsigned i = BaseArg+1; i < InputFilenames.size(); ++i) { - std::auto_ptr M(LoadFile(InputFilenames[i])); - if (M.get() == 0) return 1; +int main(int argc, char **argv) { + cl::ParseCommandLineOptions(argc, argv, " llvm linker for GCC\n"); + + std::string ErrorMessage; + std::auto_ptr Composite(LoadObject(InputFilenames[0], ErrorMessage)); + if (Composite.get() == 0) + return PrintAndReturn(argv[0], ErrorMessage); + + for (unsigned i = 1; i < InputFilenames.size(); ++i) { + std::auto_ptr M(LoadObject(InputFilenames[i], ErrorMessage)); + if (M.get() == 0) + return PrintAndReturn(argv[0], ErrorMessage); if (Verbose) std::cerr << "Linking in '" << InputFilenames[i] << "'\n"; - if (LinkModules(Composite.get(), M.get(), &ErrorMessage)) { - std::cerr << argv[0] << ": error linking in '" << InputFilenames[i] - << "': " << ErrorMessage << "\n"; - return 1; - } + if (LinkModules(Composite.get(), M.get(), &ErrorMessage)) + return PrintAndReturn(argv[0], ErrorMessage, + ": error linking in '" + InputFilenames[i] + "'"); + } + + // Link in all of the libraries next... + for (unsigned i = 0; i != Libraries.size(); ++i) { + if (Verbose) std::cerr << "Linking in library: -l" << Libraries[i] << "\n"; + if (LinkLibrary(Composite.get(), Libraries[i], ErrorMessage)) + return PrintAndReturn(argv[0], ErrorMessage); } // In addition to just linking the input from GCC, we also want to spiff it up @@ -178,33 +349,33 @@ Passes.add(createGlobalDCEPass()); // Add the pass that writes bytecode to the output file... - std::ofstream Out((OutputFilename+".bc").c_str()); - if (!Out.good()) { - std::cerr << argv[0] << ": error opening '" << OutputFilename - << ".bc' for writing!\n"; - return 1; - } + std::string RealBytecodeOutput = OutputFilename; + if (!LinkAsLibrary) RealBytecodeOutput += ".bc"; + std::ofstream Out(RealBytecodeOutput.c_str()); + if (!Out.good()) + return PrintAndReturn(argv[0], "error opening '" + RealBytecodeOutput + + "' for writing!"); Passes.add(new WriteBytecodePass(&Out)); // Write bytecode to file... // Make sure that the Out file gets unlink'd from the disk if we get a SIGINT - RemoveFileOnSignal(OutputFilename+".bc"); + RemoveFileOnSignal(RealBytecodeOutput); // Run our queue of passes all at once now, efficiently. Passes.run(*Composite.get()); Out.close(); - // Output the script to start the program... - std::ofstream Out2(OutputFilename.c_str()); - if (!Out2.good()) { - std::cerr << argv[0] << ": error opening '" << OutputFilename - << "' for writing!\n"; - return 1; - } - Out2 << "#!/bin/sh\nlli -q -abort-on-exception $0.bc $*\n"; - Out2.close(); + if (!LinkAsLibrary) { + // Output the script to start the program... + std::ofstream Out2(OutputFilename.c_str()); + if (!Out2.good()) + return PrintAndReturn(argv[0], "error opening '" + OutputFilename + + "' for writing!"); + Out2 << "#!/bin/sh\nlli -q -abort-on-exception $0.bc $*\n"; + Out2.close(); - // Make the script executable... - chmod(OutputFilename.c_str(), 0755); + // Make the script executable... + chmod(OutputFilename.c_str(), 0755); + } return 0; } From lattner at cs.uiuc.edu Sat Apr 19 18:08:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sat Apr 19 18:08:01 2003 Subject: [llvm-commits] CVS: llvm/tools/gccld/gccld.cpp Message-ID: <200304192307.SAA12804@apoc.cs.uiuc.edu> Changes in directory llvm/tools/gccld: gccld.cpp updated: 1.26 -> 1.27 --- Log message: Eliminate useless duplicate libraries --- Diffs of the changes: Index: llvm/tools/gccld/gccld.cpp diff -u llvm/tools/gccld/gccld.cpp:1.26 llvm/tools/gccld/gccld.cpp:1.27 --- llvm/tools/gccld/gccld.cpp:1.26 Sat Apr 19 17:44:38 2003 +++ llvm/tools/gccld/gccld.cpp Sat Apr 19 18:07:33 2003 @@ -120,7 +120,8 @@ bool &isArchive) { if (FileExists(Directory + "lib" + LibName + ".a")) { std::string ErrorMessage; - if (Verbose) std::cerr << "Loading '" << Directory << LibName << ".a'\n"; + if (Verbose) std::cerr << " Loading '" << Directory << "lib" + << LibName << ".a'\n"; if (!ReadArchiveFile(Directory + "lib" + LibName + ".a", Objects, &ErrorMessage)) { // Read the archive file isArchive = true; @@ -128,7 +129,7 @@ } if (Verbose) { - std::cerr << "Error loading archive '" + Directory + "lib"+LibName+".a'"; + std::cerr << " Error loading archive '" + Directory +"lib"+LibName+".a'"; if (!ErrorMessage.empty()) std::cerr << ": " << ErrorMessage; std::cerr << "\n"; } @@ -304,6 +305,10 @@ return PrintAndReturn(argv[0], ErrorMessage, ": error linking in '" + InputFilenames[i] + "'"); } + + // Remove any consecutive duplicates of the same library... + Libraries.erase(std::unique(Libraries.begin(), Libraries.end()), + Libraries.end()); // Link in all of the libraries next... for (unsigned i = 0; i != Libraries.size(); ++i) {