From: Tim Northover Date: Wed, 15 Feb 2017 23:22:33 +0000 (+0000) Subject: GlobalISel: support translating va_arg X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=432026394b19c5e4f988fd396f8e980ea072868e;p=llvm GlobalISel: support translating va_arg Since (say) i128 and [16 x i8] map to the same type in generic MIR, we also need to attach the required alignment info. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@295254 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/CodeGen/GlobalISel/IRTranslator.h b/include/llvm/CodeGen/GlobalISel/IRTranslator.h index 352eebd58c5..7ed2082f94d 100644 --- a/include/llvm/CodeGen/GlobalISel/IRTranslator.h +++ b/include/llvm/CodeGen/GlobalISel/IRTranslator.h @@ -300,6 +300,8 @@ private: return translateBinaryOp(TargetOpcode::G_FREM, U, MIRBuilder); } + bool translateVAArg(const User &U, MachineIRBuilder &MIRBuilder); + // Stubs to keep the compiler happy while we implement the rest of the // translation. bool translateResume(const User &U, MachineIRBuilder &MIRBuilder) { @@ -338,9 +340,6 @@ private: bool translateUserOp2(const User &U, MachineIRBuilder &MIRBuilder) { return false; } - bool translateVAArg(const User &U, MachineIRBuilder &MIRBuilder) { - return false; - } bool translateExtractElement(const User &U, MachineIRBuilder &MIRBuilder) { return false; } diff --git a/include/llvm/Target/GenericOpcodes.td b/include/llvm/Target/GenericOpcodes.td index 4c5d61788f2..880fbc46374 100644 --- a/include/llvm/Target/GenericOpcodes.td +++ b/include/llvm/Target/GenericOpcodes.td @@ -98,6 +98,14 @@ def G_VASTART : Instruction { let mayStore = 1; } +def G_VAARG : Instruction { + let OutOperandList = (outs type0:$val); + let InOperandList = (ins type1:$list, unknown:$align); + let hasSideEffects = 0; + let mayLoad = 1; + let mayStore = 1; +} + //------------------------------------------------------------------------------ // Binary ops. //------------------------------------------------------------------------------ diff --git a/include/llvm/Target/TargetOpcodes.def b/include/llvm/Target/TargetOpcodes.def index b38e0cfc364..2d1ff50ca10 100644 --- a/include/llvm/Target/TargetOpcodes.def +++ b/include/llvm/Target/TargetOpcodes.def @@ -283,6 +283,9 @@ HANDLE_TARGET_OPCODE(G_FCONSTANT) /// Generic va_start instruction. Stores to its one pointer operand. HANDLE_TARGET_OPCODE(G_VASTART) +/// Generic va_start instruction. Stores to its one pointer operand. +HANDLE_TARGET_OPCODE(G_VAARG) + // Generic sign extend HANDLE_TARGET_OPCODE(G_SEXT) diff --git a/lib/CodeGen/GlobalISel/IRTranslator.cpp b/lib/CodeGen/GlobalISel/IRTranslator.cpp index c5ac42f4430..e80dac1c952 100644 --- a/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -906,6 +906,18 @@ bool IRTranslator::translateAlloca(const User &U, return true; } +bool IRTranslator::translateVAArg(const User &U, MachineIRBuilder &MIRBuilder) { + // FIXME: We may need more info about the type. Because of how LLT works, + // we're completely discarding the i64/double distinction here (amongst + // others). Fortunately the ABIs I know of where that matters don't use va_arg + // anyway but that's not guaranteed. + MIRBuilder.buildInstr(TargetOpcode::G_VAARG) + .addDef(getOrCreateVReg(U)) + .addUse(getOrCreateVReg(*U.getOperand(0))) + .addImm(DL->getABITypeAlignment(U.getType())); + return true; +} + bool IRTranslator::translatePHI(const User &U, MachineIRBuilder &MIRBuilder) { const PHINode &PI = cast(U); auto MIB = MIRBuilder.buildInstr(TargetOpcode::PHI); diff --git a/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll b/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll index 418c71e3992..3c06d5c80f7 100644 --- a/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll +++ b/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll @@ -1134,6 +1134,19 @@ define void @test_va_end(i8* %list) { ret void } +define void @test_va_arg(i8* %list) { +; CHECK-LABEL: test_va_arg +; CHECK: [[LIST:%[0-9]+]](p0) = COPY %x0 +; CHECK: G_VAARG [[LIST]](p0), 8 +; CHECK: G_VAARG [[LIST]](p0), 1 +; CHECK: G_VAARG [[LIST]](p0), 16 + + %v0 = va_arg i8* %list, i64 + %v1 = va_arg i8* %list, i8 + %v2 = va_arg i8* %list, i128 + ret void +} + declare float @llvm.pow.f32(float, float) define float @test_pow_intrin(float %l, float %r) { ; CHECK-LABEL: name: test_pow_intrin