bool llvm::LowerRISCVMachineOperandToMCOperand(const MachineOperand &MO, MCOperand &MCOp, const AsmPrinter &AP) { switch (MO.getType()) { default: report_fatal_error("LowerRISCVMachineInstrToMCInst: unknown operand type"); case MachineOperand::MO_Register: // Ignore all implicit register operands. if (MO.isImplicit()) return false; MCOp = MCOperand::createReg(MO.getReg()); break; case MachineOperand::MO_RegisterMask: // Regmasks are like implicit defs. return false; case MachineOperand::MO_Immediate: MCOp = MCOperand::createImm(MO.getImm()); break; case MachineOperand::MO_MachineBasicBlock: MCOp = lowerSymbolOperand(MO, MO.getMBB()->getSymbol(), AP); break; case MachineOperand::MO_GlobalAddress: MCOp = lowerSymbolOperand(MO, AP.getSymbol(MO.getGlobal()), AP); break; case MachineOperand::MO_BlockAddress: MCOp = lowerSymbolOperand( MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()), AP); break; case MachineOperand::MO_ExternalSymbol: MCOp = lowerSymbolOperand( MO, AP.GetExternalSymbolSymbol(MO.getSymbolName()), AP); break; case MachineOperand::MO_ConstantPoolIndex: MCOp = lowerSymbolOperand(MO, AP.GetCPISymbol(MO.getIndex()), AP); break; } return true; }
static MCOperand LowerSymbolOperand(const MachineInstr *MI, const MachineOperand &MO, AsmPrinter &AP) { SparcMCExpr::VariantKind Kind = (SparcMCExpr::VariantKind)MO.getTargetFlags(); const MCSymbol *Symbol = nullptr; switch(MO.getType()) { default: llvm_unreachable("Unknown type in LowerSymbolOperand"); case MachineOperand::MO_MachineBasicBlock: Symbol = MO.getMBB()->getSymbol(); break; case MachineOperand::MO_GlobalAddress: Symbol = AP.getSymbol(MO.getGlobal()); break; case MachineOperand::MO_BlockAddress: Symbol = AP.GetBlockAddressSymbol(MO.getBlockAddress()); break; case MachineOperand::MO_ExternalSymbol: Symbol = AP.GetExternalSymbolSymbol(MO.getSymbolName()); break; case MachineOperand::MO_ConstantPoolIndex: Symbol = AP.GetCPISymbol(MO.getIndex()); break; } const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Symbol, AP.OutContext); const SparcMCExpr *expr = SparcMCExpr::Create(Kind, MCSym, AP.OutContext); return MCOperand::createExpr(expr); }
void TartGCPrinter::finishAssembly(AsmPrinter &AP) { unsigned nextLabel = 1; SafePointList safePoints; // Set up for emitting addresses. int pointerSize = AP.TM.getTargetData()->getPointerSize(); int addressAlignLog; if (pointerSize == sizeof(int32_t)) { addressAlignLog = 2; } else { addressAlignLog = 3; } MCStreamer & outStream = AP.OutStreamer; // Put this in the data section. outStream.SwitchSection(AP.getObjFileLowering().getDataSection()); // For each function... for (iterator FI = begin(), FE = end(); FI != FE; ++FI) { GCFunctionInfo & gcFn = **FI; // if (optShowGC) { // errs() << "GCStrategy: Function: " << gcFn.getFunction().getName() << "\n"; // } // And each safe point... for (GCFunctionInfo::iterator sp = gcFn.begin(); sp != gcFn.end(); ++sp) { StackTraceTable::FieldOffsetList fieldOffsets; StackTraceTable::TraceMethodList traceMethods; // And for each live root... for (GCFunctionInfo::live_iterator rt = gcFn.live_begin(sp); rt != gcFn.live_end(sp); ++rt) { int64_t offset = rt->StackOffset; const Constant * meta = rt->Metadata; if (meta != NULL && !meta->isNullValue()) { // Meta is non-null, so it's a value type. const ConstantArray * traceArray = cast<ConstantArray>(getGlobalValue(meta)); // For each trace descriptor in thre meta array... for (ConstantArray::const_op_iterator it = traceArray->op_begin(); it != traceArray->op_end(); ++it) { ConstantStruct * descriptor = cast<ConstantStruct>(*it); ConstantInt * fieldCount = cast<ConstantInt>(descriptor->getOperand(1)); int64_t dscOffset = toInt(descriptor->getOperand(2), AP.TM); if (fieldCount->isZero()) { // A zero field count means that this is a trace method descriptor. const Constant * traceMethod = descriptor->getOperand(3); assert(offset > -1000 && offset < 1000); assert(dscOffset > -1000 && dscOffset < 1000); traceMethods.push_back(TraceMethodEntry(offset + dscOffset, traceMethod)); } else { // Otherwise it's a field offset descriptor. const GlobalVariable * fieldOffsetsVar = cast<GlobalVariable>( descriptor->getOperand(3)->getOperand(0)); // Handle case where the array value is just a ConstantAggregateZero, which // can be generated by llvm::ConstantArray::get() if the array values // are all zero. if (const ConstantAggregateZero * zero = dyn_cast<ConstantAggregateZero>(fieldOffsetsVar->getInitializer())) { // Array should never contain duplicate offsets, so an all-zero array // can only have one entry. (void)zero; assert(fieldCount->isOne()); fieldOffsets.push_back(offset + dscOffset); } else { // Get the field offset array and add to field offsets for this // safe point. const ConstantArray * fieldOffsetArray = cast<ConstantArray>( fieldOffsetsVar->getInitializer()); for (ConstantArray::const_op_iterator el = fieldOffsetArray->op_begin(); el != fieldOffsetArray->op_end(); ++el) { fieldOffsets.push_back( offset + dscOffset + toInt(cast<llvm::Constant>(*el), AP.TM)); } } } } } else { // No metadata, so it's an object reference - just add the field offset. fieldOffsets.push_back(offset); } } // Nothing to trace? Then we're done. if (fieldOffsets.empty() && traceMethods.empty()) { continue; } // Create a folding set node and merge with any identical trace tables. std::sort(fieldOffsets.begin(), fieldOffsets.end()); llvm::FoldingSetNodeID id; StackTraceTable::ProfileEntries(id, fieldOffsets, traceMethods); void * insertPos; StackTraceTable * sTable = traceTables.FindNodeOrInsertPos(id, insertPos); if (sTable == NULL) { sTable = new StackTraceTable(fieldOffsets, traceMethods); // Generate the labels for the trace table and field offset table. sTable->fieldOffsetsLabel = AP.GetTempSymbol("gc_stack_offsets", nextLabel); sTable->traceTableLabel = AP.GetTempSymbol("gc_stack", nextLabel++); // Add to folding set traceTables.InsertNode(sTable, insertPos); // Generate the trace table outStream.AddBlankLine(); AP.EmitAlignment(addressAlignLog); // First the field offset descriptor outStream.EmitLabel(sTable->traceTableLabel); size_t traceMethodCount = sTable->traceMethods.size(); if (!sTable->fieldOffsets.empty()) { outStream.EmitIntValue(traceMethodCount == 0 ? 1 : 0, 2, 0); outStream.EmitIntValue(sTable->fieldOffsets.size(), 2, 0); outStream.EmitIntValue(0, 4, 0); outStream.EmitSymbolValue(sTable->fieldOffsetsLabel, pointerSize, 0); } // Next the trace method descriptors for (size_t i = 0; i < traceMethodCount; ++i) { const TraceMethodEntry * tm = &sTable->traceMethods[i]; const Function * method = dyn_cast<Function>(tm->method()); if (method == NULL) { method = cast<Function>(tm->method()->getOperand(0)); } outStream.EmitIntValue((i + 1 == traceMethodCount ? 1 : 0), 2, 0); outStream.EmitIntValue(0, 2, 0); outStream.EmitIntValue(tm->offset(), 4, 0); MCSymbol * methodSym = AP.Mang->getSymbol(method); outStream.EmitSymbolValue(methodSym, pointerSize, 0); } // Now emit the field offset array outStream.AddBlankLine(); AP.EmitAlignment(addressAlignLog); outStream.EmitLabel(sTable->fieldOffsetsLabel); for (StackTraceTable::FieldOffsetList::const_iterator it = fieldOffsets.begin(); it != fieldOffsets.end(); ++it) { outStream.EmitIntValue(*it, pointerSize, 0); } } safePoints.push_back(std::pair<MCSymbol *, MCSymbol *>(sp->Label, sTable->traceTableLabel)); // if (optShowGC) { // if (!sTable->fieldOffsets.empty()) { // errs() << "GCStrategy: Field offset descriptor:"; // for (StackTraceTable::FieldOffsetList::const_iterator it = sTable->fieldOffsets.begin(); // it != sTable->fieldOffsets.end(); ++it) { // errs() << " " << *it; // } // errs() << "\n"; // } // if (!sTable->traceMethods.empty()) { // errs() << "GCStrategy: Trace method descriptor: " << "\n"; // } // } } } // Finally, generate the safe point map. outStream.AddBlankLine(); MCSymbol * gcSafepointSymbol = AP.GetExternalSymbolSymbol("GC_safepoint_map"); outStream.EmitSymbolAttribute(gcSafepointSymbol, MCSA_Global); outStream.EmitLabel(gcSafepointSymbol); outStream.EmitIntValue(safePoints.size(), pointerSize, 0); for (SafePointList::const_iterator it = safePoints.begin(); it != safePoints.end(); ++it) { outStream.EmitSymbolValue(it->first, pointerSize, 0); outStream.EmitSymbolValue(it->second, pointerSize, 0); } }