mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-30 16:17:05 +00:00 
			
		
		
		
	git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@15328 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			171 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			171 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //===-- lib/Transforms/Scalar/LowerConstantExprs.cpp ------------*- C++ -*-===//
 | |
| // 
 | |
| //                     The LLVM Compiler Infrastructure
 | |
| //
 | |
| // This file was written by Vladimir Prus and is distributed under
 | |
| // the University of Illinois Open Source License. See LICENSE.TXT for details.
 | |
| // 
 | |
| //===----------------------------------------------------------------------===//
 | |
| //
 | |
| // This file defines the LowerConstantExpression pass, which converts all
 | |
| // constant expressions into instructions. This is primarily usefull for 
 | |
| // code generators which don't yet want or don't have a need to handle
 | |
| // constant expressions themself.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #include "llvm/Pass.h"
 | |
| #include "llvm/Function.h"
 | |
| #include "llvm/Constants.h"
 | |
| #include "llvm/Instructions.h"
 | |
| #include "llvm/Support/InstIterator.h"
 | |
| #include <vector>
 | |
| #include <iostream>
 | |
| 
 | |
| using namespace llvm;
 | |
| using namespace std;
 | |
| 
 | |
| namespace {
 | |
| 
 | |
|     class ConstantExpressionsLower : public FunctionPass {
 | |
|     private: // FunctionPass overrides
 | |
|         
 | |
|         bool runOnFunction(Function& f);
 | |
| 
 | |
|     private: // internal methods
 | |
| 
 | |
|         /// For all operands of 'insn' which are constant expressions, generates
 | |
|         /// an appropriate instruction and replaces the use of constant 
 | |
|         /// expression with the use of the generated instruction.
 | |
|         bool runOnInstruction(Instruction& insn);
 | |
| 
 | |
|         /// Given an constant expression 'c' which occures in 'instruction',
 | |
|         /// at position 'pos', 
 | |
|         /// generates instruction to compute 'c' and replaces the use of 'c'
 | |
|         /// with the use of that instruction. This handles only top-level
 | |
|         /// expression in 'c', any subexpressions are not handled.
 | |
|         Instruction* convert(const ConstantExpr& c, Instruction* where);
 | |
|     };
 | |
| 
 | |
|     RegisterOpt<ConstantExpressionsLower> X(
 | |
|         "lowerconstantexprs", "Lower constant expressions");    
 | |
| }
 | |
| 
 | |
| bool ConstantExpressionsLower::runOnFunction(Function& f)
 | |
| {
 | |
|     bool modified = false;
 | |
|     for (inst_iterator i = inst_begin(f), e = inst_end(f); i != e; ++i)
 | |
|     {
 | |
|         modified |= runOnInstruction(*i);
 | |
|     }
 | |
|     return modified;
 | |
| }
 | |
| 
 | |
| bool ConstantExpressionsLower::runOnInstruction(Instruction& instruction)
 | |
| {
 | |
|     bool modified = false;
 | |
|     for (unsigned pos = 0; pos < instruction.getNumOperands(); ++pos)
 | |
|     {
 | |
|         if (ConstantExpr* ce 
 | |
|             = dyn_cast<ConstantExpr>(instruction.getOperand(pos))) {
 | |
| 
 | |
|             // Decide where to insert the new instruction
 | |
|             Instruction* where = &instruction;
 | |
| 
 | |
|             // For PHI nodes we can't insert new instruction before phi, 
 | |
|             // since phi should always come at the beginning of the 
 | |
|             // basic block.
 | |
|             // So, we need to insert it in the predecessor, right before
 | |
|             // the terminating instruction.
 | |
|             if (PHINode* p = dyn_cast<PHINode>(&instruction)) {
 | |
|                 BasicBlock* predecessor = 0;
 | |
|                 for(unsigned i = 0; i < p->getNumIncomingValues(); ++i)
 | |
|                     if (p->getIncomingValue(i) == ce) {
 | |
|                         predecessor = p->getIncomingBlock(i);
 | |
|                         break;
 | |
|                     }
 | |
|                 assert(predecessor && "could not find predecessor");
 | |
|                 where = predecessor->getTerminator();
 | |
|             }
 | |
|             Instruction* n = convert(*ce, where);
 | |
| 
 | |
|             // Note: we can't call replaceAllUsesWith, since
 | |
|             // that might replace uses in another functions,
 | |
|             // where the instruction(s) we've generated are not
 | |
|             // available. 
 | |
|                     
 | |
|             // Moreover, we can't replace all the users in the same 
 | |
|             // function, because we can't be sure the definition 
 | |
|             // made in this block will be available in other
 | |
|             // places where the constant is used.                                       
 | |
|             instruction.setOperand(pos, n);
 | |
| 
 | |
|             // The new instruction might have constant expressions in
 | |
|             // it. Extract them too.
 | |
|             runOnInstruction(*n);
 | |
|             modified = true;
 | |
|         }
 | |
|     }            
 | |
|     return modified;
 | |
| }
 | |
| 
 | |
| Instruction* 
 | |
| ConstantExpressionsLower::convert(const ConstantExpr& c, Instruction* where)
 | |
| {
 | |
|     Instruction* result = 0;
 | |
| 
 | |
|     if (c.getOpcode() >= Instruction::BinaryOpsBegin &&
 | |
|         c.getOpcode() < Instruction::BinaryOpsEnd)
 | |
|     {
 | |
|         result = BinaryOperator::create(
 | |
|             static_cast<Instruction::BinaryOps>(c.getOpcode()), 
 | |
|             c.getOperand(0), c.getOperand(1), "", where);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         switch(c.getOpcode()) {
 | |
|         case Instruction::GetElementPtr: 
 | |
|         {
 | |
|             vector<Value*> idx;
 | |
|             for (unsigned i = 1; i < c.getNumOperands(); ++i)
 | |
|                 idx.push_back(c.getOperand(i));
 | |
|             result = new GetElementPtrInst(c.getOperand(0),
 | |
|                                            idx, "", where);
 | |
|             break;
 | |
|         }
 | |
| 
 | |
|         case Instruction::Cast:
 | |
|             result = new CastInst(c.getOperand(0), c.getType(), "", 
 | |
|                                   where);
 | |
|             break;
 | |
| 
 | |
| 
 | |
|         case Instruction::Shl:
 | |
|         case Instruction::Shr:
 | |
|             result = new ShiftInst(
 | |
|                 static_cast<Instruction::OtherOps>(c.getOpcode()), 
 | |
|                 c.getOperand(0), c.getOperand(1), "", where);
 | |
|             break;
 | |
|                     
 | |
|         case Instruction::Select:
 | |
|             result = new SelectInst(c.getOperand(0), c.getOperand(1),
 | |
|                                     c.getOperand(2), "", where);
 | |
|             break;
 | |
|                  
 | |
|         default:
 | |
|             std::cerr << "Offending expr: " << c << "\n";
 | |
|             assert(0 && "Constant expression not yet handled!\n");
 | |
|         }
 | |
|     }
 | |
|     return result;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| namespace llvm {
 | |
|     FunctionPass* createLowerConstantExpressionsPass()
 | |
|     {
 | |
|         return new ConstantExpressionsLower;
 | |
|     }
 | |
| }
 |