diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index abc850a0f5e3..2f3d21d81bb7 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -540,6 +540,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { case ISD::CONDCODE: case ISD::VALUETYPE: case ISD::SRCVALUE: + case ISD::STRING: switch (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0))) { default: assert(0 && "This action is not supported yet!"); case TargetLowering::Custom: { @@ -601,6 +602,32 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { } break; } + + case ISD::LOCATION: + assert(Node->getNumOperands() == 5 && "Invalid LOCATION node!"); + Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the input chain. + + switch (TLI.getOperationAction(ISD::LOCATION, MVT::Other)) { + case TargetLowering::Promote: + default: assert(0 && "This action is not supported yet!"); + case TargetLowering::Expand: + // If the target doesn't support line numbers, ignore this node. + Result = Tmp1; + break; + case TargetLowering::Legal: + if (Tmp1 != Node->getOperand(0)) { + std::vector Ops; + Ops.push_back(Tmp1); + Ops.push_back(Node->getOperand(1)); // line # must be legal. + Ops.push_back(Node->getOperand(2)); // col # must be legal. + Ops.push_back(Node->getOperand(3)); // filename must be legal. + Ops.push_back(Node->getOperand(4)); // working dir # must be legal. + Result = DAG.getNode(ISD::LOCATION, MVT::Other, Ops); + } + break; + } + break; + case ISD::Constant: // We know we don't need to expand constants here, constants only have one // value and we check that it is fine above. diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 7676ead3551f..1eb95864c079 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -274,6 +274,9 @@ void SelectionDAG::RemoveNodeFromCSEMaps(SDNode *N) { Erased = ConstantFPs.erase(std::make_pair(V, N->getValueType(0))); break; } + case ISD::STRING: + Erased = StringNodes.erase(cast(N)->getValue()); + break; case ISD::CONDCODE: assert(CondCodeNodes[cast(N)->get()] && "Cond code doesn't exist!"); @@ -448,6 +451,15 @@ SDOperand SelectionDAG::getConstant(uint64_t Val, MVT::ValueType VT) { return SDOperand(N, 0); } +SDOperand SelectionDAG::getString(const std::string &Val) { + StringSDNode *&N = StringNodes[Val]; + if (!N) { + N = new StringSDNode(Val); + AllNodes.push_back(N); + } + return SDOperand(N, 0); +} + SDOperand SelectionDAG::getTargetConstant(uint64_t Val, MVT::ValueType VT) { assert(MVT::isInteger(VT) && "Cannot create FP integer constant!"); // Mask out any bits that are not valid for this constant. @@ -1670,6 +1682,7 @@ const char *SDNode::getOperationName(const SelectionDAG *G) const { case ISD::READCYCLECOUNTER: return "ReadCycleCounter"; case ISD::SRCVALUE: return "SrcValue"; case ISD::VALUETYPE: return "ValueType"; + case ISD::STRING: return "String"; case ISD::EntryToken: return "EntryToken"; case ISD::TokenFactor: return "TokenFactor"; case ISD::AssertSext: return "AssertSext"; @@ -1787,6 +1800,9 @@ const char *SDNode::getOperationName(const SelectionDAG *G) const { case ISD::READIO: return "readio"; case ISD::WRITEIO: return "writeio"; + // Debug info + case ISD::LOCATION: return "location"; + case ISD::CONDCODE: switch (cast(this)->get()) { default: assert(0 && "Unknown setcc condition!"); diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 881168137420..00dc56ef9185 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -17,6 +17,7 @@ #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/Function.h" +#include "llvm/GlobalVariable.h" #include "llvm/Instructions.h" #include "llvm/Intrinsics.h" #include "llvm/CodeGen/IntrinsicLowering.h" @@ -719,6 +720,44 @@ void SelectionDAGLowering::visitAlloca(AllocaInst &I) { CurMBB->getParent()->getFrameInfo()->CreateVariableSizedObject(); } +/// getStringValue - Turn an LLVM constant pointer that eventually points to a +/// global into a string value. Return an empty string if we can't do it. +/// +static std::string getStringValue(Value *V, unsigned Offset = 0) { + if (GlobalVariable *GV = dyn_cast(V)) { + if (GV->hasInitializer() && isa(GV->getInitializer())) { + ConstantArray *Init = cast(GV->getInitializer()); + if (Init->isString()) { + std::string Result = Init->getAsString(); + if (Offset < Result.size()) { + // If we are pointing INTO The string, erase the beginning... + Result.erase(Result.begin(), Result.begin()+Offset); + + // Take off the null terminator, and any string fragments after it. + std::string::size_type NullPos = Result.find_first_of((char)0); + if (NullPos != std::string::npos) + Result.erase(Result.begin()+NullPos, Result.end()); + return Result; + } + } + } + } else if (Constant *C = dyn_cast(V)) { + if (GlobalValue *GV = dyn_cast(C)) + return getStringValue(GV, Offset); + else if (ConstantExpr *CE = dyn_cast(C)) { + if (CE->getOpcode() == Instruction::GetElementPtr) { + // Turn a gep into the specified offset. + if (CE->getNumOperands() == 3 && + cast(CE->getOperand(1))->isNullValue() && + isa(CE->getOperand(2))) { + return getStringValue(CE->getOperand(0), + Offset+cast(CE->getOperand(2))->getRawValue()); + } + } + } + } + return ""; +} void SelectionDAGLowering::visitLoad(LoadInst &I) { SDOperand Ptr = getValue(I.getOperand(0)); @@ -813,11 +852,37 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { return 0; case Intrinsic::dbg_stoppoint: + { if (TLI.getTargetMachine().getIntrinsicLowering().EmitDebugFunctions()) return "llvm_debugger_stop"; - if (I.getType() != Type::VoidTy) - setValue(&I, DAG.getNode(ISD::UNDEF, TLI.getValueType(I.getType()))); + + std::string fname = ""; + std::vector Ops; + + // Pull the filename out of the the compilation unit. + const GlobalVariable *cunit = dyn_cast(I.getOperand(4)); + if (cunit && cunit->hasInitializer()) { + ConstantStruct *CS = dyn_cast(cunit->getInitializer()); + if (CS->getNumOperands() > 0) { + std::string dirname = getStringValue(CS->getOperand(4)); + fname = dirname + "/" + getStringValue(CS->getOperand(3)); + } + } + // Input Chain + Ops.push_back(getRoot()); + + // line number + Ops.push_back(getValue(I.getOperand(2))); + + // column + Ops.push_back(getValue(I.getOperand(3))); + + // filename + Ops.push_back(DAG.getString(fname)); + Ops.push_back(DAG.getString("")); + DAG.setRoot(DAG.getNode(ISD::LOCATION, MVT::Other, Ops)); return 0; + } case Intrinsic::dbg_region_start: if (TLI.getTargetMachine().getIntrinsicLowering().EmitDebugFunctions()) return "llvm_dbg_region_start"; diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp index bcc5ba23b4aa..d554a7d392e4 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp @@ -98,7 +98,10 @@ std::string DOTGraphTraits::getNodeLabel(const SDNode *Node, Op += "getOffset()) + ">"; } else if (const VTSDNode *N = dyn_cast(Node)) { Op = Op + " VT=" + getValueTypeString(N->getVT()); + } else if (const StringSDNode *N = dyn_cast(Node)) { + Op = Op + "\"" + N->getValue() + "\""; } + return Op; }