Skip to content

Commit

Permalink
Func: add implementation of Chapter-3_2
Browse files Browse the repository at this point in the history
  • Loading branch information
Masayuki Kimura committed Dec 10, 2018
1 parent 5594042 commit 2997d95
Show file tree
Hide file tree
Showing 24 changed files with 951 additions and 1 deletion.
7 changes: 7 additions & 0 deletions lib/Target/Cpu0/CMakeLists.txt
Expand Up @@ -7,6 +7,10 @@ set(LLVM_TARGET_DEFINITIONS Cpu0Other.td)
# came from Cpu0InstrInfo.td.
tablegen(LLVM Cpu0GenRegisterInfo.inc -gen-register-info)
tablegen(LLVM Cpu0GenInstrInfo.inc -gen-instr-info)
tablegen(LLVM Cpu0GenCodeEmitter.inc -gen-emitter)
tablegen(LLVM Cpu0GenMCCodeEmitter.inc -gen-emitter)

tablegen(LLVM Cpu0GenAsmWriter.inc -gen-asm-writer)
tablegen(LLVM Cpu0GenDAGISel.inc -gen-dag-isel)
tablegen(LLVM Cpu0GenCallingConv.inc -gen-callingconv)
tablegen(LLVM Cpu0GenSubtargetInfo.inc -gen-subtarget)
Expand All @@ -17,6 +21,8 @@ add_public_tablegen_target(Cpu0CommonTableGen)

# Cpu0CodeGen should match with LLVMBuild.txt Cpu0CodeGen
add_llvm_target(Cpu0CodeGen
Cpu0AsmPrinter.cpp
Cpu0MCInstLower.cpp
Cpu0FrameLowering.cpp
Cpu0InstrInfo.cpp
Cpu0ISelLowering.cpp
Expand All @@ -32,6 +38,7 @@ add_llvm_target(Cpu0CodeGen
)

# Should match with "subdirectories = MCTargetDesc TargetInfo" in LLVMBuild.txt
add_subdirectory(InstPrinter)
add_subdirectory(TargetInfo)
add_subdirectory(MCTargetDesc)

262 changes: 262 additions & 0 deletions lib/Target/Cpu0/Cpu0AsmPrinter.cpp
@@ -0,0 +1,262 @@
//===-- Cpu0AsmPrinter.cpp - Cpu0 LLVM Assembly Printer -------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains a printer that converts from our internal representation
// of machine-dependent LLVM code to GAS-format CPU0 assembly language.
//
//===----------------------------------------------------------------------===//

#include "Cpu0AsmPrinter.h"

#include "InstPrinter/Cpu0InstPrinter.h"
#include "MCTargetDesc/Cpu0BaseInfo.h"
#include "Cpu0.h"
#include "Cpu0InstrInfo.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Twine.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Mangler.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetOptions.h"

using namespace llvm;

#define DEBUG_TYPE "cpu0-asm-printer"

bool Cpu0AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
Cpu0FI = MF.getInfo<Cpu0FunctionInfo>();
AsmPrinter::runOnMachineFunction(MF);
return true;
}

//@EmitInstruction {
//- EmitInstruction() must exists or will have run time error.
void Cpu0AsmPrinter::EmitInstruction(const MachineInstr *MI) {
//@EmitInstruction body {
if (MI->isDebugValue()) {
SmallString<128> Str;
raw_svector_ostream OS(Str);

PrintDebugValueComment(MI, OS);
return;
}

//@print out instruction:
// Print out both ordinary instruction and boudle instruction
MachineBasicBlock::const_instr_iterator I = MI->getIterator();
MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end();

do {

if (I->isPseudo())
llvm_unreachable("Pseudo opcode found in EmitInstruction()");

MCInst TmpInst0;
MCInstLowering.Lower(&*I, TmpInst0);
OutStreamer->EmitInstruction(TmpInst0, getSubtargetInfo());
} while ((++I != E) && I->isInsideBundle()); // Delay slot check
}
//@EmitInstruction }

//===----------------------------------------------------------------------===//
//
// Cpu0 Asm Directives
//
// -- Frame directive "frame Stackpointer, Stacksize, RARegister"
// Describe the stack frame.
//
// -- Mask directives "(f)mask bitmask, offset"
// Tells the assembler which registers are saved and where.
// bitmask - contain a little endian bitset indicating which registers are
// saved on function prologue (e.g. with a 0x80000000 mask, the
// assembler knows the register 31 (RA) is saved at prologue.
// offset - the position before stack pointer subtraction indicating where
// the first saved register on prologue is located. (e.g. with a
//
// Consider the following function prologue:
//
// .frame $fp,48,$ra
// .mask 0xc0000000,-8
// addiu $sp, $sp, -48
// st $ra, 40($sp)
// st $fp, 36($sp)
//
// With a 0xc0000000 mask, the assembler knows the register 31 (RA) and
// 30 (FP) are saved at prologue. As the save order on prologue is from
// left to right, RA is saved first. A -8 offset means that after the
// stack pointer subtration, the first register in the mask (RA) will be
// saved at address 48-8=40.
//
//===----------------------------------------------------------------------===//

//===----------------------------------------------------------------------===//
// Mask directives
//===----------------------------------------------------------------------===//
// .frame $sp,8,$lr
//-> .mask 0x00000000,0
// .set noreorder
// .set nomacro

// Create a bitmask with all callee saved registers for CPU or Floating Point
// registers. For CPU registers consider LR, GP and FP for saving if necessary.
void Cpu0AsmPrinter::printSavedRegsBitmask(raw_ostream &O) {
// CPU and FPU Saved Registers Bitmasks
unsigned CPUBitmask = 0;
int CPUTopSavedRegOff;

// Set the CPU and FPU Bitmasks
const MachineFrameInfo &MFI = MF->getFrameInfo();
const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
// size of stack area to which FP callee-saved regs are saved.
unsigned CPURegSize = TRI->getRegSizeInBits(Cpu0::CPURegsRegClass) / 8;
unsigned i = 0, e = CSI.size();

// Set CPU Bitmask.
for (; i != e; ++i) {
unsigned Reg = CSI[i].getReg();
unsigned RegNum = TRI->getEncodingValue(Reg);
CPUBitmask |= (1 << RegNum);
}

CPUTopSavedRegOff = CPUBitmask ? -CPURegSize : 0;

// Print CPUBitmask
O << "\t.mask \t"; printHex32(CPUBitmask, O);
O << ',' << CPUTopSavedRegOff << '\n';
}

// Print a 32 bit hex number with all numbers.
void Cpu0AsmPrinter::printHex32(unsigned Value, raw_ostream &O) {
O << "0x";
for (int i = 7; i >= 0; i--)
O.write_hex((Value & (0xF << (i*4))) >> (i*4));
}

//===----------------------------------------------------------------------===//
// Frame and Set directives
//===----------------------------------------------------------------------===//
//-> .frame $sp,8,$lr
// .mask 0x00000000,0
// .set noreorder
// .set nomacro
/// Frame Directive
void Cpu0AsmPrinter::emitFrameDirective() {
const TargetRegisterInfo &RI = *MF->getSubtarget().getRegisterInfo();

unsigned stackReg = RI.getFrameRegister(*MF);
unsigned returnReg = RI.getRARegister();
unsigned stackSize = MF->getFrameInfo().getStackSize();

if (OutStreamer->hasRawTextSupport())
OutStreamer->EmitRawText("\t.frame\t$" +
StringRef(Cpu0InstPrinter::getRegisterName(stackReg)).lower() +
"," + Twine(stackSize) + ",$" +
StringRef(Cpu0InstPrinter::getRegisterName(returnReg)).lower());
}

/// Emit Set directives.
const char *Cpu0AsmPrinter::getCurrentABIString() const {
switch (static_cast<Cpu0TargetMachine &>(TM).getABI().GetEnumValue()) {
case Cpu0ABIInfo::ABI::O32: return "abiO32";
case Cpu0ABIInfo::ABI::S32: return "abiS32";
default: llvm_unreachable("Unknown Cpu0 ABI");
}
}

// .type main,@function
//-> .ent main # @main
// main:
void Cpu0AsmPrinter::EmitFunctionEntryLabel() {
if (OutStreamer->hasRawTextSupport())
OutStreamer->EmitRawText("\t.ent\t" + Twine(CurrentFnSym->getName()));
OutStreamer->EmitLabel(CurrentFnSym);
}

// .frame $sp,8,$pc
// .mask 0x00000000,0
//-> .set noreorder
//@-> .set nomacro
/// EmitFunctionBodyStart - Targets can override this to emit stuff before
/// the first basic block in the function.
void Cpu0AsmPrinter::EmitFunctionBodyStart() {
MCInstLowering.Initialize(&MF->getContext());

emitFrameDirective();

if (OutStreamer->hasRawTextSupport()) {
SmallString<128> Str;
raw_svector_ostream OS(Str);
printSavedRegsBitmask(OS);
OutStreamer->EmitRawText(OS.str());
OutStreamer->EmitRawText(StringRef("\t.set\tnoreorder"));
OutStreamer->EmitRawText(StringRef("\t.set\tnomacro"));
if (Cpu0FI->getEmitNOAT())
OutStreamer->EmitRawText(StringRef("\t.set\tnoat"));
}
}

//-> .set macro
//-> .set reorder
//-> .end main
/// EmitFunctionBodyEnd - Targets can override this to emit stuff after
/// the last basic block in the function.
void Cpu0AsmPrinter::EmitFunctionBodyEnd() {
// There are instruction for this macros, but they must
// always be at the function end, and we can't emit and
// break with BB logic.
if (OutStreamer->hasRawTextSupport()) {
if (Cpu0FI->getEmitNOAT())
OutStreamer->EmitRawText(StringRef("\t.set\tat"));
OutStreamer->EmitRawText(StringRef("\t.set\tmacro"));
OutStreamer->EmitRawText(StringRef("\t.set\treorder"));
OutStreamer->EmitRawText("\t.end\t" + Twine(CurrentFnSym->getName()));
}
}

// .section .mdebug.abi32
// .previous
void Cpu0AsmPrinter::EmitStartOfAsmFile(Module &M) {
// FIXME: Use SwitchSection.

// Tell the assembler which ABI we are using
if (OutStreamer->hasRawTextSupport())
OutStreamer->EmitRawText("\t.section .mdebug." +
Twine(getCurrentABIString()));

// return to previous section
if (OutStreamer->hasRawTextSupport())
OutStreamer->EmitRawText(StringRef("\t.previous"));
}

void Cpu0AsmPrinter::PrintDebugValueComment(const MachineInstr *MI,
raw_ostream &OS) {
// TODO: implement
OS << "PrintDebugValueComment()";
}

// Force static initialization.
extern "C" void LLVMInitializeCpu0AsmPrinter() {
RegisterAsmPrinter<Cpu0AsmPrinter> X(TheCpu0Target);
RegisterAsmPrinter<Cpu0AsmPrinter> Y(TheCpu0elTarget);
}

76 changes: 76 additions & 0 deletions lib/Target/Cpu0/Cpu0AsmPrinter.h
@@ -0,0 +1,76 @@
//===-- Cpu0AsmPrinter.h - Cpu0 LLVM Assembly Printer ----------*- C++ -*--===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Cpu0 Assembly printer class.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIB_TARGET_CPU0_CPU0ASMPRINTER_H
#define LLVM_LIB_TARGET_CPU0_CPU0ASMPRINTER_H

#include "Cpu0Config.h"

#include "Cpu0MachineFunction.h"
#include "Cpu0MCInstLower.h"
#include "Cpu0Subtarget.h"
#include "Cpu0TargetMachine.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Target/TargetMachine.h"

namespace llvm {
class MCStreamer;
class MachineInstr;
class MachineBasicBlock;
class Module;
class raw_ostream;

class LLVM_LIBRARY_VISIBILITY Cpu0AsmPrinter : public AsmPrinter {

void EmitInstrWithMacroNoAT(const MachineInstr *MI);

private:

// lowerOperand - Convert a MachineOperand into the equivalent MCOperand.
bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp);

public:

const Cpu0Subtarget *Subtarget;
const Cpu0FunctionInfo *Cpu0FI;
Cpu0MCInstLower MCInstLowering;

explicit Cpu0AsmPrinter(TargetMachine &TM,
std::unique_ptr<MCStreamer> Streamer)
: AsmPrinter(TM, std::move(Streamer)),
MCInstLowering(*this) {
Subtarget = static_cast<Cpu0TargetMachine &>(TM).getSubtargetImpl();
}

StringRef getPassName() const override { return "Cpu0 Assembly Printer"; }

virtual bool runOnMachineFunction(MachineFunction &MF) override;

//- EmitInstruction() must exists or will have run time error.
void EmitInstruction(const MachineInstr *MI) override;
void printSavedRegsBitmask(raw_ostream &O);
void printHex32(unsigned int Value, raw_ostream &O);
void emitFrameDirective();
const char *getCurrentABIString() const;
void EmitFunctionEntryLabel() override;
void EmitFunctionBodyStart() override;
void EmitFunctionBodyEnd() override;
void EmitStartOfAsmFile(Module &M) override;
void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS);
};
}

#endif

9 changes: 9 additions & 0 deletions lib/Target/Cpu0/Cpu0ISelLowering.cpp
Expand Up @@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "Cpu0ISelLowering.h"

#include "MCTargetDesc/Cpu0BaseInfo.h"
#include "Cpu0MachineFunction.h"
#include "Cpu0TargetMachine.h"
#include "Cpu0TargetObjectFile.h"
Expand Down Expand Up @@ -60,6 +61,14 @@ Cpu0TargetLowering::Cpu0TargetLowering(const Cpu0TargetMachine &TM,
const Cpu0Subtarget &STI)
: TargetLowering(TM), Subtarget(STI), ABI(TM.getABI()) {

// Cpu0 Custom Operations

// Operations not directly supported by Cpu0.

//- Set .align 2
// It will emit .align 2 later
setMinFunctionAlignment(2);

}

const Cpu0TargetLowering *Cpu0TargetLowering::create(const Cpu0TargetMachine &TM,
Expand Down
1 change: 1 addition & 0 deletions lib/Target/Cpu0/Cpu0ISelLowering.h
Expand Up @@ -17,6 +17,7 @@

#include "Cpu0Config.h"

#include "MCTargetDesc/Cpu0BaseInfo.h"
#include "MCTargetDesc/Cpu0ABIInfo.h"
#include "Cpu0.h"
#include "llvm/CodeGen/CallingConvLower.h"
Expand Down

0 comments on commit 2997d95

Please sign in to comment.