LLVM Exercise V

Posted by on February 7, 2025

Let us add some local variables:

int foo() {
  int retval = 0x0AB;
  int dummy = 0;
  return retval;
}

This requires adding some information about accessing memory. I will just postulate that I have memory available from address 1 growing upwards. As anyone that really knows the HP-41 understands, this is a very bad idea. However we are still just showing some basic LLVM principles, not producing actually useful Nut code. I am however excluding the possibility of generating READ 0, as that instruction does not even exist.

Some code snippets:

    // Addressing modes.
    def ADDR : ComplexPattern<iPTR, 2, "SelectADDR",
                              [frameindex], []>;

    // Address operands
    def MEM : Operand {
      let MIOperandInfo = (ops RC, i16imm);
      let PrintMethod = "printMemOperand";
      let DecoderMethod = "decodeMemOperand";
    }
    
    ...
    
    let mayLoad=1 in {
    def READ : HP41MCODEInst<0x078, (outs RC:$r),
            (ins MEM:$addr), "READ $addr",
            [(set RC:$r, (load ADDR:$addr))]>;
    }

    let mayStore=1 in {
    def WRIT : HP41MCODEInst<0x068, (outs), (ins MEM:$addr,
            RC:$r), "WRIT $addr", [(store RC:$r, ADDR:$addr)]>;
    }

    ...

    bool
    HP41MCODERegisterInfo::eliminateFrameIndex(
            MachineBasicBlock::iterator II,
            int SPAdj, unsigned FIOperandNum,
            RegScavenger *RS) const {
        MachineInstr &MI = *II;
        int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
        MachineFunction &MF = *MI.getParent()->getParent();
        const HP41MCODEFrameLowering *TFI = getFrameLowering(MF);
        llvm::Register FrameReg;
        int Offset;
        Offset = TFI->getFrameIndexReference(MF, FrameIndex,
                FrameReg).getFixed()/4+1;
        MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg,
                false);
        MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
        return false;
    }

    ...

    void HP41MCODEInstPrinter::printMemOperand(const MCInst *MI,
            int opNum,
            const MCSubtargetInfo &STI,
            raw_ostream &O, const char *Modifier) {
        const MCOperand &MO = MI->getOperand(opNum+1);
        
        if (MO.isImm()) {
            O << format_decimal((int)MO.getImm(), 1); return; }
                    assert(MO.isExpr() &&
                    "Unknown operand kind in printMemOperand");
                    MO.getExpr()->print(O, &MAI);
    }

    ...

    bool HP41MCODEDAGToDAGISel::SelectADDR(SDValue Addr,
            SDValue &Base, SDValue &Offset) {
      if (FrameIndexSDNode *FIN = dyn_cast(Addr)) {
        Base = CurDAG->getTargetFrameIndex(
                FIN->getIndex(), TLI->getPointerTy(
                        CurDAG->getDataLayout()));
        Offset = CurDAG->getTargetConstant(0, SDLoc(Addr),
                        MVT::i32);
        return true;
      }

      return false;
    }


Then we end up with:

	.file	"hello.c"
	.text
	.globl	foo                     ! -- Begin function foo
	.type	foo,@function
foo:                                    ! @foo
! %bb.0:                                ! %entry
	LDI S&X HEX: 0AB
	WRIT 2
	C=0 ALL
	WRIT 1
	READ 2
	RTN
.Lfunc_end0:
	.size	foo, .Lfunc_end0-foo
                                        ! -- End function
	.ident	"clang version 20.0.0git (https://github.com/llvm/llvm-project.git ea1dfd50bfdfbd75969fd7653bc71c81f2a2350f)"
	.section	".note.GNU-stack"
	.addrsig

Comments are closed.