Soy nuevo en LLVM. Intento escribir un pase básico que inspeccionará los argumentos de una llamada printf
, cuando se le dé la representación intermedia.
Si la cadena de formato no es una cadena literal, entonces, por supuesto, no puedo inspeccionarla. Pero a menudo, lo es.¿Cómo obtener el valor de una cadena literal en LLVM IR?
El IR muestra que estoy tratando de inspeccionar es:
@.str = private unnamed_addr constant [7 x i8] c"Hi %u\0A\00", align 1
define i32 @main() nounwind {
entry:
%retval = alloca i32, align 4
store i32 0, i32* %retval
%call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([7 x i8]* @.str, i32 0, i32 0), i32 1)
ret i32 0
}
declare i32 @printf(i8*, ...)
me encontré con el paso de llama preexistente ExternalFunctionsPassedConstants
, que parecía relevante:
struct ExternalFunctionsPassedConstants : public ModulePass {
static char ID; // Pass ID, replacement for typeid
ExternalFunctionsPassedConstants() : ModulePass(ID) {}
virtual bool runOnModule(Module &M) {
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
if (!I->isDeclaration()) continue;
bool PrintedFn = false;
for (Value::use_iterator UI = I->use_begin(), E = I->use_end();
UI != E; ++UI) {
Instruction *User = dyn_cast<Instruction>(*UI);
if (!User) continue;
CallSite CS(cast<Value>(User));
if (!CS) continue;
...
por lo que añade el código:
if (I->getName() == "printf") {
errs() << "printf() arg0 type: "
<< CS.getArgument(0)->getType()->getTypeID() << "\n";
}
Hasta ahora, bien - Veo que el tipo ID es 14, lo que significa que es PointerTyID
.
Pero ahora, ¿cómo obtengo el contenido del literal de cadena que se pasa como argumento, entonces puedo validar el número de argumentos esperados contra el número realmente dado?
¡Oh impresionante! 'getOperand' me señaló en la dirección correcta! Parece que necesito 'lanzar (emitir (emitir (CS.getArgument (0)) -> getOperand (0)) -> getInitializer()) -> getAsCString()', que me da la cuerda. :) ¡Muchas gracias! –
Mehrdad